Skip to content

Commit

Permalink
feat: pass DiagnosticCollector to generated methods
Browse files Browse the repository at this point in the history
That is, instead of using getMessageAcceptor() to access the object for
recording diagnostics, pass a DiagnosticCollector object as an argument
to generated context methods.

Additionally, have the generated calls to 'validate' also specify the
CheckType of the performed check, so that the type can also be included
in any constructed diagnostics. This is something that is missing from
DispatchingCheckImpl based check execution, which always leaves
CheckType as null.
  • Loading branch information
hasu committed Jul 31, 2024
1 parent fe110c0 commit ac29fad
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ protected void _toJavaStatement(final XIssueExpression expr, final ITreeAppendab

// acceptor
b.append("// Issue diagnostic").newLine();
b.append(generatorNaming.catalogInstanceName(expr)).append(".accept(").append("getMessageAcceptor()");
b.append(generatorNaming.catalogInstanceName(expr)).append(".accept(").append("diagnosticCollector");

// context object
b.append(", //").increaseIndentation().newLine();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ class CheckGeneratorNaming {

/* Gets the name of the default validator class. */
def String defaultValidatorClassName() {
"DispatchingCheckImpl"
"AbstractDispatchingCheckImpl"
}

/* Gets the fully qualified name of the default validator class. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ import com.avaloq.tools.ddk.check.generator.CheckGeneratorNaming
import com.avaloq.tools.ddk.check.generator.CheckPropertiesGenerator
import com.avaloq.tools.ddk.check.resource.CheckLocationInFileProvider
import com.avaloq.tools.ddk.check.runtime.configuration.ICheckConfigurationStoreService
import com.avaloq.tools.ddk.check.runtime.issue.AbstractDispatchingCheckImpl
import com.avaloq.tools.ddk.check.runtime.issue.AbstractDispatchingCheckImpl.DiagnosticCollector
import com.avaloq.tools.ddk.check.runtime.issue.AbstractIssue
import com.avaloq.tools.ddk.check.runtime.issue.DispatchingCheckImpl
import com.avaloq.tools.ddk.check.runtime.issue.SeverityKind
import com.avaloq.tools.ddk.check.validation.IssueCodes
import com.avaloq.tools.ddk.xtext.tracing.ResourceValidationRuleSummaryEvent
Expand Down Expand Up @@ -143,7 +144,7 @@ class CheckJvmModelInferrer extends AbstractModelInferrer {
]);

acceptor.accept(catalog.toClass(catalog.qualifiedValidatorClassName), [
val parentType = checkedTypeRef(catalog, typeof(DispatchingCheckImpl));
val parentType = checkedTypeRef(catalog, typeof(AbstractDispatchingCheckImpl));
if (parentType !== null) {
superTypes += parentType;
}
Expand Down Expand Up @@ -194,6 +195,7 @@ class CheckJvmModelInferrer extends AbstractModelInferrer {
visibility = JvmVisibility::PUBLIC;
parameters += catalog.toParameter("checkMode", checkedTypeRef(catalog, CheckMode));
parameters += catalog.toParameter("object", objectBaseJavaTypeRef);
parameters += catalog.toParameter("diagnosticCollector", checkedTypeRef(catalog, DiagnosticCollector));
parameters += catalog.toParameter("eventCollector", checkedTypeRef(catalog, ResourceValidationRuleSummaryEvent.Collector));
annotations += createAnnotation(checkedTypeRef(catalog, typeof(Override)), []);
body = [out | emitDispatcherMethodBody(out, catalog, objectBaseJavaTypeRef)];
Expand Down Expand Up @@ -224,9 +226,12 @@ class CheckJvmModelInferrer extends AbstractModelInferrer {

for (val iterator = contextsByCheckType.entrySet.iterator(); iterator.hasNext(); ) {
val entry = iterator.next();
val checkType = '''CheckType.«entry.key»''';

out.append('''if (checkMode.shouldCheck(CheckType.«entry.key»)) {''');
out.append('''if (checkMode.shouldCheck(«checkType»)) {''');
out.increaseIndentation;
out.newLine;
out.append('''diagnosticCollector.setCurrentCheckType(«checkType»);''');
emitInstanceOfConditionals(out, entry.value, catalog, baseTypeName); // with preceding newline for each
out.decreaseIndentation;
out.newLine;
Expand Down Expand Up @@ -262,7 +267,7 @@ class CheckJvmModelInferrer extends AbstractModelInferrer {
val varName = if (typeName === null) "object" else "castObject" + (if (level > 1) Integer.toString(level) else "");

out.newLine;
out.append('''«IF typeName !== null»if (object instanceof «typeName» «varName») «ENDIF»{''');
out.append('''«IF typeName !== null»if (object instanceof final «typeName» «varName») «ENDIF»{''');
out.increaseIndentation;

val contexts = contextsByVarType.get(node);
Expand Down Expand Up @@ -290,7 +295,7 @@ class CheckJvmModelInferrer extends AbstractModelInferrer {
out.newLine;
out.append('''
validate(«jMethodName», «qMethodName», object,
() -> «methodName»(«varName»), eventCollector);''');
() -> «methodName»(«varName», diagnosticCollector), diagnosticCollector, eventCollector);''');
}

private def String toJavaLiteral(String... strings) {
Expand Down Expand Up @@ -350,7 +355,8 @@ class CheckJvmModelInferrer extends AbstractModelInferrer {
}
val String functionName = 'run' + ctx.contextVariable.type?.simpleName.toFirstUpper;
ctx.toMethod(functionName, typeRef('void')) [
parameters += ctx.contextVariable.toParameter(if (ctx.contextVariable.name === null) CheckConstants::IT else ctx.contextVariable.name, ctx.contextVariable.type);
parameters += ctx.toParameter(if (ctx.contextVariable.name === null) CheckConstants::IT else ctx.contextVariable.name, ctx.contextVariable.type);
parameters += ctx.toParameter("diagnosticCollector", checkedTypeRef(ctx, DiagnosticCollector));
body = ctx.constraint;
]
}
Expand Down Expand Up @@ -392,11 +398,12 @@ class CheckJvmModelInferrer extends AbstractModelInferrer {
// Therefore, we generate something new: each check becomes a local class

ctx.toMethod(functionName, typeRef('void')) [
parameters += ctx.contextVariable.toParameter("context", ctx.contextVariable.type);
parameters += ctx.toParameter("context", ctx.contextVariable.type);
parameters += ctx.toParameter("diagnosticCollector", checkedTypeRef(ctx, DiagnosticCollector));
annotations += createCheckAnnotation(ctx);
documentation = functionName + '.'; // Well, that's not very helpful, but it is what the old compiler did...
body = [append('''
«chk.name.toFirstLower + 'Impl'».run«ctx.contextVariable.type?.simpleName.toFirstUpper»(context);'''
«chk.name.toFirstLower + 'Impl'».run«ctx.contextVariable.type?.simpleName.toFirstUpper»(context, diagnosticCollector);'''
)]
]
}
Expand All @@ -409,7 +416,8 @@ class CheckJvmModelInferrer extends AbstractModelInferrer {
val String functionName = generateContextMethodName(ctx);

ctx.toMethod(functionName, typeRef('void')) [
parameters += ctx.contextVariable.toParameter(if (ctx.contextVariable.name === null) CheckConstants::IT else ctx.contextVariable.name, ctx.contextVariable.type);
parameters += ctx.toParameter(if (ctx.contextVariable.name === null) CheckConstants::IT else ctx.contextVariable.name, ctx.contextVariable.type);
parameters += ctx.toParameter("diagnosticCollector", checkedTypeRef(ctx, DiagnosticCollector));
annotations += createCheckAnnotation(ctx);
documentation = functionName + '.'; // Well, that's not very helpful, but it is what the old compiler did...
body = ctx.constraint;
Expand Down

0 comments on commit ac29fad

Please sign in to comment.