| 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 | 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 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 } | 190 } |
| 191 membersToAppend.add(patchMember); | 191 membersToAppend.add(patchMember); |
| 192 } | 192 } |
| 193 } else { | 193 } else { |
| 194 // TODO(scheglov) support field | 194 // TODO(scheglov) support field |
| 195 String className = patchClass.name.name; | 195 String className = patchClass.name.name; |
| 196 _failInPatch('contains an unsupported class member in $className', | 196 _failInPatch('contains an unsupported class member in $className', |
| 197 patchMember.offset); | 197 patchMember.offset); |
| 198 } | 198 } |
| 199 } | 199 } |
| 200 // Append new top-level declarations. | 200 // Append new class members. |
| 201 Token lastToken = baseClass.endToken.previous; | 201 _appendToNodeList( |
| 202 for (ClassMember newMember in membersToAppend) { | 202 baseClass.members, membersToAppend, baseClass.leftBracket); |
| 203 newMember.endToken.setNext(lastToken.next); | |
| 204 lastToken.setNext(newMember.beginToken); | |
| 205 baseClass.members.add(newMember); | |
| 206 lastToken = newMember.endToken; | |
| 207 } | |
| 208 } | 203 } |
| 209 | 204 |
| 210 void _patchDirectives( | 205 void _patchDirectives( |
| 211 Source baseSource, | 206 Source baseSource, |
| 212 CompilationUnit baseUnit, | 207 CompilationUnit baseUnit, |
| 213 Source patchSource, | 208 Source patchSource, |
| 214 CompilationUnit patchUnit, | 209 CompilationUnit patchUnit, |
| 215 bool addNewTopLevelDeclarations) { | 210 bool addNewTopLevelDeclarations) { |
| 216 for (Directive patchDirective in patchUnit.directives) { | 211 for (Directive patchDirective in patchUnit.directives) { |
| 217 if (patchDirective is ImportDirective) { | 212 if (patchDirective is ImportDirective) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 } else { | 267 } else { |
| 273 _failIfPublicName(patchDeclaration, patchDeclaration.name.name); | 268 _failIfPublicName(patchDeclaration, patchDeclaration.name.name); |
| 274 declarationsToAppend.add(patchDeclaration); | 269 declarationsToAppend.add(patchDeclaration); |
| 275 } | 270 } |
| 276 } else { | 271 } else { |
| 277 _failInPatch('contains an unsupported top-level declaration', | 272 _failInPatch('contains an unsupported top-level declaration', |
| 278 patchDeclaration.offset); | 273 patchDeclaration.offset); |
| 279 } | 274 } |
| 280 } | 275 } |
| 281 // Append new top-level declarations. | 276 // Append new top-level declarations. |
| 282 Token lastToken = baseUnit.endToken.previous; | 277 _appendToNodeList(baseUnit.declarations, declarationsToAppend, |
| 283 for (CompilationUnitMember newDeclaration in declarationsToAppend) { | 278 baseUnit.endToken.previous); |
| 284 newDeclaration.endToken.setNext(lastToken.next); | |
| 285 lastToken.setNext(newDeclaration.beginToken); | |
| 286 baseUnit.declarations.add(newDeclaration); | |
| 287 lastToken = newDeclaration.endToken; | |
| 288 } | |
| 289 } | 279 } |
| 290 | 280 |
| 291 /** | 281 /** |
| 292 * Parse the given [source] into AST. | 282 * Parse the given [source] into AST. |
| 293 */ | 283 */ |
| 294 @visibleForTesting | 284 @visibleForTesting |
| 295 static CompilationUnit parse( | 285 static CompilationUnit parse( |
| 296 Source source, bool strong, AnalysisErrorListener errorListener) { | 286 Source source, bool strong, AnalysisErrorListener errorListener) { |
| 297 String code = source.contents.data; | 287 String code = source.contents.data; |
| 298 | 288 |
| 299 CharSequenceReader reader = new CharSequenceReader(code); | 289 CharSequenceReader reader = new CharSequenceReader(code); |
| 300 Scanner scanner = new Scanner(source, reader, errorListener); | 290 Scanner scanner = new Scanner(source, reader, errorListener); |
| 301 scanner.scanGenericMethodComments = strong; | 291 scanner.scanGenericMethodComments = strong; |
| 302 Token token = scanner.tokenize(); | 292 Token token = scanner.tokenize(); |
| 303 LineInfo lineInfo = new LineInfo(scanner.lineStarts); | 293 LineInfo lineInfo = new LineInfo(scanner.lineStarts); |
| 304 | 294 |
| 305 Parser parser = new Parser(source, errorListener); | 295 Parser parser = new Parser(source, errorListener); |
| 306 parser.parseGenericMethodComments = strong; | 296 parser.parseGenericMethodComments = strong; |
| 307 CompilationUnit unit = parser.parseCompilationUnit(token); | 297 CompilationUnit unit = parser.parseCompilationUnit(token); |
| 308 unit.lineInfo = lineInfo; | 298 unit.lineInfo = lineInfo; |
| 309 return unit; | 299 return unit; |
| 310 } | 300 } |
| 311 | 301 |
| 312 /** | 302 /** |
| 303 * Append [newNodes] to the given [nodes] and attach new tokens to the end |
| 304 * token of the last [nodes] items, or, if it is empty, to [defaultPrevToken]. |
| 305 */ |
| 306 static void _appendToNodeList( |
| 307 NodeList<AstNode> nodes, List<AstNode> newNodes, Token defaultPrevToken) { |
| 308 Token prevToken = nodes.endToken ?? defaultPrevToken; |
| 309 for (AstNode newNode in newNodes) { |
| 310 newNode.endToken.setNext(prevToken.next); |
| 311 prevToken.setNext(newNode.beginToken); |
| 312 nodes.add(newNode); |
| 313 prevToken = newNode.endToken; |
| 314 } |
| 315 } |
| 316 |
| 317 /** |
| 313 * Return `true` if [metadata] has the `@patch` annotation. | 318 * Return `true` if [metadata] has the `@patch` annotation. |
| 314 */ | 319 */ |
| 315 static bool _hasPatchAnnotation(List<Annotation> metadata) { | 320 static bool _hasPatchAnnotation(List<Annotation> metadata) { |
| 316 return metadata.any((annotation) { | 321 return metadata.any((annotation) { |
| 317 Identifier name = annotation.name; | 322 Identifier name = annotation.name; |
| 318 return annotation.constructorName == null && | 323 return annotation.constructorName == null && |
| 319 name is SimpleIdentifier && | 324 name is SimpleIdentifier && |
| 320 name.name == 'patch'; | 325 name.name == 'patch'; |
| 321 }); | 326 }); |
| 322 } | 327 } |
| 323 | 328 |
| 324 /** | 329 /** |
| 325 * Remove the [token] from the stream. | 330 * Remove the [token] from the stream. |
| 326 */ | 331 */ |
| 327 static void _removeToken(Token token) { | 332 static void _removeToken(Token token) { |
| 328 token.previous.setNext(token.next); | 333 token.previous.setNext(token.next); |
| 329 } | 334 } |
| 330 | 335 |
| 331 /** | 336 /** |
| 332 * Replace tokens of the [oldNode] with tokens of the [newNode]. | 337 * Replace tokens of the [oldNode] with tokens of the [newNode]. |
| 333 */ | 338 */ |
| 334 static void _replaceNodeTokens(AstNode oldNode, AstNode newNode) { | 339 static void _replaceNodeTokens(AstNode oldNode, AstNode newNode) { |
| 335 oldNode.beginToken.previous.setNext(newNode.beginToken); | 340 oldNode.beginToken.previous.setNext(newNode.beginToken); |
| 336 newNode.endToken.setNext(oldNode.endToken.next); | 341 newNode.endToken.setNext(oldNode.endToken.next); |
| 337 } | 342 } |
| 338 } | 343 } |
| OLD | NEW |