OLD | NEW |
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:core' hide Resource; | 9 import 'dart:core' hide Resource; |
10 import 'dart:math' show max; | 10 import 'dart:math' show max; |
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 } | 443 } |
444 | 444 |
445 /** | 445 /** |
446 * Return the [AnalysisContext]s that are being used to analyze the analysis | 446 * Return the [AnalysisContext]s that are being used to analyze the analysis |
447 * roots. | 447 * roots. |
448 */ | 448 */ |
449 Iterable<AnalysisContext> getAnalysisContexts() { | 449 Iterable<AnalysisContext> getAnalysisContexts() { |
450 return folderMap.values; | 450 return folderMap.values; |
451 } | 451 } |
452 | 452 |
| 453 CompilationUnitElement getCompilationUnitElement(String file) { |
| 454 ContextSourcePair pair = getContextSourcePair(file); |
| 455 if (pair == null) { |
| 456 return null; |
| 457 } |
| 458 // prepare AnalysisContext and Source |
| 459 AnalysisContext context = pair.context; |
| 460 Source unitSource = pair.source; |
| 461 if (context == null || unitSource == null) { |
| 462 return null; |
| 463 } |
| 464 // get element in the first library |
| 465 List<Source> librarySources = context.getLibrariesContaining(unitSource); |
| 466 if (!librarySources.isNotEmpty) { |
| 467 return null; |
| 468 } |
| 469 Source librarySource = librarySources.first; |
| 470 return context.getCompilationUnitElement(unitSource, librarySource); |
| 471 } |
| 472 |
453 /** | 473 /** |
454 * Return the [AnalysisContext] that contains the given [path]. | 474 * Return the [AnalysisContext] that contains the given [path]. |
455 * Return `null` if no context contains the [path]. | 475 * Return `null` if no context contains the [path]. |
456 */ | 476 */ |
457 AnalysisContext getContainingContext(String path) { | 477 AnalysisContext getContainingContext(String path) { |
458 Folder containingFolder = null; | 478 Folder containingFolder = null; |
459 AnalysisContext containingContext = null; | 479 AnalysisContext containingContext = null; |
460 folderMap.forEach((Folder folder, AnalysisContext context) { | 480 folderMap.forEach((Folder folder, AnalysisContext context) { |
461 if (folder.isOrContains(path)) { | 481 if (folder.isOrContains(path)) { |
462 if (containingFolder == null || | 482 if (containingFolder == null || |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 if (node is SimpleIdentifier && element is PrefixElement) { | 577 if (node is SimpleIdentifier && element is PrefixElement) { |
558 element = getImportElement(node); | 578 element = getImportElement(node); |
559 } | 579 } |
560 if (element != null) { | 580 if (element != null) { |
561 elements.add(element); | 581 elements.add(element); |
562 } | 582 } |
563 } | 583 } |
564 return elements; | 584 return elements; |
565 } | 585 } |
566 | 586 |
| 587 // TODO(brianwilkerson) Add the following method after 'prioritySources' has |
| 588 // been added to InternalAnalysisContext. |
| 589 // /** |
| 590 // * Return a list containing the full names of all of the sources that are |
| 591 // * priority sources. |
| 592 // */ |
| 593 // List<String> getPriorityFiles() { |
| 594 // List<String> priorityFiles = new List<String>(); |
| 595 // folderMap.values.forEach((ContextDirectory directory) { |
| 596 // InternalAnalysisContext context = directory.context; |
| 597 // context.prioritySources.forEach((Source source) { |
| 598 // priorityFiles.add(source.fullName); |
| 599 // }); |
| 600 // }); |
| 601 // return priorityFiles; |
| 602 // } |
| 603 |
567 /** | 604 /** |
568 * Return an analysis error info containing the array of all of the errors and | 605 * Return an analysis error info containing the array of all of the errors and |
569 * the line info associated with [file]. | 606 * the line info associated with [file]. |
570 * | 607 * |
571 * Returns `null` if [file] does not belong to any [AnalysisContext], or the | 608 * Returns `null` if [file] does not belong to any [AnalysisContext], or the |
572 * file does not exist. | 609 * file does not exist. |
573 * | 610 * |
574 * The array of errors will be empty if there are no errors in [file]. The | 611 * The array of errors will be empty if there are no errors in [file]. The |
575 * errors contained in the array can be incomplete. | 612 * errors contained in the array can be incomplete. |
576 * | 613 * |
577 * This method does not wait for all errors to be computed, and returns just | 614 * This method does not wait for all errors to be computed, and returns just |
578 * the current state. | 615 * the current state. |
579 */ | 616 */ |
580 AnalysisErrorInfo getErrors(String file) { | 617 AnalysisErrorInfo getErrors(String file) { |
581 ContextSourcePair contextSource = getContextSourcePair(file); | 618 ContextSourcePair contextSource = getContextSourcePair(file); |
582 AnalysisContext context = contextSource.context; | 619 AnalysisContext context = contextSource.context; |
583 Source source = contextSource.source; | 620 Source source = contextSource.source; |
584 if (context == null) { | 621 if (context == null) { |
585 return null; | 622 return null; |
586 } | 623 } |
587 if (!context.exists(source)) { | 624 if (!context.exists(source)) { |
588 return null; | 625 return null; |
589 } | 626 } |
590 return context.getErrors(source); | 627 return context.getErrors(source); |
591 } | 628 } |
592 | 629 |
593 // TODO(brianwilkerson) Add the following method after 'prioritySources' has | |
594 // been added to InternalAnalysisContext. | |
595 // /** | |
596 // * Return a list containing the full names of all of the sources that are | |
597 // * priority sources. | |
598 // */ | |
599 // List<String> getPriorityFiles() { | |
600 // List<String> priorityFiles = new List<String>(); | |
601 // folderMap.values.forEach((ContextDirectory directory) { | |
602 // InternalAnalysisContext context = directory.context; | |
603 // context.prioritySources.forEach((Source source) { | |
604 // priorityFiles.add(source.fullName); | |
605 // }); | |
606 // }); | |
607 // return priorityFiles; | |
608 // } | |
609 | |
610 /** | 630 /** |
611 * Returns resolved [AstNode]s at the given [offset] of the given [file]. | 631 * Returns resolved [AstNode]s at the given [offset] of the given [file]. |
612 * | 632 * |
613 * May be empty, but not `null`. | 633 * May be empty, but not `null`. |
614 */ | 634 */ |
615 List<AstNode> getNodesAtOffset(String file, int offset) { | 635 List<AstNode> getNodesAtOffset(String file, int offset) { |
616 List<CompilationUnit> units = getResolvedCompilationUnits(file); | 636 List<CompilationUnit> units = getResolvedCompilationUnits(file); |
617 List<AstNode> nodes = <AstNode>[]; | 637 List<AstNode> nodes = <AstNode>[]; |
618 for (CompilationUnit unit in units) { | 638 for (CompilationUnit unit in units) { |
619 AstNode node = new NodeLocator(offset).searchWithin(unit); | 639 AstNode node = new NodeLocator(offset).searchWithin(unit); |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 } | 803 } |
784 if (!operationQueue.isEmpty) { | 804 if (!operationQueue.isEmpty) { |
785 ServerPerformanceStatistics.intertask.makeCurrent(); | 805 ServerPerformanceStatistics.intertask.makeCurrent(); |
786 _schedulePerformOperation(); | 806 _schedulePerformOperation(); |
787 } else { | 807 } else { |
788 if (generalAnalysisServices | 808 if (generalAnalysisServices |
789 .contains(GeneralAnalysisService.ANALYZED_FILES)) { | 809 .contains(GeneralAnalysisService.ANALYZED_FILES)) { |
790 sendAnalysisNotificationAnalyzedFiles(this); | 810 sendAnalysisNotificationAnalyzedFiles(this); |
791 } | 811 } |
792 sendStatusNotification(null); | 812 sendStatusNotification(null); |
| 813 _scheduleAnalysisImplementedNotification(); |
793 if (_onAnalysisCompleteCompleter != null) { | 814 if (_onAnalysisCompleteCompleter != null) { |
794 _onAnalysisCompleteCompleter.complete(); | 815 _onAnalysisCompleteCompleter.complete(); |
795 _onAnalysisCompleteCompleter = null; | 816 _onAnalysisCompleteCompleter = null; |
796 } | 817 } |
797 ServerPerformanceStatistics.idle.makeCurrent(); | 818 ServerPerformanceStatistics.idle.makeCurrent(); |
798 } | 819 } |
799 } | 820 } |
800 } | 821 } |
801 | 822 |
802 /** | 823 /** |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
986 case AnalysisService.OVERRIDES: | 1007 case AnalysisService.OVERRIDES: |
987 sendAnalysisNotificationOverrides(this, file, dartUnit); | 1008 sendAnalysisNotificationOverrides(this, file, dartUnit); |
988 break; | 1009 break; |
989 } | 1010 } |
990 } | 1011 } |
991 } | 1012 } |
992 } | 1013 } |
993 }); | 1014 }); |
994 // remember new subscriptions | 1015 // remember new subscriptions |
995 this.analysisServices = subscriptions; | 1016 this.analysisServices = subscriptions; |
| 1017 // special case for implemented elements |
| 1018 if (analysisServices.containsKey(AnalysisService.IMPLEMENTED) && |
| 1019 isAnalysisComplete()) { |
| 1020 _scheduleAnalysisImplementedNotification(); |
| 1021 } |
996 } | 1022 } |
997 | 1023 |
998 /** | 1024 /** |
999 * Implementation for `analysis.setGeneralSubscriptions`. | 1025 * Implementation for `analysis.setGeneralSubscriptions`. |
1000 */ | 1026 */ |
1001 void setGeneralAnalysisSubscriptions( | 1027 void setGeneralAnalysisSubscriptions( |
1002 List<GeneralAnalysisService> subscriptions) { | 1028 List<GeneralAnalysisService> subscriptions) { |
1003 Set<GeneralAnalysisService> newServices = subscriptions.toSet(); | 1029 Set<GeneralAnalysisService> newServices = subscriptions.toSet(); |
1004 if (newServices.contains(GeneralAnalysisService.ANALYZED_FILES) && | 1030 if (newServices.contains(GeneralAnalysisService.ANALYZED_FILES) && |
1005 !generalAnalysisServices | 1031 !generalAnalysisServices |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1275 Source librarySource = librarySources[0]; | 1301 Source librarySource = librarySources[0]; |
1276 if (context.getLibraryElement(librarySource) == null) { | 1302 if (context.getLibraryElement(librarySource) == null) { |
1277 return null; | 1303 return null; |
1278 } | 1304 } |
1279 // if library has been already resolved, resolve unit | 1305 // if library has been already resolved, resolve unit |
1280 return runWithWorkingCacheSize(context, () { | 1306 return runWithWorkingCacheSize(context, () { |
1281 return context.resolveCompilationUnit2(source, librarySource); | 1307 return context.resolveCompilationUnit2(source, librarySource); |
1282 }); | 1308 }); |
1283 } | 1309 } |
1284 | 1310 |
| 1311 _scheduleAnalysisImplementedNotification() async { |
| 1312 Set<String> files = analysisServices[AnalysisService.IMPLEMENTED]; |
| 1313 if (files != null) { |
| 1314 scheduleImplementedNotification(this, files); |
| 1315 } |
| 1316 } |
| 1317 |
1285 /** | 1318 /** |
1286 * Schedules [performOperation] exection. | 1319 * Schedules [performOperation] exection. |
1287 */ | 1320 */ |
1288 void _schedulePerformOperation() { | 1321 void _schedulePerformOperation() { |
1289 if (performOperationPending) { | 1322 if (performOperationPending) { |
1290 return; | 1323 return; |
1291 } | 1324 } |
1292 /* | 1325 /* |
1293 * TODO (danrubel) Rip out this workaround once the underlying problem | 1326 * TODO (danrubel) Rip out this workaround once the underlying problem |
1294 * is fixed. Currently, the VM and dart:io do not deliver content | 1327 * is fixed. Currently, the VM and dart:io do not deliver content |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1560 /** | 1593 /** |
1561 * The [PerformanceTag] for time spent in server request handlers. | 1594 * The [PerformanceTag] for time spent in server request handlers. |
1562 */ | 1595 */ |
1563 static PerformanceTag serverRequests = new PerformanceTag('serverRequests'); | 1596 static PerformanceTag serverRequests = new PerformanceTag('serverRequests'); |
1564 | 1597 |
1565 /** | 1598 /** |
1566 * The [PerformanceTag] for time spent in split store microtasks. | 1599 * The [PerformanceTag] for time spent in split store microtasks. |
1567 */ | 1600 */ |
1568 static PerformanceTag splitStore = new PerformanceTag('splitStore'); | 1601 static PerformanceTag splitStore = new PerformanceTag('splitStore'); |
1569 } | 1602 } |
OLD | NEW |