com.google.dart.engine.internal.index.AbstractDartTest.java Source code

Java tutorial

Introduction

Here is the source code for com.google.dart.engine.internal.index.AbstractDartTest.java

Source

/*
 * Copyright (c) 2013, the Dart project authors.
 * 
 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 * 
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package com.google.dart.engine.internal.index;

import com.google.common.base.CharMatcher;
import com.google.common.base.Joiner;
import com.google.common.collect.Sets;
import com.google.dart.engine.AnalysisEngine;
import com.google.dart.engine.ast.ASTNode;
import com.google.dart.engine.ast.CompilationUnit;
import com.google.dart.engine.ast.SimpleIdentifier;
import com.google.dart.engine.ast.visitor.GeneralizingASTVisitor;
import com.google.dart.engine.context.AnalysisContext;
import com.google.dart.engine.context.ChangeSet;
import com.google.dart.engine.element.CompilationUnitElement;
import com.google.dart.engine.element.Element;
import com.google.dart.engine.element.LibraryElement;
import com.google.dart.engine.sdk.DartSdk;
import com.google.dart.engine.sdk.DirectoryBasedDartSdk;
import com.google.dart.engine.source.DartUriResolver;
import com.google.dart.engine.source.FileBasedSource;
import com.google.dart.engine.source.Source;
import com.google.dart.engine.source.SourceFactory;
import com.google.dart.engine.utilities.io.FileUtilities2;
import com.google.dart.engine.utilities.source.SourceRange;
import com.google.dart.engine.utilities.source.SourceRangeFactory;

import static com.google.dart.engine.utilities.io.FileUtilities2.createFile;

import junit.framework.TestCase;

import org.apache.commons.lang3.StringUtils;

import static org.fest.assertions.Assertions.assertThat;

import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;

public class AbstractDartTest extends TestCase {
    protected final static String EOL = System.getProperty("line.separator", "\n");
    protected final static String EOL2 = EOL + EOL;

    protected static final DartSdk defaultSdk = DirectoryBasedDartSdk.getDefaultSdk();
    protected static final SourceFactory sourceFactory = new SourceFactory(new DartUriResolver(defaultSdk));
    protected static AnalysisContext analysisContext;

    /**
     * @return {@link ASTNode} which has required offset and type.
     */
    public static <E extends ASTNode> E findNode(ASTNode root, final int offset, final Class<E> clazz) {
        final AtomicReference<E> resultRef = new AtomicReference<E>();
        root.accept(new GeneralizingASTVisitor<Void>() {
            @Override
            @SuppressWarnings("unchecked")
            public Void visitNode(ASTNode node) {
                if (node.getOffset() <= offset && offset < node.getEnd() && clazz.isInstance(node)) {
                    resultRef.set((E) node);
                }
                return super.visitNode(node);
            }
        });
        E result = resultRef.get();
        assertNotNull(result);
        return result;
    }

    /**
     * Function to force formatter to put every string on separate line.
     */
    public static String[] formatLines(String... lines) {
        return lines;
    }

    /**
     * @return the resolved {@link CompilationUnit} for given source.
     */
    public static CompilationUnit parseUnit(Source source) throws Exception {
        // parse and resolve
        LibraryElement library = analysisContext.computeLibraryElement(source);
        CompilationUnit libraryUnit = analysisContext.resolveCompilationUnit(source, library);
        return libraryUnit;
    }

    /**
     * @return the resolved {@link CompilationUnit} for given Dart code.
     */
    public static CompilationUnit parseUnit(String path, String code) throws Exception {
        ensureAnalysisContext();
        // configure Source
        Source source = new FileBasedSource(sourceFactory.getContentCache(), FileUtilities2.createFile(path));
        {
            sourceFactory.setContents(source, "");
            ChangeSet changeSet = new ChangeSet();
            changeSet.added(source);
            analysisContext.applyChanges(changeSet);
        }
        // update Source
        analysisContext.setContents(source, code);
        // parse and resolve
        LibraryElement library = analysisContext.computeLibraryElement(source);
        CompilationUnit libraryUnit = analysisContext.resolveCompilationUnit(source, library);
        return libraryUnit;
    }

    /**
     * Ensure that {@link #analysisContext} is initialized.
     */
    protected static void ensureAnalysisContext() {
        if (analysisContext == null) {
            analysisContext = AnalysisEngine.getInstance().createAnalysisContext();
            analysisContext.setSourceFactory(sourceFactory);
        }
    }

    protected static String makeSource(String... lines) {
        return Joiner.on(EOL).join(lines);
    }

    /**
     * Prints given multi-line source in the way ready to paste back into Java test source.
     */
    protected static void printSourceLines(String source) {
        String[] lines = StringUtils.splitByWholeSeparatorPreserveAllTokens(source, EOL);
        for (int i = 0; i < lines.length; i++) {
            String line = lines[i];
            line = StringUtils.replace(line, "\"", "\\\"");
            System.out.print("\"");
            System.out.print(line);
            if (i != lines.length - 1) {
                System.out.println("\",");
            } else {
                System.out.println("\"");
            }
        }
    }

    /**
     * @return {@link String} with system line separator converted to Unix <code>\n</code>.
     */
    protected static String toUnixEol(String s) {
        return s.replace(EOL, "\n");
    }

    private final Set<Source> sourceWithSetContent = Sets.newHashSet();

    protected boolean verifyNoTestUnitErrors = true;

    protected String testCode;
    protected Source testSource;
    protected CompilationUnit testUnit;
    protected CompilationUnitElement testUnitElement;
    protected LibraryElement testLibraryElement;

    /**
     * Add a source file to the content provider.
     * 
     * @param contents the contents to be returned by the content provider for the specified file
     * @return the source object representing the added file
     */
    protected Source addSource(String contents) {
        return addSource("/test.dart", contents);
    }

    /**
     * Add a source file to the content provider. The file path should be absolute.
     * 
     * @param filePath the path of the file being added
     * @param contents the contents to be returned by the content provider for the specified file
     * @return the source object representing the added file
     */
    protected Source addSource(String filePath, String contents) {
        ensureAnalysisContext();
        Source source = new FileBasedSource(sourceFactory.getContentCache(), createFile(filePath));
        // add Source to the context
        sourceFactory.setContents(source, contents);
        {
            ChangeSet changeSet = new ChangeSet();
            changeSet.added(source);
            analysisContext.applyChanges(changeSet);
        }
        // remember Source to remove from the context later
        sourceWithSetContent.add(source);
        // done
        return source;
    }

    /**
     * @return the {@link Element} if there is {@link SimpleIdentifier} at position of "search", not
     *         {@code null} or fails.
     */
    @SuppressWarnings("unchecked")
    protected final <T extends Element> T findElement(String search) {
        Element element = findSimpleIdentifier(search).getElement();
        assertNotNull(element);
        return (T) element;
    }

    /**
     * @return the offset directly after given <code>search</code> string in {@link testUnit}. Fails
     *         test if not found.
     */
    protected final int findEnd(String search) {
        return findOffset(search) + search.length();
    }

    /**
     * @return the {@link SimpleIdentifier} at the given search pattern.
     */
    protected final SimpleIdentifier findIdentifier(String search) {
        return findNode(search, SimpleIdentifier.class);
    }

    /**
     * @return the {@link Element} of the {@link SimpleIdentifier} at the given search pattern.
     */
    @SuppressWarnings("unchecked")
    protected final <T extends Element> T findIdentifierElement(String search) {
        return (T) findIdentifier(search).getElement();
    }

    /**
     * @return {@link ASTNode} form {@link #testUnit} which has required offset and type.
     */
    protected final <E extends ASTNode> E findNode(int offset, Class<E> clazz) {
        return findNode(testUnit, offset, clazz);
    }

    /**
     * @return {@link ASTNode} from {@link #testUnit} which starts at given text has has given type.
     */
    protected final <E extends ASTNode> E findNode(String search, Class<E> clazz) {
        int offset = findOffset(search);
        return findNode(testUnit, offset, clazz);
    }

    /**
     * @return the offset of given <code>search</code> string in {@link testUnit}. Fails test if not
     *         found.
     */
    protected final int findOffset(String search) {
        int offset = testCode.indexOf(search);
        assertThat(offset).describedAs(testCode).isNotEqualTo(-1);
        return offset;
    }

    /**
     * @return the {@link SourceRange} for given sub-string. Fails test if not found.
     */
    protected final SourceRange findRange(String search) {
        int start = findOffset(search);
        return SourceRangeFactory.rangeStartLength(start, search.length());
    }

    /**
     * @return the {@link SourceRange} for given start/end search strings. Fails test if not found.
     */
    protected final SourceRange findRangeIdentifier(String search) {
        int start = findOffset(search);
        int end = CharMatcher.JAVA_LETTER_OR_DIGIT.negate().indexIn(testCode, start);
        return SourceRangeFactory.rangeStartEnd(start, end);
    }

    /**
     * @return the {@link SourceRange} for given start/end search strings. Fails test if not found.
     */
    protected final SourceRange findRangeStartEnd(String searchStart, String searchEnd) {
        return SourceRangeFactory.rangeStartEnd(findOffset(searchStart), findOffset(searchEnd));
    }

    /**
     * @return the first {@link SimpleIdentifier} which starts at position of given string.
     */
    protected final SimpleIdentifier findSimpleIdentifier(String pattern) {
        return findNode(pattern, SimpleIdentifier.class);
    }

    /**
     * Sets {@link #testUnit} with mocked {@link Source} which has given code.
     */
    protected final void parseTestUnit(Source source) throws Exception {
        testUnit = parseUnit(source);
        testSource = testUnit.getElement().getSource();
        testUnitElement = testUnit.getElement();
        testLibraryElement = testUnitElement.getEnclosingElement();
        if (verifyNoTestUnitErrors) {
            assertThat(testUnit.getParsingErrors()).describedAs(testCode).isEmpty();
            assertThat(testUnit.getResolutionErrors()).isEmpty();
        }
    }

    /**
     * Sets {@link #testUnit} with mocked {@link Source} which has given code.
     */
    protected final void parseTestUnit(String... lines) throws Exception {
        testCode = makeSource(lines);
        testUnit = parseUnit("/Test.dart", testCode);
        testSource = testUnit.getElement().getSource();
        testUnitElement = testUnit.getElement();
        testLibraryElement = testUnitElement.getEnclosingElement();
        if (verifyNoTestUnitErrors) {
            assertThat(testUnit.getParsingErrors()).describedAs(testCode).isEmpty();
            assertThat(testUnit.getResolutionErrors()).isEmpty();
        }
    }

    /**
     * Sets {@link #testUnit} with mocked {@link Source} which has given code.
     */
    protected final void parseTestUnits(Source... sources) throws Exception {
        Source librarySource = sources[0];
        testSource = sources[1];
        testCode = sourceFactory.getContentCache().getContents(testSource);
        // fill AnalysisContext
        {
            ChangeSet changeSet = new ChangeSet();
            for (Source source : sources) {
                changeSet.added(source);
            }
            analysisContext.applyChanges(changeSet);
        }
        //
        testLibraryElement = analysisContext.computeLibraryElement(librarySource);
        testUnit = analysisContext.resolveCompilationUnit(testSource, testLibraryElement);
        testUnitElement = testUnit.getElement();
        if (verifyNoTestUnitErrors) {
            assertThat(testUnit.getParsingErrors()).describedAs(testCode).isEmpty();
            assertThat(testUnit.getResolutionErrors()).isEmpty();
        }
    }

    /**
     * Configures {@link SourceFactory} to use given content for file at given path.
     * 
     * @return the {@link Source} which corresponds given path.
     */
    protected final Source setFileContent(String path, String content) {
        FileBasedSource source = new FileBasedSource(sourceFactory.getContentCache(), createFile("/" + path));
        sourceWithSetContent.add(source);
        sourceFactory.setContents(source, content);
        return source;
    }

    @Override
    protected void tearDown() throws Exception {
        // reset SourceFactory
        for (Source source : sourceWithSetContent) {
            sourceFactory.setContents(source, null);
        }
        // reset AnalysisContext
        if (analysisContext != null) {
            ChangeSet changeSet = new ChangeSet();
            if (testSource != null) {
                changeSet.removed(testSource);
            }
            for (Source source : sourceWithSetContent) {
                changeSet.removed(source);
            }
            analysisContext.applyChanges(changeSet);
        }
        // continue
        super.tearDown();
    }
}