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