mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 20:19:23 +00:00
Don't record references to the name of this node or the name of the enclosing class.
R=brianwilkerson@google.com Change-Id: Iaf66c2995cb39039f508f55e8920c59b2afec04c Reviewed-on: https://dart-review.googlesource.com/c/86825 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
f6b5f9ce2e
commit
f0d85bb914
|
@ -142,6 +142,9 @@ class _LibraryBuilder {
|
|||
/// are different.
|
||||
List<int> uriSignature;
|
||||
|
||||
/// The name of the enclosing class name, or `null` if outside a class.
|
||||
String enclosingClassName;
|
||||
|
||||
/// The precomputed signature of the enclosing class name, or `null` if
|
||||
/// outside a class.
|
||||
///
|
||||
|
@ -158,10 +161,6 @@ class _LibraryBuilder {
|
|||
_addImports();
|
||||
_addExports();
|
||||
|
||||
// TODO(scheglov) import prefixes are shadowed by class members
|
||||
|
||||
// TODO(scheglov) top-level declarations shadow external names
|
||||
|
||||
for (var unit in units) {
|
||||
_addUnit(unit);
|
||||
}
|
||||
|
@ -171,19 +170,24 @@ class _LibraryBuilder {
|
|||
}
|
||||
|
||||
void _addClassOrMixin(ClassOrMixinDeclaration node) {
|
||||
enclosingClassName = node.name.name;
|
||||
|
||||
enclosingClassNameSignature =
|
||||
(ApiSignature()..addString(node.name.name)).toByteList();
|
||||
(ApiSignature()..addString(enclosingClassName)).toByteList();
|
||||
|
||||
var hasConstConstructor = node.members.any(
|
||||
(m) => m is ConstructorDeclaration && m.constKeyword != null,
|
||||
);
|
||||
|
||||
// TODO(scheglov) do we need type parameters at all?
|
||||
List<Node> classTypeParameters;
|
||||
if (node.typeParameters != null) {
|
||||
classTypeParameters = <Node>[];
|
||||
for (var typeParameter in node.typeParameters.typeParameters) {
|
||||
var api = referenceCollector.collect(
|
||||
_computeNodeTokenSignature(typeParameter),
|
||||
enclosingClassName: enclosingClassName,
|
||||
thisNodeName: typeParameter.name.name,
|
||||
type: typeParameter.bound,
|
||||
);
|
||||
classTypeParameters.add(Node(
|
||||
|
@ -234,6 +238,7 @@ class _LibraryBuilder {
|
|||
if (node is ClassDeclaration) {
|
||||
api = referenceCollector.collect(
|
||||
apiTokenSignature,
|
||||
thisNodeName: enclosingClassName,
|
||||
typeParameters: node.typeParameters,
|
||||
extendsClause: node.extendsClause,
|
||||
withClause: node.withClause,
|
||||
|
@ -242,6 +247,7 @@ class _LibraryBuilder {
|
|||
} else if (node is MixinDeclaration) {
|
||||
api = referenceCollector.collect(
|
||||
apiTokenSignature,
|
||||
thisNodeName: enclosingClassName,
|
||||
typeParameters: node.typeParameters,
|
||||
onClause: node.onClause,
|
||||
implementsClause: node.implementsClause,
|
||||
|
@ -251,7 +257,7 @@ class _LibraryBuilder {
|
|||
}
|
||||
|
||||
var classNode = Node(
|
||||
LibraryQualifiedName(uri, node.name.name),
|
||||
LibraryQualifiedName(uri, enclosingClassName),
|
||||
node is MixinDeclaration ? NodeKind.MIXIN : NodeKind.CLASS,
|
||||
api,
|
||||
Dependencies.none,
|
||||
|
@ -262,6 +268,7 @@ class _LibraryBuilder {
|
|||
classNode.setClassMembers(classMembers);
|
||||
|
||||
declaredNodes.add(classNode);
|
||||
enclosingClassName = null;
|
||||
enclosingClassNameSignature = null;
|
||||
}
|
||||
|
||||
|
@ -291,13 +298,16 @@ class _LibraryBuilder {
|
|||
|
||||
var api = referenceCollector.collect(
|
||||
apiTokenSignature,
|
||||
enclosingClassName: enclosingClassName,
|
||||
formalParameters: node.parameters,
|
||||
);
|
||||
|
||||
// TODO(scheglov) constructor initializers
|
||||
// TODO(scheglov) constructor redirection
|
||||
var implTokenSignature = _computeNodeTokenSignature(node.body);
|
||||
var impl = referenceCollector.collect(
|
||||
implTokenSignature,
|
||||
enclosingClassName: enclosingClassName,
|
||||
formalParametersForDefaultValues: node.parameters,
|
||||
functionBody: node.body,
|
||||
);
|
||||
|
@ -394,6 +404,7 @@ class _LibraryBuilder {
|
|||
|
||||
var api = referenceCollector.collect(
|
||||
apiTokenSignature,
|
||||
thisNodeName: node.name.name,
|
||||
typeParameters: functionExpression.typeParameters,
|
||||
formalParameters: functionExpression.parameters,
|
||||
returnType: node.returnType,
|
||||
|
@ -403,6 +414,7 @@ class _LibraryBuilder {
|
|||
var implTokenSignature = _computeNodeTokenSignature(body);
|
||||
var impl = referenceCollector.collect(
|
||||
implTokenSignature,
|
||||
thisNodeName: node.name.name,
|
||||
formalParametersForDefaultValues: functionExpression.parameters,
|
||||
functionBody: body,
|
||||
);
|
||||
|
@ -420,6 +432,7 @@ class _LibraryBuilder {
|
|||
|
||||
var api = referenceCollector.collect(
|
||||
apiTokenSignature,
|
||||
thisNodeName: node.name.name,
|
||||
typeParameters: node.typeParameters,
|
||||
formalParameters: node.parameters,
|
||||
returnType: node.returnType,
|
||||
|
@ -507,6 +520,8 @@ class _LibraryBuilder {
|
|||
// TODO(scheglov) metadata, here and everywhere
|
||||
var api = referenceCollector.collect(
|
||||
apiTokenSignature,
|
||||
enclosingClassName: enclosingClassName,
|
||||
thisNodeName: node.name.name,
|
||||
typeParameters: node.typeParameters,
|
||||
formalParameters: node.parameters,
|
||||
returnType: node.returnType,
|
||||
|
@ -515,6 +530,8 @@ class _LibraryBuilder {
|
|||
var implTokenSignature = _computeNodeTokenSignature(node.body);
|
||||
var impl = referenceCollector.collect(
|
||||
implTokenSignature,
|
||||
enclosingClassName: enclosingClassName,
|
||||
thisNodeName: node.name.name,
|
||||
formalParametersForDefaultValues: node.parameters,
|
||||
functionBody: node.body,
|
||||
);
|
||||
|
@ -570,13 +587,19 @@ class _LibraryBuilder {
|
|||
var apiTokenSignature = builder.toByteList();
|
||||
var api = referenceCollector.collect(
|
||||
apiTokenSignature,
|
||||
enclosingClassName: enclosingClassName,
|
||||
thisNodeName: variable.name.name,
|
||||
type: variables.type,
|
||||
expression: appendInitializerToApi ? initializer : null,
|
||||
);
|
||||
|
||||
var implTokenSignature = _computeNodeTokenSignature(initializer);
|
||||
var impl = referenceCollector.collect(implTokenSignature,
|
||||
expression: initializer);
|
||||
var impl = referenceCollector.collect(
|
||||
implTokenSignature,
|
||||
enclosingClassName: enclosingClassName,
|
||||
thisNodeName: variable.name.name,
|
||||
expression: initializer,
|
||||
);
|
||||
|
||||
var rawName = variable.name.name;
|
||||
variableNodes.add(Node(
|
||||
|
|
|
@ -55,7 +55,9 @@ class ReferenceCollector {
|
|||
/// Construct and return a new [Dependencies] with the given [tokenSignature]
|
||||
/// and all recorded references to external nodes in the given AST nodes.
|
||||
Dependencies collect(List<int> tokenSignature,
|
||||
{Expression expression,
|
||||
{String enclosingClassName,
|
||||
String thisNodeName,
|
||||
Expression expression,
|
||||
ExtendsClause extendsClause,
|
||||
FormalParameterList formalParameters,
|
||||
FormalParameterList formalParametersForDefaultValues,
|
||||
|
@ -70,6 +72,14 @@ class ReferenceCollector {
|
|||
WithClause withClause}) {
|
||||
_localScopes.enter();
|
||||
|
||||
// The name of the node shadows any external names.
|
||||
if (enclosingClassName != null) {
|
||||
_localScopes.add(enclosingClassName);
|
||||
}
|
||||
if (thisNodeName != null) {
|
||||
_localScopes.add(thisNodeName);
|
||||
}
|
||||
|
||||
// Add type parameters first, they might be referenced later.
|
||||
_visitTypeParameterList(typeParameters);
|
||||
_visitTypeParameterList(typeParameters2);
|
||||
|
@ -82,8 +92,8 @@ class ReferenceCollector {
|
|||
_visitTypeAnnotations(implementsClause?.interfaces);
|
||||
|
||||
// Parts of executables.
|
||||
_visitFormalParameterList(formalParameters, false);
|
||||
_visitFormalParameterList(formalParametersForDefaultValues, true);
|
||||
_visitFormalParameterList(formalParameters);
|
||||
_visitFormalParameterListDefaults(formalParametersForDefaultValues);
|
||||
_visitTypeAnnotation(returnType);
|
||||
_visitFunctionBody(functionBody);
|
||||
|
||||
|
@ -96,13 +106,26 @@ class ReferenceCollector {
|
|||
var unprefixedReferencedNames = _unprefixedReferences.toList();
|
||||
_unprefixedReferences = _NameSet();
|
||||
|
||||
var numberOfPrefixes = _importPrefixedReferences.length;
|
||||
var importPrefixes = List<String>(numberOfPrefixes);
|
||||
var importPrefixedReferencedNames = List<List<String>>(numberOfPrefixes);
|
||||
for (var i = 0; i < numberOfPrefixes; i++) {
|
||||
var importPrefixCount = 0;
|
||||
for (var i = 0; i < _importPrefixedReferences.length; i++) {
|
||||
var import = _importPrefixedReferences[i];
|
||||
importPrefixes[i] = import.prefix;
|
||||
importPrefixedReferencedNames[i] = import.names.toList();
|
||||
if (import.names.isNotEmpty) {
|
||||
importPrefixCount++;
|
||||
}
|
||||
}
|
||||
|
||||
var importPrefixes = List<String>(importPrefixCount);
|
||||
var importPrefixedReferencedNames = List<List<String>>(importPrefixCount);
|
||||
var importIndex = 0;
|
||||
for (var i = 0; i < _importPrefixedReferences.length; i++) {
|
||||
var import = _importPrefixedReferences[i];
|
||||
|
||||
if (import.names.isNotEmpty) {
|
||||
importPrefixes[importIndex] = import.prefix;
|
||||
importPrefixedReferencedNames[importIndex] = import.names.toList();
|
||||
importIndex++;
|
||||
}
|
||||
|
||||
import.clear();
|
||||
}
|
||||
|
||||
|
@ -315,8 +338,7 @@ class ReferenceCollector {
|
|||
_localScopes.exit();
|
||||
}
|
||||
|
||||
void _visitFormalParameterList(
|
||||
FormalParameterList node, bool withDefaultValues) {
|
||||
void _visitFormalParameterList(FormalParameterList node) {
|
||||
if (node == null) return;
|
||||
|
||||
var parameters = node.parameters;
|
||||
|
@ -325,16 +347,13 @@ class ReferenceCollector {
|
|||
if (parameter is DefaultFormalParameter) {
|
||||
DefaultFormalParameter defaultParameter = parameter;
|
||||
parameter = defaultParameter.parameter;
|
||||
if (withDefaultValues) {
|
||||
_visitExpression(defaultParameter.defaultValue);
|
||||
}
|
||||
}
|
||||
if (parameter.identifier != null) {
|
||||
_localScopes.add(parameter.identifier.name);
|
||||
}
|
||||
if (parameter is FunctionTypedFormalParameter) {
|
||||
_visitTypeAnnotation(parameter.returnType);
|
||||
_visitFormalParameterList(parameter.parameters, withDefaultValues);
|
||||
_visitFormalParameterList(parameter.parameters);
|
||||
} else if (parameter is SimpleFormalParameter) {
|
||||
_visitTypeAnnotation(parameter.type);
|
||||
} else {
|
||||
|
@ -344,6 +363,18 @@ class ReferenceCollector {
|
|||
}
|
||||
}
|
||||
|
||||
void _visitFormalParameterListDefaults(FormalParameterList node) {
|
||||
if (node == null) return;
|
||||
|
||||
var parameters = node.parameters;
|
||||
for (var i = 0; i < parameters.length; i++) {
|
||||
FormalParameter parameter = parameters[i];
|
||||
if (parameter is DefaultFormalParameter) {
|
||||
_visitExpression(parameter.defaultValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _visitForStatement(ForStatement node) {
|
||||
_localScopes.enter();
|
||||
|
||||
|
@ -384,7 +415,8 @@ class ReferenceCollector {
|
|||
void _visitFunctionExpression(FunctionExpression node) {
|
||||
_localScopes.enter();
|
||||
_visitTypeParameterList(node.typeParameters);
|
||||
_visitFormalParameterList(node.parameters, true);
|
||||
_visitFormalParameterList(node.parameters);
|
||||
_visitFormalParameterListDefaults(node.parameters);
|
||||
_visitFunctionBody(node.body);
|
||||
_localScopes.exit();
|
||||
}
|
||||
|
@ -692,7 +724,7 @@ class ReferenceCollector {
|
|||
}
|
||||
|
||||
_visitTypeAnnotation(node.returnType);
|
||||
_visitFormalParameterList(node.parameters, true);
|
||||
_visitFormalParameterList(node.parameters);
|
||||
|
||||
_localScopes.exit();
|
||||
} else if (node is TypeName) {
|
||||
|
@ -809,6 +841,8 @@ class _LocalScopes {
|
|||
class _NameSet {
|
||||
final List<String> names = [];
|
||||
|
||||
bool get isNotEmpty => names.isNotEmpty;
|
||||
|
||||
void add(String name) {
|
||||
// TODO(scheglov) consider just adding, but toList() sort and unique
|
||||
if (!contains(name)) {
|
||||
|
|
|
@ -18,6 +18,7 @@ main() {
|
|||
defineReflectiveTests(ExpressionReferenceCollectorTest);
|
||||
defineReflectiveTests(ExpressionReferenceCollectorTest_SetLiterals);
|
||||
defineReflectiveTests(ImplReferenceCollectorTest);
|
||||
defineReflectiveTests(ShadowReferenceCollectorTest);
|
||||
defineReflectiveTests(StatementReferenceCollectorTest);
|
||||
defineReflectiveTests(TypeReferenceCollectorTest);
|
||||
});
|
||||
|
@ -242,7 +243,6 @@ class X<T extends A<B, C>> {}
|
|||
''');
|
||||
_assertApi(library, 'T', NodeKind.TYPE_PARAMETER,
|
||||
typeParameterOf: 'X', unprefixed: ['A', 'B', 'C']);
|
||||
// TODO(scheglov) test for type parameter referencing the enclosing class
|
||||
}
|
||||
|
||||
test_unit_class() async {
|
||||
|
@ -1381,7 +1381,7 @@ class ImplReferenceCollectorTest extends _Base {
|
|||
test_class_constructor() async {
|
||||
var library = await buildTestLibrary(a, r'''
|
||||
class C {
|
||||
C.test({a: x}) {
|
||||
C.test(A a, {b: x}) {
|
||||
y;
|
||||
}
|
||||
}
|
||||
|
@ -1393,7 +1393,7 @@ class C {
|
|||
test_class_method() async {
|
||||
var library = await buildTestLibrary(a, r'''
|
||||
class C {
|
||||
void test({a: x}) {
|
||||
void test(A a, {b: x}) {
|
||||
y;
|
||||
}
|
||||
}
|
||||
|
@ -1443,7 +1443,7 @@ class Test<T extends V, U extends T> = A<T> with B<U, W>;
|
|||
|
||||
test_unit_function() async {
|
||||
var library = await buildTestLibrary(a, r'''
|
||||
void test({a: x}) {
|
||||
void test(A a, {b: x}) {
|
||||
y;
|
||||
}
|
||||
''');
|
||||
|
@ -1478,6 +1478,133 @@ int test;
|
|||
}
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class ShadowReferenceCollectorTest extends _Base {
|
||||
test_importPrefix_with_classMember_getter_field() async {
|
||||
var library = await buildTestLibrary(a, r'''
|
||||
import 'b.dart' as p;
|
||||
|
||||
class X {
|
||||
p.A<B> test() {}
|
||||
|
||||
int p;
|
||||
}
|
||||
''');
|
||||
_assertApi(library, 'test', NodeKind.METHOD,
|
||||
memberOf: 'X', unprefixed: ['B', 'p']);
|
||||
}
|
||||
|
||||
test_importPrefix_with_classMember_method() async {
|
||||
var library = await buildTestLibrary(a, r'''
|
||||
import 'b.dart' as p;
|
||||
|
||||
class X {
|
||||
p.A<B> test() {}
|
||||
|
||||
p() {}
|
||||
}
|
||||
''');
|
||||
_assertApi(library, 'test', NodeKind.METHOD,
|
||||
memberOf: 'X', unprefixed: ['B', 'p']);
|
||||
}
|
||||
|
||||
test_importPrefix_with_function() async {
|
||||
var library = await buildTestLibrary(a, r'''
|
||||
import 'b.dart' as p;
|
||||
|
||||
p() {} // this is a compilation error
|
||||
|
||||
class X extends p.A<B> {}
|
||||
''');
|
||||
_assertApi(library, 'X', NodeKind.CLASS, unprefixed: [
|
||||
'B'
|
||||
], prefixed: {
|
||||
'p': ['A']
|
||||
});
|
||||
}
|
||||
|
||||
test_syntacticScope_class_constructor() async {
|
||||
var library = await buildTestLibrary(a, r'''
|
||||
class X {
|
||||
X.test(A a, X b) {
|
||||
X;
|
||||
}
|
||||
}
|
||||
''');
|
||||
_assertApi(library, 'test', NodeKind.CONSTRUCTOR,
|
||||
memberOf: 'X', unprefixed: ['A']);
|
||||
_assertImpl(library, 'test', NodeKind.CONSTRUCTOR, memberOf: 'X');
|
||||
}
|
||||
|
||||
test_syntacticScope_class_field() async {
|
||||
var library = await buildTestLibrary(a, r'''
|
||||
class X {
|
||||
var test = x + X + test;
|
||||
}
|
||||
''');
|
||||
_assertApi(library, 'test', NodeKind.GETTER,
|
||||
memberOf: 'X', unprefixed: ['x']);
|
||||
_assertImpl(library, 'test', NodeKind.GETTER,
|
||||
memberOf: 'X', unprefixed: ['x']);
|
||||
}
|
||||
|
||||
test_syntacticScope_class_method() async {
|
||||
var library = await buildTestLibrary(a, r'''
|
||||
class X {
|
||||
test(A a, X b, test c) {
|
||||
X;
|
||||
test;
|
||||
B;
|
||||
}
|
||||
}
|
||||
''');
|
||||
_assertApi(library, 'test', NodeKind.METHOD,
|
||||
memberOf: 'X', unprefixed: ['A']);
|
||||
_assertImpl(library, 'test', NodeKind.METHOD,
|
||||
memberOf: 'X', unprefixed: ['B']);
|
||||
}
|
||||
|
||||
test_syntacticScope_class_typeParameter_ofClass() async {
|
||||
var library = await buildTestLibrary(a, r'''
|
||||
class X<T extends A<B, X, T>> {}
|
||||
''');
|
||||
_assertApi(library, 'T', NodeKind.TYPE_PARAMETER,
|
||||
typeParameterOf: 'X', unprefixed: ['A', 'B']);
|
||||
}
|
||||
|
||||
test_syntacticScope_unit_class() async {
|
||||
var library = await buildTestLibrary(a, r'''
|
||||
class X extends A<B, X> {}
|
||||
''');
|
||||
_assertApi(library, 'X', NodeKind.CLASS, unprefixed: ['A', 'B']);
|
||||
}
|
||||
|
||||
test_syntacticScope_unit_function() async {
|
||||
var library = await buildTestLibrary(a, r'''
|
||||
test(A a, test b) {
|
||||
test;
|
||||
B;
|
||||
}
|
||||
''');
|
||||
_assertApi(library, 'test', NodeKind.FUNCTION, unprefixed: ['A']);
|
||||
_assertImpl(library, 'test', NodeKind.FUNCTION, unprefixed: ['B']);
|
||||
}
|
||||
|
||||
test_syntacticScope_unit_functionTypeAlias() async {
|
||||
var library = await buildTestLibrary(a, r'''
|
||||
typedef X(A a, X b);
|
||||
''');
|
||||
_assertApi(library, 'X', NodeKind.FUNCTION_TYPE_ALIAS, unprefixed: ['A']);
|
||||
}
|
||||
|
||||
test_syntacticScope_unit_mixin() async {
|
||||
var library = await buildTestLibrary(a, r'''
|
||||
mixin X on A<B, X> {}
|
||||
''');
|
||||
_assertApi(library, 'X', NodeKind.MIXIN, unprefixed: ['A', 'B']);
|
||||
}
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class StatementReferenceCollectorTest extends _Base {
|
||||
test_assertStatement() async {
|
||||
|
|
Loading…
Reference in a new issue