Fix for Import/ExportDirective annotations while applying resynthesized element model.

This takea care of the Pub analysis crash you saw.

R=brianwilkerson@google.com
BUG=

Review URL: https://codereview.chromium.org/2508223004 .
This commit is contained in:
Konstantin Shcheglov 2016-11-18 15:05:59 -08:00
parent 159a5ab366
commit 4f1fa54e34
2 changed files with 76 additions and 4 deletions

View file

@ -154,8 +154,17 @@ class DeclarationResolver extends RecursiveAstVisitor<Object> {
@override
Object visitExportDirective(ExportDirective node) {
super.visitExportDirective(node);
_resolveAnnotations(
node, node.metadata, _enclosingUnit.getAnnotations(node.offset));
List<ElementAnnotation> annotations =
_enclosingUnit.getAnnotations(node.offset);
if (annotations.isEmpty && node.metadata.isNotEmpty) {
int index = (node.parent as CompilationUnit)
.directives
.where((directive) => directive is ExportDirective)
.toList()
.indexOf(node);
annotations = _walker.element.library.exports[index].metadata;
}
_resolveAnnotations(node, node.metadata, annotations);
return null;
}
@ -263,8 +272,17 @@ class DeclarationResolver extends RecursiveAstVisitor<Object> {
@override
Object visitImportDirective(ImportDirective node) {
super.visitImportDirective(node);
_resolveAnnotations(
node, node.metadata, _enclosingUnit.getAnnotations(node.offset));
List<ElementAnnotation> annotations =
_enclosingUnit.getAnnotations(node.offset);
if (annotations.isEmpty && node.metadata.isNotEmpty) {
int index = (node.parent as CompilationUnit)
.directives
.where((directive) => directive is ImportDirective)
.toList()
.indexOf(node);
annotations = _walker.element.library.imports[index].metadata;
}
_resolveAnnotations(node, node.metadata, annotations);
return null;
}

View file

@ -101,6 +101,33 @@ class DeclarationResolverMetadataTest extends ResolverTestCase {
checkMetadata('export');
}
void test_metadata_exportDirective_resynthesized() {
CompilationUnit unit = resolveSource(r'''
@a
export "dart:async";
@b
export "dart:math";
const a = null;
const b = null;
''');
expect(unit.directives[0].metadata.single.name.name, 'a');
expect(unit.directives[1].metadata.single.name.name, 'b');
var unitElement = unit.element as CompilationUnitElementImpl;
// Damage the unit element - as if "setAnnotations" were not called.
// The ExportElement(s) still have the metadata, we should use it.
unitElement.setAnnotations(unit.directives[0].offset, []);
unitElement.setAnnotations(unit.directives[1].offset, []);
expect(unitElement.library.exports[0].metadata, hasLength(1));
expect(unitElement.library.exports[1].metadata, hasLength(1));
// DeclarationResolver on the clone should succeed.
CompilationUnit clonedUnit = AstCloner.clone(unit);
new DeclarationResolver().resolve(clonedUnit, unit.element);
expect(unit.directives[0].metadata.single.name.name, 'a');
expect(unit.directives[1].metadata.single.name.name, 'b');
}
void test_metadata_fieldDeclaration() {
setupCode('class C { @a int x; }');
checkMetadata('x');
@ -163,6 +190,33 @@ class DeclarationResolverMetadataTest extends ResolverTestCase {
checkMetadata('import');
}
void test_metadata_importDirective_resynthesized() {
CompilationUnit unit = resolveSource(r'''
@a
import "dart:async";
@b
import "dart:math";
const a = null;
const b = null;
''');
expect(unit.directives[0].metadata.single.name.name, 'a');
expect(unit.directives[1].metadata.single.name.name, 'b');
var unitElement = unit.element as CompilationUnitElementImpl;
// Damage the unit element - as if "setAnnotations" were not called.
// The ImportElement(s) still have the metadata, we should use it.
unitElement.setAnnotations(unit.directives[0].offset, []);
unitElement.setAnnotations(unit.directives[1].offset, []);
expect(unitElement.library.imports[0].metadata, hasLength(1));
expect(unitElement.library.imports[1].metadata, hasLength(1));
// DeclarationResolver on the clone should succeed.
CompilationUnit clonedUnit = AstCloner.clone(unit);
new DeclarationResolver().resolve(clonedUnit, unit.element);
expect(unit.directives[0].metadata.single.name.name, 'a');
expect(unit.directives[1].metadata.single.name.name, 'b');
}
void test_metadata_libraryDirective() {
setupCode('@a library L;');
checkMetadata('L');