Index: pkg/analyzer/lib/src/dart/sdk/patch.dart |
diff --git a/pkg/analyzer/lib/src/dart/sdk/patch.dart b/pkg/analyzer/lib/src/dart/sdk/patch.dart |
index 576cb96149b00c6e687877b6bb316b0cf38d9cd7..f2bfeb30cb8643607a550a3506f5dabb95d4e898 100644 |
--- a/pkg/analyzer/lib/src/dart/sdk/patch.dart |
+++ b/pkg/analyzer/lib/src/dart/sdk/patch.dart |
@@ -72,14 +72,13 @@ class SdkPatcher { |
_patchDirectives( |
source, unit, patchSource, patchUnit, addNewTopLevelDeclarations); |
- _patchTopLevelDeclarations( |
- source, unit, patchSource, patchUnit, addNewTopLevelDeclarations); |
+ _patchTopLevelDeclarations(unit, patchUnit, addNewTopLevelDeclarations); |
} |
} |
- void _failExternalKeyword(Source source, String name, int offset) { |
+ void _failExternalKeyword(String name, int offset) { |
throw new ArgumentError( |
- 'The keyword "external" was expected for "$name" in $source @ $offset.'); |
+ 'The keyword "external" was expected for "$name" in $_baseDesc @ $offset.'); |
} |
void _failIfPublicName(AstNode node, String name) { |
@@ -99,6 +98,53 @@ class SdkPatcher { |
return 'the line ${location.lineNumber}'; |
} |
+ void _patchClassMembers( |
+ ClassDeclaration baseClass, ClassDeclaration patchClass) { |
+ List<ClassMember> membersToAppend = []; |
+ for (ClassMember patchMember in patchClass.members) { |
+ if (patchMember is MethodDeclaration) { |
+ String name = patchMember.name.name; |
+ if (_hasPatchAnnotation(patchMember.metadata)) { |
+ for (ClassMember baseMember in baseClass.members) { |
+ if (baseMember is MethodDeclaration && |
+ baseMember.name.name == name) { |
+ // Remove the "external" keyword. |
Paul Berry
2016/10/13 19:09:52
It looks like we have some duplication between thi
scheglov
2016/10/13 20:18:14
It does not seem practical to me.
Both "externalKe
|
+ Token externalKeyword = baseMember.externalKeyword; |
+ if (externalKeyword != null) { |
+ baseMember.externalKeyword = null; |
+ _removeToken(externalKeyword); |
+ } else { |
+ _failExternalKeyword(name, baseMember.offset); |
+ } |
+ // Replace the body. |
+ FunctionBody oldBody = baseMember.body; |
+ FunctionBody newBody = patchMember.body; |
+ _replaceNodeTokens(oldBody, newBody); |
+ baseMember.body = newBody; |
+ } |
+ } |
+ } else { |
+ _failIfPublicName(patchMember, name); |
+ membersToAppend.add(patchMember); |
+ } |
+ } else { |
+ // TODO(scheglov) support field |
+ // TODO(scheglov) support constructors |
+ String className = patchClass.name.name; |
+ _failInPatch('contains an unsupported class member in $className', |
+ patchMember.offset); |
+ } |
+ } |
+ // Append new top-level declarations. |
+ Token lastToken = baseClass.endToken.previous; |
+ for (ClassMember newMember in membersToAppend) { |
+ newMember.endToken.setNext(lastToken.next); |
Paul Berry
2016/10/13 19:09:52
Consider extracting a method for this logic too.
scheglov
2016/10/13 20:18:14
OK
https://codereview.chromium.org/2417053002
|
+ lastToken.setNext(newMember.beginToken); |
+ baseClass.members.add(newMember); |
+ lastToken = newMember.endToken; |
+ } |
+ } |
+ |
void _patchDirectives( |
Source baseSource, |
CompilationUnit baseUnit, |
@@ -115,12 +161,8 @@ class SdkPatcher { |
} |
} |
- void _patchTopLevelDeclarations( |
- Source baseSource, |
- CompilationUnit baseUnit, |
- Source patchSource, |
- CompilationUnit patchUnit, |
- bool addNewTopLevelDeclarations) { |
+ void _patchTopLevelDeclarations(CompilationUnit baseUnit, |
+ CompilationUnit patchUnit, bool addNewTopLevelDeclarations) { |
List<CompilationUnitMember> declarationsToAppend = []; |
for (CompilationUnitMember patchDeclaration in patchUnit.declarations) { |
if (patchDeclaration is FunctionDeclaration) { |
@@ -130,22 +172,19 @@ class SdkPatcher { |
if (patchDeclaration is FunctionDeclaration && |
baseDeclaration is FunctionDeclaration && |
baseDeclaration.name.name == name) { |
- if (_hasPatchAnnotation(patchDeclaration.metadata)) { |
- // Remove the "external" keyword. |
- Token externalKeyword = baseDeclaration.externalKeyword; |
- if (externalKeyword != null) { |
- baseDeclaration.externalKeyword = null; |
- _removeToken(externalKeyword); |
- } else { |
- _failExternalKeyword( |
- baseSource, name, baseDeclaration.offset); |
- } |
- // Replace the body. |
- FunctionExpression oldExpr = baseDeclaration.functionExpression; |
- FunctionBody newBody = patchDeclaration.functionExpression.body; |
- _replaceNodeTokens(oldExpr.body, newBody); |
- oldExpr.body = newBody; |
+ // Remove the "external" keyword. |
+ Token externalKeyword = baseDeclaration.externalKeyword; |
+ if (externalKeyword != null) { |
+ baseDeclaration.externalKeyword = null; |
+ _removeToken(externalKeyword); |
+ } else { |
+ _failExternalKeyword(name, baseDeclaration.offset); |
} |
+ // Replace the body. |
+ FunctionExpression oldExpr = baseDeclaration.functionExpression; |
+ FunctionBody newBody = patchDeclaration.functionExpression.body; |
+ _replaceNodeTokens(oldExpr.body, newBody); |
+ oldExpr.body = newBody; |
} |
} |
} else if (addNewTopLevelDeclarations) { |
@@ -159,6 +198,19 @@ class SdkPatcher { |
} |
_failIfPublicName(patchDeclaration, patchDeclaration.name.name); |
declarationsToAppend.add(patchDeclaration); |
+ } else if (patchDeclaration is ClassDeclaration) { |
+ if (_hasPatchAnnotation(patchDeclaration.metadata)) { |
+ String name = patchDeclaration.name.name; |
+ for (CompilationUnitMember baseDeclaration in baseUnit.declarations) { |
+ if (baseDeclaration is ClassDeclaration && |
+ baseDeclaration.name.name == name) { |
+ _patchClassMembers(baseDeclaration, patchDeclaration); |
+ } |
+ } |
+ } else { |
+ _failIfPublicName(patchDeclaration, patchDeclaration.name.name); |
+ declarationsToAppend.add(patchDeclaration); |
+ } |
} else { |
_failInPatch('contains an unsupported top-level declaration', |
patchDeclaration.offset); |