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 |