New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Incremental compiler hotfixes #1483
Changes from 3 commits
bb5c6b4
1548fea
72cf3e9
5c0a581
a41f8d3
fba8ef2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -165,6 +165,8 @@ abstract class AbstractCrossTaskIncrementalJavaCompilationIntegrationTest extend | |
impl.noneRecompiled() | ||
} | ||
|
||
@NotYetImplemented | ||
// used to work in 3.4, not anymore in 3.4.1. Can re-enable with compiler plugins. See gradle/gradle#1474 | ||
def "deletion of jar with non-private constant causes rebuild if constant is used"() { | ||
java api: ["class A { public final static int x = 1; }"], impl: ["class X { int x() { return 1;} }", "class Y {}"] | ||
impl.snapshot { run "compileJava" } | ||
|
@@ -181,6 +183,8 @@ abstract class AbstractCrossTaskIncrementalJavaCompilationIntegrationTest extend | |
impl.recompiledClasses("X") | ||
} | ||
|
||
@NotYetImplemented | ||
// used to work in 3.4, not anymore in 3.4.1. Can re-enable with compiler plugins. See gradle/gradle#1474 | ||
def "change in an upstream class with non-private constant doesn't cause full rebuild if constant is not used"() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The name of this method is misleading. It should say "changing an unused constant". It's not just "any change". There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah I agree. I didn't change the test names, it should have been caught in a previous review :) |
||
java api: ["class A {}", "class B { final static int x = 1; }"], impl: ["class ImplA extends A {}", "class ImplB extends B {}"] | ||
impl.snapshot { run "compileJava" } | ||
|
@@ -203,7 +207,8 @@ abstract class AbstractCrossTaskIncrementalJavaCompilationIntegrationTest extend | |
run "impl:compileJava" | ||
|
||
then: | ||
impl.recompiledClasses('ImplA') | ||
// impl.recompiledClasses('ImplA') // used to work in 3.4, not anymore in 3.4.1. Can re-enable with compiler plugins. See gradle/gradle#1474 | ||
impl.recompiledClasses('ImplA', 'ImplB') | ||
|
||
where: | ||
constantType | constantValue | ||
|
@@ -219,6 +224,8 @@ abstract class AbstractCrossTaskIncrementalJavaCompilationIntegrationTest extend | |
} | ||
|
||
@Unroll | ||
@NotYetImplemented | ||
// used to work in 3.4, not anymore in 3.4.1. Can re-enable with compiler plugins. See gradle/gradle#1474 | ||
def "change in an upstream class with non-private constant causes rebuild only if same constant is used and no direct dependency (#constantType)"() { | ||
java api: ["class A {}", "class B { final static $constantType x = $constantValue; }"], impl: ["class X { $constantType foo() { return $constantValue; }}", "class Y {int foo() { return -2; }}"] | ||
impl.snapshot { run "compileJava" } | ||
|
@@ -244,6 +251,8 @@ abstract class AbstractCrossTaskIncrementalJavaCompilationIntegrationTest extend | |
} | ||
|
||
@Unroll | ||
@NotYetImplemented | ||
// used to work in 3.4, not anymore in 3.4.1. Can re-enable with compiler plugins. See gradle/gradle#1474 | ||
def "constant value change in an upstream class causes rebuild if previous constant value was used in previous build (#constantType)"() { | ||
java api: ["class A {}", "class B { final static $constantType x = $constantValue; }"], impl: ["class X { $constantType foo() { return $constantValue; }}", "class Y {int foo() { return -2; }}"] | ||
impl.snapshot { run "compileJava" } | ||
|
@@ -268,6 +277,8 @@ abstract class AbstractCrossTaskIncrementalJavaCompilationIntegrationTest extend | |
'String' | '"foo" + "bar"' | '"bar"' | ||
} | ||
|
||
@NotYetImplemented | ||
// used to work in 3.4, not anymore in 3.4.1. Can re-enable with compiler plugins. See gradle/gradle#1474 | ||
def "ignores irrelevant changes to constant values"() { | ||
java api: ["class A {}", "class B { final static int x = 3; final static int y = -2; }"], | ||
impl: ["class X { int foo() { return 3; }}", "class Y {int foo() { return -2; }}"] | ||
|
@@ -596,7 +607,7 @@ abstract class AbstractCrossTaskIncrementalJavaCompilationIntegrationTest extend | |
run("impl:compileJava") | ||
|
||
then: | ||
impl.recompiledClasses('C', 'C$Inner', 'D', 'D$Inner', 'E', 'E$1', 'F', 'F$Inner') | ||
impl.recompiledClasses('B', 'C', 'C$Inner', 'D', 'D$Inner', 'E', 'E$1', 'F', 'F$Inner') | ||
|
||
where: | ||
visibility << ['public', 'private' , ''] | ||
|
@@ -648,4 +659,46 @@ abstract class AbstractCrossTaskIncrementalJavaCompilationIntegrationTest extend | |
!output.contains(':api:compileJava - is not incremental (e.g. outputs have changed, no previous execution, etc.).') | ||
impl.recompiledClasses("ImplA") | ||
} | ||
|
||
@NotYetImplemented | ||
// used to work in 3.4, not anymore in 3.4.1. Can re-enable with compiler plugins. See gradle/gradle#1474 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should stop writing "used to work with 3.4", that sounds negative. The logic in 3.4 was broken and ignored way too many changes. Let's just leave "Will require compiler plugin". |
||
def "only recompiles classes potentially affected by constant change"() { | ||
java api: ["class A { public static final int FOO = 10; public static final int BAR = 20; }"], | ||
impl: ['class B { void foo() { int x = 10; } }', 'class C { void foo() { int x = 20; } }'] | ||
impl.snapshot { run 'compileJava' } | ||
|
||
when: | ||
java api: ['class A { public static final int FOO = 100; public static final int BAR = 20; }'] | ||
run 'impl:compileJava' | ||
|
||
then: | ||
impl.recompiledClasses 'B' | ||
} | ||
|
||
def "recompiles dependent class in case a constant is switched"() { | ||
java api: ["class A { public static final int FOO = 10; public static final int BAR = 20; }"], | ||
impl: ['class B { void foo() { int x = 10; } }', 'class C { void foo() { int x = 20; } }'] | ||
impl.snapshot { run 'compileJava' } | ||
|
||
when: | ||
java api: ['class A { public static final int FOO = 20; public static final int BAR = 10; }'] | ||
run 'impl:compileJava' | ||
|
||
then: | ||
impl.recompiledClasses 'B', 'C' | ||
} | ||
|
||
@Issue("gradle/gradle#1474") | ||
def "recompiles dependent class in case a constant is computed from another constant"() { | ||
java api: ["class A { public static final int FOO = 10; }"], impl: ['class B { public static final int BAR = 2 + A.FOO; } '] | ||
impl.snapshot { run 'compileJava' } | ||
|
||
when: | ||
java api: ['class A { public static final int FOO = 100; }'] | ||
run 'impl:compileJava' | ||
|
||
then: | ||
impl.recompiledClasses 'B' | ||
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -257,6 +257,8 @@ class SourceIncrementalJavaCompilationIntegrationTest extends AbstractIntegratio | |
outputs.recompiledClasses 'B', 'A' | ||
} | ||
|
||
@NotYetImplemented | ||
// used to work in 3.4, not anymore in 3.4.1. Can re-enable with compiler plugins. See gradle/gradle#1474 | ||
def "changed class with unused non-private constant incurs partial rebuild"() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above, this method name is misleading. It's not just "any change", but changing the unused constant (removing in this case). |
||
java "class A { int foo() { return 2; } }", "class B { final static int x = 1;}" | ||
outputs.snapshot { run "compileJava" } | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,7 +46,7 @@ public DependentsSet getRelevantDependents(Iterable<String> classes, Set<Integer | |
for (String dependentClass : dependentClasses) { | ||
result.add(dependentClass); | ||
Set<String> children = data.classesToChildren.get(dependentClass); | ||
if (children!=null && children.contains(cls)) { | ||
if (children != null && children.contains(cls)) { | ||
System.out.println("children = " + children); | ||
} | ||
} | ||
|
@@ -63,19 +63,26 @@ public DependentsSet getRelevantDependents(String className, Set<Integer> consta | |
if (deps == null && constants.isEmpty()) { | ||
return DefaultDependentsSet.EMPTY; | ||
} | ||
// since 3.4.1, the Set<Integer> of constants here doesn't match the set of literals, so we cannot use them | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this comment makes sense to anyone who didn't write this code or reads the whole git history. I'd just remove this comment, because the logic seems clearer to me without it. The code says clearly: If there are any constant changes, recompile everything. |
||
// anymore. If the set above is not empty, it means a constant has been added or changed, and we need to | ||
// recompile everything | ||
if (!constants.isEmpty()) { | ||
return DependencyToAll.INSTANCE; | ||
} | ||
Set<String> result = new HashSet<String>(); | ||
if (deps != null && !deps.isDependencyToAll()) { | ||
recurseDependents(new HashSet<String>(), result, deps.getDependentClasses()); | ||
} | ||
for (Integer constant : constants) { | ||
/*for (Integer constant : constants) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove commented-out code. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay... I kept it explicitly because it's easier to figure out why there's a |
||
Set<String> classes = data.literalsToClasses.get(constant); | ||
if (classes != null) { | ||
result.addAll(classes); | ||
} | ||
} | ||
|
||
*/ | ||
result.remove(className); | ||
return new DefaultDependentsSet(result); | ||
|
||
} | ||
|
||
public boolean isDependencyToAll(String className) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should still cause a (full) rebuild, because a constant disappeared.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do a full rebuild. The method name doesn't say "full rebuild". The previous version, in 3.4, only rebuilt one of the classes, not all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have a test that tests the full rebuild?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, and that's a fair point. That's what makes this PR a bit ugly. There were passing tests, that do not pass anymore. We want to keep them because we know we can make that work. On the other hand, we want to test the not so good behavior... So 2 tests testing the absolute opposite in the same class...