Skip to content

Commit a8df4c3

Browse files
committed
Limit field warnings and slim pull request CI
1 parent 74732ff commit a8df4c3

3 files changed

Lines changed: 34 additions & 44 deletions

File tree

.github/workflows/build.yml

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,15 @@ concurrency:
1111
cancel-in-progress: true
1212

1313
jobs:
14-
# Emit a wider matrix on master pushes (adds macOS), narrow on PRs (saves minutes)
15-
setup:
16-
runs-on: ubuntu-latest
17-
outputs:
18-
matrix: ${{ steps.set-matrix.outputs.matrix }}
19-
steps:
20-
- id: set-matrix
21-
shell: bash
22-
run: |
23-
if [[ "${{ github.event_name }}" == "push" ]]; then
24-
echo 'matrix={"include":[{"os":"ubuntu-latest"},{"os":"windows-latest"},{"os":"macos-latest"},{"os":"macos-15-intel"}]}' >> "$GITHUB_OUTPUT"
25-
else
26-
echo 'matrix={"include":[{"os":"ubuntu-latest"},{"os":"windows-latest"}]}' >> "$GITHUB_OUTPUT"
27-
fi
28-
14+
# Master pushes exercise every supported host. Pull requests use one Linux job
15+
# so that the normal feedback loop does not spend four runner-minutes on the
16+
# same compiler test suite; the full host matrix still runs before release.
2917
build:
3018
name: Gradle build on ${{ matrix.os }}
31-
needs: setup
3219
strategy:
3320
fail-fast: false
34-
matrix: ${{ fromJson(needs.setup.outputs.matrix) }}
21+
matrix:
22+
os: ${{ fromJSON(github.event_name == 'push' && '["ubuntu-latest","windows-latest","macos-latest","macos-15-intel"]' || '["ubuntu-latest"]') }}
3523
runs-on: ${{ matrix.os }}
3624
permissions:
3725
checks: write
@@ -96,8 +84,10 @@ jobs:
9684
- name: Setup Gradle (cache)
9785
uses: gradle/actions/setup-gradle@v4
9886

99-
# ---- FAIL FAST: package first (so jlink issues show immediately) ----
87+
# Packaging is a release artifact, not a pull-request gate. Keeping it on
88+
# master avoids paying for a second full build on every PR update.
10089
- name: Package slim runtime (fail fast)
90+
if: github.event_name == 'push'
10191
shell: bash
10292
run: ./gradlew packageSlimCompilerDist --no-daemon --stacktrace
10393

@@ -119,14 +109,14 @@ jobs:
119109
- name: Run tests
120110
shell: bash
121111
run: |
122-
if [[ "${{ runner.os }}" == "Linux" ]]; then
112+
if [[ "${{ github.event_name }}" == "push" && "${{ runner.os }}" == "Linux" ]]; then
123113
./gradlew test jacocoTestReport --no-daemon --stacktrace --quiet
124114
else
125115
./gradlew test --no-daemon --stacktrace --quiet
126116
fi
127117
128118
- name: Upload coverage to Coveralls
129-
if: runner.os == 'Linux'
119+
if: github.event_name == 'push' && runner.os == 'Linux'
130120
uses: coverallsapp/github-action@v2
131121
with:
132122
github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -157,6 +147,7 @@ jobs:
157147
retention-days: 14
158148

