Index: sdk/lib/_internal/compiler/implementation/typechecker.dart |
diff --git a/sdk/lib/_internal/compiler/implementation/typechecker.dart b/sdk/lib/_internal/compiler/implementation/typechecker.dart |
index 83b4db82842afdbab928426a0c67df5af736a7c5..4e0bd9601cd612c94d5e57039896ec22437a54ae 100644 |
--- a/sdk/lib/_internal/compiler/implementation/typechecker.dart |
+++ b/sdk/lib/_internal/compiler/implementation/typechecker.dart |
@@ -170,6 +170,8 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
listType = compiler.listClass.computeType(compiler); |
} |
+ LibraryElement get currentLibrary => elements.currentElement.getLibrary(); |
+ |
reportTypeWarning(Node node, MessageKind kind, [Map arguments = const {}]) { |
compiler.reportWarning(node, new TypeWarning(kind, arguments)); |
} |
@@ -350,6 +352,19 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
return thenType.join(elseType); |
} |
+ void checkPrivateAccess(Node node, Element element, SourceString name) { |
+ if (name != null && |
+ name.isPrivate() && |
+ element.getLibrary() != currentLibrary) { |
+ reportTypeWarning( |
+ node, |
+ MessageKind.PRIVATE_ACCESS, |
+ {'name': name, |
+ 'libraryName': element.getLibrary().getLibraryOrScriptName()}); |
+ } |
+ |
+ } |
+ |
ElementAccess lookupMember(Node node, DartType type, SourceString name, |
MemberKind memberKind) { |
if (identical(type, types.dynamicType)) { |
@@ -357,6 +372,7 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
} |
Member member = type.lookupMember(name); |
if (member != null) { |
+ checkPrivateAccess(node, member.element, name); |
return new MemberAccess(member); |
} |
switch (memberKind) { |
@@ -542,12 +558,12 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
name, memberKind); |
} else if (element.isFunction()) { |
// foo() where foo is a method in the same class. |
- return new ResolvedAccess(element); |
+ return createResolvedAccess(node, name, element); |
} else if (element.isVariable() || |
element.isParameter() || |
element.isField()) { |
// foo() where foo is a field in the same class. |
- return new ResolvedAccess(element); |
+ return createResolvedAccess(node, name, element); |
} else if (element.impliesType()) { |
// The literal `Foo` where Foo is a class, a typedef, or a type variable. |
if (elements.getType(node) != null) { |
@@ -557,15 +573,21 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
'${elements.getType(node)}')); |
return new TypeLiteralAccess(element); |
} |
- return new ResolvedAccess(element); |
+ return createResolvedAccess(node, name, element); |
} else if (element.isGetter() || element.isSetter()) { |
- return new ResolvedAccess(element); |
+ return createResolvedAccess(node, name, element); |
} else { |
compiler.internalErrorOnElement( |
element, 'unexpected element kind ${element.kind}'); |
} |
} |
+ ElementAccess createResolvedAccess(Send node, SourceString name, |
+ Element element) { |
+ checkPrivateAccess(node, element, name); |
+ return new ResolvedAccess(element); |
+ } |
+ |
/** |
* Computes the type of the access of [name] on the [node] possibly using the |
* [element] provided for [node] by the resolver. |
@@ -891,6 +913,12 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
DartType visitNewExpression(NewExpression node) { |
Element element = elements[node.send]; |
+ if (Elements.isUnresolved(element)) return types.dynamicType; |
+ |
+ ClassElement enclosingClass = element.getEnclosingClass(); |
+ SourceString name = Elements.deconstructConstructorName( |
+ element.name, enclosingClass); |
+ checkPrivateAccess(node, element, name); |
DartType constructorType = computeType(element); |
DartType newType = elements.getType(node); |
// TODO(johnniwinther): Use [:lookupMember:] to account for type variable |