11// ignore_for_file: public_member_api_docs
2-
32import 'dart:async' ;
43
5- import 'package:analyzer/dart/analysis/context_locator.dart' ;
4+ import 'package:analyzer/dart/analysis/analysis_context.dart' ;
5+ import 'package:analyzer/dart/analysis/analysis_context_collection.dart' ;
66import 'package:analyzer/dart/analysis/results.dart' ;
7- import 'package:analyzer/file_system/physical_file_system.dart' ;
8- // ignore: implementation_imports
9- import 'package:analyzer/src/analysis_options/analysis_options_provider.dart' ;
10- // ignore: implementation_imports
11- import 'package:analyzer/src/dart/analysis/context_builder.dart' ;
12- // ignore: implementation_imports
13- import 'package:analyzer/src/dart/analysis/driver.dart' ;
147import 'package:analyzer_plugin/plugin/plugin.dart' ;
158import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
169
@@ -20,18 +13,14 @@ import '../analyzers/lint_analyzer/metrics/metrics_list/number_of_parameters_met
2013import '../analyzers/lint_analyzer/metrics/metrics_list/source_lines_of_code/source_lines_of_code_metric.dart' ;
2114import '../config_builder/config_builder.dart' ;
2215import '../config_builder/models/analysis_options.dart' ;
23- import '../utils/analyzer_utils.dart' ;
24- import '../utils/yaml_utils.dart' ;
2516import 'analyzer_plugin_utils.dart' ;
2617
27- final _byteStore = createByteStore (PhysicalResourceProvider .INSTANCE );
28-
2918class AnalyzerPlugin extends ServerPlugin {
3019 static const _analyzer = LintAnalyzer ();
3120
32- final _configs = < AnalysisDriverGeneric , LintAnalysisConfig > {};
21+ final _configs = < String , LintAnalysisConfig > {};
3322
34- var _filesFromSetPriorityFilesRequest = < String > [] ;
23+ AnalysisContextCollection ? _contextCollection ;
3524
3625 @override
3726 String get contactInfo =>
@@ -46,172 +35,101 @@ class AnalyzerPlugin extends ServerPlugin {
4635 @override
4736 String get version => '1.0.0-alpha.0' ;
4837
49- AnalyzerPlugin (super .resourceProvider);
50-
51- @override
52- void contentChanged (String path) {
53- super .driverForPath (path)? .addFile (path);
54- }
55-
56- @override
57- AnalysisDriverGeneric createAnalysisDriver (plugin.ContextRoot contextRoot) {
58- final rootPath = contextRoot.root;
59- final locator =
60- ContextLocator (resourceProvider: resourceProvider).locateRoots (
61- includedPaths: [rootPath],
62- excludedPaths: contextRoot.exclude,
63- optionsFile: contextRoot.optionsFile,
64- );
65-
66- if (locator.isEmpty) {
67- final error = StateError ('Unexpected empty context' );
68- channel.sendNotification (plugin.PluginErrorParams (
69- true ,
70- error.message,
71- error.stackTrace.toString (),
72- ).toNotification ());
73-
74- throw error;
75- }
76-
77- final builder = ContextBuilderImpl (resourceProvider: resourceProvider);
78- final context = builder.createContext (
79- contextRoot: locator.first,
80- byteStore: _byteStore,
81- );
82- final dartDriver = context.driver;
83- final config = _createConfig (dartDriver, rootPath);
84-
85- if (config == null ) {
86- return dartDriver;
87- }
88-
89- // Temporary disable deprecation check
90- //
91- // final deprecations = checkConfigDeprecatedOptions(
92- // config,
93- // deprecatedOptions,
94- // contextRoot.optionsFile!,
95- // );
96- // if (deprecations.isNotEmpty) {
97- // channel.sendNotification(plugin.AnalysisErrorsParams(
98- // contextRoot.optionsFile!,
99- // deprecations.map((deprecation) => deprecation.error).toList(),
100- // ).toNotification());
101- // }
102-
103- runZonedGuarded (
104- () {
105- dartDriver.results.listen ((analysisResult) {
106- if (analysisResult is ResolvedUnitResult ) {
107- _processResult (dartDriver, analysisResult);
108- }
109- });
110- },
111- (e, stackTrace) {
112- channel.sendNotification (
113- plugin.PluginErrorParams (false , e.toString (), stackTrace.toString ())
114- .toNotification (),
115- );
116- },
117- );
118-
119- return dartDriver;
120- }
38+ AnalyzerPlugin ({
39+ required super .resourceProvider,
40+ });
12141
12242 @override
123- Future <plugin.AnalysisSetContextRootsResult > handleAnalysisSetContextRoots (
124- plugin.AnalysisSetContextRootsParams parameters,
125- ) async {
126- final result = await super .handleAnalysisSetContextRoots (parameters);
127- // The super-call adds files to the driver, so we need to prioritize them so they get analyzed.
128- _updatePriorityFiles ();
43+ Future <void > afterNewContextCollection ({
44+ required AnalysisContextCollection contextCollection,
45+ }) {
46+ _contextCollection = contextCollection;
12947
130- return result;
131- }
48+ contextCollection.contexts.forEach (_createConfig);
13249
133- @override
134- Future <plugin.AnalysisSetPriorityFilesResult > handleAnalysisSetPriorityFiles (
135- plugin.AnalysisSetPriorityFilesParams parameters,
136- ) async {
137- _filesFromSetPriorityFilesRequest = parameters.files;
138- _updatePriorityFiles ();
139-
140- return plugin.AnalysisSetPriorityFilesResult ();
50+ return super
51+ .afterNewContextCollection (contextCollection: contextCollection);
14152 }
14253
14354 @override
144- Future <plugin.EditGetFixesResult > handleEditGetFixes (
145- plugin.EditGetFixesParams parameters,
146- ) async {
55+ Future <void > analyzeFile ({
56+ required AnalysisContext analysisContext,
57+ required String path,
58+ }) async {
14759 try {
148- final driver = driverForPath (parameters.file) as AnalysisDriver ;
149- // ignore: deprecated_member_use
150- final analysisResult = await driver.getResult2 (parameters.file);
151-
152- if (analysisResult is ! ResolvedUnitResult ) {
153- return plugin.EditGetFixesResult ([]);
154- }
60+ final resolvedUnit =
61+ await analysisContext.currentSession.getResolvedUnit (path);
15562
156- final fixes = _check (driver, analysisResult).where ((fix) {
157- final location = fix.error.location;
158-
159- return location.file == parameters.file &&
160- location.offset <= parameters.offset &&
161- parameters.offset <= location.offset + location.length &&
162- fix.fixes.isNotEmpty;
163- }).toList ();
63+ if (resolvedUnit is ResolvedUnitResult ) {
64+ final analysisErrors = _getErrorsForResolvedUnit (
65+ resolvedUnit,
66+ analysisContext.contextRoot.root.path,
67+ );
16468
165- return plugin.EditGetFixesResult (fixes);
69+ channel.sendNotification (
70+ plugin.AnalysisErrorsParams (
71+ path,
72+ analysisErrors.map ((analysisError) => analysisError.error).toList (),
73+ ).toNotification (),
74+ );
75+ } else {
76+ channel.sendNotification (
77+ plugin.AnalysisErrorsParams (path, []).toNotification (),
78+ );
79+ }
16680 } on Exception catch (e, stackTrace) {
16781 channel.sendNotification (
16882 plugin.PluginErrorParams (false , e.toString (), stackTrace.toString ())
16983 .toNotification (),
17084 );
171-
172- return plugin.EditGetFixesResult ([]);
17385 }
17486 }
17587
176- void _processResult (
177- AnalysisDriver driver,
178- ResolvedUnitResult analysisResult ,
179- ) {
88+ @override
89+ Future <plugin. EditGetFixesResult > handleEditGetFixes (
90+ plugin. EditGetFixesParams parameters ,
91+ ) async {
18092 try {
181- if (driver.analysisContext? .contextRoot.isAnalyzed (analysisResult.path) ??
182- false ) {
183- final fixes = _check (driver, analysisResult);
184-
185- channel.sendNotification (
186- plugin.AnalysisErrorsParams (
187- analysisResult.path,
188- fixes.map ((fix) => fix.error).toList (),
189- ).toNotification (),
190- );
191- } else {
192- channel.sendNotification (
193- plugin.AnalysisErrorsParams (analysisResult.path, []).toNotification (),
194- );
93+ final path = parameters.file;
94+ final analysisContext = _contextCollection? .contextFor (path);
95+ final resolvedUnit =
96+ await analysisContext? .currentSession.getResolvedUnit (path);
97+
98+ if (analysisContext != null && resolvedUnit is ResolvedUnitResult ) {
99+ final analysisErrors = _getErrorsForResolvedUnit (
100+ resolvedUnit,
101+ analysisContext.contextRoot.root.path,
102+ ).where ((analysisError) {
103+ final location = analysisError.error.location;
104+
105+ return location.file == parameters.file &&
106+ location.offset <= parameters.offset &&
107+ parameters.offset <= location.offset + location.length &&
108+ analysisError.fixes.isNotEmpty;
109+ }).toList ();
110+
111+ return plugin.EditGetFixesResult (analysisErrors);
195112 }
196113 } on Exception catch (e, stackTrace) {
197114 channel.sendNotification (
198115 plugin.PluginErrorParams (false , e.toString (), stackTrace.toString ())
199116 .toNotification (),
200117 );
201118 }
119+
120+ return plugin.EditGetFixesResult ([]);
202121 }
203122
204- Iterable <plugin.AnalysisErrorFixes > _check (
205- AnalysisDriver driver,
123+ Iterable <plugin.AnalysisErrorFixes > _getErrorsForResolvedUnit (
206124 ResolvedUnitResult analysisResult,
125+ String rootPath,
207126 ) {
208127 final result = < plugin.AnalysisErrorFixes > [];
209- final config = _configs[driver ];
128+ final config = _configs[rootPath ];
210129
211130 if (config != null ) {
212- final root = driver.analysisContext? .contextRoot.root.path;
213-
214- final report = _analyzer.runPluginAnalysis (analysisResult, config, root! );
131+ final report =
132+ _analyzer.runPluginAnalysis (analysisResult, config, rootPath);
215133
216134 if (report != null ) {
217135 result.addAll ([
@@ -237,69 +155,26 @@ class AnalyzerPlugin extends ServerPlugin {
237155 return result;
238156 }
239157
240- LintAnalysisConfig ? _createConfig (AnalysisDriver driver, String rootPath) {
241- final file = driver.analysisContext? .contextRoot.optionsFile;
158+ void _createConfig (AnalysisContext analysisContext) {
159+ final rootPath = analysisContext.contextRoot.root.path;
160+ final file = analysisContext.contextRoot.optionsFile;
161+
242162 if (file != null && file.exists) {
243- final options = AnalysisOptions (
244- file.path,
245- yamlMapToDartMap (
246- AnalysisOptionsProvider (driver.sourceFactory)
247- .getOptionsFromFile (file),
248- ),
249- );
250- final config = ConfigBuilder .getLintConfigFromOptions (options);
163+ final analysisOptions = analysisOptionsFromContext (analysisContext) ??
164+ analysisOptionsFromFilePath (file.parent.path, analysisContext);
165+ final config = ConfigBuilder .getLintConfigFromOptions (analysisOptions);
166+
251167 final lintConfig = ConfigBuilder .getLintAnalysisConfig (
252168 config,
253- options .folderPath ?? rootPath,
169+ analysisOptions .folderPath ?? rootPath,
254170 classMetrics: const [],
255171 functionMetrics: [
256172 NumberOfParametersMetric (config: config.metrics),
257173 SourceLinesOfCodeMetric (config: config.metrics),
258174 ],
259175 );
260176
261- _configs[driver] = lintConfig;
262-
263- return lintConfig;
264- }
265-
266- return null ;
267- }
268-
269- /// AnalysisDriver doesn't fully resolve files that are added via `addFile` ; they need to be either explicitly requested
270- /// via `getResult` /etc, or added to `priorityFiles` .
271- ///
272- /// This method updates `priorityFiles` on the driver to include:
273- ///
274- /// - Any files prioritized by the analysis server via [handleAnalysisSetPriorityFiles]
275- /// - All other files the driver has been told to analyze via addFile (in [ServerPlugin.handleAnalysisSetContextRoots] )
276- ///
277- /// As a result, [_processResult] will get called with resolved units, and thus all of our diagnostics
278- /// will get run on all files in the repo instead of only the currently open/edited ones!
279- void _updatePriorityFiles () {
280- final filesToFullyResolve = {
281- // Ensure these go first, since they're actually considered priority; ...
282- ..._filesFromSetPriorityFilesRequest,
283-
284- // ... all other files need to be analyzed, but don't trump priority
285- for (final driver2 in driverMap.values)
286- ...(driver2 as AnalysisDriver ).addedFiles,
287- };
288-
289- // From ServerPlugin.handleAnalysisSetPriorityFiles.
290- final filesByDriver = < AnalysisDriverGeneric , List <String >> {};
291- for (final file in filesToFullyResolve) {
292- final contextRoot = contextRootContaining (file);
293- if (contextRoot != null ) {
294- // TODO(dkrutskikh): Which driver should we use if there is no context root?
295- final driver = driverMap[contextRoot];
296- if (driver != null ) {
297- filesByDriver.putIfAbsent (driver, () => < String > []).add (file);
298- }
299- }
177+ _configs[rootPath] = lintConfig;
300178 }
301- filesByDriver.forEach ((driver, files) {
302- driver.priorityFiles = files;
303- });
304179 }
305180}
0 commit comments