Skip to content

Commit f536f82

Browse files
authored
Error message improvements (#189)
1 parent 326e621 commit f536f82

File tree

9 files changed

+53
-26
lines changed

9 files changed

+53
-26
lines changed

aop/aop-annotation-processor/src/main/java/ru/tinkoff/kora/aop/annotation/processor/AopAnnotationProcessor.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ private TypeElement findTypeElement(Element element) {
135135
return null;
136136
}
137137
if (element.getModifiers().contains(Modifier.FINAL)) {
138-
this.errors.add(new ProcessingError("Aspects can be applied only to non final classes, but " + element.getSimpleName() + " is final", element));
138+
this.errors.add(new ProcessingError("Aspects can't be applied to final classes, but " + element.getSimpleName() + " is final", element));
139139
return null;
140140
}
141141
var typeElement = (TypeElement) element;
@@ -153,8 +153,12 @@ private TypeElement findTypeElement(Element element) {
153153
this.errors.add(new ProcessingError("Aspects can be applied only to classes or methods, got %s".formatted(element.getKind()), element));
154154
return null;
155155
}
156-
if (element.getModifiers().contains(Modifier.FINAL) || element.getModifiers().contains(Modifier.PRIVATE)) {
157-
this.errors.add(new ProcessingError("Aspects can be applied only to non final non private methods", element));
156+
if (element.getModifiers().contains(Modifier.FINAL)) {
157+
this.errors.add(new ProcessingError("Aspects can't be applied to final methods, but method " + element.getEnclosingElement().getSimpleName() + "#" + element.getSimpleName() + "() is final", element));
158+
return null;
159+
}
160+
if (element.getModifiers().contains(Modifier.PRIVATE)) {
161+
this.errors.add(new ProcessingError("Aspects can't be applied to private methods, but method " + element.getEnclosingElement().getSimpleName() + "#" + element.getSimpleName() + "() is private", element));
158162
return null;
159163
}
160164
return this.findTypeElement(element.getEnclosingElement());

aop/aop-symbol-processor/src/main/kotlin/ru/tinkoff/kora/aop/symbol/processor/AopSymbolProcessor.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,11 @@ class AopSymbolProcessor(
112112
}
113113
ClassKind.CLASS -> {
114114
if (declaration.isAbstract()) {
115-
errors.add(ProcessingError("Aspects can not be applied to abstract classes, but $declaration is not abstract", declaration))
115+
errors.add(ProcessingError("Aspects can't be applied to abstract classes, but $declaration is abstract", declaration))
116116
return null
117117
}
118118
if (!declaration.isOpen()) {
119-
errors.add(ProcessingError("Aspects can be applied only to non final classes, but $declaration is not open", declaration))
119+
errors.add(ProcessingError("Aspects can be applied only to open classes, but $declaration is not open", declaration))
120120
return null
121121
}
122122
val constructor = findAopConstructor(declaration)
@@ -131,7 +131,7 @@ class AopSymbolProcessor(
131131
}
132132
is KSFunctionDeclaration -> {
133133
return if (!declaration.isOpen()) {
134-
errors.add(ProcessingError("Aspects can be applied only to non final functions, but function ${declaration.parentDeclaration}#$declaration is not open", declaration))
134+
errors.add(ProcessingError("Aspects applied only to open functions, but function ${declaration.parentDeclaration}#$declaration is not open", declaration))
135135
return null
136136
} else if (declaration.parentDeclaration is KSClassDeclaration) {
137137
findKsClassDeclaration(declaration.parentDeclaration as KSClassDeclaration)
@@ -148,6 +148,7 @@ class AopSymbolProcessor(
148148

149149
@KspExperimental
150150
class AopSymbolProcessorProvider : SymbolProcessorProvider {
151+
151152
override fun create(
152153
environment: SymbolProcessorEnvironment
153154
): SymbolProcessor {

json/json-annotation-processor/src/main/java/ru/tinkoff/kora/json/annotation/processor/reader/ReaderTypeMetaParser.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ public ReaderTypeMetaParser(ProcessingEnvironment env, KnownType knownTypes) {
3333

3434
public JsonClassReaderMeta parse(TypeElement jsonClass, TypeMirror typeMirror) throws ProcessingErrorException {
3535
if (jsonClass.getKind() != ElementKind.CLASS && jsonClass.getKind() != ElementKind.RECORD) {
36-
throw new IllegalArgumentException("Should not be called for non class elements");
36+
throw new ProcessingErrorException("JsonReader can't be called for non class elements: " + jsonClass, jsonClass);
3737
}
3838
if (jsonClass.getModifiers().contains(Modifier.ABSTRACT)) {
39-
throw new IllegalArgumentException("Should not be called for abstract elements");
39+
throw new ProcessingErrorException("JsonReader can't be called for abstract classes: " + jsonClass, jsonClass);
4040
}
4141
var jsonConstructor = this.findJsonConstructor(jsonClass);
4242
if (jsonConstructor == null) {
43-
throw new ProcessingErrorException("Class: %s\nTo generate json reader class must have one public constructor or constructor annotated with any of @Json/@JsonReader"
43+
throw new ProcessingErrorException("Class: %s\nIn order to generate JsonReader class must have one public constructor or constructor annotated with any of @Json/@JsonReader"
4444
.formatted(jsonClass),
4545
jsonClass
4646
);

kora-app-annotation-processor/src/main/java/ru/tinkoff/kora/kora/app/annotation/processor/GraphBuilder.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,12 @@ public static ProcessingState processProcessing(ProcessingContext ctx, RoundEnvi
149149
}
150150
if (results.size() > 1) {
151151
var deps = templates.stream().map(Objects::toString).collect(Collectors.joining("\n")).indent(2);
152-
throw new ProcessingErrorException("More than one component matches dependency claim " + dependencyClaim.type() + ":\n" + deps, declaration.source());
152+
if(dependencyClaim.tags().isEmpty()) {
153+
throw new ProcessingErrorException("More than one component matches dependency claim " + dependencyClaim.type() + ":\n" + deps, declaration.source());
154+
} else {
155+
var tagMsg = dependencyClaim.tags().stream().collect(Collectors.joining(", ", "@Tag(", ")"));
156+
throw new ProcessingErrorException("More than one component matches dependency claim " + dependencyClaim.type() + " with tag " + tagMsg + " :\n" + deps, declaration.source());
157+
}
153158
}
154159
throw exception;
155160
}
@@ -205,9 +210,14 @@ public static ProcessingState processProcessing(ProcessingContext ctx, RoundEnvi
205210
var msg = new StringBuilder();
206211
var claimTypeName = TypeName.get(dependencyClaim.type()).annotated(List.of());
207212
if (dependencyClaim.tags().isEmpty()) {
208-
msg.append(String.format("Required dependency was not found: %s", claimTypeName));
213+
msg.append(String.format("Required dependency type was not found and can't be auto created: %s.\n" +
214+
"Please check class for @%s annotation or that required module with component is plugged in.",
215+
claimTypeName, CommonClassNames.component.simpleName()));
209216
} else {
210-
msg.append(String.format("Required dependency was not found: %s %s", dependencyClaim.tags().stream().collect(Collectors.joining(", ", "@Tag(", ")")), claimTypeName));
217+
var tagMsg = dependencyClaim.tags().stream().collect(Collectors.joining(", ", "@Tag(", ")"));
218+
msg.append(String.format("Required dependency type was not found and can't be auto created: %s with tag %s.\n" +
219+
"Please check class for @%s annotation or that required module with component is plugged in.",
220+
claimTypeName, tagMsg, CommonClassNames.component.simpleName()));
211221
}
212222
for (var hint : hints) {
213223
msg.append("\n Hint: ").append(hint.message());

kora-app-annotation-processor/src/test/java/ru/tinkoff/kora/kora/app/annotation/processor/DependencyTest.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -250,11 +250,11 @@ final class TestClass1 {}
250250

251251
assertThat(compileResult.isFailed()).isTrue();
252252
assertThat(compileResult.errors()).hasSize(1);
253-
assertThat(compileResult.errors().get(0).getMessage(Locale.ENGLISH))
254-
.contains("Required dependency was not found: ")
255-
.contains("@Tag(ru.tinkoff.kora.kora.app.annotation.processor.packageForDependencyTest.testDiscoveredFinalClassDependencyTaggedDependencyNoTagOnClass.ExampleApplication.TestClass1) ")
256-
.contains("ru.tinkoff.kora.kora.app.annotation.processor.packageForDependencyTest.testDiscoveredFinalClassDependencyTaggedDependencyNoTagOnClass.ExampleApplication.TestClass1")
257-
;
253+
assertThat(compileResult.errors().get(0).getMessage(Locale.ENGLISH)).startsWith(
254+
"""
255+
Required dependency type was not found and can't be auto created: ru.tinkoff.kora.kora.app.annotation.processor.packageForDependencyTest.testDiscoveredFinalClassDependencyTaggedDependencyNoTagOnClass.ExampleApplication.TestClass1 with tag @Tag(ru.tinkoff.kora.kora.app.annotation.processor.packageForDependencyTest.testDiscoveredFinalClassDependencyTaggedDependencyNoTagOnClass.ExampleApplication.TestClass1).
256+
Please check class for @Component annotation or that required module with component is plugged in.
257+
""");
258258
}
259259

260260
@Test

kora-app-annotation-processor/src/test/java/ru/tinkoff/kora/kora/app/annotation/processor/KoraAppProcessorTest.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,8 @@ void unresolvedDependency() {
154154
assertThatThrownBy(() -> testClass(AppWithUnresolvedDependency.class))
155155
.isInstanceOfSatisfying(CompilationErrorException.class, e -> SoftAssertions.assertSoftly(s -> {
156156
s.assertThat(e.getMessage()).isEqualTo("""
157-
Required dependency was not found: ru.tinkoff.kora.kora.app.annotation.processor.app.AppWithUnresolvedDependency.Class3
157+
Required dependency type was not found and can't be auto created: ru.tinkoff.kora.kora.app.annotation.processor.app.AppWithUnresolvedDependency.Class3.
158+
Please check class for @Component annotation or that required module with component is plugged in.
158159
Requested at: ru.tinkoff.kora.kora.app.annotation.processor.app.AppWithUnresolvedDependency.class2(ru.tinkoff.kora.kora.app.annotation.processor.app.AppWithUnresolvedDependency.Class3)""");
159160
s.assertThat(e.diagnostics.get(0).getPosition()).isEqualTo(327);
160161
s.assertThat(e.diagnostics.get(0).getLineNumber()).isEqualTo(14);
@@ -195,17 +196,17 @@ void appWithFactory() throws Throwable {
195196
testClass(AppWithFactories9.class).init().block();
196197
assertThatThrownBy(() -> testClass(AppWithFactories10.class))
197198
.isInstanceOf(CompilationErrorException.class)
198-
.hasMessageStartingWith("Required dependency was not found: java.io.Closeable")
199+
.hasMessageStartingWith("Required dependency type was not found and can't be auto created: java.io.Closeable")
199200
.asInstanceOf(type(CompilationErrorException.class))
200201
.extracting(CompilationErrorException::getDiagnostics, list(Diagnostic.class))
201202
.anySatisfy(d -> {
202203
assertThat(d.getKind()).isEqualTo(Diagnostic.Kind.ERROR);
203204
assertThat(d.getMessage(Locale.ENGLISH)).isEqualTo("""
204-
Required dependency was not found: java.io.Closeable
205+
Required dependency type was not found and can't be auto created: java.io.Closeable.
206+
Please check class for @Component annotation or that required module with component is plugged in.
205207
Requested at: ru.tinkoff.kora.kora.app.annotation.processor.app.AppWithFactories10.mock1(java.io.Closeable)
206208
""".trim());
207-
})
208-
;
209+
});
209210
// assertThatThrownBy(() -> testClass(AppWithFactories11.class))
210211
// .isInstanceOf(CompilationErrorException.class)
211212
// .hasMessageContaining("Required dependency was not found and candidate class ru.tinkoff.kora.kora.app.annotation.processor.app.AppWithFactories11.GenericClass<java.lang.String> is not final")

kora-app-symbol-processor/src/main/kotlin/ru/tinkoff/kora/kora/app/ksp/GraphBuilder.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,18 @@ object GraphBuilder {
198198
}
199199
}
200200
val hints = ctx.dependencyHintProvider.findHints(dependencyClaim.type, dependencyClaim.tags)
201-
val msg = StringBuilder("Required dependency type ${dependencyClaim.type.toTypeName()} was not found and can't be autocreated.")
201+
val msg = if(dependencyClaim.tags.isEmpty()) {
202+
StringBuilder(
203+
"Required dependency type was not found and can't be auto created: ${dependencyClaim.type.toTypeName()}.\n" +
204+
"Please check class for @${CommonClassNames.component.canonicalName} annotation or that required module with component is plugged in."
205+
)
206+
} else {
207+
val tagMsg = dependencyClaim.tags.joinToString(", ", "@Tag(", ")")
208+
StringBuilder(
209+
"Required dependency type was not found and can't be auto created: ${dependencyClaim.type.toTypeName()} with tag ${tagMsg}.\n" +
210+
"Please check class for @${CommonClassNames.component.canonicalName} annotation or that required module with component is plugged in."
211+
)
212+
}
202213
for (hint in hints) {
203214
msg.append("\n Hint: ").append(hint.message())
204215
}

kora-app-symbol-processor/src/main/kotlin/ru/tinkoff/kora/kora/app/ksp/declaration/ComponentDeclaration.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ sealed interface ComponentDeclaration {
135135
fun fromDependency(ctx: ProcessingContext, classDeclaration: KSClassDeclaration): DiscoveredAsDependencyComponent {
136136
val constructor = classDeclaration.primaryConstructor
137137
if (constructor == null) {
138-
throw ProcessingErrorException("No primary constructor to parse component", classDeclaration)
138+
throw ProcessingErrorException("No primary constructor to parse component for: $classDeclaration", classDeclaration)
139139
}
140140
val type = classDeclaration.asType(listOf())
141141
if (type.isError) {

kora-app-symbol-processor/src/test/kotlin/ru/tinkoff/kora/kora/app/ksp/KoraAppKspTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ class KoraAppKspTest {
206206
.isInstanceOfSatisfying(CompilationErrorException::class.java) { e ->
207207
SoftAssertions.assertSoftly { s: SoftAssertions ->
208208
s.assertThat(e.messages)
209-
.anyMatch { it.contains("Required dependency type ru.tinkoff.kora.kora.app.ksp.app.AppWithUnresolvedDependency.Class3 was not found and can't be autocreated") }
209+
.anyMatch { it.contains("Required dependency type was not found and can't be auto created: ru.tinkoff.kora.kora.app.ksp.app.AppWithUnresolvedDependency.Class3") }
210210
}
211211
}
212212
}
@@ -257,7 +257,7 @@ class KoraAppKspTest {
257257
.isInstanceOfSatisfying(CompilationErrorException::class.java) { e ->
258258
SoftAssertions.assertSoftly { s: SoftAssertions ->
259259
s.assertThat(e.messages).anyMatch {
260-
it.contains("Required dependency type java.io.Closeable was not found and can't be autocreated")
260+
it.contains("Required dependency type was not found and can't be auto created: java.io.Closeable")
261261
}
262262
}
263263
}

0 commit comments

Comments
 (0)