Skip to content

Commit 46f8142

Browse files
trexemDagger Team
authored andcommitted
Validate that package names do not contain Java keywords in Dagger.
This change adds a check in `DaggerSuperficialValidation` to ensure that no part of a type's package name is a Java keyword. This is necessary for KSP because Dagger generates Java code, and using Java keywords in package names can lead to compilation errors in the generated code. A new `ValidationException` type is introduced to handle these errors. RELNOTES=N/A PiperOrigin-RevId: 839405001
1 parent 34dab76 commit 46f8142

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

dagger-compiler/main/java/dagger/internal/codegen/base/KeywordValidator.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,16 @@
2424
import static dagger.internal.codegen.xprocessing.XElements.asField;
2525
import static dagger.internal.codegen.xprocessing.XElements.asMethod;
2626
import static dagger.internal.codegen.xprocessing.XElements.asMethodParameter;
27+
import static dagger.internal.codegen.xprocessing.XElements.asTypeElement;
2728
import static dagger.internal.codegen.xprocessing.XElements.getSimpleName;
2829
import static dagger.internal.codegen.xprocessing.XElements.isExecutable;
2930
import static dagger.internal.codegen.xprocessing.XTypes.isPrimitive;
3031
import static javax.lang.model.SourceVersion.isKeyword;
3132

3233
import androidx.room3.compiler.processing.XElement;
3334
import androidx.room3.compiler.processing.XType;
35+
import androidx.room3.compiler.processing.XTypeElement;
36+
import com.google.common.base.Splitter;
3437
import java.util.Optional;
3538
import javax.annotation.Nullable;
3639
import javax.inject.Inject;
@@ -57,6 +60,7 @@ ValidationReport validateJavaKeyword(XElement element) {
5760
if (isTypeElement(element)) {
5861
keywordFromName(getSimpleName(element))
5962
.ifPresent(keyword -> report.addError(javaKeywordErrorMessage(keyword), element));
63+
validatePackageName(asTypeElement(element), report);
6064
// For KAPT We need to validate the Kotlin metadata methods name for type elements.
6165
// TODO(emjich): Re-enable this validation once we figure out how to avoid false positives.
6266
// As of now, we are seeing false positives for this validation because KAPT stubs do not
@@ -84,6 +88,19 @@ ValidationReport validateJavaKeyword(XElement element) {
8488
return report.build();
8589
}
8690

91+
private void validatePackageName(XTypeElement element, ValidationReport.Builder report) {
92+
String packageName = element.getPackageName();
93+
if (packageName == null) {
94+
return;
95+
}
96+
Iterable<String> names = Splitter.on('.').split(packageName);
97+
for (String name : names) {
98+
keywordFromName(name)
99+
.ifPresent(
100+
keyword -> report.addError(javaKeywordInPackageErrorMessage(keyword), element));
101+
}
102+
}
103+
87104
private void validateJavaKeywordType(@Nullable XType type, ValidationReport.Builder report) {
88105
if (type == null || type.isError() || isPrimitive(type)) {
89106
return;
@@ -118,4 +135,11 @@ private String javaKeywordErrorMessage(String keyword) {
118135
+ " Please use a different name.",
119136
keyword);
120137
}
138+
139+
private String javaKeywordInPackageErrorMessage(String keyword) {
140+
return String.format(
141+
"The name '%s' cannot be used as a package name because it is a Java keyword."
142+
+ " Please use a different package name.",
143+
keyword);
144+
}
121145
}

javatests/dagger/internal/codegen/KeywordValidatorTest.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,4 +402,34 @@ public void javaKeywordAsAssistedFactoryParameterName_doesNotFail() {
402402
"}");
403403
CompilerTests.daggerCompiler(source).compile(subject -> subject.hasErrorCount(0));
404404
}
405+
406+
@Test
407+
public void javaKeywordAsPackageName_failsWithExpectedError() {
408+
Source componentSrc =
409+
CompilerTests.kotlinSource(
410+
"test/TestComponent.kt",
411+
"package test.default",
412+
"",
413+
"import dagger.Component",
414+
"",
415+
"@Component",
416+
"interface TestComponent {}" // "default" is a Java keyword
417+
);
418+
CompilerTests.daggerCompiler(componentSrc)
419+
.compile(
420+
subject -> {
421+
switch (CompilerTests.backend(subject)) {
422+
case KSP:
423+
subject
424+
.hasErrorContaining(
425+
"The name 'default' cannot be used as a package name because")
426+
.onSource(componentSrc);
427+
break;
428+
case JAVAC:
429+
// JAVAC does not generate stubs for this case, thus no error is reported.
430+
subject.hasErrorCount(0);
431+
break;
432+
}
433+
});
434+
}
405435
}

0 commit comments

Comments
 (0)