Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: pkg/analysis_server/lib/src/context_manager.dart

Issue 1399893004: Context invalidation on option changes (Implements #24574). (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Doc fix. Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/analysis_server/test/analysis/notification_analysis_options_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library context.directory.manager; 5 library context.directory.manager;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:collection'; 8 import 'dart:collection';
9 import 'dart:convert'; 9 import 'dart:convert';
10 import 'dart:core' hide Resource; 10 import 'dart:core' hide Resource;
11 11
12 import 'package:analyzer/src/context/context.dart' as context;
12 import 'package:analysis_server/plugin/analysis/resolver_provider.dart'; 13 import 'package:analysis_server/plugin/analysis/resolver_provider.dart';
13 import 'package:analysis_server/src/analysis_server.dart'; 14 import 'package:analysis_server/src/analysis_server.dart';
14 import 'package:analysis_server/src/server_options.dart'; 15 import 'package:analysis_server/src/server_options.dart';
15 import 'package:analyzer/file_system/file_system.dart'; 16 import 'package:analyzer/file_system/file_system.dart';
16 import 'package:analyzer/instrumentation/instrumentation.dart'; 17 import 'package:analyzer/instrumentation/instrumentation.dart';
17 import 'package:analyzer/plugin/options.dart'; 18 import 'package:analyzer/plugin/options.dart';
18 import 'package:analyzer/source/analysis_options_provider.dart'; 19 import 'package:analyzer/source/analysis_options_provider.dart';
19 import 'package:analyzer/source/package_map_provider.dart'; 20 import 'package:analyzer/source/package_map_provider.dart';
20 import 'package:analyzer/source/package_map_resolver.dart'; 21 import 'package:analyzer/source/package_map_resolver.dart';
21 import 'package:analyzer/source/path_filter.dart'; 22 import 'package:analyzer/source/path_filter.dart';
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 void updateContextPackageUriResolver( 305 void updateContextPackageUriResolver(
305 Folder contextFolder, FolderDisposition disposition); 306 Folder contextFolder, FolderDisposition disposition);
306 } 307 }
307 308
308 /** 309 /**
309 * Class that maintains a mapping from included/excluded paths to a set of 310 * Class that maintains a mapping from included/excluded paths to a set of
310 * folders that should correspond to analysis contexts. 311 * folders that should correspond to analysis contexts.
311 */ 312 */
312 class ContextManagerImpl implements ContextManager { 313 class ContextManagerImpl implements ContextManager {
313 /** 314 /**
315 * File name of analysis options files.
316 */
317 static const String ANALYSIS_OPTIONS_FILE = '.analysis_options';
Brian Wilkerson 2015/10/15 00:20:36 Do we have other definitions of this constant (or
pquitslund 2015/10/15 03:39:06 Agreed. The only other ones are in tests and in a
Brian Wilkerson 2015/10/15 13:15:31 Not really, no.
318
319 /**
314 * Temporary flag to hide WIP .packages support (DEP 5). 320 * Temporary flag to hide WIP .packages support (DEP 5).
315 */ 321 */
316 static bool ENABLE_PACKAGESPEC_SUPPORT = serverOptions.isSet( 322 static bool ENABLE_PACKAGESPEC_SUPPORT = serverOptions.isSet(
317 'ContextManagerImpl.ENABLE_PACKAGESPEC_SUPPORT', 323 'ContextManagerImpl.ENABLE_PACKAGESPEC_SUPPORT',
318 defaultValue: true); 324 defaultValue: true);
319 325
320 /** 326 /**
321 * The name of the `lib` directory. 327 * The name of the `lib` directory.
322 */ 328 */
323 static const String LIB_DIR_NAME = 'lib'; 329 static const String LIB_DIR_NAME = 'lib';
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 return true; 465 return true;
460 } 466 }
461 } 467 }
462 // no 468 // no
463 return false; 469 return false;
464 } 470 }
465 471
466 /** 472 /**
467 * Process [options] for the given context [info]. 473 * Process [options] for the given context [info].
468 */ 474 */
469 void processOptionsForContext( 475 void processOptionsForContext(ContextInfo info, Folder folder,
470 ContextInfo info, Map<String, YamlNode> options) { 476 {bool optionsRemoved: false}) {
471 if (options == null) { 477 Map<String, YamlNode> options;
478 try {
479 options = analysisOptionsProvider.getOptions(folder);
480 } catch (e, stacktrace) {
481 AnalysisEngine.instance.logger.logError(
482 'Error processing .analysis_options',
483 new CaughtException(e, stacktrace));
484 // TODO(pquitslund): contribute plugin that sends error notification on
485 // options file.
486 // Related test:
487 // context_manager_test.test_analysis_options_parse_failure()
488 // AnalysisEngine.instance.optionsPlugin.optionsProcessors
489 // .forEach((OptionsProcessor p) => p.onError(e));
490 }
491
492 if (options == null && !optionsRemoved) {
472 return; 493 return;
473 } 494 }
474 495
475 // Notify options processors. 496 // Notify options processors.
476 AnalysisEngine.instance.optionsPlugin.optionsProcessors.forEach( 497 AnalysisEngine.instance.optionsPlugin.optionsProcessors
477 (OptionsProcessor p) => p.optionsProcessed(info.context, options)); 498 .forEach((OptionsProcessor p) {
499 try {
500 p.optionsProcessed(info.context, options);
501 } catch (e, stacktrace) {
502 AnalysisEngine.instance.logger.logError(
503 'Error processing .analysis_options',
504 new CaughtException(e, stacktrace));
505 }
506 });
507
508 // In case options files are removed, revert to default options.
509 if (optionsRemoved) {
510 info.context.analysisOptions = new AnalysisOptionsImpl();
511 return;
512 }
478 513
479 // Analysis options are processed 'in-line'. 514 // Analysis options are processed 'in-line'.
480 // TODO(pq): consider pushing exclude handling into a plugin.
481 YamlMap analyzer = options['analyzer']; 515 YamlMap analyzer = options['analyzer'];
482 if (analyzer == null) { 516 if (analyzer == null) {
483 // No options for analyzer. 517 // No options for analyzer.
484 return; 518 return;
485 } 519 }
486 520
487 // Set strong mode. 521 // Set strong mode.
488 var strongMode = analyzer['strong-mode']; 522 var strongMode = analyzer['strong-mode'];
489 if (strongMode == true) { 523 if (strongMode is bool) {
Brian Wilkerson 2015/10/15 00:20:36 If the key isn't there I think we want to treat it
pquitslund 2015/10/15 03:39:06 Ah. Good catch! I took this approach: bool
490 AnalysisContext context = info.context; 524 AnalysisContext context = info.context;
491 AnalysisOptionsImpl options = 525 if (context.analysisOptions.strongMode != strongMode) {
492 new AnalysisOptionsImpl.from(context.analysisOptions); 526 AnalysisOptionsImpl options =
493 options.strongMode = true; 527 new AnalysisOptionsImpl.from(context.analysisOptions);
494 context.analysisOptions = options; 528 options.strongMode = strongMode;
529 context.analysisOptions = options;
530 }
495 } 531 }
496 532
497 // Set ignore patterns. 533 // Set ignore patterns.
498 YamlList exclude = analyzer['exclude']; 534 YamlList exclude = analyzer['exclude'];
499 if (exclude != null) { 535 if (exclude != null) {
500 setIgnorePatternsForContext(info, exclude); 536 setIgnorePatternsForContext(info, exclude);
501 } 537 }
502 } 538 }
503 539
504 @override 540 @override
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
837 // Next resort to a package uri resolver. 873 // Next resort to a package uri resolver.
838 if (disposition == null) { 874 if (disposition == null) {
839 disposition = 875 disposition =
840 _computeFolderDisposition(folder, dependencies.add, packagespecFile); 876 _computeFolderDisposition(folder, dependencies.add, packagespecFile);
841 } 877 }
842 878
843 info.setDependencies(dependencies); 879 info.setDependencies(dependencies);
844 info.context = callbacks.addContext(folder, disposition); 880 info.context = callbacks.addContext(folder, disposition);
845 info.context.name = folder.path; 881 info.context.name = folder.path;
846 882
847 try { 883 processOptionsForContext(info, folder);
848 Map<String, YamlNode> options =
849 analysisOptionsProvider.getOptions(folder);
850 processOptionsForContext(info, options);
851 } catch (e, stacktrace) {
852 AnalysisEngine.instance.logger.logError(
853 'Error processing .analysis_options',
854 new CaughtException(e, stacktrace));
855 // TODO(pquitslund): contribute plugin that sends error notification on
856 // options file.
857 // Related test:
858 // context_manager_test.test_analysis_options_parse_failure()
859 // AnalysisEngine.instance.optionsPlugin.optionsProcessors
860 // .forEach((OptionsProcessor p) => p.onError(e));
861 }
862 884
863 return info; 885 return info;
864 } 886 }
865 887
866 /** 888 /**
867 * Potentially create a new context associated with the given [folder]. 889 * Potentially create a new context associated with the given [folder].
868 * 890 *
869 * If there are subfolders with 'pubspec.yaml' files, separate contexts are 891 * If there are subfolders with 'pubspec.yaml' files, separate contexts are
870 * created for them and excluded from the context associated with the 892 * created for them and excluded from the context associated with the
871 * [folder]. 893 * [folder].
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
1154 List<Source> sources = info.context.getSourcesWithFullName(path); 1176 List<Source> sources = info.context.getSourcesWithFullName(path);
1155 if (!sources.isEmpty) { 1177 if (!sources.isEmpty) {
1156 ChangeSet changeSet = new ChangeSet(); 1178 ChangeSet changeSet = new ChangeSet();
1157 sources.forEach((Source source) { 1179 sources.forEach((Source source) {
1158 changeSet.changedSource(source); 1180 changeSet.changedSource(source);
1159 }); 1181 });
1160 callbacks.applyChangesToContext(info.folder, changeSet); 1182 callbacks.applyChangesToContext(info.folder, changeSet);
1161 } 1183 }
1162 break; 1184 break;
1163 } 1185 }
1186 _checkForPackagespecUpdate(path, info, info.folder);
1187 _checkForAnalysisOptionsUpdate(path, info, event.type);
1188 }
1164 1189
1165 //TODO(pquitslund): find the right place for this 1190 void _checkForAnalysisOptionsUpdate(
1166 _checkForPackagespecUpdate(path, info, info.folder); 1191 String path, ContextInfo info, ChangeType changeType) {
1192 if (pathContext.basename(path) == ANALYSIS_OPTIONS_FILE) {
1193 var analysisContext = info.context;
1194 if (analysisContext is context.AnalysisContextImpl) {
1195 processOptionsForContext(info, info.folder,
1196 optionsRemoved: changeType == ChangeType.REMOVE);
1197 analysisContext.invalidateCachedResults();
1198 callbacks.applyChangesToContext(info.folder, new ChangeSet());
1199 }
1200 }
1167 } 1201 }
1168 1202
1169 /** 1203 /**
1170 * Determine whether the given [path], when interpreted relative to the 1204 * Determine whether the given [path], when interpreted relative to the
1171 * context root [root], contains a folder whose name starts with '.'. 1205 * context root [root], contains a folder whose name starts with '.'.
1172 */ 1206 */
1173 bool _isContainedInDotFolder(String root, String path) { 1207 bool _isContainedInDotFolder(String root, String path) {
1174 String relativePath = 1208 String relativePath =
1175 pathContext.relative(pathContext.dirname(path), from: root); 1209 pathContext.relative(pathContext.dirname(path), from: root);
1176 for (String pathComponent in pathContext.split(relativePath)) { 1210 for (String pathComponent in pathContext.split(relativePath)) {
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
1442 var path = resourceProvider.pathContext.fromUri(uri); 1476 var path = resourceProvider.pathContext.fromUri(uri);
1443 packageMap[name] = <Folder>[resourceProvider.getFolder(path)]; 1477 packageMap[name] = <Folder>[resourceProvider.getFolder(path)];
1444 } 1478 }
1445 }); 1479 });
1446 return <UriResolver>[new SdkExtUriResolver(packageMap)]; 1480 return <UriResolver>[new SdkExtUriResolver(packageMap)];
1447 } else { 1481 } else {
1448 return const <UriResolver>[]; 1482 return const <UriResolver>[];
1449 } 1483 }
1450 } 1484 }
1451 } 1485 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analysis_server/test/analysis/notification_analysis_options_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698