Skip to content

Commit

Permalink
Rework analyzed files support to use globs
Browse files Browse the repository at this point in the history
R=scheglov@google.com

Review URL: https://codereview.chromium.org/1413643006 .
  • Loading branch information
bwilkerson committed Nov 3, 2015
1 parent c34b23c commit 879cf82
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 48 deletions.
36 changes: 15 additions & 21 deletions pkg/analysis_server/lib/plugin/analysis/analyzed_files.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,35 @@
* Support for client code that extends the set of files being analyzed by the
* analysis server.
*
* Plugins can register a function that takes a [File] and returns a [bool]
* indicating whether the plugin is interested in having that file be analyzed.
* The analysis server will invoke the contributed functions and analyze the
* file if at least one of the functions returns `true`. (The server is not
* required to invoke every function with every file.)
* Plugins can contribute a list of file patterns. Any file whose path matches
* one or more of the contributed patterns will be analyzed. The file patterns
* are interpreted as glob patterns as defined by the 'glob' package.
*
* If a plugin is interested in analyzing a certain kind of files, it needs to
* ensure that files of that kind will be analyzed. It should register a
* function by including code like the following in the plugin's
* If a plugin is interested in analyzing a certain kind of file, it needs to
* ensure that files of that kind will be analyzed. It should register a list of
* file patterns by including code like the following in the plugin's
* registerExtensions method:
*
* @override
* void registerExtensions(RegisterExtension registerExtension) {
* ...
* registerExtension(
* ANALYZE_FILE_EXTENSION_POINT_ID,
* (File file) => file.path.endsWith(...));
* ANALYZED_FILE_PATTERNS_EXTENSION_POINT_ID,
* ['*.yaml']);
* ...
* }
*/
library analysis_server.plugin.analysis.analyzed_files;

import 'package:analysis_server/src/plugin/server_plugin.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:plugin/plugin.dart';

/**
* The identifier of the extension point that allows plugins to register
* functions that can cause files to be analyzed. The object used as an
* extension must be a [ShouldAnalyzeFile] function.
* The identifier of the extension point that allows plugins to cause certain
* kinds of files to be analyzed. The object used as an extension must be a list
* of strings. The strings are interpreted as glob patterns as defined by the
* 'glob' package.
*/
final String ANALYZE_FILE_EXTENSION_POINT_ID = Plugin.join(
ServerPlugin.UNIQUE_IDENTIFIER, ServerPlugin.ANALYZE_FILE_EXTENSION_POINT);

/**
* A function that returns `true` if the given [file] should be analyzed.
*/
typedef bool ShouldAnalyzeFile(File file);
final String ANALYZED_FILE_PATTERNS_EXTENSION_POINT_ID = Plugin.join(
ServerPlugin.UNIQUE_IDENTIFIER,
ServerPlugin.ANALYZED_FILE_PATTERNS_EXTENSION_POINT);
35 changes: 31 additions & 4 deletions pkg/analysis_server/lib/src/analysis_server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/java_io.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:glob/glob.dart';
import 'package:plugin/plugin.dart';

