| Index: dart/compiler/javatests/com/google/dart/compiler/IdeTest.java
|
| diff --git a/dart/compiler/javatests/com/google/dart/compiler/IdeTest.java b/dart/compiler/javatests/com/google/dart/compiler/IdeTest.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..198a14554df52b6d26f4928f7bc23b8ec7a44f7f
|
| --- /dev/null
|
| +++ b/dart/compiler/javatests/com/google/dart/compiler/IdeTest.java
|
| @@ -0,0 +1,270 @@
|
| +// 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;
|
| +
|
| +import com.google.dart.compiler.ast.DartClass;
|
| +import com.google.dart.compiler.ast.DartExprStmt;
|
| +import com.google.dart.compiler.ast.DartExpression;
|
| +import com.google.dart.compiler.ast.DartIdentifier;
|
| +import com.google.dart.compiler.ast.DartMethodDefinition;
|
| +import com.google.dart.compiler.ast.DartNode;
|
| +import com.google.dart.compiler.ast.DartPropertyAccess;
|
| +import com.google.dart.compiler.ast.DartReturnStatement;
|
| +import com.google.dart.compiler.ast.DartStatement;
|
| +import com.google.dart.compiler.ast.DartUnit;
|
| +import com.google.dart.compiler.ast.DartUnqualifiedInvocation;
|
| +import com.google.dart.compiler.ast.LibraryUnit;
|
| +import com.google.dart.compiler.resolver.ClassElement;
|
| +import com.google.dart.compiler.resolver.CoreTypeProvider;
|
| +import com.google.dart.compiler.resolver.CoreTypeProviderImplementation;
|
| +import com.google.dart.compiler.resolver.Element;
|
| +import com.google.dart.compiler.resolver.FieldElement;
|
| +import com.google.dart.compiler.resolver.MethodElement;
|
| +import com.google.dart.compiler.resolver.Scope;
|
| +import com.google.dart.compiler.testing.TestCompilerConfiguration;
|
| +import com.google.dart.compiler.testing.TestCompilerContext;
|
| +import com.google.dart.compiler.testing.TestCompilerContext.EventKind;
|
| +import com.google.dart.compiler.testing.TestDartArtifactProvider;
|
| +import com.google.dart.compiler.testing.TestLibrarySource;
|
| +import com.google.dart.compiler.type.FunctionType;
|
| +import com.google.dart.compiler.type.InterfaceType;
|
| +import com.google.dart.compiler.type.Type;
|
| +import com.google.dart.compiler.type.TypeAnalyzer;
|
| +
|
| +import junit.framework.TestCase;
|
| +
|
| +import java.io.IOException;
|
| +
|
| +/**
|
| + * Test of the IDE API in DartCompiler.
|
| + */
|
| +public class IdeTest extends TestCase {
|
| +
|
| + private final TestCompilerContext context = new TestCompilerContext(EventKind.ERROR,
|
| + EventKind.TYPE_ERROR) {
|
| + @Override
|
| + protected void handleEvent(DartCompilationError event, EventKind kind) {
|
| + super.handleEvent(event, kind);
|
| + // For debugging:
|
| + // System.err.println(event);
|
| + }
|
| + };
|
| +
|
| + private final DartCompilerListener listener = context;
|
| +
|
| + private final DartArtifactProvider provider = new TestDartArtifactProvider();
|
| +
|
| + private final CompilerConfiguration config = new TestCompilerConfiguration();
|
| +
|
| + public void testAnalyseNoSemicolonPropertyAccess() {
|
| + DartUnit unit =
|
| + analyzeUnit(
|
| + "no_semicolon_property_access",
|
| + "class Foo {",
|
| + " int i;",
|
| + " void foo() {",
|
| + " i.y", // Missing semicolon.
|
| + " }",
|
| + "}");
|
| + assertEquals("errorCount", 1, context.getErrorCount()); // Missing semicolon.
|
| + assertEquals("typeErrorCount", 1, context.getTypeErrorCount()); // No member named "y".
|
| + DartExprStmt statement = (DartExprStmt) firstStatementOfMethod(unit, "Foo", "foo");
|
| + FieldElement element = (FieldElement) qualifierElement(statement.getExpression());
|
| + assertEquals("int", element.getType().getElement().getName());
|
| + }
|
| +
|
| + public void testAnalyseNoSemicolonBrokenPropertyAccess() {
|
| + DartUnit unit =
|
| + analyzeUnit(
|
| + "no_semicolon_broken_property_access",
|
| + "class Foo {",
|
| + " int i;",
|
| + " void foo() {",
|
| + " i.", // Syntax error and missing semicolon.
|
| + " }",
|
| + "}");
|
| + // Expected identifier and missing semicolon
|
| + assertEquals("errorCount", 2, context.getErrorCount());
|
| + assertEquals("typeErrorCount", 1, context.getTypeErrorCount()); // No member named "".
|
| + DartExprStmt statement = (DartExprStmt) firstStatementOfMethod(unit, "Foo", "foo");
|
| + FieldElement element = (FieldElement) qualifierElement(statement.getExpression());
|
| + assertEquals("int", element.getType().getElement().getName());
|
| + }
|
| +
|
| + public void testAnalyseBrokenPropertyAccess() {
|
| + DartUnit unit =
|
| + analyzeUnit(
|
| + "broken_property_access",
|
| + "class Foo {",
|
| + " int i;",
|
| + " void foo() {",
|
| + " i.;", // Syntax error here.
|
| + " }",
|
| + "}");
|
| + assertEquals("errorCount", 1, context.getErrorCount()); // Expected identifier.
|
| + assertEquals("typeErrorCount", 1, context.getTypeErrorCount()); // No member named "".
|
| + DartExprStmt statement = (DartExprStmt) firstStatementOfMethod(unit, "Foo", "foo");
|
| + FieldElement element = (FieldElement) qualifierElement(statement.getExpression());
|
| + assertEquals("int", element.getType().getElement().getName());
|
| + }
|
| +
|
| + public void testAnalyseNoSemicolonIdentifier() {
|
| + DartUnit unit =
|
| + analyzeUnit(
|
| + "no_semicolon_identifier",
|
| + "class Foo {",
|
| + " int i;",
|
| + " void foo() {",
|
| + " i", // Missing semicolon.
|
| + " }",
|
| + "}");
|
| + assertEquals("errorCount", 1, context.getErrorCount()); // Missing semicolon.
|
| + assertEquals("typeErrorCount", 0, context.getTypeErrorCount());
|
| + DartExprStmt statement = (DartExprStmt) firstStatementOfMethod(unit, "Foo", "foo");
|
| + FieldElement field = (FieldElement) targetElement(statement.getExpression());
|
| + assertEquals("int", field.getType().getElement().getName());
|
| + }
|
| +
|
| + public void testAnalyseNoSemicolonMethodCall() {
|
| + DartUnit unit =
|
| + analyzeUnit(
|
| + "no_semicolon_method_call",
|
| + "class Foo {",
|
| + " int i () { return 0; }",
|
| + " void foo() {",
|
| + " i()", // Missing semicolon.
|
| + " }",
|
| + "}");
|
| + assertEquals("errorCount", 1, context.getErrorCount()); // Missing semicolon.
|
| + assertEquals("typeErrorCount", 0, context.getTypeErrorCount());
|
| + DartExprStmt statement = (DartExprStmt) firstStatementOfMethod(unit, "Foo", "foo");
|
| + DartExpression expression = statement.getExpression();
|
| + DartUnqualifiedInvocation invocation = (DartUnqualifiedInvocation) expression;
|
| + MethodElement method = (MethodElement) targetElement(invocation.getTarget());
|
| + assertEquals("i", method.getName());
|
| + FunctionType type = (FunctionType) method.getType();
|
| + assertEquals("int", type.getReturnType().getElement().getName());
|
| + }
|
| +
|
| + public void testAnalyseVoidKeyword() {
|
| + DartUnit unit =
|
| + analyzeUnit(
|
| + "void_keyword",
|
| + "class Foo {",
|
| + " Function voidFunction;",
|
| + " void foo() {",
|
| + " void", // Missing semicolon and keyword
|
| + " }",
|
| + "}");
|
| + // Expected identifier and missing semicolon.
|
| + assertEquals("errorCount", 2, context.getErrorCount());
|
| + // You can't use 'void' as a member name. It might be the beginning of a variable declaration
|
| + // so it isn't an error in and of itself.
|
| + assertEquals("typeErrorCount", 0, context.getTypeErrorCount());
|
| + DartExprStmt statement = (DartExprStmt) firstStatementOfMethod(unit, "Foo", "foo");
|
| + DartIdentifier expression = (DartIdentifier) statement.getExpression();
|
| + assertEquals("", expression.getName());
|
| + }
|
| +
|
| + public void testAnalyseVoidKeywordPropertyAccess() {
|
| + DartUnit unit =
|
| + analyzeUnit(
|
| + "void_keyword_property_access",
|
| + "class Foo {",
|
| + " Function voidFunction;",
|
| + " void foo() {",
|
| + " this.void", // Missing semicolon and keyword
|
| + " }",
|
| + "}");
|
| + // Expected identifier and missing semicolon.
|
| + assertEquals("errorCount", 2, context.getErrorCount());
|
| + assertEquals("typeErrorCount", 1, context.getTypeErrorCount());
|
| + DartExprStmt statement = (DartExprStmt) firstStatementOfMethod(unit, "Foo", "foo");
|
| + DartPropertyAccess expression = (DartPropertyAccess) statement.getExpression();
|
| + assertEquals("", expression.getPropertyName());
|
| + }
|
| +
|
| + public void testReturnIntTypeAnalysis() {
|
| + DartUnit unit =
|
| + analyzeUnit(
|
| + "return_int_type_analysis",
|
| + "class Foo {",
|
| + " int i;",
|
| + " int foo() {",
|
| + " return i;",
|
| + " }",
|
| + "}");
|
| + Scope unitScope = unit.getLibrary().getElement().getScope();
|
| + CoreTypeProvider typeProvider = new CoreTypeProviderImplementation(unitScope, context);
|
| + DartClass classNode = getClassOfUnit(unit, "Foo");
|
| + DartReturnStatement rtnStmt = (DartReturnStatement) firstStatementOfMethod(unit, "Foo", "foo");
|
| + ClassElement classElement = classNode.getElement();
|
| + InterfaceType definingType = classElement.getType();
|
| + Type type = TypeAnalyzer.analyze(rtnStmt.getValue(), typeProvider, context, definingType);
|
| + assertNotNull(type);
|
| + assertEquals("int", type.getElement().getName());
|
| + }
|
| +
|
| + private Element targetElement(DartExpression expression) {
|
| + DartIdentifier identifier = (DartIdentifier) expression;
|
| + Element element = identifier.getElement();
|
| + assertNotNull(element);
|
| + return element;
|
| + }
|
| +
|
| + private Element qualifierElement(DartExpression node) {
|
| + DartPropertyAccess propertyAccess = (DartPropertyAccess) node;
|
| + DartIdentifier identifier = (DartIdentifier) propertyAccess.getQualifier();
|
| + Element element = identifier.getElement();
|
| + assertNotNull(element);
|
| + return element;
|
| + }
|
| +
|
| + private DartClass getClassOfUnit(DartUnit unit, String cls) {
|
| + DartClass dartClass = null;
|
| + for (DartNode node : unit.getTopLevelNodes()) {
|
| + DartClass classNode = (DartClass) node;
|
| + if (node instanceof DartClass) {
|
| + if (classNode.getName().getName().equals(cls)) {
|
| + dartClass = classNode;
|
| + }
|
| + }
|
| + }
|
| + assertNotNull(dartClass);
|
| + return dartClass;
|
| + }
|
| +
|
| + private DartStatement firstStatementOfMethod(DartUnit unit, String cls, String member) {
|
| + DartClass classNode = getClassOfUnit(unit, cls);
|
| + for (DartNode memberNode : classNode.getMembers()) {
|
| + if (memberNode instanceof DartMethodDefinition) {
|
| + DartMethodDefinition methodNode = (DartMethodDefinition) memberNode;
|
| + if (methodNode.getName() instanceof DartIdentifier) {
|
| + DartIdentifier methodName = (DartIdentifier) methodNode.getName();
|
| + if (methodName.getName().equals(member)) {
|
| + return methodNode.getFunction().getBody().getStatements().get(0);
|
| + }
|
| + }
|
| + }
|
| + }
|
| + fail();
|
| + return null;
|
| + }
|
| +
|
| + private DartUnit analyzeUnit(String name, String... sourceLines) throws AssertionError {
|
| + TestLibrarySource lib = new TestLibrarySource(name);
|
| + lib.addSource(name + ".dart", sourceLines);
|
| + LibraryUnit libraryUnit;
|
| + try {
|
| + libraryUnit = DartCompiler.analyzeLibrary(lib, null, config, provider, listener);
|
| + assertNotNull("libraryUnit == null", libraryUnit);
|
| + } catch (IOException e) {
|
| + throw new AssertionError(e);
|
| + }
|
| + DartUnit unit = libraryUnit.getUnit(name + ".dart");
|
| + assertNotNull("unit == null", unit);
|
| + return unit;
|
| + }
|
| +}
|
|
|