Index: pkg/polymer/lib/src/build/linter.dart |
diff --git a/pkg/polymer/lib/src/build/linter.dart b/pkg/polymer/lib/src/build/linter.dart |
index 3ec663769151c6e0897c15c8178257374c4d84b3..6daf982718d04122cab215a78a190096742f4469 100644 |
--- a/pkg/polymer/lib/src/build/linter.dart |
+++ b/pkg/polymer/lib/src/build/linter.dart |
@@ -11,13 +11,15 @@ import 'dart:convert'; |
import 'package:barback/barback.dart'; |
import 'package:code_transformers/assets.dart'; |
+import 'package:code_transformers/messages/build_logger.dart'; |
+import 'package:code_transformers/messages/messages.dart' show Message; |
import 'package:html5lib/dom.dart'; |
import 'package:html5lib/dom_parsing.dart'; |
import 'package:source_span/source_span.dart'; |
import 'common.dart'; |
import 'utils.dart'; |
-import 'wrapped_logger.dart'; |
+import 'messages.dart'; |
/// A linter that checks for common Polymer errors and produces warnings to |
/// show on the editor or the command line. Leaves sources unchanged, but |
@@ -38,17 +40,17 @@ class Linter extends Transformer with PolymerTransformer { |
seen.add(id); |
bool isEntryPoint = options.isHtmlEntryPoint(id); |
- var logger = options.releaseMode ? transform.logger : |
- new WrappedLogger(transform, convertErrorsToWarnings: true); |
+ var logger = new BuildLogger(transform, |
+ convertErrorsToWarnings: !options.releaseMode); |
- return readPrimaryAsHtml(transform).then((document) { |
+ return readPrimaryAsHtml(transform, logger).then((document) { |
return _collectElements(document, id, transform, logger, seen) |
.then((elements) { |
new _LinterVisitor(id, logger, elements, isEntryPoint).run(document); |
- // Write out the logs collected by our [WrappedLogger]. |
- if (options.injectBuildLogsInOutput && logger is WrappedLogger) { |
- return (logger as WrappedLogger).writeOutput(); |
+ // Write out the logs collected by our [BuildLogger]. |
+ if (options.injectBuildLogsInOutput && logger is BuildLogger) { |
+ return (logger as BuildLogger).writeOutput(); |
} |
}); |
}); |
@@ -60,7 +62,7 @@ class Linter extends Transformer with PolymerTransformer { |
/// first. |
Future<Map<String, _ElementSummary>> _collectElements( |
Document document, AssetId sourceId, Transform transform, |
- TransformLogger logger, Set<AssetId> seen, |
+ BuildLogger logger, Set<AssetId> seen, |
[Map<String, _ElementSummary> elements]) { |
if (elements == null) elements = <String, _ElementSummary>{}; |
return _getImportedIds(document, sourceId, transform, logger) |
@@ -81,17 +83,17 @@ class Linter extends Transformer with PolymerTransformer { |
} |
Future _readAndCollectElements(AssetId id, Transform transform, |
- TransformLogger logger, Set<AssetId> seen, |
+ BuildLogger logger, Set<AssetId> seen, |
Map<String, _ElementSummary> elements) { |
if (id == null || seen.contains(id)) return new Future.value(null); |
seen.add(id); |
- return readAsHtml(id, transform, showWarnings: false).then( |
+ return readAsHtml(id, transform, logger, showWarnings: false).then( |
(doc) => _collectElements(doc, id, transform, logger, seen, elements)); |
} |
Future<List<AssetId>> _getImportedIds( |
Document document, AssetId sourceId, Transform transform, |
- TransformLogger logger) { |
+ BuildLogger logger) { |
var importIds = []; |
for (var tag in document.querySelectorAll('link')) { |
if (tag.attributes['rel'] != 'import') continue; |
@@ -102,15 +104,15 @@ class Linter extends Transformer with PolymerTransformer { |
importIds.add(assetExists(id, transform).then((exists) { |
if (exists) return id; |
if (sourceId == transform.primaryInput.id) { |
- logger.warning('couldn\'t find imported asset "${id.path}" in package' |
- ' "${id.package}".', span: span); |
+ logger.warning(IMPORT_NOT_FOUND.create( |
+ {'path': id.path, 'package': id.package}), span: span); |
} |
})); |
} |
return Future.wait(importIds); |
} |
- void _addElements(Document document, TransformLogger logger, |
+ void _addElements(Document document, BuildLogger logger, |
Map<String, _ElementSummary> elements) { |
for (var tag in document.querySelectorAll('polymer-element')) { |
var name = tag.attributes['name']; |
@@ -123,10 +125,12 @@ class Linter extends Transformer with PolymerTransformer { |
// Report warning only once. |
if (existing.hasConflict) continue; |
existing.hasConflict = true; |
- logger.warning('duplicate definition for custom tag "$name".', |
+ logger.warning(DUPLICATE_DEFINITION.create( |
+ {'name': name, 'second': ''}), |
span: existing.span); |
- logger.warning('duplicate definition for custom tag "$name" ' |
- ' (second definition).', span: span); |
+ logger.warning(DUPLICATE_DEFINITION.create( |
+ {'name': name, 'second': ' (second definition).'}), |
+ span: span); |
continue; |
} |
@@ -161,7 +165,7 @@ class _ElementSummary { |
} |
class _LinterVisitor extends TreeVisitor { |
- TransformLogger _logger; |
+ BuildLogger _logger; |
AssetId _sourceId; |
bool _inPolymerElement = false; |
bool _dartTagSeen = false; |
@@ -198,7 +202,7 @@ class _LinterVisitor extends TreeVisitor { |
visit(doc); |
if (_isEntryPoint && !_dartTagSeen && !_polymerExperimentalHtmlSeen) { |
- _logger.warning(USE_INIT_DART, span: doc.body.sourceSpan); |
+ _logger.warning(MISSING_INIT_POLYMER, span: doc.body.sourceSpan); |
} |
} |
@@ -208,13 +212,12 @@ class _LinterVisitor extends TreeVisitor { |
if (rel != 'import' && rel != 'stylesheet') return; |
if (rel == 'import' && _dartTagSeen) { |
- _logger.warning("Move HTML imports above your Dart script tag.", |
- span: node.sourceSpan); |
+ _logger.warning(MOVE_IMPORTS_UP, span: node.sourceSpan); |
} |
var href = node.attributes['href']; |
if (href == null || href == '') { |
- _logger.warning('link rel="$rel" missing href.', span: node.sourceSpan); |
+ _logger.warning(MISSING_HREF.create({'rel': rel}), span: node.sourceSpan); |
return; |
} |
@@ -233,8 +236,7 @@ class _LinterVisitor extends TreeVisitor { |
/// Produce warnings if using `<element>` instead of `<polymer-element>`. |
void _validateElementElement(Element node) { |
- _logger.warning('<element> elements are not supported, use' |
- ' <polymer-element> instead', span: node.sourceSpan); |
+ _logger.warning(ELEMENT_DEPRECATED_EONS_AGO, span: node.sourceSpan); |
} |
/// Produce warnings if using `<polymer-element>` in the wrong place or if the |
@@ -246,8 +248,7 @@ class _LinterVisitor extends TreeVisitor { |
} |
if (_inPolymerElement) { |
- _logger.error('Nested polymer element definitions are not allowed.', |
- span: node.sourceSpan); |
+ _logger.error(NESTED_POLYMER_ELEMENT, span: node.sourceSpan); |
return; |
} |
@@ -255,18 +256,14 @@ class _LinterVisitor extends TreeVisitor { |
var extendsTag = node.attributes['extends']; |
if (tagName == null) { |
- _logger.error('Missing tag name of the custom element. Please include an ' |
- 'attribute like \'name="your-tag-name"\'.', |
- span: node.sourceSpan); |
+ _logger.error(MISSING_TAG_NAME, span: node.sourceSpan); |
} else if (!isCustomTagName(tagName)) { |
- _logger.error('Invalid name "$tagName". Custom element names must have ' |
- 'at least one dash and can\'t be any of the following names: ' |
- '${invalidTagNames.keys.join(", ")}.', |
+ _logger.error(INVALID_TAG_NAME.create({'name': tagName}), |
span: node.sourceSpan); |
} |
if (_elements[extendsTag] == null && isCustomTagName(extendsTag)) { |
- _logger.warning('custom element with name "$extendsTag" not found.', |
+ _logger.warning(CUSTOM_ELEMENT_NOT_FOUND.create({'tag': extendsTag}), |
span: node.sourceSpan); |
} |
@@ -305,26 +302,23 @@ class _LinterVisitor extends TreeVisitor { |
if (src == null) { |
if (isDart && isEmpty) { |
- _logger.warning('script tag seems empty.', span: node.sourceSpan); |
+ _logger.warning(SCRIPT_TAG_SEEMS_EMPTY, span: node.sourceSpan); |
} |
return; |
} |
if (src.endsWith('.dart') && !isDart) { |
- _logger.warning('Wrong script type, expected type="application/dart".', |
- span: node.sourceSpan); |
+ _logger.warning(EXPECTED_DART_MIME_TYPE, span: node.sourceSpan); |
return; |
} |
if (!src.endsWith('.dart') && isDart) { |
- _logger.warning('"application/dart" scripts should use the .dart file ' |
- 'extension.', span: node.sourceSpan); |
+ _logger.warning(EXPECTED_DART_EXTENSION, span: node.sourceSpan); |
return; |
} |
if (!isEmpty) { |
- _logger.warning('script tag has "src" attribute and also has script ' |
- 'text.', span: node.sourceSpan); |
+ _logger.warning(FOUND_BOTH_SCRIPT_SRC_AND_TEXT, span: node.sourceSpan); |
} |
} |
@@ -359,39 +353,27 @@ class _LinterVisitor extends TreeVisitor { |
var info = _elements[customTagName]; |
if (info == null) { |
- // TODO(jmesserly): this warning is wrong if someone is using raw custom |
- // elements. Is there another way we can handle this warning that won't |
- // generate false positives? |
- _logger.warning('definition for Polymer element with tag name ' |
- '"$customTagName" not found.', span: node.sourceSpan); |
+ _logger.warning(CUSTOM_ELEMENT_NOT_FOUND.create({'tag': customTagName}), |
+ span: node.sourceSpan); |
return; |
} |
var baseTag = info.baseExtendsTag; |
if (baseTag != null && !hasIsAttribute) { |
- _logger.warning( |
- 'custom element "$customTagName" extends from "$baseTag", but ' |
- 'this tag will not include the default properties of "$baseTag". ' |
- 'To fix this, either write this tag as <$baseTag ' |
- 'is="$customTagName"> or remove the "extends" attribute from ' |
- 'the custom element declaration.', span: node.sourceSpan); |
+ _logger.warning(BAD_INSTANTIATION_MISSING_BASE_TAG.create( |
+ {'tag': customTagName, 'base': baseTag}), span: node.sourceSpan); |
return; |
} |
if (hasIsAttribute && baseTag == null) { |
- _logger.warning( |
- 'custom element "$customTagName" doesn\'t declare any type ' |
- 'extensions. To fix this, either rewrite this tag as ' |
- '<$customTagName> or add \'extends="$nodeTag"\' to ' |
- 'the custom element declaration.', span: node.sourceSpan); |
+ _logger.warning(BAD_INSTANTIATION_BOGUS_BASE_TAG.create( |
+ {'tag': customTagName, 'base': nodeTag}), span: node.sourceSpan); |
return; |
} |
if (hasIsAttribute && baseTag != nodeTag) { |
- _logger.warning( |
- 'custom element "$customTagName" extends from "$baseTag". ' |
- 'Did you mean to write <$baseTag is="$customTagName">?', |
- span: node.sourceSpan); |
+ _logger.warning(BAD_INSTANTIATION_WRONG_BASE_TAG.create( |
+ {'tag': customTagName, 'base': baseTag}), span: node.sourceSpan); |
} |
} |
@@ -399,9 +381,9 @@ class _LinterVisitor extends TreeVisitor { |
bool _validateCustomAttributeName(String name, FileSpan span) { |
if (name.contains('-')) { |
var newName = toCamelCase(name); |
- _logger.warning('PolymerElement no longer recognizes attribute names with ' |
- 'dashes such as "$name". Use "$newName" or "${newName.toLowerCase()}" ' |
- 'instead (both forms are equivalent in HTML).', span: span); |
+ var alternative = '"$newName" or "${newName.toLowerCase()}"'; |
+ _logger.warning(NO_DASHES_IN_CUSTOM_ATTRIBUTES.create( |
+ {'name': name, 'alternative': alternative}), span: span); |
return false; |
} |
return true; |
@@ -412,8 +394,7 @@ class _LinterVisitor extends TreeVisitor { |
if (!name.startsWith('on-')) return; |
if (!_inPolymerElement) { |
- _logger.warning('Inline event handlers are only supported inside ' |
- 'declarations of <polymer-element>.', |
+ _logger.warning(EVENT_HANDLERS_ONLY_WITHIN_POLYMER, |
span: node.attributeSpans[name]); |
return; |
} |
@@ -423,18 +404,14 @@ class _LinterVisitor extends TreeVisitor { |
// non empty. |
if (!value.startsWith("{{") || !value.endsWith("}}") || value.contains('(') |
|| value.substring(2, value.length - 2).trim() == '') { |
- _logger.warning('Invalid event handler body "$value". Declare a method ' |
- 'in your custom element "void handlerName(event, detail, target)" ' |
- 'and use the form $name="{{handlerName}}".', |
+ _logger.warning(INVALID_EVENT_HANDLER_BODY.create( |
+ {'value': value, 'name': name}), |
span: node.attributeSpans[name]); |
} |
} |
} |
-const String ONLY_ONE_TAG = |
- 'Only one "application/dart" script tag per document is allowed.'; |
- |
-String usePolymerHtmlMessageFrom(AssetId id) { |
+Message usePolymerHtmlMessageFrom(AssetId id) { |
var segments = id.path.split('/'); |
var upDirCount = 0; |
if (segments[0] == 'lib') { |
@@ -444,30 +421,9 @@ String usePolymerHtmlMessageFrom(AssetId id) { |
// web/a/foo.html => ../packages/ |
upDirCount = segments.length - 2; |
} |
- return usePolymerHtmlMessage(upDirCount); |
-} |
- |
-String usePolymerHtmlMessage(int upDirCount) { |
var reachOutPrefix = '../' * upDirCount; |
- return 'Missing definition for <polymer-element>, please add the following ' |
- 'HTML import at the top of this file: <link rel="import" ' |
- 'href="${reachOutPrefix}packages/polymer/polymer.html">.'; |
+ return USE_POLYMER_HTML.create({'reachOutPrefix': reachOutPrefix}); |
} |
-const String NO_IMPORT_WITHIN_ELEMENT = 'Polymer.dart\'s implementation of ' |
- 'HTML imports are not supported within polymer element definitions, yet. ' |
- 'Please move the import out of this <polymer-element>.'; |
- |
-const String USE_INIT_DART = |
- 'To run a polymer application, you need to call "initPolymer". You can ' |
- 'either include a generic script tag that does this for you:' |
- '\'<script type="application/dart">export "package:polymer/init.dart";' |
- '</script>\' or add your own script tag and call that function. ' |
- 'Make sure the script tag is placed after all HTML imports.'; |
- |
-const String NO_DART_SCRIPT_AND_EXPERIMENTAL = |
- 'The experimental bootstrap feature doesn\'t support script tags on ' |
- 'the main document (for now).'; |
- |
const List<String> INTERNALLY_DEFINED_ELEMENTS = |
const ['auto-binding-dart', 'polymer-element']; |