diff --git a/annotator-core/src/main/java/edu/ucr/cs/riple/core/Annotator.java b/annotator-core/src/main/java/edu/ucr/cs/riple/core/Annotator.java index 0b0ccd63..a0ab8776 100644 --- a/annotator-core/src/main/java/edu/ucr/cs/riple/core/Annotator.java +++ b/annotator-core/src/main/java/edu/ucr/cs/riple/core/Annotator.java @@ -35,8 +35,6 @@ import edu.ucr.cs.riple.core.evaluators.VoidEvaluator; import edu.ucr.cs.riple.core.evaluators.suppliers.Supplier; import edu.ucr.cs.riple.core.evaluators.suppliers.TargetModuleSupplier; -import edu.ucr.cs.riple.core.injectors.AnnotationInjector; -import edu.ucr.cs.riple.core.injectors.PhysicalInjector; import edu.ucr.cs.riple.core.registries.index.Fix; import edu.ucr.cs.riple.core.util.Utility; import java.util.Set; @@ -49,9 +47,6 @@ */ public class Annotator { - /** Injector instance. */ - private final AnnotationInjector injector; - /** Annotator context. */ public final Context context; @@ -65,7 +60,6 @@ public Annotator(Config config) { this.config = config; this.context = new Context(config); this.cache = new ReportCache(config); - this.injector = new PhysicalInjector(context); } /** Starts the annotating process consist of preprocess followed by the "annotate" phase. */ @@ -89,7 +83,7 @@ public void start() { */ private void preprocess() { System.out.println("Preprocessing..."); - context.checker.preprocess(injector); + context.checker.preprocess(); } /** Performs iterations of inference/injection until no unseen fix is suggested. */ @@ -123,7 +117,7 @@ private void annotate() { } } if (config.suppressRemainingErrors) { - context.checker.suppressRemainingErrors(injector); + context.checker.suppressRemainingErrors(); } System.out.println("\nFinished annotating."); Utility.writeReports(context, cache.reports().stream().collect(ImmutableSet.toImmutableSet())); @@ -157,7 +151,7 @@ private void executeNextIteration( .filter(Report::approved) .flatMap(report -> config.chain ? report.tree.stream() : Stream.of(report.root)) .collect(Collectors.toSet()); - injector.injectFixes(selectedFixes); + context.getInjector().injectFixes(selectedFixes); // Update log. context.log.updateInjectedAnnotations( selectedFixes.stream().flatMap(fix -> fix.changes.stream()).collect(Collectors.toSet())); diff --git a/annotator-core/src/main/java/edu/ucr/cs/riple/core/Context.java b/annotator-core/src/main/java/edu/ucr/cs/riple/core/Context.java index 51c93f57..81ff8c48 100644 --- a/annotator-core/src/main/java/edu/ucr/cs/riple/core/Context.java +++ b/annotator-core/src/main/java/edu/ucr/cs/riple/core/Context.java @@ -27,6 +27,8 @@ import com.google.common.collect.ImmutableSet; import edu.ucr.cs.riple.core.checkers.Checker; import edu.ucr.cs.riple.core.checkers.CheckerBaseClass; +import edu.ucr.cs.riple.core.injectors.AnnotationInjector; +import edu.ucr.cs.riple.core.injectors.PhysicalInjector; import edu.ucr.cs.riple.core.log.Log; import edu.ucr.cs.riple.core.module.ModuleConfiguration; import edu.ucr.cs.riple.core.module.ModuleInfo; @@ -69,6 +71,8 @@ public class Context { /** Checker instance. Used to execute checker specific tasks. */ public final Checker checker; + public final AnnotationInjector injector; + /** * Builds context from command line arguments. * @@ -84,6 +88,16 @@ public Context(Config config) { this.targetModuleInfo = new ModuleInfo(this, config.target, config.buildCommand); // Checker compatibility check must be after target module info is initialized. this.checker.verifyCheckerCompatibility(); + this.injector = new PhysicalInjector(this); + } + + /** + * Gets the injector. + * + * @return Injector instance. + */ + public AnnotationInjector getInjector() { + return injector; } /** Responsible for handling offset changes in source file. */ diff --git a/annotator-core/src/main/java/edu/ucr/cs/riple/core/checkers/Checker.java b/annotator-core/src/main/java/edu/ucr/cs/riple/core/checkers/Checker.java index cec44582..ecabae83 100644 --- a/annotator-core/src/main/java/edu/ucr/cs/riple/core/checkers/Checker.java +++ b/annotator-core/src/main/java/edu/ucr/cs/riple/core/checkers/Checker.java @@ -25,7 +25,6 @@ package edu.ucr.cs.riple.core.checkers; import com.google.common.collect.ImmutableSet; -import edu.ucr.cs.riple.core.injectors.AnnotationInjector; import edu.ucr.cs.riple.core.module.ModuleConfiguration; import edu.ucr.cs.riple.core.module.ModuleInfo; import edu.ucr.cs.riple.core.registries.index.Error; @@ -46,20 +45,11 @@ public interface Checker { */ Set deserializeErrors(ModuleInfo module); - /** - * Suppresses remaining errors reported by the checker. - * - * @param injector Annotation injector to inject selected annotations. - */ - void suppressRemainingErrors(AnnotationInjector injector); + /** Suppresses remaining errors reported by the checker. */ + void suppressRemainingErrors(); - /** - * Used to do any pre-processing steps before running the inference. - * - * @param injector Annotation injector, can be used to inject any annotations during the - * pre-processing phase. - */ - void preprocess(AnnotationInjector injector); + /** Used to do any pre-processing steps before running the inference. */ + void preprocess(); /** * Verifies that the checker representation in Annotator is compatible with the actual running diff --git a/annotator-core/src/main/java/edu/ucr/cs/riple/core/checkers/nullaway/NullAway.java b/annotator-core/src/main/java/edu/ucr/cs/riple/core/checkers/nullaway/NullAway.java index 58823912..9b5f37a2 100644 --- a/annotator-core/src/main/java/edu/ucr/cs/riple/core/checkers/nullaway/NullAway.java +++ b/annotator-core/src/main/java/edu/ucr/cs/riple/core/checkers/nullaway/NullAway.java @@ -28,7 +28,6 @@ import com.google.common.collect.ImmutableSet; import edu.ucr.cs.riple.core.Context; import edu.ucr.cs.riple.core.checkers.CheckerBaseClass; -import edu.ucr.cs.riple.core.injectors.AnnotationInjector; import edu.ucr.cs.riple.core.module.ModuleConfiguration; import edu.ucr.cs.riple.core.module.ModuleInfo; import edu.ucr.cs.riple.core.registries.field.FieldInitializationStore; @@ -225,11 +224,9 @@ private ImmutableSet computeAddAnnotationInstancesForUninitialize *
  • Explicit {@code Nullable} assignments to fields will be annotated as * {@code @SuppressWarnings("NullAway")}. * - * - * @param injector Annotation injector to inject selected annotations. */ @Override - public void suppressRemainingErrors(AnnotationInjector injector) { + public void suppressRemainingErrors() { // Collect regions with remaining errors. Utility.buildTarget(context); Set remainingErrors = deserializeErrors(context.targetModuleInfo); @@ -336,7 +333,7 @@ public void suppressRemainingErrors(AnnotationInjector injector) { fix.toField(), "SuppressWarnings", "NullAway.Init", false)) .collect(Collectors.toSet()); result.addAll(initializationSuppressWarningsAnnotations); - injector.injectAnnotations(result); + context.getInjector().injectAnnotations(result); // update log context.log.updateInjectedAnnotations(result); // Collect @NullUnmarked annotations on classes for any remaining error. @@ -351,13 +348,13 @@ public void suppressRemainingErrors(AnnotationInjector injector) { context.targetModuleInfo.getLocationOnClass(error.getRegion().clazz), config.nullUnMarkedAnnotation)) .collect(Collectors.toSet()); - injector.injectAnnotations(nullUnMarkedAnnotations); + context.getInjector().injectAnnotations(nullUnMarkedAnnotations); // update log context.log.updateInjectedAnnotations(nullUnMarkedAnnotations); } @Override - public void preprocess(AnnotationInjector injector) { + public void preprocess() { // Collect @Initializer annotations. Heuristically, we add @Initializer on methods which writes // a @Nonnull value to more than one uninitialized field, and guarantees initialized fields are // nonnull at all exit paths. @@ -378,7 +375,7 @@ public void preprocess(AnnotationInjector injector) { .map(onMethod -> new AddMarkerAnnotation(onMethod, config.initializerAnnot)) .collect(Collectors.toSet()); // Inject @Initializer annotations. - injector.injectAnnotations(initializers); + context.getInjector().injectAnnotations(initializers); } /**