1 /* 2 * Copyright (C) 2018 The Dagger Authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package dagger.internal.codegen.validation; 18 19 import static com.google.common.base.Preconditions.checkNotNull; 20 import static javax.tools.Diagnostic.Kind.ERROR; 21 22 import com.google.common.collect.ImmutableSet; 23 import dagger.internal.codegen.compileroption.CompilerOptions; 24 import dagger.internal.codegen.compileroption.ValidationType; 25 import dagger.internal.codegen.validation.DiagnosticReporterFactory.DiagnosticReporterImpl; 26 import dagger.model.BindingGraph; 27 import dagger.spi.BindingGraphPlugin; 28 import javax.inject.Inject; 29 import javax.inject.Singleton; 30 import javax.lang.model.element.TypeElement; 31 32 /** Validates a {@link BindingGraph}. */ 33 @Singleton 34 public final class BindingGraphValidator { 35 private final ImmutableSet<BindingGraphPlugin> validationPlugins; 36 private final ImmutableSet<BindingGraphPlugin> externalPlugins; 37 private final DiagnosticReporterFactory diagnosticReporterFactory; 38 private final CompilerOptions compilerOptions; 39 40 @Inject BindingGraphValidator( @alidation ImmutableSet<BindingGraphPlugin> validationPlugins, ImmutableSet<BindingGraphPlugin> externalPlugins, DiagnosticReporterFactory diagnosticReporterFactory, CompilerOptions compilerOptions)41 BindingGraphValidator( 42 @Validation ImmutableSet<BindingGraphPlugin> validationPlugins, 43 ImmutableSet<BindingGraphPlugin> externalPlugins, 44 DiagnosticReporterFactory diagnosticReporterFactory, 45 CompilerOptions compilerOptions) { 46 this.validationPlugins = validationPlugins; 47 this.externalPlugins = externalPlugins; 48 this.diagnosticReporterFactory = checkNotNull(diagnosticReporterFactory); 49 this.compilerOptions = compilerOptions; 50 } 51 52 /** Returns {@code true} if validation or analysis is required on the full binding graph. */ shouldDoFullBindingGraphValidation(TypeElement component)53 public boolean shouldDoFullBindingGraphValidation(TypeElement component) { 54 return requiresFullBindingGraphValidation() 55 || compilerOptions.pluginsVisitFullBindingGraphs(component); 56 } 57 requiresFullBindingGraphValidation()58 private boolean requiresFullBindingGraphValidation() { 59 return !compilerOptions.fullBindingGraphValidationType().equals(ValidationType.NONE); 60 } 61 62 /** Returns {@code true} if no errors are reported for {@code graph}. */ isValid(BindingGraph graph)63 public boolean isValid(BindingGraph graph) { 64 return validate(graph) && visitPlugins(graph); 65 } 66 67 /** Returns {@code true} if validation plugins report no errors. */ validate(BindingGraph graph)68 private boolean validate(BindingGraph graph) { 69 if (graph.isFullBindingGraph() && !requiresFullBindingGraphValidation()) { 70 return true; 71 } 72 73 boolean errorsAsWarnings = 74 graph.isFullBindingGraph() 75 && compilerOptions.fullBindingGraphValidationType().equals(ValidationType.WARNING); 76 77 return runPlugins(validationPlugins, graph, errorsAsWarnings); 78 } 79 80 /** Returns {@code true} if external plugins report no errors. */ visitPlugins(BindingGraph graph)81 private boolean visitPlugins(BindingGraph graph) { 82 TypeElement component = graph.rootComponentNode().componentPath().currentComponent(); 83 if (graph.isFullBindingGraph() 84 // TODO(b/135938915): Consider not visiting plugins if only 85 // fullBindingGraphValidation is enabled. 86 && !requiresFullBindingGraphValidation() 87 && !compilerOptions.pluginsVisitFullBindingGraphs(component)) { 88 return true; 89 } 90 return runPlugins(externalPlugins, graph, /*errorsAsWarnings=*/ false); 91 } 92 93 /** Returns {@code false} if any of the plugins reported an error. */ runPlugins( ImmutableSet<BindingGraphPlugin> plugins, BindingGraph graph, boolean errorsAsWarnings)94 private boolean runPlugins( 95 ImmutableSet<BindingGraphPlugin> plugins, BindingGraph graph, boolean errorsAsWarnings) { 96 boolean isClean = true; 97 for (BindingGraphPlugin plugin : plugins) { 98 DiagnosticReporterImpl reporter = 99 diagnosticReporterFactory.reporter(graph, plugin, errorsAsWarnings); 100 plugin.visitGraph(graph, reporter); 101 if (reporter.reportedDiagnosticKinds().contains(ERROR)) { 102 isClean = false; 103 } 104 } 105 return isClean; 106 } 107 } 108