| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 library kernel.checks; | 4 library kernel.checks; |
| 5 | 5 |
| 6 import 'ast.dart'; | 6 import 'ast.dart'; |
| 7 import 'transformations/flags.dart'; | 7 import 'transformations/flags.dart'; |
| 8 | 8 |
| 9 void verifyProgram(Program program) { | 9 void verifyProgram(Program program) { |
| 10 VerifyingVisitor.check(program); | 10 VerifyingVisitor.check(program); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 final List<VariableDeclaration> variableStack = <VariableDeclaration>[]; | 50 final List<VariableDeclaration> variableStack = <VariableDeclaration>[]; |
| 51 final Map<Typedef, TypedefState> typedefState = <Typedef, TypedefState>{}; | 51 final Map<Typedef, TypedefState> typedefState = <Typedef, TypedefState>{}; |
| 52 bool classTypeParametersAreInScope = false; | 52 bool classTypeParametersAreInScope = false; |
| 53 | 53 |
| 54 /// If true, relax certain checks for *outline* mode. For example, don't | 54 /// If true, relax certain checks for *outline* mode. For example, don't |
| 55 /// attempt to validate constructor initializers. | 55 /// attempt to validate constructor initializers. |
| 56 bool isOutline = false; | 56 bool isOutline = false; |
| 57 | 57 |
| 58 bool inCatchBlock = false; | 58 bool inCatchBlock = false; |
| 59 | 59 |
| 60 Library currentLibrary; |
| 61 |
| 60 Member currentMember; | 62 Member currentMember; |
| 63 |
| 61 Class currentClass; | 64 Class currentClass; |
| 65 |
| 62 TreeNode currentParent; | 66 TreeNode currentParent; |
| 63 | 67 |
| 64 TreeNode get context => currentMember ?? currentClass; | 68 TreeNode get context => currentMember ?? currentClass; |
| 65 | 69 |
| 66 static void check(Program program) { | 70 static void check(Program program) { |
| 67 program.accept(new VerifyingVisitor()); | 71 program.accept(new VerifyingVisitor()); |
| 68 } | 72 } |
| 69 | 73 |
| 70 defaultTreeNode(TreeNode node) { | 74 defaultTreeNode(TreeNode node) { |
| 71 visitChildren(node); | 75 visitChildren(node); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 180 for (var library in program.libraries) { | 184 for (var library in program.libraries) { |
| 181 library.members.forEach(undeclareMember); | 185 library.members.forEach(undeclareMember); |
| 182 for (var class_ in library.classes) { | 186 for (var class_ in library.classes) { |
| 183 class_.members.forEach(undeclareMember); | 187 class_.members.forEach(undeclareMember); |
| 184 } | 188 } |
| 185 } | 189 } |
| 186 variableStack.forEach(undeclareVariable); | 190 variableStack.forEach(undeclareVariable); |
| 187 } | 191 } |
| 188 } | 192 } |
| 189 | 193 |
| 194 void visitLibrary(Library node) { |
| 195 currentLibrary = node; |
| 196 super.visitLibrary(node); |
| 197 currentLibrary = null; |
| 198 } |
| 199 |
| 190 void checkTypedef(Typedef node) { | 200 void checkTypedef(Typedef node) { |
| 191 var state = typedefState[node]; | 201 var state = typedefState[node]; |
| 192 if (state == TypedefState.Done) return; | 202 if (state == TypedefState.Done) return; |
| 193 if (state == TypedefState.BeingChecked) { | 203 if (state == TypedefState.BeingChecked) { |
| 194 problem(node, "The typedef '$node' refers to itself", context: node); | 204 problem(node, "The typedef '$node' refers to itself", context: node); |
| 195 } | 205 } |
| 196 assert(state == null); | 206 assert(state == null); |
| 197 typedefState[node] = TypedefState.BeingChecked; | 207 typedefState[node] = TypedefState.BeingChecked; |
| 198 var savedTypeParameters = typeParametersInScope; | 208 var savedTypeParameters = typeParametersInScope; |
| 199 typeParametersInScope = node.typeParameters.toSet(); | 209 typeParametersInScope = node.typeParameters.toSet(); |
| 200 var savedParent = currentParent; | 210 var savedParent = currentParent; |
| 201 currentParent = node; | 211 currentParent = node; |
| 202 // Visit children without checking the parent pointer on the typedef itself | 212 // Visit children without checking the parent pointer on the typedef itself |
| 203 // since this can be called from a context other than its true parent. | 213 // since this can be called from a context other than its true parent. |
| 204 node.visitChildren(this); | 214 node.visitChildren(this); |
| 205 currentParent = savedParent; | 215 currentParent = savedParent; |
| 206 typeParametersInScope = savedTypeParameters; | 216 typeParametersInScope = savedTypeParameters; |
| 207 typedefState[node] = TypedefState.Done; | 217 typedefState[node] = TypedefState.Done; |
| 208 } | 218 } |
| 209 | 219 |
| 210 visitTypedef(Typedef node) { | 220 visitTypedef(Typedef node) { |
| 211 checkTypedef(node); | 221 checkTypedef(node); |
| 212 // Enter and exit the node to check the parent pointer on the typedef node. | 222 // Enter and exit the node to check the parent pointer on the typedef node. |
| 213 exitParent(enterParent(node)); | 223 exitParent(enterParent(node)); |
| 214 } | 224 } |
| 215 | 225 |
| 216 visitField(Field node) { | 226 visitField(Field node) { |
| 217 currentMember = node; | 227 currentMember = node; |
| 218 var oldParent = enterParent(node); | 228 var oldParent = enterParent(node); |
| 229 bool isTopLevel = node.parent == currentLibrary; |
| 230 if (isTopLevel && !node.isStatic) { |
| 231 problem(node, "The top-level field '${node.name.name}' should be static", |
| 232 context: node); |
| 233 } |
| 234 if (node.isConst && !node.isStatic) { |
| 235 problem(node, "The const field '${node.name.name}' should be static", |
| 236 context: node); |
| 237 } |
| 219 classTypeParametersAreInScope = !node.isStatic; | 238 classTypeParametersAreInScope = !node.isStatic; |
| 220 node.initializer?.accept(this); | 239 node.initializer?.accept(this); |
| 221 node.type.accept(this); | 240 node.type.accept(this); |
| 222 classTypeParametersAreInScope = false; | 241 classTypeParametersAreInScope = false; |
| 223 visitList(node.annotations, this); | 242 visitList(node.annotations, this); |
| 224 exitParent(oldParent); | 243 exitParent(oldParent); |
| 225 currentMember = null; | 244 currentMember = null; |
| 226 } | 245 } |
| 227 | 246 |
| 228 visitProcedure(Procedure node) { | 247 visitProcedure(Procedure node) { |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 601 var oldParent = parent; | 620 var oldParent = parent; |
| 602 parent = node; | 621 parent = node; |
| 603 node.visitChildren(this); | 622 node.visitChildren(this); |
| 604 parent = oldParent; | 623 parent = oldParent; |
| 605 } | 624 } |
| 606 } | 625 } |
| 607 | 626 |
| 608 void checkInitializers(Constructor constructor) { | 627 void checkInitializers(Constructor constructor) { |
| 609 // TODO(ahe): I'll add more here in other CLs. | 628 // TODO(ahe): I'll add more here in other CLs. |
| 610 } | 629 } |
| OLD | NEW |