Ignore files that are hidden by generated files.
We cannot analyze them - their URIs will be resolved to other files, element models will not correspond to ASTs, etc. R=brianwilkerson@google.com, paulberry@google.com BUG= Review-Url: https://codereview.chromium.org/2654303003 .
This commit is contained in:
@@ -74,7 +74,7 @@ class AnalysisDriver {
|
||||
/**
|
||||
* The version of data format, should be incremented on every format change.
|
||||
*/
|
||||
static const int DATA_VERSION = 13;
|
||||
static const int DATA_VERSION = 14;
|
||||
|
||||
/**
|
||||
* The name of the driver, e.g. the name of the folder.
|
||||
@@ -416,6 +416,9 @@ class AnalysisDriver {
|
||||
* The results of analysis are eventually produced by the [results] stream.
|
||||
*/
|
||||
void addFile(String path) {
|
||||
if (!_fsState.hasUri(path)) {
|
||||
return;
|
||||
}
|
||||
if (AnalysisEngine.isDartFileName(path)) {
|
||||
_addedFiles.add(path);
|
||||
_filesToAnalyze.add(path);
|
||||
@@ -497,9 +500,13 @@ class AnalysisDriver {
|
||||
|
||||
/**
|
||||
* Return a [Future] that completes with the [AnalysisDriverUnitIndex] for
|
||||
* the file with the given [path].
|
||||
* the file with the given [path], or with `null` if the file cannot be
|
||||
* analyzed.
|
||||
*/
|
||||
Future<AnalysisDriverUnitIndex> getIndex(String path) {
|
||||
if (!_fsState.hasUri(path)) {
|
||||
return null;
|
||||
}
|
||||
var completer = new Completer<AnalysisDriverUnitIndex>();
|
||||
_indexRequestedFiles
|
||||
.putIfAbsent(path, () => <Completer<AnalysisDriverUnitIndex>>[])
|
||||
@@ -511,8 +518,8 @@ class AnalysisDriver {
|
||||
|
||||
/**
|
||||
* Return a [Future] that completes with a [AnalysisResult] for the Dart
|
||||
* file with the given [path]. If the file is not a Dart file, the [Future]
|
||||
* completes with `null`.
|
||||
* file with the given [path]. If the file is not a Dart file or cannot
|
||||
* be analyzed, the [Future] completes with `null`.
|
||||
*
|
||||
* The [path] must be absolute and normalized.
|
||||
*
|
||||
@@ -527,6 +534,10 @@ class AnalysisDriver {
|
||||
* state transitions to "idle".
|
||||
*/
|
||||
Future<AnalysisResult> getResult(String path) {
|
||||
if (!_fsState.hasUri(path)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Return the cached result.
|
||||
{
|
||||
AnalysisResult result = _priorityResults[path];
|
||||
@@ -560,9 +571,12 @@ class AnalysisDriver {
|
||||
|
||||
/**
|
||||
* Return a [Future] that completes with the [CompilationUnitElement] for the
|
||||
* file with the given [path].
|
||||
* file with the given [path], or with `null` if the file cannot be analyzed.
|
||||
*/
|
||||
Future<CompilationUnitElement> getUnitElement(String path) {
|
||||
if (!_fsState.hasUri(path)) {
|
||||
return null;
|
||||
}
|
||||
var completer = new Completer<CompilationUnitElement>();
|
||||
_unitElementRequestedFiles
|
||||
.putIfAbsent(path, () => <Completer<CompilationUnitElement>>[])
|
||||
|
||||
@@ -539,6 +539,11 @@ class FileSystemState {
|
||||
*/
|
||||
final Set<String> knownFilePaths = new Set<String>();
|
||||
|
||||
/**
|
||||
* Mapping from a path to the flag whether there is a URI for the path.
|
||||
*/
|
||||
final Map<String, bool> _hasUriForPath = {};
|
||||
|
||||
/**
|
||||
* Mapping from a path to the corresponding [FileState]s, canonical or not.
|
||||
*/
|
||||
@@ -592,7 +597,7 @@ class FileSystemState {
|
||||
// Try to get the existing instance.
|
||||
file = _uriToFile[uri];
|
||||
// If we have a file, call it the canonical one and return it.
|
||||
if (file != null && file.path == path) {
|
||||
if (file != null) {
|
||||
_pathToCanonicalFile[path] = file;
|
||||
return file;
|
||||
}
|
||||
@@ -647,6 +652,26 @@ class FileSystemState {
|
||||
..insert(0, canonicalFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return `true` if there is a URI that can be resolved to the [path].
|
||||
*
|
||||
* When a file exists, but for the URI that corresponds to the file is
|
||||
* resolved to another file, e.g. a generated one in Bazel, Gn, etc, we
|
||||
* cannot analyze the original file.
|
||||
*/
|
||||
bool hasUri(String path) {
|
||||
bool flag = _hasUriForPath[path];
|
||||
if (flag == null) {
|
||||
File resource = _resourceProvider.getFile(path);
|
||||
Source fileSource = resource.createSource();
|
||||
Uri uri = _sourceFactory.restoreUri(fileSource);
|
||||
Source uriSource = _sourceFactory.forUri2(uri);
|
||||
flag = uriSource.fullName == path;
|
||||
_hasUriForPath[path] = flag;
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the file with the given [path].
|
||||
*/
|
||||
|
||||
@@ -48,10 +48,12 @@ class Search {
|
||||
for (FileState file in _driver.fsState.knownFiles) {
|
||||
CompilationUnitElement unitElement =
|
||||
await _driver.getUnitElement(file.path);
|
||||
for (ClassElement clazz in unitElement.types) {
|
||||
clazz.accessors.forEach(addElement);
|
||||
clazz.fields.forEach(addElement);
|
||||
clazz.methods.forEach(addElement);
|
||||
if (unitElement != null) {
|
||||
for (ClassElement clazz in unitElement.types) {
|
||||
clazz.accessors.forEach(addElement);
|
||||
clazz.fields.forEach(addElement);
|
||||
clazz.methods.forEach(addElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
return elements;
|
||||
@@ -132,12 +134,14 @@ class Search {
|
||||
for (FileState file in _driver.fsState.knownFiles) {
|
||||
CompilationUnitElement unitElement =
|
||||
await _driver.getUnitElement(file.path);
|
||||
unitElement.accessors.forEach(addElement);
|
||||
unitElement.enums.forEach(addElement);
|
||||
unitElement.functions.forEach(addElement);
|
||||
unitElement.functionTypeAliases.forEach(addElement);
|
||||
unitElement.topLevelVariables.forEach(addElement);
|
||||
unitElement.types.forEach(addElement);
|
||||
if (unitElement != null) {
|
||||
unitElement.accessors.forEach(addElement);
|
||||
unitElement.enums.forEach(addElement);
|
||||
unitElement.functions.forEach(addElement);
|
||||
unitElement.functionTypeAliases.forEach(addElement);
|
||||
unitElement.topLevelVariables.forEach(addElement);
|
||||
unitElement.types.forEach(addElement);
|
||||
}
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
@@ -157,17 +161,19 @@ class Search {
|
||||
List<SearchResult> results = [];
|
||||
for (String file in files) {
|
||||
AnalysisDriverUnitIndex index = await _driver.getIndex(file);
|
||||
_IndexRequest request = new _IndexRequest(index);
|
||||
var fileResults = await request.getUnresolvedMemberReferences(
|
||||
name,
|
||||
const {
|
||||
IndexRelationKind.IS_READ_BY: SearchResultKind.READ,
|
||||
IndexRelationKind.IS_WRITTEN_BY: SearchResultKind.WRITE,
|
||||
IndexRelationKind.IS_READ_WRITTEN_BY: SearchResultKind.READ_WRITE,
|
||||
IndexRelationKind.IS_INVOKED_BY: SearchResultKind.INVOCATION
|
||||
},
|
||||
() => _driver.getUnitElement(file));
|
||||
results.addAll(fileResults);
|
||||
if (index != null) {
|
||||
_IndexRequest request = new _IndexRequest(index);
|
||||
var fileResults = await request.getUnresolvedMemberReferences(
|
||||
name,
|
||||
const {
|
||||
IndexRelationKind.IS_READ_BY: SearchResultKind.READ,
|
||||
IndexRelationKind.IS_WRITTEN_BY: SearchResultKind.WRITE,
|
||||
IndexRelationKind.IS_READ_WRITTEN_BY: SearchResultKind.READ_WRITE,
|
||||
IndexRelationKind.IS_INVOKED_BY: SearchResultKind.INVOCATION
|
||||
},
|
||||
() => _driver.getUnitElement(file));
|
||||
results.addAll(fileResults);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
@@ -217,12 +223,14 @@ class Search {
|
||||
Map<IndexRelationKind, SearchResultKind> relationToResultKind,
|
||||
String file) async {
|
||||
AnalysisDriverUnitIndex index = await _driver.getIndex(file);
|
||||
_IndexRequest request = new _IndexRequest(index);
|
||||
int elementId = request.findElementId(element);
|
||||
if (elementId != -1) {
|
||||
List<SearchResult> fileResults = await request.getRelations(
|
||||
elementId, relationToResultKind, () => _driver.getUnitElement(file));
|
||||
results.addAll(fileResults);
|
||||
if (index != null) {
|
||||
_IndexRequest request = new _IndexRequest(index);
|
||||
int elementId = request.findElementId(element);
|
||||
if (elementId != -1) {
|
||||
List<SearchResult> fileResults = await request.getRelations(elementId,
|
||||
relationToResultKind, () => _driver.getUnitElement(file));
|
||||
results.addAll(fileResults);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -689,15 +697,17 @@ class _IndexRequest {
|
||||
if (resultKind != null) {
|
||||
int offset = index.usedElementOffsets[i];
|
||||
enclosingUnitElement ??= await getEnclosingUnitElement();
|
||||
Element enclosingElement =
|
||||
_getEnclosingElement(enclosingUnitElement, offset);
|
||||
results.add(new SearchResult._(
|
||||
enclosingElement,
|
||||
resultKind,
|
||||
offset,
|
||||
index.usedElementLengths[i],
|
||||
true,
|
||||
index.usedElementIsQualifiedFlags[i]));
|
||||
if (enclosingUnitElement != null) {
|
||||
Element enclosingElement =
|
||||
_getEnclosingElement(enclosingUnitElement, offset);
|
||||
results.add(new SearchResult._(
|
||||
enclosingElement,
|
||||
resultKind,
|
||||
offset,
|
||||
index.usedElementLengths[i],
|
||||
true,
|
||||
index.usedElementIsQualifiedFlags[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
return results;
|
||||
@@ -763,10 +773,12 @@ class _IndexRequest {
|
||||
if (resultKind != null) {
|
||||
int offset = index.usedNameOffsets[i];
|
||||
enclosingUnitElement ??= await getEnclosingUnitElement();
|
||||
Element enclosingElement =
|
||||
_getEnclosingElement(enclosingUnitElement, offset);
|
||||
results.add(new SearchResult._(enclosingElement, resultKind, offset,
|
||||
name.length, false, index.usedNameIsQualifiedFlags[i]));
|
||||
if (enclosingUnitElement != null) {
|
||||
Element enclosingElement =
|
||||
_getEnclosingElement(enclosingUnitElement, offset);
|
||||
results.add(new SearchResult._(enclosingElement, resultKind, offset,
|
||||
name.length, false, index.usedNameIsQualifiedFlags[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
|
||||
import 'package:analyzer/src/generated/sdk.dart';
|
||||
import 'package:analyzer/src/generated/source.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:typed_mock/typed_mock.dart';
|
||||
|
||||
import '../../context/mock_sdk.dart';
|
||||
|
||||
@@ -51,10 +52,12 @@ class BaseAnalysisDriverTest {
|
||||
final StringBuffer logBuffer = new StringBuffer();
|
||||
PerformanceLog logger;
|
||||
|
||||
final UriResolver generatedUriResolver = new _GeneratedUriResolverMock();
|
||||
AnalysisDriverScheduler scheduler;
|
||||
AnalysisDriver driver;
|
||||
final List<AnalysisStatus> allStatuses = <AnalysisStatus>[];
|
||||
final List<AnalysisResult> allResults = <AnalysisResult>[];
|
||||
final List<ExceptionResult> allExceptions = <ExceptionResult>[];
|
||||
|
||||
String testProject;
|
||||
String testFile;
|
||||
@@ -113,6 +116,7 @@ class BaseAnalysisDriverTest {
|
||||
'test',
|
||||
new SourceFactory([
|
||||
new DartUriResolver(sdk),
|
||||
generatedUriResolver,
|
||||
new PackageMapUriResolver(provider, <String, List<Folder>>{
|
||||
'test': [provider.getFolder(testProject)]
|
||||
}),
|
||||
@@ -122,6 +126,7 @@ class BaseAnalysisDriverTest {
|
||||
scheduler.start();
|
||||
driver.status.listen(allStatuses.add);
|
||||
driver.results.listen(allResults.add);
|
||||
driver.exceptions.listen(allExceptions.add);
|
||||
}
|
||||
|
||||
String _p(String path) => provider.convertPath(path);
|
||||
@@ -140,3 +145,5 @@ class _ElementVisitorFunctionWrapper extends GeneralizingElementVisitor {
|
||||
super.visitElement(element);
|
||||
}
|
||||
}
|
||||
|
||||
class _GeneratedUriResolverMock extends TypedMock implements UriResolver {}
|
||||
|
||||
@@ -28,6 +28,7 @@ import 'package:convert/convert.dart';
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
import 'package:typed_mock/typed_mock.dart';
|
||||
|
||||
import '../../context/mock_sdk.dart';
|
||||
import 'base.dart';
|
||||
@@ -633,6 +634,66 @@ part 'foo.dart';
|
||||
expect(errors[0].errorCode, CompileTimeErrorCode.URI_DOES_NOT_EXIST);
|
||||
}
|
||||
|
||||
test_generatedFile() async {
|
||||
Uri uri = Uri.parse('package:aaa/foo.dart');
|
||||
String templatePath = _p('/aaa/lib/foo.dart');
|
||||
String generatedPath = _p('/generated/aaa/lib/foo.dart');
|
||||
|
||||
provider.newFile(
|
||||
templatePath,
|
||||
r'''
|
||||
a() {}
|
||||
b() {}
|
||||
''');
|
||||
|
||||
provider.newFile(
|
||||
generatedPath,
|
||||
r'''
|
||||
aaa() {}
|
||||
bbb() {}
|
||||
''');
|
||||
|
||||
Source generatedSource = new _SourceMock();
|
||||
when(generatedSource.uri).thenReturn(uri);
|
||||
when(generatedSource.fullName).thenReturn(generatedPath);
|
||||
|
||||
when(generatedUriResolver.resolveAbsolute(uri, uri))
|
||||
.thenReturn(generatedSource);
|
||||
when(generatedUriResolver.restoreAbsolute(anyObject))
|
||||
.thenInvoke((Source source) {
|
||||
String path = source.fullName;
|
||||
if (path == templatePath || path == generatedPath) {
|
||||
return uri;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
driver.addFile(templatePath);
|
||||
|
||||
await driver.waitForIdle();
|
||||
expect(allExceptions, isEmpty);
|
||||
expect(allResults, isEmpty);
|
||||
|
||||
var result = await driver.getResult(templatePath);
|
||||
expect(result, isNull);
|
||||
expect(allExceptions, isEmpty);
|
||||
expect(allResults, isEmpty);
|
||||
|
||||
var element = await driver.getUnitElement(templatePath);
|
||||
expect(element, isNull);
|
||||
expect(allExceptions, isEmpty);
|
||||
expect(allResults, isEmpty);
|
||||
|
||||
driver.priorityFiles = [templatePath];
|
||||
driver.changeFile(templatePath);
|
||||
await driver.waitForIdle();
|
||||
expect(allExceptions, isEmpty);
|
||||
expect(allResults, isEmpty);
|
||||
|
||||
expect(driver.knownFiles, isNot(contains(templatePath)));
|
||||
}
|
||||
|
||||
test_getFilesReferencingName() async {
|
||||
var a = _p('/test/bin/a.dart');
|
||||
var b = _p('/test/bin/b.dart');
|
||||
@@ -1836,3 +1897,5 @@ var A = B;
|
||||
return hex.encode(md5.convert(UTF8.encode(content)).bytes);
|
||||
}
|
||||
}
|
||||
|
||||
class _SourceMock extends TypedMock implements Source {}
|
||||
|
||||
@@ -275,29 +275,6 @@ class A2 {}
|
||||
expect(file.unlinked.classes, isEmpty);
|
||||
}
|
||||
|
||||
test_getFileForPath_generatedFile() {
|
||||
Uri uri = Uri.parse('package:aaa/foo.dart');
|
||||
String templatePath = _p('/aaa/lib/foo.dart');
|
||||
String generatedPath = _p('/generated/aaa/lib/foo.dart');
|
||||
|
||||
Source generatedSource = new _SourceMock();
|
||||
when(generatedSource.fullName).thenReturn(generatedPath);
|
||||
when(generatedSource.uri).thenReturn(uri);
|
||||
|
||||
when(generatedUriResolver.resolveAbsolute(uri, uri))
|
||||
.thenReturn(generatedSource);
|
||||
|
||||
FileState generatedFile = fileSystemState.getFileForUri(uri);
|
||||
expect(generatedFile.path, generatedPath);
|
||||
expect(generatedFile.uri, uri);
|
||||
|
||||
FileState templateFile = fileSystemState.getFileForPath(templatePath);
|
||||
expect(templateFile.path, templatePath);
|
||||
expect(templateFile.uri, uri);
|
||||
|
||||
expect(fileSystemState.getFilesForPath(templatePath), [templateFile]);
|
||||
}
|
||||
|
||||
test_getFileForPath_library() {
|
||||
String a1 = _p('/aaa/lib/a1.dart');
|
||||
String a2 = _p('/aaa/lib/a2.dart');
|
||||
@@ -464,6 +441,22 @@ part 'not-a2.dart';
|
||||
expect(files, [filePackageUri, fileFileUri]);
|
||||
}
|
||||
|
||||
test_hasUri() {
|
||||
Uri uri = Uri.parse('package:aaa/foo.dart');
|
||||
String templatePath = _p('/aaa/lib/foo.dart');
|
||||
String generatedPath = _p('/generated/aaa/lib/foo.dart');
|
||||
|
||||
Source generatedSource = new _SourceMock();
|
||||
when(generatedSource.fullName).thenReturn(generatedPath);
|
||||
when(generatedSource.uri).thenReturn(uri);
|
||||
|
||||
when(generatedUriResolver.resolveAbsolute(uri, uri))
|
||||
.thenReturn(generatedSource);
|
||||
|
||||
expect(fileSystemState.hasUri(templatePath), isFalse);
|
||||
expect(fileSystemState.hasUri(generatedPath), isTrue);
|
||||
}
|
||||
|
||||
test_referencedNames() {
|
||||
String path = _p('/aaa/lib/a.dart');
|
||||
provider.newFile(
|
||||
|
||||
Reference in New Issue
Block a user