• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
20 import static javax.tools.Diagnostic.Kind.ERROR;
21 
22 import androidx.room.compiler.processing.XProcessingEnv;
23 import com.google.common.base.Optional;
24 import com.google.common.base.Supplier;
25 import com.google.common.collect.ImmutableMap;
26 import com.google.common.collect.ImmutableSet;
27 import com.google.common.collect.Maps;
28 import dagger.internal.codegen.compileroption.CompilerOptions;
29 import dagger.internal.codegen.compileroption.ProcessingOptions;
30 import dagger.internal.codegen.compileroption.ValidationType;
31 import dagger.internal.codegen.model.BindingGraph;
32 import dagger.internal.codegen.model.BindingGraphPlugin;
33 import dagger.internal.codegen.model.DaggerProcessingEnv;
34 import dagger.internal.codegen.validation.DiagnosticReporterFactory.DiagnosticReporterImpl;
35 import java.util.ArrayList;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Set;
39 import javax.inject.Inject;
40 
41 /** Initializes {@link BindingGraphPlugin}s. */
42 public final class ValidationBindingGraphPlugins {
43   private final ImmutableSet<ValidationBindingGraphPlugin> plugins;
44   private final DiagnosticReporterFactory diagnosticReporterFactory;
45   private final XProcessingEnv processingEnv;
46   private final CompilerOptions compilerOptions;
47   private final Map<String, String> processingOptions;
48 
49   @Inject
ValidationBindingGraphPlugins( @alidation ImmutableSet<ValidationBindingGraphPlugin> plugins, DiagnosticReporterFactory diagnosticReporterFactory, XProcessingEnv processingEnv, CompilerOptions compilerOptions, @ProcessingOptions Map<String, String> processingOptions)50   ValidationBindingGraphPlugins(
51       @Validation ImmutableSet<ValidationBindingGraphPlugin> plugins,
52       DiagnosticReporterFactory diagnosticReporterFactory,
53       XProcessingEnv processingEnv,
54       CompilerOptions compilerOptions,
55       @ProcessingOptions Map<String, String> processingOptions) {
56     this.plugins = plugins;
57     this.diagnosticReporterFactory = diagnosticReporterFactory;
58     this.processingEnv = processingEnv;
59     this.compilerOptions = compilerOptions;
60     this.processingOptions = processingOptions;
61   }
62 
63   /** Returns {@link BindingGraphPlugin#supportedOptions()} from all the plugins. */
allSupportedOptions()64   public ImmutableSet<String> allSupportedOptions() {
65     return plugins.stream()
66         .flatMap(plugin -> plugin.supportedOptions().stream())
67         .collect(toImmutableSet());
68   }
69 
70   /** Initializes the plugins. */
71   // TODO(ronshapiro): Should we validate the uniqueness of plugin names?
initializePlugins()72   public void initializePlugins() {
73     DaggerProcessingEnv daggerProcessingEnv = DaggerProcessingEnv.from(processingEnv);
74     plugins.forEach(plugin -> plugin.init(daggerProcessingEnv, pluginOptions(plugin)));
75   }
76 
77   /** Returns the filtered map of processing options supported by the given plugin. */
pluginOptions(BindingGraphPlugin plugin)78   private ImmutableMap<String, String> pluginOptions(BindingGraphPlugin plugin) {
79     Set<String> supportedOptions = plugin.supportedOptions();
80     return supportedOptions.isEmpty()
81         ? ImmutableMap.of()
82         : ImmutableMap.copyOf(Maps.filterKeys(processingOptions, supportedOptions::contains));
83   }
84 
85   /** Returns {@code false} if any of the plugins reported an error. */
visit(Optional<BindingGraph> prunedGraph, Supplier<BindingGraph> fullGraphSupplier)86   boolean visit(Optional<BindingGraph> prunedGraph, Supplier<BindingGraph> fullGraphSupplier) {
87     BindingGraph graph = prunedGraph.isPresent() ? prunedGraph.get() : fullGraphSupplier.get();
88 
89     boolean isClean = true;
90     List<ValidationBindingGraphPlugin> rerunPlugins = new ArrayList<>();
91     for (ValidationBindingGraphPlugin plugin : plugins) {
92       DiagnosticReporterImpl reporter = createReporter(plugin.pluginName(), graph);
93       plugin.visitGraph(graph, reporter);
94       if (plugin.visitFullGraphRequested(graph)) {
95         rerunPlugins.add(plugin);
96       }
97       if (reporter.reportedDiagnosticKinds().contains(ERROR)) {
98         isClean = false;
99       }
100     }
101     if (!rerunPlugins.isEmpty()) {
102       BindingGraph fullGraph = fullGraphSupplier.get();
103       for (ValidationBindingGraphPlugin plugin : rerunPlugins) {
104         DiagnosticReporterImpl reporter = createReporter(plugin.pluginName(), fullGraph);
105         plugin.revisitFullGraph(prunedGraph.get(), fullGraph, reporter);
106         if (reporter.reportedDiagnosticKinds().contains(ERROR)) {
107           isClean = false;
108         }
109       }
110     }
111     return isClean;
112   }
113 
createReporter(String pluginName, BindingGraph graph)114   private DiagnosticReporterImpl createReporter(String pluginName, BindingGraph graph) {
115     boolean errorsAsWarnings =
116         graph.isFullBindingGraph()
117             && compilerOptions.fullBindingGraphValidationType().equals(ValidationType.WARNING);
118     return errorsAsWarnings
119         ? diagnosticReporterFactory.reporterWithErrorAsWarnings(graph, pluginName)
120         : diagnosticReporterFactory.reporter(graph, pluginName);
121   }
122 
endPlugins()123   public void endPlugins() {
124     plugins.forEach(BindingGraphPlugin::onPluginEnd);
125   }
126 }
127