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

Side by Side Diff: pkg/polymer/lib/src/build/common.dart

Issue 513023002: Step one towards stable error messages with details: (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 3 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 /// Common methods used by transfomers. 5 /// Common methods used by transfomers.
6 library polymer.src.build.common; 6 library polymer.src.build.common;
7 7
8 import 'dart:async'; 8 import 'dart:async';
9 9
10 import 'package:analyzer/src/generated/ast.dart'; 10 import 'package:analyzer/src/generated/ast.dart';
11 import 'package:analyzer/src/generated/error.dart'; 11 import 'package:analyzer/src/generated/error.dart';
12 import 'package:analyzer/src/generated/parser.dart'; 12 import 'package:analyzer/src/generated/parser.dart';
13 import 'package:analyzer/src/generated/scanner.dart'; 13 import 'package:analyzer/src/generated/scanner.dart';
14 import 'package:barback/barback.dart'; 14 import 'package:barback/barback.dart';
15 import 'package:code_transformers/messages/build_logger.dart';
15 import 'package:html5lib/dom.dart' show Document; 16 import 'package:html5lib/dom.dart' show Document;
16 import 'package:html5lib/parser.dart' show HtmlParser; 17 import 'package:html5lib/parser.dart' show HtmlParser;
18 import 'package:observe/transformer.dart' show ObservableTransformer;
17 import 'package:path/path.dart' as path; 19 import 'package:path/path.dart' as path;
18 import 'package:observe/transformer.dart' show ObservableTransformer; 20
21 import 'constants.dart';
22 import 'messages.dart';
23
24 export 'constants.dart';
19 25
20 const _ignoredErrors = const [ 26 const _ignoredErrors = const [
21 'unexpected-dash-after-double-dash-in-comment', 27 'unexpected-dash-after-double-dash-in-comment',
22 'unexpected-char-in-comment', 28 'unexpected-char-in-comment',
23 ]; 29 ];
24 30
25 /// Parses an HTML file [contents] and returns a DOM-like tree. Adds emitted 31 /// Parses an HTML file [contents] and returns a DOM-like tree. Adds emitted
26 /// error/warning to [logger]. 32 /// error/warning to [logger].
27 Document _parseHtml(String contents, String sourcePath, TransformLogger logger, 33 Document _parseHtml(String contents, String sourcePath, BuildLogger logger,
28 {bool checkDocType: true, bool showWarnings: true}) { 34 {bool checkDocType: true, bool showWarnings: true}) {
29 // TODO(jmesserly): make HTTP encoding configurable 35 // TODO(jmesserly): make HTTP encoding configurable
30 var parser = new HtmlParser(contents, encoding: 'utf8', 36 var parser = new HtmlParser(contents, encoding: 'utf8',
31 generateSpans: true, sourceUrl: sourcePath); 37 generateSpans: true, sourceUrl: sourcePath);
32 var document = parser.parse(); 38 var document = parser.parse();
33 39
34 // Note: errors aren't fatal in HTML (unless strict mode is on). 40 // Note: errors aren't fatal in HTML (unless strict mode is on).
35 // So just print them as warnings. 41 // So just print them as warnings.
36 if (showWarnings) { 42 if (showWarnings) {
37 for (var e in parser.errors) { 43 for (var e in parser.errors) {
38 if (_ignoredErrors.contains(e.errorCode)) continue; 44 if (_ignoredErrors.contains(e.errorCode)) continue;
39 if (checkDocType || e.errorCode != 'expected-doctype-but-got-start-tag') { 45 if (checkDocType || e.errorCode != 'expected-doctype-but-got-start-tag') {
40 logger.warning(e.message, span: e.span); 46 logger.warning(HTML5_WARNING.create({'message': e.message}),
47 span: e.span);
41 } 48 }
42 } 49 }
43 } 50 }
44 return document; 51 return document;
45 } 52 }
46 53
47 /// Additional options used by polymer transformers 54 /// Additional options used by polymer transformers
48 class TransformOptions { 55 class TransformOptions {
49 /// List of entrypoints paths. The paths are relative to the package root and 56 /// List of entrypoints paths. The paths are relative to the package root and
50 /// are represented using posix style, which matches the representation used 57 /// are represented using posix style, which matches the representation used
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 // Then check the global default setting. 126 // Then check the global default setting.
120 var globalDefault = inlineStylesheets['default']; 127 var globalDefault = inlineStylesheets['default'];
121 return (globalDefault != null) ? globalDefault : true; 128 return (globalDefault != null) ? globalDefault : true;
122 } 129 }
123 } 130 }
124 131
125 /// Mixin for polymer transformers. 132 /// Mixin for polymer transformers.
126 abstract class PolymerTransformer { 133 abstract class PolymerTransformer {
127 TransformOptions get options; 134 TransformOptions get options;
128 135
129 Future<Document> readPrimaryAsHtml(Transform transform) { 136 Future<Document> readPrimaryAsHtml(Transform transform, BuildLogger logger) {
130 var asset = transform.primaryInput; 137 var asset = transform.primaryInput;
131 var id = asset.id; 138 var id = asset.id;
132 return asset.readAsString().then((content) { 139 return asset.readAsString().then((content) {
133 return _parseHtml(content, id.path, transform.logger, 140 return _parseHtml(content, id.path, logger,
134 checkDocType: options.isHtmlEntryPoint(id)); 141 checkDocType: options.isHtmlEntryPoint(id));
135 }); 142 });
136 } 143 }
137 144
138 Future<Document> readAsHtml(AssetId id, Transform transform, 145 Future<Document> readAsHtml(AssetId id, Transform transform,
146 BuildLogger logger,
139 {bool showWarnings: true}) { 147 {bool showWarnings: true}) {
140 var primaryId = transform.primaryInput.id; 148 var primaryId = transform.primaryInput.id;
141 bool samePackage = id.package == primaryId.package; 149 bool samePackage = id.package == primaryId.package;
142 var url = spanUrlFor(id, transform); 150 var url = spanUrlFor(id, transform, logger);
143 return transform.readInputAsString(id).then((content) { 151 return transform.readInputAsString(id).then((content) {
144 return _parseHtml(content, url, transform.logger, 152 return _parseHtml(content, url, logger,
145 checkDocType: samePackage && options.isHtmlEntryPoint(id), 153 checkDocType: samePackage && options.isHtmlEntryPoint(id),
146 showWarnings: showWarnings); 154 showWarnings: showWarnings);
147 }); 155 });
148 } 156 }
149 157
150 Future<bool> assetExists(AssetId id, Transform transform) => 158 Future<bool> assetExists(AssetId id, Transform transform) =>
151 transform.getInput(id).then((_) => true).catchError((_) => false); 159 transform.getInput(id).then((_) => true).catchError((_) => false);
152 160
153 String toString() => 'polymer ($runtimeType)'; 161 String toString() => 'polymer ($runtimeType)';
154 } 162 }
155 163
156 /// Gets the appropriate URL to use in a span to produce messages (e.g. 164 /// Gets the appropriate URL to use in a span to produce messages (e.g.
157 /// warnings) for users. This will attempt to format the URL in the most useful 165 /// warnings) for users. This will attempt to format the URL in the most useful
158 /// way: 166 /// way:
159 /// 167 ///
160 /// - If the asset is within the primary package, then use the [id.path], 168 /// - If the asset is within the primary package, then use the [id.path],
161 /// the user will know it is a file from their own code. 169 /// the user will know it is a file from their own code.
162 /// - If the asset is from another package, then use [assetUrlFor], this will 170 /// - If the asset is from another package, then use [assetUrlFor], this will
163 /// likely be a "package:" url to the file in the other package, which is 171 /// likely be a "package:" url to the file in the other package, which is
164 /// enough for users to identify where the error is. 172 /// enough for users to identify where the error is.
165 String spanUrlFor(AssetId id, Transform transform) { 173 String spanUrlFor(AssetId id, Transform transform, logger) {
166 var primaryId = transform.primaryInput.id; 174 var primaryId = transform.primaryInput.id;
167 bool samePackage = id.package == primaryId.package; 175 bool samePackage = id.package == primaryId.package;
168 return samePackage ? id.path 176 return samePackage ? id.path
169 : assetUrlFor(id, primaryId, transform.logger, allowAssetUrl: true); 177 : assetUrlFor(id, primaryId, logger, allowAssetUrl: true);
170 } 178 }
171 179
172 /// Transformer phases which should be applied to the Polymer package. 180 /// Transformer phases which should be applied to the Polymer package.
173 List<List<Transformer>> get phasesForPolymer => 181 List<List<Transformer>> get phasesForPolymer =>
174 [[new ObservableTransformer(['lib/src/instance.dart'])]]; 182 [[new ObservableTransformer(['lib/src/instance.dart'])]];
175 183
176 /// Generate the import url for a file described by [id], referenced by a file 184 /// Generate the import url for a file described by [id], referenced by a file
177 /// with [sourceId]. 185 /// with [sourceId].
178 // TODO(sigmund): this should also be in barback (dartbug.com/12610) 186 // TODO(sigmund): this should also be in barback (dartbug.com/12610)
179 String assetUrlFor(AssetId id, AssetId sourceId, TransformLogger logger, 187 String assetUrlFor(AssetId id, AssetId sourceId, BuildLogger logger,
180 {bool allowAssetUrl: false}) { 188 {bool allowAssetUrl: false}) {
181 // use package: and asset: urls if possible 189 // use package: and asset: urls if possible
182 if (id.path.startsWith('lib/')) { 190 if (id.path.startsWith('lib/')) {
183 return 'package:${id.package}/${id.path.substring(4)}'; 191 return 'package:${id.package}/${id.path.substring(4)}';
184 } 192 }
185 193
186 if (id.path.startsWith('asset/')) { 194 if (id.path.startsWith('asset/')) {
187 if (!allowAssetUrl) { 195 if (!allowAssetUrl) {
188 logger.error("asset urls not allowed. " 196 logger.error(INTERNAL_ERROR_DONT_KNOW_HOW_TO_IMPORT.create({
189 "Don't know how to refer to $id from $sourceId"); 197 'target': id,
198 'source': sourceId,
199 'extra': ' (asset urls not allowed.)'}));
190 return null; 200 return null;
191 } 201 }
192 return 'asset:${id.package}/${id.path.substring(6)}'; 202 return 'asset:${id.package}/${id.path.substring(6)}';
193 } 203 }
194 204
195 // Use relative urls only if it's possible. 205 // Use relative urls only if it's possible.
196 if (id.package != sourceId.package) { 206 if (id.package != sourceId.package) {
197 logger.error("don't know how to refer to $id from $sourceId"); 207 logger.error("don't know how to refer to $id from $sourceId");
198 return null; 208 return null;
199 } 209 }
200 210
201 var builder = path.url; 211 var builder = path.url;
202 return builder.relative(builder.join('/', id.path), 212 return builder.relative(builder.join('/', id.path),
203 from: builder.join('/', builder.dirname(sourceId.path))); 213 from: builder.join('/', builder.dirname(sourceId.path)));
204 } 214 }
205 215
206 216
207 /// Convert system paths to asset paths (asset paths are posix style). 217 /// Convert system paths to asset paths (asset paths are posix style).
208 String systemToAssetPath(String assetPath) { 218 String systemToAssetPath(String assetPath) {
209 if (path.Style.platform != path.Style.windows) return assetPath; 219 if (path.Style.platform != path.Style.windows) return assetPath;
210 return path.posix.joinAll(path.split(assetPath)); 220 return path.posix.joinAll(path.split(assetPath));
211 } 221 }
212 222
213 /// These names have meaning in SVG or MathML, so they aren't allowed as custom
214 /// tags. See [isCustomTagName].
215 const invalidTagNames = const {
216 'annotation-xml': '',
217 'color-profile': '',
218 'font-face': '',
219 'font-face-src': '',
220 'font-face-uri': '',
221 'font-face-format': '',
222 'font-face-name': '',
223 'missing-glyph': '',
224 };
225
226 /// Returns true if this is a valid custom element name. See: 223 /// Returns true if this is a valid custom element name. See:
227 /// <http://w3c.github.io/webcomponents/spec/custom/#dfn-custom-element-type> 224 /// <http://w3c.github.io/webcomponents/spec/custom/#dfn-custom-element-type>
228 bool isCustomTagName(String name) { 225 bool isCustomTagName(String name) {
229 if (name == null || !name.contains('-')) return false; 226 if (name == null || !name.contains('-')) return false;
230 return !invalidTagNames.containsKey(name); 227 return !invalidTagNames.containsKey(name);
231 } 228 }
232 229
233 /// Regex to split names in the 'attributes' attribute, which supports 'a b c', 230 /// Regex to split names in the 'attributes' attribute, which supports 'a b c',
234 /// 'a,b,c', or even 'a b,c'. This is the same as in `lib/src/declaration.dart`. 231 /// 'a,b,c', or even 'a b,c'. This is the same as in `lib/src/declaration.dart`.
235 final ATTRIBUTES_REGEX = new RegExp(r'\s|,'); 232 final ATTRIBUTES_REGEX = new RegExp(r'\s|,');
236
237 const POLYMER_EXPERIMENTAL_HTML = 'packages/polymer/polymer_experimental.html';
238
239 const String LOG_EXTENSION = '._buildLogs';
OLDNEW
« no previous file with comments | « pkg/polymer/lib/src/build/build_log_combiner.dart ('k') | pkg/polymer/lib/src/build/constants.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698