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

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

Issue 987663002: Fix for subscribing for notifications for files in packages. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 9 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 | Annotate | Revision Log
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 analysis.server; 5 library analysis.server;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:collection'; 8 import 'dart:collection';
9 import 'dart:math' show max; 9 import 'dart:math' show max;
10 10
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
360 } 360 }
361 361
362 /** 362 /**
363 * Return the preferred [AnalysisContext] for analyzing the given [path]. 363 * Return the preferred [AnalysisContext] for analyzing the given [path].
364 * This will be the context that explicitly contains the path, if any such 364 * This will be the context that explicitly contains the path, if any such
365 * context exists, otherwise it will be the first analysis context that 365 * context exists, otherwise it will be the first analysis context that
366 * implicitly analyzes it. Return `null` if no context is analyzing the 366 * implicitly analyzes it. Return `null` if no context is analyzing the
367 * path. 367 * path.
368 */ 368 */
369 AnalysisContext getAnalysisContext(String path) { 369 AnalysisContext getAnalysisContext(String path) {
370 // try to find a containing context 370 return getContextSourcePair(path).context;
371 Folder containingFolder = null;
372 for (Folder folder in folderMap.keys) {
373 if (folder.path == path || folder.contains(path)) {
374 if (containingFolder == null) {
375 containingFolder = folder;
376 } else if (containingFolder.path.length < folder.path.length) {
377 containingFolder = folder;
378 }
379 }
380 }
381 if (containingFolder != null) {
382 return folderMap[containingFolder];
383 }
384 Resource resource = resourceProvider.getResource(path);
385 if (resource is Folder) {
386 return null;
387 }
388 // check if there is a context that analyzed this source
389 return getAnalysisContextForSource(_getSourceWithoutContext(path));
390 } 371 }
391 372
392 /** 373 /**
374 * Return the [AnalysisContext] that contains the given [path].
375 * Return `null` if no context contains the [path].
376 */
377 AnalysisContext getContainingContext(String path) {
378 Folder containingFolder = null;
379 AnalysisContext containingContext = null;
380 folderMap.forEach((Folder folder, AnalysisContext context) {
381 if (folder.isOrContains(path)) {
382 if (containingFolder == null ||
383 containingFolder.path.length < folder.path.length) {
384 containingFolder = folder;
385 containingContext = context;
386 }
387 }
388 });
389 return containingContext;
390 }
391
392 /**
393 * Return any [AnalysisContext] that is analyzing the given [source], either 393 * Return any [AnalysisContext] that is analyzing the given [source], either
394 * explicitly or implicitly. Return `null` if there is no such context. 394 * explicitly or implicitly. Return `null` if there is no such context.
395 */ 395 */
396 AnalysisContext getAnalysisContextForSource(Source source) { 396 AnalysisContext getAnalysisContextForSource(Source source) {
397 for (AnalysisContext context in folderMap.values) { 397 for (AnalysisContext context in folderMap.values) {
398 SourceKind kind = context.getKindOf(source); 398 SourceKind kind = context.getKindOf(source);
399 if (kind != SourceKind.UNKNOWN) { 399 if (kind != SourceKind.UNKNOWN) {
400 return context; 400 return context;
401 } 401 }
402 } 402 }
403 return null; 403 return null;
404 } 404 }
405 405
406 /** 406 /**
407 * Return the [AnalysisContext]s that are being used to analyze the analysis 407 * Return the [AnalysisContext]s that are being used to analyze the analysis
408 * roots. 408 * roots.
409 */ 409 */
410 Iterable<AnalysisContext> getAnalysisContexts() { 410 Iterable<AnalysisContext> getAnalysisContexts() {
411 return folderMap.values; 411 return folderMap.values;
412 } 412 }
413 413
414 /** 414 /**
415 * Return the primary [ContextSourcePair] representing the given [path].
416 *
417 * The [AnalysisContext] of this pair will be the context that explicitly
418 * contains the path, if any such context exists, otherwise it will be the
419 * first context that implicitly analyzes it.
420 *
421 * If the [path] is not analyzed by any context, a [ContextSourcePair] with
422 * `null` context and `file` [Source] is returned.
423 *
424 * If the [path] dosn't represent a file, `null` is returned as a [Source].
425 *
426 * Does not return `null`.
427 */
428 ContextSourcePair getContextSourcePair(String path) {
429 // try SDK
430 {
431 Uri uri = resourceProvider.pathContext.toUri(path);
432 Source sdkSource = defaultSdk.fromFileUri(uri);
433 if (sdkSource != null) {
434 AnalysisContext anyContext = folderMap.values.first;
435 return new ContextSourcePair(anyContext, sdkSource);
436 }
437 }
438 // try to find the deep-most containing context
439 Resource resource = resourceProvider.getResource(path);
440 File file = resource is File ? resource : null;
441 {
442 Folder containingFolder = null;
Brian Wilkerson 2015/03/06 15:04:27 This is very similar to getContainingContext; it w
scheglov 2015/03/06 21:47:03 Done.
443 AnalysisContext containingContext = null;
444 folderMap.forEach((Folder folder, AnalysisContext context) {
445 if (folder.isOrContains(path)) {
446 if (containingFolder == null ||
447 containingFolder.path.length < folder.path.length) {
448 containingFolder = folder;
449 containingContext = context;
450 }
451 }
452 });
453 if (containingContext != null) {
454 Source source = file != null
455 ? ContextManager.createSourceInContext(containingContext, file)
456 : null;
457 return new ContextSourcePair(containingContext, source);
458 }
459 }
460 // try to find a context that analysed the file
461 for (AnalysisContext context in folderMap.values) {
462 Source source = file != null
463 ? ContextManager.createSourceInContext(context, file)
464 : null;
465 SourceKind kind = context.getKindOf(source);
466 if (kind != SourceKind.UNKNOWN) {
467 return new ContextSourcePair(context, source);
468 }
469 }
470 // file-based source
471 Source fileSource = file != null ? file.createSource() : null;
472 return new ContextSourcePair(null, fileSource);
473 }
474
475 /**
415 * Returns [Element]s at the given [offset] of the given [file]. 476 * Returns [Element]s at the given [offset] of the given [file].
416 * 477 *
417 * May be empty if cannot be resolved, but not `null`. 478 * May be empty if cannot be resolved, but not `null`.
418 */ 479 */
419 List<Element> getElementsAtOffset(String file, int offset) { 480 List<Element> getElementsAtOffset(String file, int offset) {
420 List<AstNode> nodes = getNodesAtOffset(file, offset); 481 List<AstNode> nodes = getNodesAtOffset(file, offset);
421 return getElementsOfNodes(nodes, offset); 482 return getElementsOfNodes(nodes, offset);
422 } 483 }
423 484
424 /** 485 /**
(...skipping 28 matching lines...) Expand all
453 * Returns `null` if [file] does not belong to any [AnalysisContext], or the 514 * Returns `null` if [file] does not belong to any [AnalysisContext], or the
454 * file does not exist. 515 * file does not exist.
455 * 516 *
456 * The array of errors will be empty if there are no errors in [file]. The 517 * The array of errors will be empty if there are no errors in [file]. The
457 * errors contained in the array can be incomplete. 518 * errors contained in the array can be incomplete.
458 * 519 *
459 * This method does not wait for all errors to be computed, and returns just 520 * This method does not wait for all errors to be computed, and returns just
460 * the current state. 521 * the current state.
461 */ 522 */
462 AnalysisErrorInfo getErrors(String file) { 523 AnalysisErrorInfo getErrors(String file) {
463 // prepare AnalysisContext 524 ContextSourcePair contextSource = getContextSourcePair(file);
464 AnalysisContext context = getAnalysisContext(file); 525 AnalysisContext context = contextSource.context;
526 Source source = contextSource.source;
465 if (context == null) { 527 if (context == null) {
466 return null; 528 return null;
467 } 529 }
468 // prepare Source 530 if (!source.exists()) {
469 Source source = getSource(file);
470 if (context.getKindOf(source) == SourceKind.UNKNOWN) {
471 return null; 531 return null;
472 } 532 }
473 // get errors for the file
474 return context.getErrors(source); 533 return context.getErrors(source);
475 } 534 }
476 535
477 /**
478 * Returns resolved [AstNode]s at the given [offset] of the given [file].
479 *
480 * May be empty, but not `null`.
481 */
482 List<AstNode> getNodesAtOffset(String file, int offset) {
483 List<CompilationUnit> units = getResolvedCompilationUnits(file);
484 List<AstNode> nodes = <AstNode>[];
485 for (CompilationUnit unit in units) {
486 AstNode node = new NodeLocator.con1(offset).searchWithin(unit);
487 if (node != null) {
488 nodes.add(node);
489 }
490 }
491 return nodes;
492 }
493
494 // TODO(brianwilkerson) Add the following method after 'prioritySources' has 536 // TODO(brianwilkerson) Add the following method after 'prioritySources' has
495 // been added to InternalAnalysisContext. 537 // been added to InternalAnalysisContext.
496 // /** 538 // /**
497 // * Return a list containing the full names of all of the sources that are 539 // * Return a list containing the full names of all of the sources that are
498 // * priority sources. 540 // * priority sources.
499 // */ 541 // */
500 // List<String> getPriorityFiles() { 542 // List<String> getPriorityFiles() {
501 // List<String> priorityFiles = new List<String>(); 543 // List<String> priorityFiles = new List<String>();
502 // folderMap.values.forEach((ContextDirectory directory) { 544 // folderMap.values.forEach((ContextDirectory directory) {
503 // InternalAnalysisContext context = directory.context; 545 // InternalAnalysisContext context = directory.context;
504 // context.prioritySources.forEach((Source source) { 546 // context.prioritySources.forEach((Source source) {
505 // priorityFiles.add(source.fullName); 547 // priorityFiles.add(source.fullName);
506 // }); 548 // });
507 // }); 549 // });
508 // return priorityFiles; 550 // return priorityFiles;
509 // } 551 // }
510 552
511 /** 553 /**
554 * Returns resolved [AstNode]s at the given [offset] of the given [file].
555 *
556 * May be empty, but not `null`.
557 */
558 List<AstNode> getNodesAtOffset(String file, int offset) {
559 List<CompilationUnit> units = getResolvedCompilationUnits(file);
560 List<AstNode> nodes = <AstNode>[];
561 for (CompilationUnit unit in units) {
562 AstNode node = new NodeLocator.con1(offset).searchWithin(unit);
563 if (node != null) {
564 nodes.add(node);
565 }
566 }
567 return nodes;
568 }
569
570 /**
512 * Returns resolved [CompilationUnit]s of the Dart file with the given [path]. 571 * Returns resolved [CompilationUnit]s of the Dart file with the given [path].
513 * 572 *
514 * May be empty, but not `null`. 573 * May be empty, but not `null`.
515 */ 574 */
516 List<CompilationUnit> getResolvedCompilationUnits(String path) { 575 List<CompilationUnit> getResolvedCompilationUnits(String path) {
517 List<CompilationUnit> units = <CompilationUnit>[]; 576 List<CompilationUnit> units = <CompilationUnit>[];
577 ContextSourcePair contextSource = getContextSourcePair(path);
518 // prepare AnalysisContext 578 // prepare AnalysisContext
519 AnalysisContext context = getAnalysisContext(path); 579 AnalysisContext context = contextSource.context;
520 if (context == null) { 580 if (context == null) {
521 return units; 581 return units;
522 } 582 }
523 // add a unit for each unit/library combination 583 // add a unit for each unit/library combination
524 Source unitSource = getSource(path); 584 Source unitSource = contextSource.source;
525 List<Source> librarySources = context.getLibrariesContaining(unitSource); 585 List<Source> librarySources = context.getLibrariesContaining(unitSource);
526 for (Source librarySource in librarySources) { 586 for (Source librarySource in librarySources) {
527 CompilationUnit unit = 587 CompilationUnit unit =
528 context.resolveCompilationUnit2(unitSource, librarySource); 588 context.resolveCompilationUnit2(unitSource, librarySource);
529 if (unit != null) { 589 if (unit != null) {
530 units.add(unit); 590 units.add(unit);
531 } 591 }
532 } 592 }
533 // done 593 // done
534 return units; 594 return units;
535 } 595 }
536 596
537 /** 597 /**
538 * Returns the [CompilationUnit] of the Dart file with the given [path] that
539 * should be used to resend notifications for already resolved unit.
540 * Returns `null` if the file is not a part of any context, library has not
541 * been yet resolved, or any problem happened.
542 */
543 CompilationUnit getResolvedCompilationUnitToResendNotification(String path) {
544 // prepare AnalysisContext
545 AnalysisContext context = getAnalysisContext(path);
546 if (context == null) {
547 return null;
548 }
549 // prepare sources
550 Source unitSource = getSource(path);
551 List<Source> librarySources = context.getLibrariesContaining(unitSource);
552 if (librarySources.isEmpty) {
553 return null;
554 }
555 // if library has not been resolved yet, the unit will be resolved later
556 Source librarySource = librarySources[0];
557 if (context.getLibraryElement(librarySource) == null) {
558 return null;
559 }
560 // if library has been already resolved, resolve unit
561 return context.resolveCompilationUnit2(unitSource, librarySource);
562 }
563
564 /**
565 * Return the [Source] of the Dart file with the given [path].
566 */
567 Source getSource(String path) {
568 // try SDK
569 {
570 Uri uri = resourceProvider.pathContext.toUri(path);
571 Source sdkSource = defaultSdk.fromFileUri(uri);
572 if (sdkSource != null) {
573 return sdkSource;
574 }
575 }
576 // file-based source
577 File file = resourceProvider.getResource(path);
578 return ContextManager.createSourceInContext(getAnalysisContext(path), file);
579 }
580
581 /**
582 * Handle a [request] that was read from the communication channel. 598 * Handle a [request] that was read from the communication channel.
583 */ 599 */
584 void handleRequest(Request request) { 600 void handleRequest(Request request) {
585 _performance.logRequest(request); 601 _performance.logRequest(request);
586 runZoned(() { 602 runZoned(() {
587 ServerPerformanceStatistics.serverRequests.makeCurrentWhile(() { 603 ServerPerformanceStatistics.serverRequests.makeCurrentWhile(() {
588 int count = handlers.length; 604 int count = handlers.length;
589 for (int i = 0; i < count; i++) { 605 for (int i = 0; i < count; i++) {
590 try { 606 try {
591 Response response = handlers[i].handleRequest(request); 607 Response response = handlers[i].handleRequest(request);
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
845 * Implementation for `analysis.setSubscriptions`. 861 * Implementation for `analysis.setSubscriptions`.
846 */ 862 */
847 void setAnalysisSubscriptions( 863 void setAnalysisSubscriptions(
848 Map<AnalysisService, Set<String>> subscriptions) { 864 Map<AnalysisService, Set<String>> subscriptions) {
849 // send notifications for already analyzed sources 865 // send notifications for already analyzed sources
850 subscriptions.forEach((service, Set<String> newFiles) { 866 subscriptions.forEach((service, Set<String> newFiles) {
851 Set<String> oldFiles = analysisServices[service]; 867 Set<String> oldFiles = analysisServices[service];
852 Set<String> todoFiles = 868 Set<String> todoFiles =
853 oldFiles != null ? newFiles.difference(oldFiles) : newFiles; 869 oldFiles != null ? newFiles.difference(oldFiles) : newFiles;
854 for (String file in todoFiles) { 870 for (String file in todoFiles) {
855 Source source = getSource(file); 871 ContextSourcePair contextSource = getContextSourcePair(file);
856 // prepare context 872 // prepare context
857 AnalysisContext context = getAnalysisContext(file); 873 AnalysisContext context = contextSource.context;
858 if (context == null) { 874 if (context == null) {
859 continue; 875 continue;
860 } 876 }
861 // Dart unit notifications. 877 // Dart unit notifications.
862 if (AnalysisEngine.isDartFileName(file)) { 878 if (AnalysisEngine.isDartFileName(file)) {
879 Source source = contextSource.source;
863 CompilationUnit dartUnit = 880 CompilationUnit dartUnit =
864 getResolvedCompilationUnitToResendNotification(file); 881 _getResolvedCompilationUnitToResendNotification(context, source);
865 if (dartUnit != null) { 882 if (dartUnit != null) {
866 switch (service) { 883 switch (service) {
867 case AnalysisService.HIGHLIGHTS: 884 case AnalysisService.HIGHLIGHTS:
868 sendAnalysisNotificationHighlights(this, file, dartUnit); 885 sendAnalysisNotificationHighlights(this, file, dartUnit);
869 break; 886 break;
870 case AnalysisService.NAVIGATION: 887 case AnalysisService.NAVIGATION:
871 // TODO(scheglov) consider support for one unit in 2+ libraries 888 // TODO(scheglov) consider support for one unit in 2+ libraries
872 sendAnalysisNotificationNavigation(this, file, dartUnit); 889 sendAnalysisNotificationNavigation(this, file, dartUnit);
873 break; 890 break;
874 case AnalysisService.OCCURRENCES: 891 case AnalysisService.OCCURRENCES:
875 sendAnalysisNotificationOccurrences(this, file, dartUnit); 892 sendAnalysisNotificationOccurrences(this, file, dartUnit);
876 break; 893 break;
877 case AnalysisService.OUTLINE: 894 case AnalysisService.OUTLINE:
895 AnalysisContext context = dartUnit.element.context;
878 LineInfo lineInfo = context.getLineInfo(source); 896 LineInfo lineInfo = context.getLineInfo(source);
879 sendAnalysisNotificationOutline(this, file, lineInfo, dartUnit); 897 sendAnalysisNotificationOutline(this, file, lineInfo, dartUnit);
880 break; 898 break;
881 case AnalysisService.OVERRIDES: 899 case AnalysisService.OVERRIDES:
882 sendAnalysisNotificationOverrides(this, file, dartUnit); 900 sendAnalysisNotificationOverrides(this, file, dartUnit);
883 break; 901 break;
884 } 902 }
885 } 903 }
886 } 904 }
887 } 905 }
888 }); 906 });
889 // remember new subscriptions 907 // remember new subscriptions
890 this.analysisServices = subscriptions; 908 this.analysisServices = subscriptions;
891 } 909 }
892 910
893 /** 911 /**
894 * Set the priority files to the given [files]. 912 * Set the priority files to the given [files].
895 */ 913 */
896 void setPriorityFiles(String requestId, List<String> files) { 914 void setPriorityFiles(String requestId, List<String> files) {
897 // Note: when a file is a priority file, that information needs to be 915 // Note: when a file is a priority file, that information needs to be
898 // propagated to all contexts that analyze the file, so that all contexts 916 // propagated to all contexts that analyze the file, so that all contexts
899 // will be able to do incremental resolution of the file. See 917 // will be able to do incremental resolution of the file. See
900 // dartbug.com/22209. 918 // dartbug.com/22209.
901 Map<AnalysisContext, List<Source>> sourceMap = 919 Map<AnalysisContext, List<Source>> sourceMap =
902 new HashMap<AnalysisContext, List<Source>>(); 920 new HashMap<AnalysisContext, List<Source>>();
903 List<String> unanalyzed = new List<String>(); 921 List<String> unanalyzed = new List<String>();
922 Source firstSource = null;
904 files.forEach((file) { 923 files.forEach((file) {
905 AnalysisContext preferredContext = getAnalysisContext(file); 924 ContextSourcePair contextSource = getContextSourcePair(file);
906 Source source = getSource(file); 925 AnalysisContext preferredContext = contextSource.context;
926 Source source = contextSource.source;
907 bool contextFound = false; 927 bool contextFound = false;
908 for (AnalysisContext context in folderMap.values) { 928 for (AnalysisContext context in folderMap.values) {
909 if (context == preferredContext || 929 if (context == preferredContext ||
910 context.getKindOf(source) != SourceKind.UNKNOWN) { 930 context.getKindOf(source) != SourceKind.UNKNOWN) {
911 sourceMap.putIfAbsent(context, () => <Source>[]).add(source); 931 sourceMap.putIfAbsent(context, () => <Source>[]).add(source);
912 contextFound = true; 932 contextFound = true;
913 } 933 }
914 } 934 }
935 if (firstSource == null) {
936 firstSource = source;
937 }
915 if (!contextFound) { 938 if (!contextFound) {
916 unanalyzed.add(file); 939 unanalyzed.add(file);
917 } 940 }
918 }); 941 });
919 if (unanalyzed.isNotEmpty) { 942 if (unanalyzed.isNotEmpty) {
920 StringBuffer buffer = new StringBuffer(); 943 StringBuffer buffer = new StringBuffer();
921 buffer.writeAll(unanalyzed, ', '); 944 buffer.writeAll(unanalyzed, ', ');
922 throw new RequestFailure( 945 throw new RequestFailure(
923 new Response.unanalyzedPriorityFiles(requestId, buffer.toString())); 946 new Response.unanalyzedPriorityFiles(requestId, buffer.toString()));
924 } 947 }
925 folderMap.forEach((Folder folder, AnalysisContext context) { 948 folderMap.forEach((Folder folder, AnalysisContext context) {
926 List<Source> sourceList = sourceMap[context]; 949 List<Source> sourceList = sourceMap[context];
927 if (sourceList == null) { 950 if (sourceList == null) {
928 sourceList = Source.EMPTY_ARRAY; 951 sourceList = Source.EMPTY_ARRAY;
929 } 952 }
930 context.analysisPriorityOrder = sourceList; 953 context.analysisPriorityOrder = sourceList;
931 // Schedule the context for analysis so that it has the opportunity to 954 // Schedule the context for analysis so that it has the opportunity to
932 // cache the AST's for the priority sources as soon as possible. 955 // cache the AST's for the priority sources as soon as possible.
933 schedulePerformAnalysisOperation(context); 956 schedulePerformAnalysisOperation(context);
934 }); 957 });
935 operationQueue.reschedule(); 958 operationQueue.reschedule();
936 Source firstSource = files.length > 0 ? getSource(files[0]) : null;
937 _onPriorityChangeController.add(new PriorityChangeEvent(firstSource)); 959 _onPriorityChangeController.add(new PriorityChangeEvent(firstSource));
938 } 960 }
939 961
940 /** 962 /**
941 * Returns `true` if errors should be reported for [file] with the given 963 * Returns `true` if errors should be reported for [file] with the given
942 * absolute path. 964 * absolute path.
943 */ 965 */
944 bool shouldSendErrorsNotificationFor(String file) { 966 bool shouldSendErrorsNotificationFor(String file) {
945 return !_noErrorNotification && 967 return !_noErrorNotification &&
946 contextDirectoryManager.isInAnalysisRoot(file); 968 contextDirectoryManager.isInAnalysisRoot(file);
947 } 969 }
948 970
949 void shutdown() { 971 void shutdown() {
950 running = false; 972 running = false;
951 if (index != null) { 973 if (index != null) {
952 index.clear(); 974 index.clear();
953 index.stop(); 975 index.stop();
954 } 976 }
955 // Defer closing the channel and shutting down the instrumentation server so 977 // Defer closing the channel and shutting down the instrumentation server so
956 // that the shutdown response can be sent and logged. 978 // that the shutdown response can be sent and logged.
957 new Future(() { 979 new Future(() {
958 instrumentationService.shutdown(); 980 instrumentationService.shutdown();
959 channel.close(); 981 channel.close();
960 }); 982 });
961 } 983 }
962 984
963 void test_flushResolvedUnit(String file) { 985 void test_flushResolvedUnit(String file) {
964 if (AnalysisEngine.isDartFileName(file)) { 986 if (AnalysisEngine.isDartFileName(file)) {
965 AnalysisContextImpl context = getAnalysisContext(file); 987 ContextSourcePair contextSource = getContextSourcePair(file);
966 Source source = getSource(file); 988 AnalysisContextImpl context = contextSource.context;
989 Source source = contextSource.source;
967 DartEntry dartEntry = context.getReadableSourceEntryOrNull(source); 990 DartEntry dartEntry = context.getReadableSourceEntryOrNull(source);
968 dartEntry.flushAstStructures(); 991 dartEntry.flushAstStructures();
969 } 992 }
970 } 993 }
971 994
972 /** 995 /**
973 * Performs all scheduled analysis operations. 996 * Performs all scheduled analysis operations.
974 */ 997 */
975 void test_performAllAnalysisOperations() { 998 void test_performAllAnalysisOperations() {
976 while (true) { 999 while (true) {
977 ServerOperation operation = operationQueue.takeIf((operation) { 1000 ServerOperation operation = operationQueue.takeIf((operation) {
978 return operation is PerformAnalysisOperation; 1001 return operation is PerformAnalysisOperation;
979 }); 1002 });
980 if (operation == null) { 1003 if (operation == null) {
981 break; 1004 break;
982 } 1005 }
983 operation.perform(this); 1006 operation.perform(this);
984 } 1007 }
985 } 1008 }
986 1009
987 /** 1010 /**
988 * Implementation for `analysis.updateContent`. 1011 * Implementation for `analysis.updateContent`.
989 */ 1012 */
990 void updateContent(String id, Map<String, dynamic> changes) { 1013 void updateContent(String id, Map<String, dynamic> changes) {
991 changes.forEach((file, change) { 1014 changes.forEach((file, change) {
992 Source source = getSource(file); 1015 ContextSourcePair contextSource = getContextSourcePair(file);
1016 Source source = contextSource.source;
993 operationQueue.sourceAboutToChange(source); 1017 operationQueue.sourceAboutToChange(source);
994 // Prepare the new contents. 1018 // Prepare the new contents.
995 String oldContents = overlayState.getContents(source); 1019 String oldContents = overlayState.getContents(source);
996 String newContents; 1020 String newContents;
997 if (change is AddContentOverlay) { 1021 if (change is AddContentOverlay) {
998 newContents = change.content; 1022 newContents = change.content;
999 } else if (change is ChangeContentOverlay) { 1023 } else if (change is ChangeContentOverlay) {
1000 if (oldContents == null) { 1024 if (oldContents == null) {
1001 // The client may only send a ChangeContentOverlay if there is 1025 // The client may only send a ChangeContentOverlay if there is
1002 // already an existing overlay for the source. 1026 // already an existing overlay for the source.
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1066 // 1090 //
1067 // Update the defaults used to create new contexts. 1091 // Update the defaults used to create new contexts.
1068 // 1092 //
1069 AnalysisOptionsImpl options = contextDirectoryManager.defaultOptions; 1093 AnalysisOptionsImpl options = contextDirectoryManager.defaultOptions;
1070 optionUpdaters.forEach((OptionUpdater optionUpdater) { 1094 optionUpdaters.forEach((OptionUpdater optionUpdater) {
1071 optionUpdater(options); 1095 optionUpdater(options);
1072 }); 1096 });
1073 } 1097 }
1074 1098
1075 /** 1099 /**
1076 * Return the [Source] of the Dart file with the given [path], assuming that 1100 * Returns the [CompilationUnit] of the Dart file with the given [source] that
1077 * we do not know the context in which the path should be interpreted. 1101 * should be used to resend notifications for already resolved unit.
1102 * Returns `null` if the file is not a part of any context, library has not
1103 * been yet resolved, or any problem happened.
1078 */ 1104 */
1079 Source _getSourceWithoutContext(String path) { 1105 CompilationUnit _getResolvedCompilationUnitToResendNotification(
1080 // try SDK 1106 AnalysisContext context, Source source) {
1081 { 1107 List<Source> librarySources = context.getLibrariesContaining(source);
1082 Uri uri = resourceProvider.pathContext.toUri(path); 1108 if (librarySources.isEmpty) {
1083 Source sdkSource = defaultSdk.fromFileUri(uri); 1109 return null;
1084 if (sdkSource != null) {
1085 return sdkSource;
1086 }
1087 } 1110 }
1088 // file-based source 1111 // if library has not been resolved yet, the unit will be resolved later
1089 File file = resourceProvider.getResource(path); 1112 Source librarySource = librarySources[0];
1090 return file.createSource(); 1113 if (context.getLibraryElement(librarySource) == null) {
1114 return null;
1115 }
1116 // if library has been already resolved, resolve unit
1117 return context.resolveCompilationUnit2(source, librarySource);
1091 } 1118 }
1092 1119
1093 /** 1120 /**
1094 * Schedules [performOperation] exection. 1121 * Schedules [performOperation] exection.
1095 */ 1122 */
1096 void _schedulePerformOperation() { 1123 void _schedulePerformOperation() {
1097 if (performOperationPending) { 1124 if (performOperationPending) {
1098 return; 1125 return;
1099 } 1126 }
1100 /* 1127 /*
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1148 /** 1175 /**
1149 * The contexts that were removed from the server. 1176 * The contexts that were removed from the server.
1150 */ 1177 */
1151 final List<AnalysisContext> removed; 1178 final List<AnalysisContext> removed;
1152 1179
1153 ContextsChangedEvent({this.added: AnalysisContext.EMPTY_LIST, 1180 ContextsChangedEvent({this.added: AnalysisContext.EMPTY_LIST,
1154 this.changed: AnalysisContext.EMPTY_LIST, 1181 this.changed: AnalysisContext.EMPTY_LIST,
1155 this.removed: AnalysisContext.EMPTY_LIST}); 1182 this.removed: AnalysisContext.EMPTY_LIST});
1156 } 1183 }
1157 1184
1185 class ContextSourcePair {
Brian Wilkerson 2015/03/06 15:04:27 Comments?
scheglov 2015/03/06 21:47:03 Done.
1186 final AnalysisContext context;
1187 final Source source;
1188 ContextSourcePair(this.context, this.source);
1189 }
1190
1158 /** 1191 /**
1159 * A [PriorityChangeEvent] indicates the set the priority files has changed. 1192 * A [PriorityChangeEvent] indicates the set the priority files has changed.
1160 */ 1193 */
1161 class PriorityChangeEvent { 1194 class PriorityChangeEvent {
1162 final Source firstSource; 1195 final Source firstSource;
1163 1196
1164 PriorityChangeEvent(this.firstSource); 1197 PriorityChangeEvent(this.firstSource);
1165 } 1198 }
1166 1199
1167 class ServerContextManager extends ContextManager { 1200 class ServerContextManager extends ContextManager {
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
1364 /** 1397 /**
1365 * The [PerformanceTag] for time spent in server request handlers. 1398 * The [PerformanceTag] for time spent in server request handlers.
1366 */ 1399 */
1367 static PerformanceTag serverRequests = new PerformanceTag('serverRequests'); 1400 static PerformanceTag serverRequests = new PerformanceTag('serverRequests');
1368 1401
1369 /** 1402 /**
1370 * The [PerformanceTag] for time spent in split store microtasks. 1403 * The [PerformanceTag] for time spent in split store microtasks.
1371 */ 1404 */
1372 static PerformanceTag splitStore = new PerformanceTag('splitStore'); 1405 static PerformanceTag splitStore = new PerformanceTag('splitStore');
1373 } 1406 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analysis_server/lib/src/context_manager.dart » ('j') | pkg/analysis_server/lib/src/context_manager.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698