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

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

Issue 2405383002: Patch imports and function type aliases. Report more errors. (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';
11 import 'package:analyzer/src/dart/scanner/reader.dart'; 11 import 'package:analyzer/src/dart/scanner/reader.dart';
12 import 'package:analyzer/src/dart/scanner/scanner.dart'; 12 import 'package:analyzer/src/dart/scanner/scanner.dart';
13 import 'package:analyzer/src/dart/sdk/sdk.dart'; 13 import 'package:analyzer/src/dart/sdk/sdk.dart';
14 import 'package:analyzer/src/generated/parser.dart'; 14 import 'package:analyzer/src/generated/parser.dart';
15 import 'package:analyzer/src/generated/sdk.dart'; 15 import 'package:analyzer/src/generated/sdk.dart';
16 import 'package:analyzer/src/generated/source.dart'; 16 import 'package:analyzer/src/generated/source.dart';
17 import 'package:meta/meta.dart'; 17 import 'package:meta/meta.dart';
18 import 'package:path/src/context.dart'; 18 import 'package:path/src/context.dart';
19 19
20 /** 20 /**
21 * [SdkPatcher] applies patches to SDK [CompilationUnit]. 21 * [SdkPatcher] applies patches to SDK [CompilationUnit].
22 */ 22 */
23 class SdkPatcher { 23 class SdkPatcher {
24 String _baseDesc;
25 String _patchDesc;
26 CompilationUnit _patchUnit;
27
24 /** 28 /**
25 * Patch the given [unit] of a SDK [source] with the patches defined in 29 * Patch the given [unit] of a SDK [source] with the patches defined in
26 * the [sdk] for the given [platform]. Throw [ArgumentError] if a patch 30 * the [sdk] for the given [platform]. Throw [ArgumentError] if a patch
27 * file cannot be read, or the contents violates rules for patch files. 31 * file cannot be read, or the contents violates rules for patch files.
28 * 32 *
29 * If [addNewTopLevelDeclarations] is `true`, then the [unit] is the 33 * If [addNewTopLevelDeclarations] is `true`, then the [unit] is the
30 * defining unit of a library, so new top-level declarations should be 34 * defining unit of a library, so new top-level declarations should be
31 * added to this unit. For parts new declarations may be added only to the 35 * added to this unit. For parts new declarations may be added only to the
32 * patched classes. 36 * patched classes.
33 * 37 *
(...skipping 15 matching lines...) Expand all
49 patchPaths = sdkLibrary.getPatches(platform); 53 patchPaths = sdkLibrary.getPatches(platform);
50 } 54 }
51 55
52 bool strongMode = sdk.analysisOptions.strongMode; 56 bool strongMode = sdk.analysisOptions.strongMode;
53 Context pathContext = sdk.resourceProvider.pathContext; 57 Context pathContext = sdk.resourceProvider.pathContext;
54 for (String path in patchPaths) { 58 for (String path in patchPaths) {
55 String pathInLib = pathContext.joinAll(path.split('/')); 59 String pathInLib = pathContext.joinAll(path.split('/'));
56 File patchFile = sdk.libraryDirectory.getChildAssumingFile(pathInLib); 60 File patchFile = sdk.libraryDirectory.getChildAssumingFile(pathInLib);
57 if (!patchFile.exists) { 61 if (!patchFile.exists) {
58 throw new ArgumentError( 62 throw new ArgumentError(
59 'The patch file ${patchFile.path} does not exist.'); 63 'The patch file ${patchFile.path} for $source does not exist.');
60 } 64 }
61 Source patchSource = patchFile.createSource(); 65 Source patchSource = patchFile.createSource();
62 CompilationUnit patchUnit = parse(patchSource, strongMode, errorListener); 66 CompilationUnit patchUnit = parse(patchSource, strongMode, errorListener);
67
68 // Prepare for reporting errors.
69 _baseDesc = source.toString();
70 _patchDesc = patchFile.path;
71 _patchUnit = patchUnit;
72
73 _patchDirectives(
74 source, unit, patchSource, patchUnit, addNewTopLevelDeclarations);
63 _patchTopLevelDeclarations( 75 _patchTopLevelDeclarations(
64 source, unit, patchSource, patchUnit, addNewTopLevelDeclarations); 76 source, unit, patchSource, patchUnit, addNewTopLevelDeclarations);
65 } 77 }
66 } 78 }
67 79
68 void _failExternalKeyword(Source source, String name, int offset) { 80 void _failExternalKeyword(Source source, String name, int offset) {
69 throw new ArgumentError( 81 throw new ArgumentError(
70 'The keyword "external" was expected for "$name" in $source @ $offset.') ; 82 'The keyword "external" was expected for "$name" in $source @ $offset.') ;
71 } 83 }
72 84
85 void _failIfPublicName(AstNode node, String name) {
86 if (!Identifier.isPrivateName(name)) {
87 _failInPatch('contains a public declaration "$name"', node.offset);
88 }
89 }
90
91 void _failInPatch(String message, int offset) {
92 String loc = _getLocationDesc3(_patchUnit, offset);
93 throw new ArgumentError(
94 'The patch file $_patchDesc for $_baseDesc $message at $loc.');
95 }
96
97 String _getLocationDesc3(CompilationUnit unit, int offset) {
98 LineInfo_Location location = unit.lineInfo.getLocation(offset);
99 return 'the line ${location.lineNumber}';
100 }
101
102 void _patchDirectives(
103 Source baseSource,
104 CompilationUnit baseUnit,
105 Source patchSource,
106 CompilationUnit patchUnit,
107 bool addNewTopLevelDeclarations) {
108 for (Directive patchDirective in patchUnit.directives) {
109 if (patchDirective is ImportDirective) {
110 baseUnit.directives.add(patchDirective);
111 } else {
112 _failInPatch('contains an unsupported "$patchDirective" directive',
113 patchDirective.offset);
114 }
115 }
116 }
117
73 void _patchTopLevelDeclarations( 118 void _patchTopLevelDeclarations(
74 Source baseSource, 119 Source baseSource,
75 CompilationUnit baseUnit, 120 CompilationUnit baseUnit,
76 Source patchSource, 121 Source patchSource,
77 CompilationUnit patchUnit, 122 CompilationUnit patchUnit,
78 bool addNewTopLevelDeclarations) { 123 bool addNewTopLevelDeclarations) {
79 List<CompilationUnitMember> declarationsToAppend = []; 124 List<CompilationUnitMember> declarationsToAppend = [];
80 for (CompilationUnitMember patchDeclaration in patchUnit.declarations) { 125 for (CompilationUnitMember patchDeclaration in patchUnit.declarations) {
81 if (patchDeclaration is FunctionDeclaration) { 126 if (patchDeclaration is FunctionDeclaration) {
82 String name = patchDeclaration.name.name; 127 String name = patchDeclaration.name.name;
(...skipping 10 matching lines...) Expand all
93 _failExternalKeyword( 138 _failExternalKeyword(
94 baseSource, name, baseDeclaration.offset); 139 baseSource, name, baseDeclaration.offset);
95 } 140 }
96 // Replace the body. 141 // Replace the body.
97 baseDeclaration.functionExpression.body = 142 baseDeclaration.functionExpression.body =
98 patchDeclaration.functionExpression.body; 143 patchDeclaration.functionExpression.body;
99 } 144 }
100 } 145 }
101 } 146 }
102 } else if (addNewTopLevelDeclarations) { 147 } else if (addNewTopLevelDeclarations) {
103 // No @patch, must be private. 148 _failIfPublicName(patchDeclaration, name);
104 if (!Identifier.isPrivateName(name)) {
105 throw new ArgumentError(
106 'The patch file $patchSource attempts to append '
107 'a non-private declaration "$name".');
108 }
109 declarationsToAppend.add(patchDeclaration); 149 declarationsToAppend.add(patchDeclaration);
110 } 150 }
151 } else if (patchDeclaration is FunctionTypeAlias) {
152 if (patchDeclaration.metadata.isNotEmpty) {
153 _failInPatch('contains a function type alias with an annotation',
154 patchDeclaration.offset);
155 }
156 _failIfPublicName(patchDeclaration, patchDeclaration.name.name);
157 declarationsToAppend.add(patchDeclaration);
158 } else {
159 _failInPatch('contains an unsupported top-level declaration',
160 patchDeclaration.offset);
111 } 161 }
112 } 162 }
113 // Append new top-level declarations. 163 // Append new top-level declarations.
114 baseUnit.declarations.addAll(declarationsToAppend); 164 baseUnit.declarations.addAll(declarationsToAppend);
115 } 165 }
116 166
117 /** 167 /**
118 * Parse the given [source] into AST. 168 * Parse the given [source] into AST.
119 */ 169 */
120 @visibleForTesting 170 @visibleForTesting
(...skipping 19 matching lines...) Expand all
140 */ 190 */
141 static bool _hasPatchAnnotation(List<Annotation> metadata) { 191 static bool _hasPatchAnnotation(List<Annotation> metadata) {
142 return metadata.any((annotation) { 192 return metadata.any((annotation) {
143 Identifier name = annotation.name; 193 Identifier name = annotation.name;
144 return annotation.constructorName == null && 194 return annotation.constructorName == null &&
145 name is SimpleIdentifier && 195 name is SimpleIdentifier &&
146 name.name == 'patch'; 196 name.name == 'patch';
147 }); 197 });
148 } 198 }
149 } 199 }
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