| Index: pkg/polymer/lib/src/build/linter.dart
|
| ===================================================================
|
| --- pkg/polymer/lib/src/build/linter.dart (revision 37373)
|
| +++ pkg/polymer/lib/src/build/linter.dart (working copy)
|
| @@ -37,7 +37,7 @@
|
| return readPrimaryAsHtml(transform).then((document) {
|
| return _collectElements(document, id, transform, seen).then((elements) {
|
| bool isEntrypoint = options.isHtmlEntryPoint(id);
|
| - new _LinterVisitor(transform.logger, elements, isEntrypoint)
|
| + new _LinterVisitor(id, transform.logger, elements, isEntrypoint)
|
| .run(document);
|
| });
|
| });
|
| @@ -55,7 +55,15 @@
|
| // Note: the import order is relevant, so we visit in that order.
|
| .then((ids) => Future.forEach(ids,
|
| (id) => _readAndCollectElements(id, transform, seen, elements)))
|
| - .then((_) => _addElements(document, transform.logger, elements))
|
| + .then((_) {
|
| + if (sourceId.package == 'polymer' &&
|
| + sourceId.path == 'lib/src/js/polymer/polymer.html' &&
|
| + elements['polymer-element'] == null) {
|
| + elements['polymer-element'] =
|
| + new _ElementSummary('polymer-element', null, null);
|
| + }
|
| + return _addElements(document, transform.logger, elements);
|
| + })
|
| .then((_) => elements);
|
| }
|
|
|
| @@ -63,7 +71,7 @@
|
| 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).then(
|
| + return readAsHtml(id, transform, showWarnings: false).then(
|
| (doc) => _collectElements(doc, id, transform, seen, elements));
|
| }
|
|
|
| @@ -80,8 +88,8 @@
|
| importIds.add(assetExists(id, transform).then((exists) {
|
| if (exists) return id;
|
| if (sourceId == transform.primaryInput.id) {
|
| - logger.error('couldn\'t find imported asset "${id.path}" in package '
|
| - '"${id.package}".', span: span);
|
| + logger.warning('couldn\'t find imported asset "${id.path}" in package'
|
| + ' "${id.package}".', span: span);
|
| }
|
| }));
|
| }
|
| @@ -102,9 +110,9 @@
|
| if (existing.hasConflict) continue;
|
| existing.hasConflict = true;
|
| logger.warning('duplicate definition for custom tag "$name".',
|
| - span: existing.span);
|
| + span: existing.span);
|
| logger.warning('duplicate definition for custom tag "$name" '
|
| - ' (second definition).', span: span);
|
| + ' (second definition).', span: span);
|
| continue;
|
| }
|
|
|
| @@ -127,8 +135,11 @@
|
| _ElementSummary extendsType;
|
| bool hasConflict = false;
|
|
|
| - String get baseExtendsTag => extendsType == null
|
| - ? extendsTag : extendsType.baseExtendsTag;
|
| + String get baseExtendsTag {
|
| + if (extendsType != null) return extendsType.baseExtendsTag;
|
| + if (extendsTag != null && !extendsTag.contains('-')) return extendsTag;
|
| + return null;
|
| + }
|
|
|
| _ElementSummary(this.tagName, this.extendsTag, this.span);
|
|
|
| @@ -137,6 +148,7 @@
|
|
|
| class _LinterVisitor extends TreeVisitor {
|
| TransformLogger _logger;
|
| + AssetId _sourceId;
|
| bool _inPolymerElement = false;
|
| bool _dartTagSeen = false;
|
| bool _polymerHtmlSeen = false;
|
| @@ -144,7 +156,8 @@
|
| bool _isEntrypoint;
|
| Map<String, _ElementSummary> _elements;
|
|
|
| - _LinterVisitor(this._logger, this._elements, this._isEntrypoint) {
|
| + _LinterVisitor(
|
| + this._sourceId, this._logger, this._elements, this._isEntrypoint) {
|
| // We normalize the map, so each element has a direct reference to any
|
| // element it extends from.
|
| for (var tag in _elements.values) {
|
| @@ -170,10 +183,6 @@
|
| void run(Document doc) {
|
| visit(doc);
|
|
|
| - if (_isEntrypoint && !_polymerHtmlSeen && !_polymerExperimentalHtmlSeen) {
|
| - _logger.warning(USE_POLYMER_HTML, span: doc.body.sourceSpan);
|
| - }
|
| -
|
| if (_isEntrypoint && !_dartTagSeen && !_polymerExperimentalHtmlSeen) {
|
| _logger.warning(USE_INIT_DART, span: doc.body.sourceSpan);
|
| }
|
| @@ -195,9 +204,14 @@
|
| return;
|
| }
|
|
|
| - if (href == 'packages/polymer/polymer.html') {
|
| - _polymerHtmlSeen = true;
|
| - } else if (href == POLYMER_EXPERIMENTAL_HTML) {
|
| + if (rel != 'import') return;
|
| +
|
| + if (_inPolymerElement) {
|
| + _logger.error(NO_IMPORT_WITHIN_ELEMENT, span: node.sourceSpan);
|
| + return;
|
| + }
|
| +
|
| + if (href == POLYMER_EXPERIMENTAL_HTML) {
|
| _polymerExperimentalHtmlSeen = true;
|
| }
|
| // TODO(sigmund): warn also if href can't be resolved.
|
| @@ -212,6 +226,11 @@
|
| /// Produce warnings if using `<polymer-element>` in the wrong place or if the
|
| /// definition is not complete.
|
| void _validatePolymerElement(Element node) {
|
| + if (!_elements.containsKey('polymer-element')) {
|
| + _logger.warning(usePolymerHtmlMessageFrom(_sourceId),
|
| + span: node.sourceSpan);
|
| + }
|
| +
|
| if (_inPolymerElement) {
|
| _logger.error('Nested polymer element definitions are not allowed.',
|
| span: node.sourceSpan);
|
| @@ -366,17 +385,7 @@
|
|
|
| /// Validate event handlers are used correctly.
|
| void _validateEventHandler(Element node, String name, String value) {
|
| - if (!name.startsWith('on-')) {
|
| - // TODO(sigmund): technically these are valid attribtues in HTML, so we
|
| - // might want to remove this warning, or only produce it if the value
|
| - // looks like a binding.
|
| - _logger.warning('Event handler "$name" will be interpreted as an inline'
|
| - ' JavaScript event handler. Use the form '
|
| - 'on-event-name="{{handlerName}}" if you want a Dart handler '
|
| - 'that will automatically update the UI based on model changes.',
|
| - span: node.attributeSpans[name]);
|
| - return;
|
| - }
|
| + if (!name.startsWith('on-')) return;
|
|
|
| if (!_inPolymerElement) {
|
| _logger.warning('Inline event handlers are only supported inside '
|
| @@ -401,12 +410,30 @@
|
| const String ONLY_ONE_TAG =
|
| 'Only one "application/dart" script tag per document is allowed.';
|
|
|
| -const String USE_POLYMER_HTML =
|
| - 'Besides the initPolymer invocation, to run a polymer application you need '
|
| - 'to include the following HTML import: '
|
| - '<link rel="import" href="packages/polymer/polymer.html">. This will '
|
| - 'include the common polymer logic needed to boostrap your application.';
|
| +String usePolymerHtmlMessageFrom(AssetId id) {
|
| + var segments = id.path.split('/');
|
| + var upDirCount = 0;
|
| + if (segments[0] == 'lib') {
|
| + // lib/foo.html => ../../packages/
|
| + upDirCount = segments.length;
|
| + } else if (segments.length > 2) {
|
| + // 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">.';
|
| +}
|
| +
|
| +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:'
|
|
|