Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(851)

Unified Diff: pkg/kernel/lib/verifier.dart

Issue 2620133004: Report problems through a method. (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/kernel/lib/verifier.dart
diff --git a/pkg/kernel/lib/verifier.dart b/pkg/kernel/lib/verifier.dart
index b2ceb9cf7f0a9cef5248ad3a01b7cfdc0980c41e..2600f8dbf08bfd201b3e9aba0a3c377356974d45 100644
--- a/pkg/kernel/lib/verifier.dart
+++ b/pkg/kernel/lib/verifier.dart
@@ -10,6 +10,33 @@ void verifyProgram(Program program) {
VerifyingVisitor.check(program);
}
+class VerificationError {
+ final TreeNode context;
+
+ final TreeNode node;
+
+ final String details;
+
+ VerificationError(this.context, this.node, this.details);
+
+ toString() {
+ Location location;
+ try {
+ location = node?.location ?? context?.location;
+ } catch (_) {
+ // TODO(ahe): Fix the compiler instead.
+ }
+ if (location != null) {
+ String file = location.file ?? "";
+ return "$file:${location.line}:${location.column}: Verification error:"
+ " $details";
+ } else {
+ return
+ "Verification error: $details\nContext: '$context'.\nNode: '$node'.";
+ }
+ }
+}
+
/// Checks that a kernel program is well-formed.
///
/// This does not include any kind of type checking.
@@ -37,11 +64,15 @@ class VerifyingVisitor extends RecursiveVisitor {
visitChildren(node);
}
+ problem(TreeNode node, String details) {
+ throw new VerificationError(context, node, details);
+ }
+
TreeNode enterParent(TreeNode node) {
if (!identical(node.parent, currentParent)) {
- throw 'Incorrect parent pointer on ${node.runtimeType} in $context. '
- 'Parent pointer is ${node.parent.runtimeType}, '
- 'actual parent is ${currentParent.runtimeType}.';
+ problem(node,
+ "Incorrect parent pointer: expected '${node.parent.runtimeType}',"
+ " but found: '${currentParent.runtimeType}'.");
}
var oldParent = currentParent;
currentParent = node;
@@ -75,7 +106,8 @@ class VerifyingVisitor extends RecursiveVisitor {
void declareMember(Member member) {
if (member.transformerFlags & TransformerFlag.seenByVerifier != 0) {
- throw '$member has been declared more than once (${member.location})';
+ problem(member.function,
+ "Member '$member' has been declared more than once.");
}
member.transformerFlags |= TransformerFlag.seenByVerifier;
}
@@ -86,7 +118,7 @@ class VerifyingVisitor extends RecursiveVisitor {
void declareVariable(VariableDeclaration variable) {
if (variable.flags & VariableDeclaration.FlagInScope != 0) {
- throw '$variable declared more than once (${variable.location})';
+ problem(variable, "Variable '$variable' declared more than once.");
}
variable.flags |= VariableDeclaration.FlagInScope;
variableStack.add(variable);
@@ -100,7 +132,7 @@ class VerifyingVisitor extends RecursiveVisitor {
for (int i = 0; i < parameters.length; ++i) {
var parameter = parameters[i];
if (!typeParameters.add(parameter)) {
- throw 'Type parameter $parameter redeclared in $context';
+ problem(parameter, "Type parameter '$parameter' redeclared.");
}
}
}
@@ -111,8 +143,7 @@ class VerifyingVisitor extends RecursiveVisitor {
void checkVariableInScope(VariableDeclaration variable, TreeNode where) {
if (variable.flags & VariableDeclaration.FlagInScope == 0) {
- throw 'Variable $variable used out of scope in $context '
- '(${where.location})';
+ problem(where, "Variable '$variable' used out of scope.");
}
}
@@ -121,7 +152,7 @@ class VerifyingVisitor extends RecursiveVisitor {
for (var library in program.libraries) {
for (var class_ in library.classes) {
if (!classes.add(class_)) {
- throw 'Class $class_ declared more than once.';
+ problem(class_, "Class '$class_' declared more than once.");
}
}
library.members.forEach(declareMember);
@@ -208,8 +239,8 @@ class VerifyingVisitor extends RecursiveVisitor {
visitFunctionType(FunctionType node) {
for (int i = 1; i < node.namedParameters.length; ++i) {
if (node.namedParameters[i - 1].compareTo(node.namedParameters[i]) >= 0) {
- throw 'Named parameters are not sorted on function type found in '
- '$context';
+ problem(currentParent,
+ "Named parameters are not sorted on function type ($node).");
}
}
declareTypeParameters(node.typeParameters);
@@ -260,13 +291,13 @@ class VerifyingVisitor extends RecursiveVisitor {
visitStaticGet(StaticGet node) {
visitChildren(node);
if (node.target == null) {
- throw 'StaticGet without target found in $context.';
+ problem(node, "StaticGet without target.");
}
if (!node.target.hasGetter) {
- throw 'StaticGet to ${node.target} without getter found in $context';
+ problem(node, "StaticGet of '${node.target}' without getter.");
}
if (node.target.isInstanceMember) {
- throw 'StaticGet to ${node.target} that is not static found in $context';
+ problem(node, "StaticGet of '${node.target}' that's an instance member.");
}
}
@@ -274,34 +305,49 @@ class VerifyingVisitor extends RecursiveVisitor {
visitStaticSet(StaticSet node) {
visitChildren(node);
if (node.target == null) {
- throw 'StaticSet without target found in $context.';
+ problem(node, "StaticSet without target.");
}
if (!node.target.hasSetter) {
- throw 'StaticSet to ${node.target} without setter found in $context';
+ problem(node, "StaticSet to '${node.target}' without setter.");
}
if (node.target.isInstanceMember) {
- throw 'StaticSet to ${node.target} that is not static found in $context';
+ problem(node, "StaticSet to '${node.target}' that's an instance member.");
}
}
@override
visitStaticInvocation(StaticInvocation node) {
+ checkTargetedInvocation(node.target, node);
+ if (node.target.isInstanceMember) {
+ problem(node,
+ "StaticInvocation of '${node.target}' that's an instance member.");
+ }
+ if (node.isConst &&
+ (!node.target.isConst || !node.target.isExternal ||
+ node.target.kind != ProcedureKind.Factory)) {
+ problem(node, "Constant StaticInvocation of '${node.target}' that isn't"
+ " a const external factory.");
+ }
+ }
+
+ void checkTargetedInvocation(Member target, InvocationExpression node) {
visitChildren(node);
- if (node.target == null) {
- throw 'StaticInvocation without target found in $context.';
+ if (target == null) {
+ problem(node, "${node.runtimeType} without target.");
}
- if (node.target.isInstanceMember) {
- throw 'StaticInvocation to ${node.target} that is not static found in '
- '$context';
+ if (target.function == null) {
+ problem(node, "${node.runtimeType} without function.");
}
- if (!areArgumentsCompatible(node.arguments, node.target.function)) {
- throw 'StaticInvocation with incompatible arguments to '
- '${node.target} found in $context';
+ if (!areArgumentsCompatible(node.arguments, target.function)) {
+ problem(node,
+ "${node.runtimeType} with incompatible arguments for '${target}'.");
}
- if (node.arguments.types.length !=
- node.target.function.typeParameters.length) {
- throw 'Wrong number of type arguments provided in StaticInvocation '
- 'to ${node.target} found in $context';
+ int expectedTypeParameters = target is Constructor
+ ? target.enclosingClass.typeParameters.length
+ : target.function.typeParameters.length;
+ if (node.arguments.types.length != expectedTypeParameters) {
+ problem(node, "${node.runtimeType} with wrong number of type arguments"
+ " for '${target}'.");
}
}
@@ -309,15 +355,14 @@ class VerifyingVisitor extends RecursiveVisitor {
visitDirectPropertyGet(DirectPropertyGet node) {
visitChildren(node);
if (node.target == null) {
- throw 'DirectPropertyGet without target found in $context.';
+ problem(node, "DirectPropertyGet without target.");
}
if (!node.target.hasGetter) {
- throw 'DirectPropertyGet to ${node.target} without getter found in '
- '$context';
+ problem(node, "DirectPropertyGet of '${node.target}' without getter.");
}
if (!node.target.isInstanceMember) {
- throw 'DirectPropertyGet to ${node.target} that is static found in '
- '$context';
+ problem(node, "DirectPropertyGet of '${node.target}' that isn't an"
+ " instance member.");
}
}
@@ -325,56 +370,33 @@ class VerifyingVisitor extends RecursiveVisitor {
visitDirectPropertySet(DirectPropertySet node) {
visitChildren(node);
if (node.target == null) {
- throw 'DirectPropertySet without target found in $context.';
+ problem(node, "DirectPropertySet without target.");
}
if (!node.target.hasSetter) {
- throw 'DirectPropertyGet to ${node.target} without setter found in '
- '$context';
+ problem(node, "DirectPropertySet of '${node.target}' without setter.");
}
if (!node.target.isInstanceMember) {
- throw 'DirectPropertySet to ${node.target} that is static found in '
- '$context';
+ problem(node, "DirectPropertySet of '${node.target}' that is static.");
}
}
@override
visitDirectMethodInvocation(DirectMethodInvocation node) {
- visitChildren(node);
- if (node.target == null) {
- throw 'DirectMethodInvocation without target found in $context.';
- }
- if (!node.target.isInstanceMember) {
- throw 'DirectMethodInvocation to ${node.target} that is static found in '
- '$context';
- }
- if (!areArgumentsCompatible(node.arguments, node.target.function)) {
- throw 'DirectMethodInvocation with incompatible arguments to '
- '${node.target} found in $context';
- }
- if (node.arguments.types.length !=
- node.target.function.typeParameters.length) {
- throw 'Wrong number of type arguments provided in DirectMethodInvocation '
- 'to ${node.target} found in $context';
+ checkTargetedInvocation(node.target, node);
+ if (node.receiver == null) {
+ problem(node, "DirectMethodInvocation without receiver.");
}
}
@override
visitConstructorInvocation(ConstructorInvocation node) {
- visitChildren(node);
- if (node.target == null) {
- throw 'ConstructorInvocation without target found in $context.';
- }
+ checkTargetedInvocation(node.target, node);
if (node.target.enclosingClass.isAbstract) {
- throw 'ConstructorInvocation to abstract class found in $context';
- }
- if (!areArgumentsCompatible(node.arguments, node.target.function)) {
- throw 'ConstructorInvocation with incompatible arguments to '
- '${node.target} found in $context';
+ problem(node, "ConstructorInvocation of abstract class.");
}
- if (node.arguments.types.length !=
- node.target.enclosingClass.typeParameters.length) {
- throw 'Wrong number of type arguments provided in ConstructorInvocation '
- 'to ${node.target} found in $context';
+ if (node.isConst && !node.target.isConst) {
+ problem(node, "Constant ConstructorInvocation fo '${node.target}' that"
+ " isn't const.");
}
}
@@ -400,16 +422,16 @@ class VerifyingVisitor extends RecursiveVisitor {
@override
defaultMemberReference(Member node) {
if (node.transformerFlags & TransformerFlag.seenByVerifier == 0) {
- throw 'Dangling reference to $node found in $context.\n'
- 'Parent pointer is set to ${node.parent}';
+ problem(node,
+ "Dangling reference to '$node', parent is: '${node.parent}'.");
}
}
@override
visitClassReference(Class node) {
if (!classes.contains(node)) {
- throw 'Dangling reference to $node found in $context.\n'
- 'Parent pointer is set to ${node.parent}';
+ problem(node,
+ "Dangling reference to '$node', parent is: '${node.parent}'.");
}
}
@@ -417,13 +439,12 @@ class VerifyingVisitor extends RecursiveVisitor {
visitTypeParameterType(TypeParameterType node) {
var parameter = node.parameter;
if (!typeParameters.contains(parameter)) {
- throw 'Type parameter $parameter referenced out of scope in $context.\n'
- 'Parent pointer is set to ${parameter.parent}';
+ problem(currentParent, "Type parameter '$parameter' referenced out of"
+ " scope, parent is: '${parameter.parent}'.");
}
if (parameter.parent is Class && !classTypeParametersAreInScope) {
- throw 'Type parameter $parameter referenced from static context '
- 'in $context.\n'
- 'Parent pointer is set to ${parameter.parent}';
+ problem(currentParent, "Type parameter '$parameter' referenced from"
+ " static context, parent is '${parameter.parent}'.");
}
}
@@ -431,9 +452,9 @@ class VerifyingVisitor extends RecursiveVisitor {
visitInterfaceType(InterfaceType node) {
node.visitChildren(this);
if (node.typeArguments.length != node.classNode.typeParameters.length) {
- throw 'Type $node provides ${node.typeArguments.length} type arguments '
- 'but the class declares ${node.classNode.typeParameters.length} '
- 'parameters. Found in $context.';
+ problem(currentParent, "Type $node provides ${node.typeArguments.length}"
+ " type arguments but the class declares"
+ " ${node.classNode.typeParameters.length} parameters.");
}
}
}
@@ -449,9 +470,10 @@ class CheckParentPointers extends Visitor {
defaultTreeNode(TreeNode node) {
if (node.parent != parent) {
- throw 'Parent pointer on ${node.runtimeType} '
- 'is ${node.parent.runtimeType} '
- 'but should be ${parent.runtimeType}';
+ throw new VerificationError(parent, node,
+ "Parent pointer on '${node.runtimeType}' "
+ "is '${node.parent.runtimeType}' "
+ "but should be '${parent.runtimeType}'.");
}
var oldParent = parent;
parent = node;
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698