| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 library fasta.scope; | |
| 6 | |
| 7 import 'builder.dart' show Builder, MixedAccessor; | |
| 8 | |
| 9 import '../errors.dart' show internalError; | |
| 10 | |
| 11 class Scope { | |
| 12 /// Names declared in this scope. | |
| 13 final Map<String, Builder> local; | |
| 14 | |
| 15 /// The scope that this scope is nested within, or `null` if this is the top | |
| 16 /// level scope. | |
| 17 final Scope parent; | |
| 18 | |
| 19 /// Indicates whether an attempt to declare new names in this scope should | |
| 20 /// succeed. | |
| 21 final bool isModifiable; | |
| 22 | |
| 23 Map<String, Builder> labels; | |
| 24 | |
| 25 Map<String, Builder> forwardDeclaredLabels; | |
| 26 | |
| 27 Scope(this.local, this.parent, {this.isModifiable: true}); | |
| 28 | |
| 29 Scope createNestedScope({bool isModifiable: true}) { | |
| 30 return new Scope(<String, Builder>{}, this, isModifiable: isModifiable); | |
| 31 } | |
| 32 | |
| 33 Builder lookup(String name, int charOffset, Uri fileUri) { | |
| 34 Builder builder = local[name]; | |
| 35 if (builder != null) { | |
| 36 if (builder.next != null) { | |
| 37 return lookupAmbiguous(name, builder, false, charOffset, fileUri); | |
| 38 } | |
| 39 return builder.isSetter | |
| 40 ? new AccessErrorBuilder(name, builder, charOffset, fileUri) | |
| 41 : builder; | |
| 42 } else { | |
| 43 return parent?.lookup(name, charOffset, fileUri); | |
| 44 } | |
| 45 } | |
| 46 | |
| 47 Builder lookupSetter(String name, int charOffset, Uri fileUri) { | |
| 48 Builder builder = local[name]; | |
| 49 if (builder != null) { | |
| 50 if (builder.next != null) { | |
| 51 return lookupAmbiguous(name, builder, true, charOffset, fileUri); | |
| 52 } | |
| 53 if (builder.isField) { | |
| 54 if (builder.isFinal) { | |
| 55 return new AccessErrorBuilder(name, builder, charOffset, fileUri); | |
| 56 } else { | |
| 57 return builder; | |
| 58 } | |
| 59 } else if (builder.isSetter) { | |
| 60 return builder; | |
| 61 } else { | |
| 62 return new AccessErrorBuilder(name, builder, charOffset, fileUri); | |
| 63 } | |
| 64 } else { | |
| 65 return parent?.lookupSetter(name, charOffset, fileUri); | |
| 66 } | |
| 67 } | |
| 68 | |
| 69 Builder lookupAmbiguous( | |
| 70 String name, Builder builder, bool setter, int charOffset, Uri fileUri) { | |
| 71 assert(builder.next != null); | |
| 72 if (builder is MixedAccessor) { | |
| 73 return setter ? builder.setter : builder.getter; | |
| 74 } | |
| 75 Builder setterBuilder; | |
| 76 Builder getterBuilder; | |
| 77 Builder current = builder; | |
| 78 while (current != null) { | |
| 79 if (current.isGetter && getterBuilder == null) { | |
| 80 getterBuilder = current; | |
| 81 } else if (current.isSetter && setterBuilder == null) { | |
| 82 setterBuilder = current; | |
| 83 } else { | |
| 84 return new AmbiguousBuilder(name, builder, charOffset, fileUri); | |
| 85 } | |
| 86 current = current.next; | |
| 87 } | |
| 88 assert(getterBuilder != null); | |
| 89 assert(setterBuilder != null); | |
| 90 return setter ? setterBuilder : getterBuilder; | |
| 91 } | |
| 92 | |
| 93 bool hasLocalLabel(String name) => labels != null && labels.containsKey(name); | |
| 94 | |
| 95 void declareLabel(String name, Builder target) { | |
| 96 if (isModifiable) { | |
| 97 labels ??= <String, Builder>{}; | |
| 98 labels[name] = target; | |
| 99 } else { | |
| 100 internalError("Can't extend an unmodifiable scope."); | |
| 101 } | |
| 102 } | |
| 103 | |
| 104 void forwardDeclareLabel(String name, Builder target) { | |
| 105 declareLabel(name, target); | |
| 106 forwardDeclaredLabels ??= <String, Builder>{}; | |
| 107 forwardDeclaredLabels[name] = target; | |
| 108 } | |
| 109 | |
| 110 void claimLabel(String name) { | |
| 111 if (forwardDeclaredLabels == null) return; | |
| 112 forwardDeclaredLabels.remove(name); | |
| 113 if (forwardDeclaredLabels.length == 0) { | |
| 114 forwardDeclaredLabels = null; | |
| 115 } | |
| 116 } | |
| 117 | |
| 118 Map<String, Builder> get unclaimedForwardDeclarations { | |
| 119 return forwardDeclaredLabels; | |
| 120 } | |
| 121 | |
| 122 Builder lookupLabel(String name) { | |
| 123 return (labels == null ? null : labels[name]) ?? parent?.lookupLabel(name); | |
| 124 } | |
| 125 | |
| 126 // TODO(ahe): Rename to extend or something. | |
| 127 void operator []=(String name, Builder member) { | |
| 128 if (isModifiable) { | |
| 129 local[name] = member; | |
| 130 } else { | |
| 131 internalError("Can't extend an unmodifiable scope."); | |
| 132 } | |
| 133 } | |
| 134 } | |
| 135 | |
| 136 abstract class ProblemBuilder extends Builder { | |
| 137 final String name; | |
| 138 | |
| 139 final Builder builder; | |
| 140 | |
| 141 ProblemBuilder(this.name, this.builder, int charOffset, Uri fileUri) | |
| 142 : super(null, charOffset, fileUri); | |
| 143 | |
| 144 get target => null; | |
| 145 | |
| 146 bool get hasProblem => true; | |
| 147 | |
| 148 String get message; | |
| 149 | |
| 150 @override | |
| 151 String get fullNameForErrors => name; | |
| 152 } | |
| 153 | |
| 154 /// Represents a [builder] that's being accessed incorrectly. For example, an | |
| 155 /// attempt to write to a final field, or to read from a setter. | |
| 156 class AccessErrorBuilder extends ProblemBuilder { | |
| 157 AccessErrorBuilder(String name, Builder builder, int charOffset, Uri fileUri) | |
| 158 : super(name, builder, charOffset, fileUri); | |
| 159 | |
| 160 Builder get parent => builder; | |
| 161 | |
| 162 bool get isFinal => builder.isFinal; | |
| 163 | |
| 164 bool get isField => builder.isField; | |
| 165 | |
| 166 bool get isRegularMethod => builder.isRegularMethod; | |
| 167 | |
| 168 bool get isGetter => !builder.isGetter; | |
| 169 | |
| 170 bool get isSetter => !builder.isSetter; | |
| 171 | |
| 172 bool get isInstanceMember => builder.isInstanceMember; | |
| 173 | |
| 174 bool get isStatic => builder.isStatic; | |
| 175 | |
| 176 bool get isTopLevel => builder.isTopLevel; | |
| 177 | |
| 178 bool get isTypeDeclaration => builder.isTypeDeclaration; | |
| 179 | |
| 180 bool get isLocal => builder.isLocal; | |
| 181 | |
| 182 String get message => "Access error: '$name'."; | |
| 183 } | |
| 184 | |
| 185 class AmbiguousBuilder extends ProblemBuilder { | |
| 186 AmbiguousBuilder(String name, Builder builder, int charOffset, Uri fileUri) | |
| 187 : super(name, builder, charOffset, fileUri); | |
| 188 | |
| 189 String get message => "Duplicated named: '$name'."; | |
| 190 } | |
| OLD | NEW |