typedef void OptionUpdater(AnalysisOptionsImpl options);
Expand Down Expand Up @@ -1404,8 +1406,35 @@ class ServerContextManagerCallbacks extends ContextManagerCallbacks {
*/
final ResourceProvider resourceProvider;

/**
* A list of the globs used to determine which files should be analyzed. The
* list is lazily created and should be accessed using [analyzedFilesGlobs].
*/
List<Glob> _analyzedFilesGlobs = null;

ServerContextManagerCallbacks(this.analysisServer, this.resourceProvider);

/**
* Return a list of the globs used to determine which files should be analyzed.
*/
List<Glob> get analyzedFilesGlobs {
if (_analyzedFilesGlobs == null) {
_analyzedFilesGlobs = <Glob>[];
List<String> patterns = analysisServer.serverPlugin.analyzedFilePatterns;
for (String pattern in patterns) {
try {
_analyzedFilesGlobs
.add(new Glob(pattern, context: JavaFile.pathContext));
} catch (exception, stackTrace) {
AnalysisEngine.instance.logger.logError(
'Invalid glob pattern: "$pattern"',
new CaughtException(exception, stackTrace));
}
}
}
return _analyzedFilesGlobs;
}

@override
AnalysisContext addContext(Folder folder, FolderDisposition disposition) {
InternalAnalysisContext context =
Expand Down Expand Up @@ -1463,10 +1492,8 @@ class ServerContextManagerCallbacks extends ContextManagerCallbacks {

@override
bool shouldFileBeAnalyzed(File file) {
List<ShouldAnalyzeFile> functions =
analysisServer.serverPlugin.analyzeFileFunctions;
for (ShouldAnalyzeFile shouldAnalyzeFile in functions) {
if (shouldAnalyzeFile(file)) {
for (Glob glob in analyzedFilesGlobs) {
if (glob.matches(file.path)) {
// Emacs creates dummy links to track the fact that a file is open for
// editing and has unsaved changes (e.g. having unsaved changes to
// 'foo.dart' causes a link '.#foo.dart' to be created, which points to
Expand Down
66 changes: 43 additions & 23 deletions pkg/analysis_server/lib/src/plugin/server_plugin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import 'package:analysis_server/src/search/search_domain.dart';
import 'package:analysis_server/src/services/correction/assist_internal.dart';
import 'package:analysis_server/src/services/correction/fix_internal.dart';
import 'package:analysis_server/src/services/index/index_contributor.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:plugin/plugin.dart';

Expand All @@ -48,9 +47,10 @@ typedef RequestHandler RequestHandlerFactory(AnalysisServer server);
class ServerPlugin implements Plugin {
/**
* The simple identifier of the extension point that allows plugins to
* register functions that can cause files to be analyzed.
* register file patterns that will cause files to be analyzed.
*/
static const String ANALYZE_FILE_EXTENSION_POINT = 'analyzeFile';
static const String ANALYZED_FILE_PATTERNS_EXTENSION_POINT =
'analyzedFilePatterns';

/**
* The simple identifier of the extension point that allows plugins to
Expand Down Expand Up @@ -109,10 +109,10 @@ class ServerPlugin implements Plugin {
static const String UNIQUE_IDENTIFIER = 'analysis_server.core';

/**
* The extension point that allows plugins to register functions that can
* The extension point that allows plugins to register file patterns that will
* cause files to be analyzed.
*/
ExtensionPoint analyzeFileExtensionPoint;
ExtensionPoint analyzedFilePatternsExtensionPoint;

/**
* The extension point that allows plugins to register assist contributors.
Expand Down Expand Up @@ -166,11 +166,17 @@ class ServerPlugin implements Plugin {
ServerPlugin();

/**
* Return a list containing all of the functions that can cause files to be
* analyzed.
* Return a list containing all of the file patterns that can cause files to
* be analyzed.
*/
List<ShouldAnalyzeFile> get analyzeFileFunctions =>
analyzeFileExtensionPoint.extensions;
List<String> get analyzedFilePatterns {
List<String> patterns = <String>[];
for (List<String> extension
in analyzedFilePatternsExtensionPoint.extensions) {
patterns.addAll(extension);
}
return patterns;
}

/**
* Return a list containing all of the assist contributors that were
Expand Down Expand Up @@ -241,8 +247,9 @@ class ServerPlugin implements Plugin {
setAnalysisDomainExtensionPoint = registerExtensionPoint(
SET_ANALISYS_DOMAIN_EXTENSION_POINT,
_validateSetAnalysisDomainFunction);
analyzeFileExtensionPoint = registerExtensionPoint(
ANALYZE_FILE_EXTENSION_POINT, _validateAnalyzeFileExtension);
analyzedFilePatternsExtensionPoint = registerExtensionPoint(
ANALYZED_FILE_PATTERNS_EXTENSION_POINT,
_validateAnalyzedFilePatternsExtension);
assistContributorExtensionPoint = registerExtensionPoint(
ASSIST_CONTRIBUTOR_EXTENSION_POINT,
_validateAssistContributorExtension);
Expand All @@ -266,13 +273,15 @@ class ServerPlugin implements Plugin {
@override
void registerExtensions(RegisterExtension registerExtension) {
//
// Register analyze file functions.
// Register analyzed file patterns.
//
registerExtension(
ANALYZE_FILE_EXTENSION_POINT_ID,
(File file) => AnalysisEngine.isDartFileName(file.path) ||
AnalysisEngine.isHtmlFileName(file.path) ||
AnalysisEngine.isAnalysisOptionsFileName(file.path));
List<String> patterns = <String>[
'/**/*.${AnalysisEngine.SUFFIX_DART}',
'/**/*.${AnalysisEngine.SUFFIX_HTML}',
'/**/*.${AnalysisEngine.SUFFIX_HTM}',
'/**/${AnalysisEngine.ANALYSIS_OPTIONS_FILE}'
];
registerExtension(ANALYZED_FILE_PATTERNS_EXTENSION_POINT_ID, patterns);
//
// Register assist contributors.
//
Expand Down Expand Up @@ -318,18 +327,29 @@ class ServerPlugin implements Plugin {
//
registerExtension(
INDEX_CONTRIBUTOR_EXTENSION_POINT_ID, new DartIndexContributor());
}

/**
* Return `true` if the list being used as an [extension] contains any
* elements that are not strings.
*/
bool _containsNonString(List extension) {
for (Object element in extension) {
if (element is! String) {
return true;
}
}
return false;
}

/**
* Validate the given extension by throwing an [ExtensionError] if it is not a
* valid assist contributor.
* valid list of analyzed file patterns.
*/
void _validateAnalyzeFileExtension(Object extension) {
if (extension is! ShouldAnalyzeFile) {
String id = analyzeFileExtensionPoint.uniqueIdentifier;
throw new ExtensionError(
'Extensions to $id must be a ShouldAnalyzeFile function');
void _validateAnalyzedFilePatternsExtension(Object extension) {
if (extension is! List || _containsNonString(extension)) {
String id = analyzedFilePatternsExtensionPoint.uniqueIdentifier;
throw new ExtensionError('Extensions to $id must be a List of Strings');
}
}

Expand Down

0 comments on commit 879cf82

Please sign in to comment.