159149
- name: Upload packaged artifact (per-OS)
150+
if: github.event_name == 'push'
160151
uses: actions/upload-artifact@v4
161152
with:
162153
name: wurst-compiler-${{ matrix.os }}

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/WurstValidator.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1759,12 +1759,13 @@ private void checkUninitializedVars(FunctionLike f) {
17591759

17601760
/**
17611761
* Instance fields without an initializer are reset to the language default when an object is
1762-
* allocated, but that value is often accidental. Warn when a method reads such a field and no
1763-
* constructor is known to assign it on every construction path. This deliberately stays a
1764-
* cheap, local check: it does not attempt interprocedural or path-sensitive reasoning.
1762+
* allocated, but that value is often accidental. Warn when a constructor reads such a field
1763+
* before its value is definitely established. Ordinary methods are intentionally out of scope:
1764+
* their callers may establish fields through APIs or other construction-time hooks that this
1765+
* cheap local check cannot see.
17651766
*/
17661767
private void checkPotentiallyUninitializedClassFields(FunctionLike function) {
1767-
if (function instanceof OnDestroyDef) {
1768+
if (function instanceof OnDestroyDef || !(function instanceof ConstructorDef)) {
17681769
return;
17691770
}
17701771

de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/ClassesTests.java

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,9 @@ public void warnsWhenClassFieldHasNoInitializerOrConstructorAssignment() {
2828
"package Test",
2929
"class Counter",
3030
" int value",
31-
" function get() returns int",
32-
" return value",
33-
" function readBeforeSet() returns int",
31+
" construct()",
3432
" int oldValue = value",
35-
" value = 42",
36-
" return oldValue"
33+
" value = 42"
3734
);
3835
}
3936

@@ -70,8 +67,7 @@ public void warnsWhenConstructorOnlyAssignsOtherInstanceField() {
7067
" int value",
7168
" construct(Counter other)",
7269
" other.value = 1",
73-
" function get() returns int",
74-
" return value"
70+
" int _observed = this.value"
7571
);
7672

7773
assertEquals(result.getGui().getWarningList().stream()
@@ -105,8 +101,8 @@ public void warnsWhenUnqualifiedArrayFieldHasNoInitializer() {
105101
"package Test",
106102
"class Counter",
107103
" int values[2]",
108-
" function get() returns int",
109-
" return values[0]"
104+
" construct()",
105+
" int first = values[0]"
110106
);
111107
}
112108

@@ -120,14 +116,14 @@ public void warnsWhenFieldIsReadOnRightHandSideBeforeAssignment() {
120116
"package Test",
121117
"class Counter",
122118
" int value",
123-
" function increment() returns int",
119+
" construct()",
124120
" value = value + 1",
125-
" return value"
121+
" skip"
126122
);
127123
}
128124

129125
@Test
130-
public void warnsWhenOtherInstanceFieldIsReadAfterThisFieldWrite() {
126+
public void warnsWhenOtherInstanceFieldIsReadInConstructor() {
131127
test()
132128
.setStopOnFirstError(false)
133129
.executeProg(false)
@@ -136,9 +132,8 @@ public void warnsWhenOtherInstanceFieldIsReadAfterThisFieldWrite() {
136132
"package Test",
137133
"class Counter",
138134
" int value",
139-
" function getOther(Counter other) returns int",
140-
" value = 1",
141-
" return other.value"
135+
" construct(Counter other)",
136+
" let _observed = other.value"
142137
);
143138
}
144139

@@ -152,9 +147,9 @@ public void warnsWhenOnlyOneArrayElementWasAssigned() {
152147
"package Test",
153148
"class Counter",
154149
" int values[2]",
155-
" function getOther() returns int",
150+
" construct()",
156151
" values[0] = 1",
157-
" return values[1]"
152+
" int observed = values[1]"
158153
);
159154
}
160155

@@ -300,18 +295,21 @@ public void doesNotWarnForInitializedExplicitReceiverInsideConstructor() {
300295
}
301296

302297
@Test
303-
public void warnsForUninitializedFieldReadFromPackageFunction() {
304-
test()
298+
public void doesNotWarnForUninitializedFieldReadFromPackageFunction() {
299+
CompilationResult result = test()
305300
.setStopOnFirstError(false)
306301
.executeProg(false)
307-
.expectWarning("no explicit initializer and is not definitely assigned")
308302
.lines(
309303
"package Test",
310304
"class Counter",
311305
" int value",
312306
"function read(Counter counter) returns int",
313307
" return counter.value"
314308
);
309+
310+
assertFalse(result.getGui().getWarningList().stream()
311+
.anyMatch(w -> w.getMessage().contains("no explicit initializer and is not definitely assigned")),
312+
result.getGui().getWarningList().toString());
315313
}
316314

317315
@Test

0 commit comments

Comments
 (0)