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

Side by Side Diff: pkg/analyzer/lib/src/dart/sdk/patch.dart

Issue 2413293002: Patch token stream when replace/add nodes. (Closed)
Patch Set: Created 4 years, 2 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 unified diff | Download patch
« no previous file with comments | « no previous file | pkg/analyzer/test/src/dart/sdk/patch_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 4
5 library analyzer.src.dart.sdk.patch; 5 library analyzer.src.dart.sdk.patch;
6 6
7 import 'package:analyzer/dart/ast/ast.dart'; 7 import 'package:analyzer/dart/ast/ast.dart';
8 import 'package:analyzer/dart/ast/token.dart'; 8 import 'package:analyzer/dart/ast/token.dart';
9 import 'package:analyzer/error/listener.dart'; 9 import 'package:analyzer/error/listener.dart';
10 import 'package:analyzer/file_system/file_system.dart'; 10 import 'package:analyzer/file_system/file_system.dart';
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 for (CompilationUnitMember patchDeclaration in patchUnit.declarations) { 125 for (CompilationUnitMember patchDeclaration in patchUnit.declarations) {
126 if (patchDeclaration is FunctionDeclaration) { 126 if (patchDeclaration is FunctionDeclaration) {
127 String name = patchDeclaration.name.name; 127 String name = patchDeclaration.name.name;
128 if (_hasPatchAnnotation(patchDeclaration.metadata)) { 128 if (_hasPatchAnnotation(patchDeclaration.metadata)) {
129 for (CompilationUnitMember baseDeclaration in baseUnit.declarations) { 129 for (CompilationUnitMember baseDeclaration in baseUnit.declarations) {
130 if (patchDeclaration is FunctionDeclaration && 130 if (patchDeclaration is FunctionDeclaration &&
131 baseDeclaration is FunctionDeclaration && 131 baseDeclaration is FunctionDeclaration &&
132 baseDeclaration.name.name == name) { 132 baseDeclaration.name.name == name) {
133 if (_hasPatchAnnotation(patchDeclaration.metadata)) { 133 if (_hasPatchAnnotation(patchDeclaration.metadata)) {
134 // Remove the "external" keyword. 134 // Remove the "external" keyword.
135 if (baseDeclaration.externalKeyword != null) { 135 Token externalKeyword = baseDeclaration.externalKeyword;
136 if (externalKeyword != null) {
136 baseDeclaration.externalKeyword = null; 137 baseDeclaration.externalKeyword = null;
138 _removeToken(externalKeyword);
137 } else { 139 } else {
138 _failExternalKeyword( 140 _failExternalKeyword(
139 baseSource, name, baseDeclaration.offset); 141 baseSource, name, baseDeclaration.offset);
140 } 142 }
141 // Replace the body. 143 // Replace the body.
142 baseDeclaration.functionExpression.body = 144 FunctionExpression oldExpr = baseDeclaration.functionExpression;
143 patchDeclaration.functionExpression.body; 145 FunctionBody newBody = patchDeclaration.functionExpression.body;
146 _replaceNodeTokens(oldExpr.body, newBody);
147 oldExpr.body = newBody;
144 } 148 }
145 } 149 }
146 } 150 }
147 } else if (addNewTopLevelDeclarations) { 151 } else if (addNewTopLevelDeclarations) {
148 _failIfPublicName(patchDeclaration, name); 152 _failIfPublicName(patchDeclaration, name);
149 declarationsToAppend.add(patchDeclaration); 153 declarationsToAppend.add(patchDeclaration);
150 } 154 }
151 } else if (patchDeclaration is FunctionTypeAlias) { 155 } else if (patchDeclaration is FunctionTypeAlias) {
152 if (patchDeclaration.metadata.isNotEmpty) { 156 if (patchDeclaration.metadata.isNotEmpty) {
153 _failInPatch('contains a function type alias with an annotation', 157 _failInPatch('contains a function type alias with an annotation',
154 patchDeclaration.offset); 158 patchDeclaration.offset);
155 } 159 }
156 _failIfPublicName(patchDeclaration, patchDeclaration.name.name); 160 _failIfPublicName(patchDeclaration, patchDeclaration.name.name);
157 declarationsToAppend.add(patchDeclaration); 161 declarationsToAppend.add(patchDeclaration);
158 } else { 162 } else {
159 _failInPatch('contains an unsupported top-level declaration', 163 _failInPatch('contains an unsupported top-level declaration',
160 patchDeclaration.offset); 164 patchDeclaration.offset);
161 } 165 }
162 } 166 }
163 // Append new top-level declarations. 167 // Append new top-level declarations.
164 baseUnit.declarations.addAll(declarationsToAppend); 168 Token lastToken = baseUnit.endToken.previous;
169 for (CompilationUnitMember newDeclaration in declarationsToAppend) {
170 newDeclaration.endToken.setNext(lastToken.next);
171 lastToken.setNext(newDeclaration.beginToken);
172 baseUnit.declarations.add(newDeclaration);
173 lastToken = newDeclaration.endToken;
174 }
165 } 175 }
166 176
167 /** 177 /**
168 * Parse the given [source] into AST. 178 * Parse the given [source] into AST.
169 */ 179 */
170 @visibleForTesting 180 @visibleForTesting
171 static CompilationUnit parse( 181 static CompilationUnit parse(
172 Source source, bool strong, AnalysisErrorListener errorListener) { 182 Source source, bool strong, AnalysisErrorListener errorListener) {
173 String code = source.contents.data; 183 String code = source.contents.data;
174 184
(...skipping 14 matching lines...) Expand all
189 * Return `true` if [metadata] has the `@patch` annotation. 199 * Return `true` if [metadata] has the `@patch` annotation.
190 */ 200 */
191 static bool _hasPatchAnnotation(List<Annotation> metadata) { 201 static bool _hasPatchAnnotation(List<Annotation> metadata) {
192 return metadata.any((annotation) { 202 return metadata.any((annotation) {
193 Identifier name = annotation.name; 203 Identifier name = annotation.name;
194 return annotation.constructorName == null && 204 return annotation.constructorName == null &&
195 name is SimpleIdentifier && 205 name is SimpleIdentifier &&
196 name.name == 'patch'; 206 name.name == 'patch';
197 }); 207 });
198 } 208 }
209
210 /**
211 * Remove the [token] from the stream.
212 */
213 static void _removeToken(Token token) {
214 token.previous.setNext(token.next);
215 }
216
217 /**
218 * Replace tokens of the [oldNode] with tokens of the [newNode].
219 */
220 static void _replaceNodeTokens(AstNode oldNode, AstNode newNode) {
221 oldNode.beginToken.previous.setNext(newNode.beginToken);
222 newNode.endToken.setNext(oldNode.endToken.next);
223 }
199 } 224 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/test/src/dart/sdk/patch_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698