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

Unified Diff: pkg/analysis_server/lib/src/analysis_server.dart

Issue 300023004: Partial implementation of the 'setAnalysisRoots' API. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fixes for review comments. Created 6 years, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/analysis_server/lib/src/domain_analysis.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analysis_server/lib/src/analysis_server.dart
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 7ebd6c680fc2cfde806d6178e3a0591fd9f4b63d..9ede7e812a2ebf9c02709d1e9bbdb4ecf77af295 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -9,9 +9,14 @@ import 'dart:async';
import 'package:analysis_server/src/analysis_logger.dart';
import 'package:analysis_server/src/channel.dart';
import 'package:analysis_server/src/protocol.dart';
+import 'package:analysis_server/src/resource.dart';
+import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/java_core.dart';
+import 'package:analyzer/src/generated/sdk.dart';
+import 'package:analyzer/src/generated/sdk_io.dart';
+import 'package:analyzer/src/generated/source_io.dart';
/**
* Instances of the class [AnalysisServer] implement a server that listens on a
@@ -50,6 +55,11 @@ class AnalysisServer {
final ServerCommunicationChannel channel;
/**
+ * The [ResourceProvider] using which paths are converted into [Resource]s.
+ */
+ final ResourceProvider resourceProvider;
+
+ /**
* A flag indicating whether the server is running. When false, contexts
* will no longer be added to [contextWorkQueue], and [performTask] will
* discard any tasks it finds on [contextWorkQueue].
@@ -62,15 +72,26 @@ class AnalysisServer {
*/
List<RequestHandler> handlers;
+ // TODO(scheglov) remove once setAnalysisRoots() is completely implemented
+// /**
+// * A table mapping context id's to the analysis contexts associated with them.
+// */
+// final Map<String, AnalysisContext> contextMap = new Map<String, AnalysisContext>();
+//
+// /**
+// * A table mapping analysis contexts to the context id's associated with them.
+// */
+// final Map<AnalysisContext, String> contextIdMap = new Map<AnalysisContext, String>();
+
/**
- * A table mapping context id's to the analysis contexts associated with them.
+ * The current default [DartSdk].
*/
- final Map<String, AnalysisContext> contextMap = new Map<String, AnalysisContext>();
+ DartSdk defaultSdk = DirectoryBasedDartSdk.defaultSdk;
/**
- * A table mapping analysis contexts to the context id's associated with them.
+ * A table mapping [Folder]s to the [PubFolder]s associated with them.
*/
- final Map<AnalysisContext, String> contextIdMap = new Map<AnalysisContext, String>();
+ final Map<Folder, PubFolder> folderMap = <Folder, PubFolder>{};
/**
* A list of the analysis contexts for which analysis work needs to be
@@ -91,7 +112,7 @@ class AnalysisServer {
* Initialize a newly created server to receive requests from and send
* responses to the given [channel].
*/
- AnalysisServer(this.channel) {
+ AnalysisServer(this.channel, this.resourceProvider) {
AnalysisEngine.instance.logger = new AnalysisLogger();
running = true;
Notification notification = new Notification(CONNECTED_NOTIFICATION);
@@ -172,10 +193,10 @@ class AnalysisServer {
// Look for a context that has work to be done and then perform one task.
//
List<ChangeNotice> notices = null;
- String contextId;
+// String contextId;
try {
AnalysisContext context = contextWorkQueue[0];
- contextId = contextIdMap[context];
+// contextId = contextIdMap[context];
AnalysisResult result = context.performAnalysisTask();
notices = result.changeNotices;
} finally {
@@ -194,24 +215,116 @@ class AnalysisServer {
_scheduleTask();
}
}
- if (notices != null) {
- sendNotices(contextId, notices);
+ // TODO(scheglov) implement for [PubFolder]
+// if (notices != null) {
+// sendNotices(contextId, notices);
+// }
+ }
+
+ // TODO(scheglov) rewrite for the new API.
+// /**
+// * Send the information in the given list of notices back to the client.
+// */
+// void sendNotices(String contextId, List<ChangeNotice> notices) {
+// for (int i = 0; i < notices.length; i++) {
+// ChangeNotice notice = notices[i];
+// Notification notification = new Notification(ERROR_NOTIFICATION_NAME);
+// notification.setParameter(CONTEXT_ID_PARAM, contextId);
+// notification.setParameter(SOURCE_PARAM, notice.source.encoding);
+// notification.setParameter(ERRORS_PARAM, notice.errors.map(
+// errorToJson).toList());
+// sendNotification(notification);
+// }
+// }
+
+ /**
+ * Implementation for `server.setAnalysisRoots`.
+ *
+ * TODO(scheglov) implement complete projects/contexts semantics.
+ *
+ * The current implementation is intentionally simplified and expected
+ * that only folders are given each given folder corresponds to the exactly
+ * one context.
+ *
+ * So, we can start working in parallel on adding services and improving
+ * projects/contexts support.
+ */
+ void setAnalysisRoots(String requestId,
+ List<String> includedPaths,
+ List<String> excludedPaths) {
+ // included
+ Set<Folder> includedFolders = new Set<Folder>();
+ for (int i = 0; i < includedPaths.length; i++) {
+ String path = includedPaths[i];
+ Resource resource = resourceProvider.getResource(path);
+ if (resource is Folder) {
+ includedFolders.add(resource);
+ } else {
+ // TODO(scheglov) implemented separate files analysis
+ throw new RequestFailure(
+ new Response.unsupportedFeature(
+ requestId,
+ '$path is not a folder. '
+ 'Only support for folder analysis is implemented currently.'));
+ }
}
+ // excluded
+ // TODO(scheglov) remove when implemented
+ if (excludedPaths.isNotEmpty) {
+ throw new RequestFailure(
+ new Response.unsupportedFeature(
+ requestId,
+ 'Excluded paths are not supported yet'));
+ }
+ Set<Folder> excludedFolders = new Set<Folder>();
+ // diff
+ Set<Folder> currentFolders = new Set<Folder>.from(folderMap.keys);
+ Set<Folder> newFolders = includedFolders.difference(currentFolders);
+ Set<Folder> oldFolders = currentFolders.difference(includedFolders);
+ // remove old contexts
+ for (Folder folder in oldFolders) {
+ // TODO(scheglov) implement
+ }
+ // add new contexts
+ for (Folder folder in newFolders) {
+ PubFolder pubFolder = new PubFolder(defaultSdk, folder);
+ folderMap[folder] = pubFolder;
+ addContextToWorkQueue(pubFolder.context);
+ }
+ }
+
+ /**
+ * Return the [AnalysisContext] that is used to analyze the given [path].
+ * Return `null` if there is no such context.
+ */
+ AnalysisContext test_getAnalysisContext(String path) {
+ for (Folder folder in folderMap.keys) {
+ if (path.startsWith(folder.fullName)) {
+ return folderMap[folder].context;
+ }
+ }
+ return null;
}
/**
- * Send the information in the given list of notices back to the client.
+ * Return the [CompilationUnit] of the Dart file with the given [path].
+ * Return `null` if the file is not a part of any context.
*/
- void sendNotices(String contextId, List<ChangeNotice> notices) {
- for (int i = 0; i < notices.length; i++) {
- ChangeNotice notice = notices[i];
- Notification notification = new Notification(ERROR_NOTIFICATION_NAME);
- notification.setParameter(CONTEXT_ID_PARAM, contextId);
- notification.setParameter(SOURCE_PARAM, notice.source.encoding);
- notification.setParameter(ERRORS_PARAM, notice.errors.map(
- errorToJson).toList());
- sendNotification(notification);
+ CompilationUnit test_getResolvedCompilationUnit(String path) {
+ // prepare AnalysisContext
+ AnalysisContext context = test_getAnalysisContext(path);
+ if (context == null) {
+ return null;
}
+ // prepare sources
+ File file = resourceProvider.getResource(path);
+ Source unitSource = file.createSource(UriKind.FILE_URI);
+ List<Source> librarySources = context.getLibrariesContaining(unitSource);
+ if (librarySources.isEmpty) {
+ return null;
+ }
+ // get a resolved unit
+ return context.getResolvedCompilationUnit2(unitSource, librarySources[0]);
}
static Map<String, Object> errorToJson(AnalysisError analysisError) {
@@ -265,6 +378,79 @@ class AnalysisService extends Enum2<AnalysisService> {
/**
+ * Instances of [PubFolder] represents a [Folder] with a Pub `pubspec.yaml`.
+ *
+ * TODO(scheglov) implement complete projects/contexts semantics.
+ *
+ * This class is intentionally simplified to serve as a base to start working
+ * on services while work on complete semantics is being done in parallel.
+ */
+class PubFolder {
+ /**
+ * The root [Folder] of this [PubFolder].
+ */
+ final Folder _folder;
+
+ /**
+ * The `pubspec.yaml` file in [_folder].
+ */
+ File _pubspecFile;
+
+ /**
+ * The [AnalysisContext] of this [_folder].
+ */
+ AnalysisContext _context;
+
+ PubFolder(DartSdk sdk, this._folder) {
+ // prepare pubspec.yaml
+ _pubspecFile = _folder.getChild('pubspec.yaml');
+ if (!_pubspecFile.exists) {
+ throw new ArgumentError('$_pubspecFile does not exist');
+ }
+ // create AnalysisContext
+ _context = AnalysisEngine.instance.createAnalysisContext();
+ // TODO(scheglov) replace FileUriResolver with an Resource based resolver
+ // TODO(scheglov) create packages resolver
+ _context.sourceFactory = new SourceFactory([
+ new DartUriResolver(sdk),
+ new FileUriResolver(),
+ // new PackageUriResolver(),
+ ]);
+ // add folder files
+ {
+ ChangeSet changeSet = new ChangeSet();
+ _addSourceFiles(changeSet, _folder);
+ _context.applyChanges(changeSet);
+ }
+ }
+
+ /**
+ * Return the [AnalysisContext] of this folder.
+ */
+ AnalysisContext get context => _context;
+
+ /**
+ * Resursively adds all Dart and HTML files to the [changeSet].
+ */
+ static void _addSourceFiles(ChangeSet changeSet, Folder folder) {
+ List<Resource> children = folder.getChildren();
+ for (Resource child in children) {
+ if (child is File) {
+ String fileName = child.shortName;
+ if (AnalysisEngine.isDartFileName(fileName)
+ || AnalysisEngine.isHtmlFileName(fileName)) {
+ Source source = child.createSource(UriKind.FILE_URI);
+ changeSet.addedSource(source);
+ }
+ } else if (child is Folder) {
+ _addSourceFiles(changeSet, child);
+ }
+ }
+ }
+}
+
+
+/**
* An enumeration of the services provided by the server domain.
*/
class ServerService extends Enum2<ServerService> {
« no previous file with comments | « no previous file | pkg/analysis_server/lib/src/domain_analysis.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698