mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
Restore partial analysis of analysis options files
R=devoncarew@google.com Review-Url: https://codereview.chromium.org/2946313003 .
This commit is contained in:
parent
ca6c60f447
commit
e28064f405
|
@ -4,5 +4,5 @@ linter:
|
|||
rules:
|
||||
- empty_constructor_bodies
|
||||
- empty_statements
|
||||
- unnecessary_brace_in_string_interp
|
||||
- unnecessary_brace_in_string_interps
|
||||
- valid_regexps
|
||||
|
|
|
@ -1463,6 +1463,10 @@ class ServerContextManagerCallbacks extends ContextManagerCallbacks {
|
|||
|
||||
ServerContextManagerCallbacks(this.analysisServer, this.resourceProvider);
|
||||
|
||||
@override
|
||||
NotificationManager get notificationManager =>
|
||||
analysisServer.notificationManager;
|
||||
|
||||
@override
|
||||
nd.AnalysisDriver addAnalysisDriver(
|
||||
Folder folder, ContextRoot contextRoot, AnalysisOptions options) {
|
||||
|
|
|
@ -7,7 +7,9 @@ import 'dart:collection';
|
|||
import 'dart:convert';
|
||||
import 'dart:core';
|
||||
|
||||
import 'package:analysis_server/src/plugin/notification_manager.dart';
|
||||
import 'package:analyzer/context/context_root.dart';
|
||||
import 'package:analyzer/error/error.dart';
|
||||
import 'package:analyzer/file_system/file_system.dart';
|
||||
import 'package:analyzer/instrumentation/instrumentation.dart';
|
||||
import 'package:analyzer/plugin/resolver_provider.dart';
|
||||
|
@ -21,6 +23,7 @@ import 'package:analyzer/src/context/builder.dart';
|
|||
import 'package:analyzer/src/dart/analysis/driver.dart';
|
||||
import 'package:analyzer/src/dart/sdk/sdk.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';
|
||||
|
@ -29,6 +32,7 @@ import 'package:analyzer/src/task/options.dart';
|
|||
import 'package:analyzer/src/util/absolute_path.dart';
|
||||
import 'package:analyzer/src/util/glob.dart';
|
||||
import 'package:analyzer/src/util/yaml.dart';
|
||||
import 'package:analyzer_plugin/utilities/analyzer_converter.dart';
|
||||
import 'package:package_config/packages.dart';
|
||||
import 'package:package_config/packages_file.dart' as pkgfile show parse;
|
||||
import 'package:package_config/src/packages_impl.dart' show MapPackages;
|
||||
|
@ -356,6 +360,11 @@ abstract class ContextManager {
|
|||
* modified.
|
||||
*/
|
||||
abstract class ContextManagerCallbacks {
|
||||
/**
|
||||
* Return the notification manager associated with the server.
|
||||
*/
|
||||
NotificationManager get notificationManager;
|
||||
|
||||
/**
|
||||
* Create and return a new analysis driver rooted at the given [folder], with
|
||||
* the given analysis [options].
|
||||
|
@ -967,6 +976,26 @@ class ContextManagerImpl implements ContextManager {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the given analysis [driver] to analyze the content of the analysis
|
||||
* options file at the given [path].
|
||||
*/
|
||||
void _analyzeAnalysisOptionsFile(AnalysisDriver driver, String path) {
|
||||
String content = driver.fsState.getFileForPath(path).content;
|
||||
List<AnalysisError> errors =
|
||||
GenerateOptionsErrorsTask.analyzeAnalysisOptions(
|
||||
resourceProvider.getFile(path).createSource(),
|
||||
content,
|
||||
driver.sourceFactory);
|
||||
AnalyzerConverter converter = new AnalyzerConverter();
|
||||
LineInfo lineInfo = _computeLineInfo(content);
|
||||
callbacks.notificationManager.recordAnalysisErrors(
|
||||
NotificationManager.serverId,
|
||||
path,
|
||||
converter.convertAnalysisErrors(errors,
|
||||
lineInfo: lineInfo, options: driver.analysisOptions));
|
||||
}
|
||||
|
||||
void _checkForAnalysisOptionsUpdate(
|
||||
String path, ContextInfo info, ChangeType changeType) {
|
||||
if (AnalysisEngine.isAnalysisOptionsFileName(path, pathContext)) {
|
||||
|
@ -979,6 +1008,7 @@ class ContextManagerImpl implements ContextManager {
|
|||
SourceFactory factory = builder.createSourceFactory(contextRoot, options);
|
||||
driver.configure(analysisOptions: options, sourceFactory: factory);
|
||||
// TODO(brianwilkerson) Set exclusion patterns.
|
||||
_analyzeAnalysisOptionsFile(driver, path);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1094,6 +1124,14 @@ class ContextManagerImpl implements ContextManager {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute line information for the given [content].
|
||||
*/
|
||||
LineInfo _computeLineInfo(String content) {
|
||||
List<int> lineStarts = StringUtilities.computeLineStarts(content);
|
||||
return new LineInfo(lineStarts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an object that can be used to find and read the analysis options
|
||||
* file for code being analyzed using the given [packages].
|
||||
|
@ -1153,6 +1191,9 @@ class ContextManagerImpl implements ContextManager {
|
|||
}
|
||||
info.analysisDriver =
|
||||
callbacks.addAnalysisDriver(folder, contextRoot, options);
|
||||
if (optionsFile != null) {
|
||||
_analyzeAnalysisOptionsFile(info.analysisDriver, optionsFile.path);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
|
|
|
@ -196,7 +196,7 @@ class CompletionDomainHandler extends AbstractRequestHandler {
|
|||
request,
|
||||
'params.offset',
|
||||
'Expected offset between 0 and source length inclusive,'
|
||||
' but found ${offset}'));
|
||||
' but found $offset'));
|
||||
return;
|
||||
}
|
||||
source =
|
||||
|
|
|
@ -576,7 +576,7 @@ abstract class DiagnosticPage extends Page {
|
|||
void generateFooter() {
|
||||
buf.writeln('''
|
||||
<footer class="footer">
|
||||
Dart ${site.title} <span style="float:right">SDK ${_sdkVersion}</span>
|
||||
Dart ${site.title} <span style="float:right">SDK $_sdkVersion</span>
|
||||
</footer>
|
||||
''');
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import 'dart:async';
|
|||
import 'dart:collection';
|
||||
|
||||
import 'package:analysis_server/src/context_manager.dart';
|
||||
import 'package:analysis_server/src/plugin/notification_manager.dart';
|
||||
import 'package:analysis_server/src/utilities/null_string_sink.dart';
|
||||
import 'package:analyzer/context/context_root.dart';
|
||||
import 'package:analyzer/error/error.dart';
|
||||
|
@ -39,6 +40,7 @@ import 'package:watcher/watcher.dart';
|
|||
|
||||
import 'mock_sdk.dart';
|
||||
import 'mocks.dart';
|
||||
import 'src/plugin/plugin_manager_test.dart';
|
||||
|
||||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
|
@ -2034,7 +2036,7 @@ include: package:boo/other_options.yaml
|
|||
String sdkExtSrcPath = newFolder([projPath, 'sdk_ext', 'src']);
|
||||
newFile([sdkExtSrcPath, 'part.dart']);
|
||||
// Setup analysis options file with ignore list.
|
||||
newFile(
|
||||
String optionsFilePath = newFile(
|
||||
[projPath, optionsFileName],
|
||||
r'''
|
||||
;
|
||||
|
@ -2042,7 +2044,11 @@ include: package:boo/other_options.yaml
|
|||
// Setup context.
|
||||
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
|
||||
|
||||
// No error means success.
|
||||
// Check that an error was produced.
|
||||
TestNotificationManager notificationManager = callbacks.notificationManager;
|
||||
var errors = notificationManager.recordedErrors;
|
||||
expect(errors, hasLength(1));
|
||||
expect(errors[errors.keys.first][optionsFilePath], hasLength(1));
|
||||
}
|
||||
|
||||
test_deleteRoot_hasAnalysisOptions() async {
|
||||
|
@ -2587,6 +2593,9 @@ class TestContextManagerCallbacks extends ContextManagerCallbacks {
|
|||
*/
|
||||
List<WatchEvent> watchEvents = <WatchEvent>[];
|
||||
|
||||
@override
|
||||
NotificationManager notificationManager = new TestNotificationManager();
|
||||
|
||||
TestContextManagerCallbacks(
|
||||
this.resourceProvider, this.sdkManager, this.logger, this.scheduler);
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ class DiagnosticDomainTest extends AbstractAnalysisTest {
|
|||
expect(context.name, '/project');
|
||||
expect(context.explicitFileCount, 1); /* test.dart */
|
||||
|
||||
expect(context.implicitFileCount, 4);
|
||||
expect(context.implicitFileCount, 5);
|
||||
|
||||
expect(context.workItemQueueLength, isNotNull);
|
||||
}
|
||||
|
|
|
@ -43,10 +43,14 @@ class Foo {
|
|||
expect(searchParams.isLast, isTrue);
|
||||
expect(searchParams.results, isNotEmpty);
|
||||
|
||||
SearchResult result = searchParams.results.first;
|
||||
expect(result.location.file, pathname);
|
||||
expect(result.isPotential, isFalse);
|
||||
expect(result.kind.name, SearchResultKind.DECLARATION.name);
|
||||
expect(result.path.first.name, 'qux');
|
||||
for (SearchResult result in searchParams.results) {
|
||||
if (result.location.file == pathname) {
|
||||
expect(result.isPotential, isFalse);
|
||||
expect(result.kind.name, SearchResultKind.DECLARATION.name);
|
||||
expect(result.path.first.name, 'qux');
|
||||
return;
|
||||
}
|
||||
}
|
||||
fail('No result for $pathname');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -670,6 +670,9 @@ class MinimalPlugin extends ServerPlugin {
|
|||
class TestNotificationManager implements NotificationManager {
|
||||
List<Notification> notifications = <Notification>[];
|
||||
|
||||
Map<String, Map<String, List<AnalysisError>>> recordedErrors =
|
||||
<String, Map<String, List<AnalysisError>>>{};
|
||||
|
||||
@override
|
||||
void handlePluginNotification(String pluginId, Notification notification) {
|
||||
notifications.add(notification);
|
||||
|
@ -679,6 +682,13 @@ class TestNotificationManager implements NotificationManager {
|
|||
noSuchMethod(Invocation invocation) {
|
||||
fail('Unexpected invocation of ${invocation.memberName}');
|
||||
}
|
||||
|
||||
@override
|
||||
void recordAnalysisErrors(
|
||||
String pluginId, String filePath, List<AnalysisError> errorData) {
|
||||
recordedErrors.putIfAbsent(
|
||||
pluginId, () => <String, List<AnalysisError>>{})[filePath] = errorData;
|
||||
}
|
||||
}
|
||||
|
||||
class TestServerCommunicationChannel implements ServerCommunicationChannel {
|
||||
|
|
|
@ -4,5 +4,5 @@ linter:
|
|||
rules:
|
||||
- empty_constructor_bodies
|
||||
- empty_statements
|
||||
- unnecessary_brace_in_string_interp
|
||||
- unnecessary_brace_in_string_interps
|
||||
- valid_regexps
|
||||
|
|
|
@ -39,7 +39,7 @@ class ConflictingSummaryException implements Exception {
|
|||
These summaries conflict because they overlap:
|
||||
- ${summary1Uri.substring(prefix)}
|
||||
- ${summary2Uri.substring(prefix)}
|
||||
Both contain the file: ${duplicatedUri}.
|
||||
Both contain the file: $duplicatedUri.
|
||||
This typically indicates an invalid build rule where two or more targets
|
||||
include the same source.
|
||||
''';
|
||||
|
|
|
@ -233,10 +233,21 @@ class GenerateOptionsErrorsTask extends SourceBasedAnalysisTask {
|
|||
@override
|
||||
void internalPerform() {
|
||||
String content = getRequiredInput(CONTENT_INPUT_NAME);
|
||||
//
|
||||
// Record outputs.
|
||||
//
|
||||
outputs[ANALYSIS_OPTIONS_ERRORS] =
|
||||
analyzeAnalysisOptions(source, content, context?.sourceFactory);
|
||||
outputs[LINE_INFO] = computeLineInfo(content);
|
||||
}
|
||||
|
||||
static List<AnalysisError> analyzeAnalysisOptions(
|
||||
Source source, String content, SourceFactory sourceFactory) {
|
||||
List<AnalysisError> errors = <AnalysisError>[];
|
||||
Source initialSource = source;
|
||||
SourceSpan initialIncludeSpan;
|
||||
AnalysisOptionsProvider optionsProvider =
|
||||
new AnalysisOptionsProvider(sourceFactory);
|
||||
|
||||
// Validate the specified options and any included option files
|
||||
void validate(Source source, Map<String, YamlNode> options) {
|
||||
|
@ -268,8 +279,7 @@ class GenerateOptionsErrorsTask extends SourceBasedAnalysisTask {
|
|||
SourceSpan span = node.span;
|
||||
initialIncludeSpan ??= span;
|
||||
String includeUri = span.text;
|
||||
Source includedSource =
|
||||
context.sourceFactory.resolveUri(source, includeUri);
|
||||
Source includedSource = sourceFactory.resolveUri(source, includeUri);
|
||||
if (!includedSource.exists()) {
|
||||
errors.add(new AnalysisError(
|
||||
initialSource,
|
||||
|
@ -310,12 +320,7 @@ class GenerateOptionsErrorsTask extends SourceBasedAnalysisTask {
|
|||
errors.add(new AnalysisError(source, span.start.column + 1, span.length,
|
||||
AnalysisOptionsErrorCode.PARSE_ERROR, [e.message]));
|
||||
}
|
||||
|
||||
//
|
||||
// Record outputs.
|
||||
//
|
||||
outputs[ANALYSIS_OPTIONS_ERRORS] = errors;
|
||||
outputs[LINE_INFO] = computeLineInfo(content);
|
||||
return errors;
|
||||
}
|
||||
|
||||
/// Return a map from the names of the inputs of this kind of task to the
|
||||
|
|
|
@ -6,5 +6,5 @@ linter:
|
|||
rules:
|
||||
- empty_constructor_bodies
|
||||
- empty_statements
|
||||
- unnecessary_brace_in_string_interp
|
||||
- unnecessary_brace_in_string_interps
|
||||
- valid_regexps
|
||||
|
|
|
@ -169,7 +169,7 @@ class AnalyzerImpl {
|
|||
: context.computeKindOf(librarySource);
|
||||
if (librarySourceKind == SourceKind.PART) {
|
||||
stderr.writeln("Only libraries can be analyzed.");
|
||||
stderr.writeln("${path} is a part and can not be analyzed.");
|
||||
stderr.writeln("$path is a part and can not be analyzed.");
|
||||
return ErrorSeverity.ERROR;
|
||||
}
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ void parseFiles(Set<Source> files) {
|
|||
parseTimer.stop();
|
||||
|
||||
// Report size and scanning time again. See discussion above.
|
||||
if (old != scanTotalChars) print('input size changed? ${old} chars');
|
||||
if (old != scanTotalChars) print('input size changed? $old chars');
|
||||
report("scan", scanTimer.elapsedMicroseconds);
|
||||
|
||||
var pTime = parseTimer.elapsedMicroseconds - scanTimer.elapsedMicroseconds;
|
||||
|
@ -136,7 +136,7 @@ void scanFiles(Set<Source> files) {
|
|||
}
|
||||
|
||||
// Report size and scanning time again. See discussion above.
|
||||
if (old != scanTotalChars) print('input size changed? ${old} chars');
|
||||
if (old != scanTotalChars) print('input size changed? $old chars');
|
||||
report("scan", scanTimer.elapsedMicroseconds);
|
||||
}
|
||||
|
||||
|
@ -167,7 +167,7 @@ Set<Source> scanReachableFiles(Uri entryUri) {
|
|||
|
||||
loadTimer.stop();
|
||||
|
||||
print('input size: ${scanTotalChars} chars');
|
||||
print('input size: $scanTotalChars chars');
|
||||
var loadTime = loadTimer.elapsedMicroseconds - scanTimer.elapsedMicroseconds;
|
||||
report("load", loadTime);
|
||||
report("scan", scanTimer.elapsedMicroseconds);
|
||||
|
|
|
@ -7,5 +7,5 @@ linter:
|
|||
- empty_statements
|
||||
- prefer_single_quotes
|
||||
- unawaited_futures
|
||||
- unnecessary_brace_in_string_interp
|
||||
- unnecessary_brace_in_string_interps
|
||||
- valid_regexps
|
||||
|
|
Loading…
Reference in a new issue