Chromium Code Reviews| Index: compiler/java/com/google/dart/compiler/type/ExternalTypeAnalyzers.java |
| diff --git a/compiler/java/com/google/dart/compiler/type/ExternalTypeAnalyzers.java b/compiler/java/com/google/dart/compiler/type/ExternalTypeAnalyzers.java |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..cd4ce8cd488900318ddbc2639da2529c1e3a4f24 |
| --- /dev/null |
| +++ b/compiler/java/com/google/dart/compiler/type/ExternalTypeAnalyzers.java |
| @@ -0,0 +1,175 @@ |
| +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| + |
| +package com.google.dart.compiler.type; |
| + |
| +import com.google.common.collect.Maps; |
| +import com.google.dart.compiler.ast.DartExpression; |
| +import com.google.dart.compiler.ast.DartMethodInvocation; |
| +import com.google.dart.compiler.ast.DartStringLiteral; |
| +import com.google.dart.compiler.ast.DartUnqualifiedInvocation; |
| +import com.google.dart.compiler.resolver.Element; |
| +import com.google.dart.compiler.resolver.ElementKind; |
| +import com.google.dart.compiler.resolver.Elements; |
| +import com.google.dart.compiler.resolver.EnclosingElement; |
| +import com.google.dart.compiler.resolver.LibraryElement; |
| +import com.google.dart.compiler.util.apache.StringUtils; |
| + |
| +import java.util.List; |
| +import java.util.Map; |
| + |
| +/** |
| + * Provides type information which can not be inferred from source itself. |
|
Brian Wilkerson
2012/08/01 17:45:46
nit: "can not" --> "cannot", here and below
|
| + */ |
| +public class ExternalTypeAnalyzers { |
| + private static final Map<String, String> tagToElementType = Maps.newHashMap(); |
| + static { |
| + tagToElementType.put("A", "AnchorElement"); |
| + tagToElementType.put("AREA", "AreaElement"); |
| + tagToElementType.put("BR", "BRElement"); |
| + tagToElementType.put("BASE", "BaseElement"); |
| + tagToElementType.put("BODY", "BodyElement"); |
| + tagToElementType.put("BUTTON", "ButtonElement"); |
| + tagToElementType.put("CANVAS", "CanvasElement"); |
| + tagToElementType.put("DL", "DListElement"); |
| + tagToElementType.put("DETAILS", "DetailsElement"); |
| + tagToElementType.put("DIV", "DivElement"); |
| + tagToElementType.put("EMBED", "EmbedElement"); |
| + tagToElementType.put("FIELDSET", "FieldSetElement"); |
| + tagToElementType.put("FORM", "FormElement"); |
| + tagToElementType.put("HR", "HRElement"); |
| + tagToElementType.put("HEAD", "HeadElement"); |
| + tagToElementType.put("H1", "HeadingElement"); |
| + tagToElementType.put("H2", "HeadingElement"); |
| + tagToElementType.put("H3", "HeadingElement"); |
| + tagToElementType.put("H4", "HeadingElement"); |
| + tagToElementType.put("H5", "HeadingElement"); |
| + tagToElementType.put("H6", "HeadingElement"); |
| + tagToElementType.put("HTML", "HtmlElement"); |
| + tagToElementType.put("IFRAME", "IFrameElement"); |
| + tagToElementType.put("IMG", "ImageElement"); |
| + tagToElementType.put("INPUT", "InputElement"); |
| + tagToElementType.put("KEYGEN", "KeygenElement"); |
| + tagToElementType.put("LI", "LIElement"); |
| + tagToElementType.put("LABEL", "LabelElement"); |
| + tagToElementType.put("LEGEND", "LegendElement"); |
| + tagToElementType.put("LINK", "LinkElement"); |
| + tagToElementType.put("MAP", "MapElement"); |
| + tagToElementType.put("MENU", "MenuElement"); |
| + tagToElementType.put("METER", "MeterElement"); |
| + tagToElementType.put("OL", "OListElement"); |
| + tagToElementType.put("OBJECT", "ObjectElement"); |
| + tagToElementType.put("OPTGROUP", "OptGroupElement"); |
| + tagToElementType.put("OUTPUT", "OutputElement"); |
| + tagToElementType.put("P", "ParagraphElement"); |
| + tagToElementType.put("PARAM", "ParamElement"); |
| + tagToElementType.put("PRE", "PreElement"); |
| + tagToElementType.put("PROGRESS", "ProgressElement"); |
| + tagToElementType.put("SCRIPT", "ScriptElement"); |
| + tagToElementType.put("SOURCE", "SourceElement"); |
| + tagToElementType.put("SPAN", "SpanElement"); |
| + tagToElementType.put("STYLE", "StyleElement"); |
| + tagToElementType.put("CAPTION", "TableCaptionElement"); |
| + tagToElementType.put("TD", "TableCellElement"); |
| + tagToElementType.put("COL", "TableColElement"); |
| + tagToElementType.put("TABLE", "TableElement"); |
| + tagToElementType.put("TR", "TableRowElement"); |
| + tagToElementType.put("TEXTAREA", "TextAreaElement"); |
| + tagToElementType.put("TITLE", "TitleElement"); |
| + tagToElementType.put("TRACK", "TrackElement"); |
| + tagToElementType.put("UL", "UListElement"); |
| + tagToElementType.put("VIDEO", "VideoElement"); |
| + tagToElementType.put("DART_EDITOR_NO_SUCH_TYPE", "DartEditorNoSuchElement"); |
| + } |
| + |
| + /** |
| + * Attempts to make better guess about return type of invocation. |
| + * |
| + * @return the better {@link Type} guess, may be "defaultType" if can not make better guess. |
| + */ |
| + public static Type resolve(Types types, DartUnqualifiedInvocation invocation, Element element, |
| + Type defaultType) { |
| + if (element == null) { |
| + return defaultType; |
| + } |
| + String name = element.getName(); |
| + List<DartExpression> arguments = invocation.getArguments(); |
| + LibraryElement libraryElement = Elements.getDeclaringLibrary(element); |
| + // html.query(String) |
| + if ("query".equals(name) && isHtmlLibraryFunction(element)) { |
| + return analyzeQuery(arguments, libraryElement, defaultType); |
| + } |
| + // no guess |
| + return defaultType; |
| + } |
| + |
| + /** |
| + * Attempts to make better guess about return type of invocation. |
| + * |
| + * @return the better {@link Type} guess, may be "defaultType" if can not make better guess. |
| + */ |
| + public static Type resolve(Types types, DartMethodInvocation invocation, Element element, |
| + Type defaultType) { |
| + if (element == null) { |
| + return defaultType; |
| + } |
| + String name = element.getName(); |
| + List<DartExpression> arguments = invocation.getArguments(); |
| + LibraryElement libraryElement = Elements.getDeclaringLibrary(element); |
| + // NodeSelector.query(String) |
| + EnclosingElement enclosingElement = element.getEnclosingElement(); |
| + if ("query".equals(name) && isDeclaredInHtmlLibrary(element) |
| + && ElementKind.of(enclosingElement) == ElementKind.CLASS |
| + && "NodeSelector".equals(enclosingElement.getName())) { |
| + return analyzeQuery(arguments, libraryElement, defaultType); |
| + } |
| + // no guess |
| + return defaultType; |
| + } |
| + |
| + private static Type analyzeQuery(List<DartExpression> arguments, LibraryElement libraryElement, |
| + Type defaultType) { |
| + if (arguments.size() == 1 && arguments.get(0) instanceof DartStringLiteral) { |
| + String selectors = ((DartStringLiteral) arguments.get(0)).getValue(); |
| + // if has spaces, full parsing required, because may be: E[text='warning text'] |
| + if (selectors.contains(" ")) { |
| + return defaultType; |
| + } |
| + // try to extract tag |
| + // http://www.w3.org/TR/CSS2/selector.html |
| + String tag = selectors; |
| + tag = StringUtils.substringBefore(tag, ":"); |
| + tag = StringUtils.substringBefore(tag, "["); |
| + tag = StringUtils.substringBefore(tag, "."); |
| + tag = StringUtils.substringBefore(tag, "#"); |
| + tag = tag.toUpperCase(); |
| + // prepare Element type name |
| + String tagTypeName = tagToElementType.get(tag); |
| + if (tagTypeName == null) { |
| + return defaultType; |
| + } |
| + // lookup tag Element |
| + Element tagTypeElement = libraryElement.lookupLocalElement(tagTypeName); |
| + if (tagTypeElement == null) { |
| + return defaultType; |
| + } |
| + // OK, we know more specific return type |
| + Type tagType = tagTypeElement.getType(); |
| + if (tagType != null) { |
| + return tagType; |
| + } |
| + } |
| + // no guess |
| + return defaultType; |
| + } |
| + |
| + private static boolean isHtmlLibraryFunction(Element element) { |
| + return ElementKind.of(element) == ElementKind.METHOD && isDeclaredInHtmlLibrary(element); |
| + } |
| + |
| + private static boolean isDeclaredInHtmlLibrary(Element element) { |
| + LibraryElement libraryElement = Elements.getDeclaringLibrary(element); |
| + return StringUtils.startsWith(libraryElement.getName(), "dart://html"); |
| + } |
| +} |