Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ subprojects {
showCauses(true)
showExceptions(true)
showStackTraces(true)
events("passed", "skipped", "failed")
events("skipped", "failed")
exceptionFormat("full")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,9 @@ record ModuleHint(TypeName type, @Nullable String tag, String artifact, String m
public String message() {
if (tag == null) {
return """
Missing component: %s
Component is provided by standard Kora module you may forgot to plug it:
Gradle dependency: implementation("%s")
Module interface: %s
%s is provided by a standard Kora module.
Gradle dependency: implementation("%s")
Module interface: %s
""".formatted(type, artifact, module);
} else {
String tagForMsg;
Expand All @@ -56,10 +55,9 @@ public String message() {
}

return """
Missing component: %s with %s
Component is provided by standard Kora module you may forgot to plug it:
Gradle dependency: implementation("%s")
Module interface: %s
%s with %s is provided by a standard Kora module.
Gradle dependency: implementation("%s")
Module interface: %s
""".formatted(type, tagForMsg, artifact, module);
}
}
Expand Down Expand Up @@ -88,7 +86,7 @@ List<Hint> findHints(TypeMirror missingType, @Nullable String missingTag) {
} else if (hint instanceof KoraHint.KoraTipHint t) {
result.add(new Hint.TipHint(typeName, t.tag(), t.tip()));
} else {
throw new UnsupportedOperationException("Unknown hint type: " + hint);
throw new IllegalStateException("Kora internal error: unknown dependency hint type: " + hint);
}
}
} else {
Expand Down Expand Up @@ -165,7 +163,7 @@ static KoraHint parse(JsonParser p) throws IOException {
next = p.nextToken();
}
if (!tags.isEmpty() && tags.size() != 1) {
throw new IllegalArgumentException("More than one tag found in hint: " + tags);
throw new IllegalStateException("Kora internal error: dependency hint declares more than one tag: " + tags);
}
}
case "tag" -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,13 @@ public Component withCurrentDependency(int currentDependency) {
public ResolvedGraph build() {
if (rootSet.isEmpty()) {
throw new ProcessingErrorException(
"@KoraApp has no root components, expected at least one declaration annotated with @Root",
"""
@KoraApp has no root components.

Fix:
- Annotate at least one component or module method with @Root.
- Check that root component is visible from this @KoraApp module set.
""".stripTrailing(),
root
);
}
Expand Down Expand Up @@ -139,11 +145,31 @@ public ResolvedGraph build() {
.filter(d -> componentCondition.canonicalName().equals(d.declaration().tag()))
.toList();
if (conditionDeclarations.isEmpty()) {
throw new ProcessingErrorException("Component declares condition with tag %s, but none found in graph: %s".formatted(componentCondition.toString(), declaration), declaration.source());
throw new ProcessingErrorException("""
Component condition cannot be resolved:
required condition tag: @Tag(%s.class)
component: %s

Fix:
- Add a GraphCondition component with this tag.
- Include a module that provides this GraphCondition.
- Check that @Conditional uses the intended tag.
""".formatted(componentCondition, declaration).stripTrailing(), declaration.source());
}
if (conditionDeclarations.size() > 1) {
var str = conditionDeclarations.stream().map(DeclarationWithIndex::declaration).map(Object::toString).collect(Collectors.joining("\n")).indent(2);
throw new ProcessingErrorException("Component declares condition with tag %s, but multiple candidates found in graph:\n%s\n%s".formatted(componentCondition.toString(), declaration, str), declaration.source());
throw new ProcessingErrorException("""
Multiple GraphCondition components match condition tag:
required condition tag: @Tag(%s.class)
component: %s

Candidates:
%s

Fix:
- Keep only one GraphCondition for this tag.
- Use different @Tag(...) values for different conditions.
""".formatted(componentCondition, declaration, str).stripTrailing(), declaration.source());
}
var conditionDeclaration = conditionDeclarations.getFirst();
resolvedCondition = this.resolvedComponents.getByDeclaration(conditionDeclaration);
Expand Down Expand Up @@ -266,7 +292,14 @@ public ResolvedGraph build() {
try {
extensionResult = Objects.requireNonNull(extension.generateDependency());
} catch (IOException e) {
throw new RuntimeException(e);
throw new ProcessingErrorException("""
Extension failed to generate dependency:
dependency: %s

Fix:
- Check earlier errors from the extension annotation processor.
- If no earlier errors exist, report this as a Kora extension bug.
""".formatted(dependencyClaim.type()).stripTrailing(), dependencyClaim.source() == null ? declaration.source() : dependencyClaim.source());
}
var extensionComponent = switch (extensionResult) {
case ExtensionResult.CodeBlockResult codeBlockResult -> ComponentDeclaration.fromExtension(codeBlockResult);
Expand Down Expand Up @@ -301,7 +334,15 @@ public ResolvedGraph build() {
for (var resolvedDependency : dependencies) {
if (resolvedDependency.component().index() > component.index()) {
throw new ProcessingErrorException(
"All<T> dependency appeared in graph after component requesting it, this is a bug that we will fix later",
"""
All<T> dependency appeared in graph after the component that requests it.

This is an internal graph ordering limitation.

Fix:
- Move the component that provides the All<T> item so it is reachable before the requesting component.
- If this graph should be valid, please report this as a Kora bug with the dependency path.
""".stripTrailing(),
resolvedDependency.component().declaration().source()
);
}
Expand All @@ -311,7 +352,7 @@ public ResolvedGraph build() {
if (dependency instanceof ComponentDependency.PromisedProxyParameterDependency proxy) {
var componentDeclarations = GraphResolutionHelper.findDependencyDeclarations(ctx, declarations, proxy.claim());
if (componentDeclarations.size() != 1) {
throw new IllegalStateException();
throw new IllegalStateException("Kora internal error: promised proxy dependency expected exactly one target declaration, got " + componentDeclarations.size() + " for " + proxy.claim());
}
var realDependency = Objects.requireNonNull(resolvedComponents.getByDeclaration(componentDeclarations.getFirst()));
proxy.setPromised(realDependency);
Expand Down Expand Up @@ -363,7 +404,7 @@ private ComponentDependency processAllOf(ResolutionFrame.Component componentFram
if (dependencyClaim.claimType() == ALL_OF_PROMISE) {
return new ComponentDependency.AllOfDependency(dependencyClaim);
}
throw new IllegalStateException();
throw new IllegalStateException("Kora internal error: processAllOf called for non-All dependency claim: " + dependencyClaim);
}

private List<ResolutionFrame.Component> findInterceptors(ProcessingContext ctx, ResolvedComponents resolvedComponents, Deque<ResolutionFrame> resolutionStack, ComponentDeclaration declaration) {
Expand Down Expand Up @@ -446,7 +487,7 @@ private static ComponentDeclaration generatePromisedProxy(ProcessingContext ctx,
try {
javaFile.build().writeTo(ctx.filer);
} catch (IOException e) {
throw new RuntimeException(e);
throw new IllegalStateException("Kora internal error: failed to write promised proxy component for " + typeElement.getQualifiedName(), e);
}
return new ComponentDeclaration.PromisedProxyComponent(typeElement, ClassName.get(packageElement.getQualifiedName().toString(), resultClassName));
}
Expand Down Expand Up @@ -481,12 +522,12 @@ private boolean checkCycle(ComponentDeclaration declaration) {
var declarations = GraphResolutionHelper.findDependencyDeclarations(ctx, this.declarations, proxyDependencyClaim);
if (!declarations.isEmpty()) {
if (declarations.size() > 1) {
throw new IllegalStateException();
throw new IllegalStateException("Kora internal error: promised proxy declaration is ambiguous for " + proxyDependencyClaim + ", declarations: " + declarations);
}
var decl = declarations.getFirst();
var resolved = resolvedComponents.getByDeclaration(decl);
if (resolved == null) {
throw new IllegalStateException();
throw new IllegalStateException("Kora internal error: promised proxy declaration was found but is not resolved: " + decl.declaration().declarationString());
}
stack.removeLast();
prevComponent.resolvedDependencies().add(GraphResolutionHelper.toDependency(ctx, resolved, dependencyClaim));
Expand All @@ -506,7 +547,7 @@ private boolean checkCycle(ComponentDeclaration declaration) {
ctx, declaration, templates, proxyDependencyClaim
);
if (proxyComponentDeclarations.size() != 1) {
throw new IllegalStateException();
throw new IllegalStateException("Kora internal error: generated promised proxy template expected one declaration, got " + proxyComponentDeclarations.size() + " for " + proxyDependencyClaim);
}
proxyComponentDeclaration = proxyComponentDeclarations.getFirst();
declIdx = this.declarations.add(proxyComponentDeclaration);
Expand All @@ -516,7 +557,7 @@ private boolean checkCycle(ComponentDeclaration declaration) {
}
} else {
if (proxyComponentDeclarations.size() > 1) {
throw new IllegalStateException();
throw new IllegalStateException("Kora internal error: promised proxy template is ambiguous for " + proxyDependencyClaim + ", declarations: " + proxyComponentDeclarations);
}
proxyComponentDeclaration = proxyComponentDeclarations.getFirst();
declIdx = this.declarations.add(proxyComponentDeclaration);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ private CodeBlock generateComponentStatement(ClassName graphTypeName, ResolvedCo
var optionalOf = ((DeclaredType) optional.type()).getTypeArguments().get(0);
statement.add("$T.<$T>ofNullable($L)", Optional.class, optionalOf, dependenciesCode);
}
case null, default -> throw new RuntimeException("Unknown type " + declaration);
case null, default -> throw new IllegalStateException("Kora internal error: graph generator got unsupported component declaration: " + declaration);
}
statement.add(")");
return statement.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public static ComponentDependency.SingleDependency toDependency(ProcessingContex
var isDirectAssignable = ctx.types.isAssignable(resolvedComponent.type(), dependencyClaim.type());
var isWrappedAssignable = ctx.serviceTypeHelper.isAssignableToUnwrapped(resolvedComponent.type(), dependencyClaim.type());
if (!isDirectAssignable && !isWrappedAssignable) {
throw new IllegalStateException();
throw new IllegalStateException("Kora internal error: resolved component is not assignable to dependency claim. Component=" + resolvedComponent.declaration().declarationString() + ", claim=" + dependencyClaim);
}

var targetDependency = isWrappedAssignable
Expand All @@ -56,7 +56,7 @@ public static ComponentDependency.SingleDependency toDependency(ProcessingContex
case ONE_REQUIRED, ONE_NULLABLE, NODE_OF -> targetDependency;
case PROMISE_OF, NULLABLE_PROMISE_OF -> new ComponentDependency.PromiseOfDependency(dependencyClaim, targetDependency);
case VALUE_OF, NULLABLE_VALUE_OF -> new ComponentDependency.ValueOfDependency(dependencyClaim, targetDependency);
case ALL_OF_ONE, ALL_OF_PROMISE, ALL_OF_VALUE, TYPE_REF, GRAPH -> throw new IllegalStateException();
case ALL_OF_ONE, ALL_OF_PROMISE, ALL_OF_VALUE, TYPE_REF, GRAPH -> throw new IllegalStateException("Kora internal error: unsupported single dependency claim type " + dependencyClaim.claimType() + " for " + dependencyClaim);
};
}

Expand Down Expand Up @@ -84,8 +84,7 @@ public static List<ComponentDependency.SingleDependency> findDependenciesForAllO
// that's fine, default component wasn't directly requested by anyone, so we don't need it
continue;
} else {
// something went wrong
throw new NullPointerException();
throw new IllegalStateException("Kora internal error: non-default All<T> dependency declaration is not resolved: " + declaration.declarationString());
}
}
if (ctx.types.isAssignable(declaration.type(), dependencyClaim.type())) {
Expand All @@ -94,7 +93,7 @@ public static List<ComponentDependency.SingleDependency> findDependenciesForAllO
case ALL_OF_ONE -> targetDependency;
case ALL_OF_PROMISE -> new ComponentDependency.PromiseOfDependency(dependencyClaim, targetDependency);
case ALL_OF_VALUE -> new ComponentDependency.ValueOfDependency(dependencyClaim, targetDependency);
case null, default -> throw new IllegalStateException("Unexpected value: " + dependencyClaim.claimType());
case null, default -> throw new IllegalStateException("Kora internal error: unsupported All<T> claim type " + dependencyClaim.claimType() + " for " + dependencyClaim);
};
result.add(dependency);
}
Expand All @@ -104,7 +103,7 @@ public static List<ComponentDependency.SingleDependency> findDependenciesForAllO
case ALL_OF_ONE -> targetDependency;
case ALL_OF_PROMISE -> new ComponentDependency.PromiseOfDependency(dependencyClaim, targetDependency);
case ALL_OF_VALUE -> new ComponentDependency.ValueOfDependency(dependencyClaim, targetDependency);
case null, default -> throw new IllegalStateException("Unexpected value: " + dependencyClaim.claimType());
case null, default -> throw new IllegalStateException("Kora internal error: unsupported wrapped All<T> claim type " + dependencyClaim.claimType() + " for " + dependencyClaim);
};
result.add(dependency);
}
Expand All @@ -114,12 +113,19 @@ public static List<ComponentDependency.SingleDependency> findDependenciesForAllO

public static List<ComponentDeclaration> findDependencyDeclarationsFromTemplate(ProcessingContext ctx, ComponentDeclaration forDeclaration, List<ComponentDeclaration> sourceDeclarations, DependencyClaim dependencyClaim) {
if (dependencyClaim.type().getKind() == TypeKind.ERROR) {
throw new ProcessingErrorException("Component error type dependency claim " + dependencyClaim.type(), forDeclaration.source());
throw new ProcessingErrorException("""
Dependency type cannot be resolved:
type: %s

Fix:
- Check imports and module dependencies.
- Compile again after fixing earlier compiler errors.
""".formatted(dependencyClaim.type()).stripTrailing(), dependencyClaim.source() == null ? forDeclaration.source() : dependencyClaim.source());
}

var claimType = dependencyClaim.claimType();
if (claimType == ALL_OF_ONE || claimType == ALL_OF_PROMISE || claimType == ALL_OF_VALUE) {
throw new UnsupportedOperationException();
throw new IllegalStateException("Kora internal error: component templates cannot be resolved for All<T> dependency claim: " + dependencyClaim);
}
var types = ctx.types;
var declarations = new ArrayList<ComponentDeclaration>();
Expand All @@ -138,7 +144,7 @@ public static List<ComponentDeclaration> findDependencyDeclarationsFromTemplate(
continue sources;
}
if (!(match instanceof ComponentTemplateHelper.TemplateMatch.Some(var map))) {
throw new IllegalStateException();
throw new IllegalStateException("Kora internal error: unknown component template match result " + match + " for " + sourceDeclaration.declarationString());
}
var realReturnType = ComponentTemplateHelper.replace(types, declarationDeclaredType, map);

Expand Down Expand Up @@ -212,7 +218,7 @@ public static List<ComponentDeclaration> findDependencyDeclarationsFromTemplate(
));
}
case ComponentDeclaration.PromisedProxyComponent promisedProxyComponent -> declarations.add(promisedProxyComponent.withType(realReturnType));
default -> throw new IllegalArgumentException(sourceDeclaration.toString());
default -> throw new IllegalStateException("Kora internal error: unsupported template component declaration: " + sourceDeclaration);
}
}
if (declarations.isEmpty()) {
Expand Down
Loading
Loading