org.netbeans.modules.jackpot30.indexer.usages.IndexerImplTest.java Source code

Java tutorial

Introduction

Here is the source code for org.netbeans.modules.jackpot30.indexer.usages.IndexerImplTest.java

Source

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
 *
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
 * Other names may be trademarks of their respective owners.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common
 * Development and Distribution License("CDDL") (collectively, the
 * "License"). You may not use this file except in compliance with the
 * License. You can obtain a copy of the License at
 * http://www.netbeans.org/cddl-gplv2.html
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
 * specific language governing permissions and limitations under the
 * License.  When distributing the software, include this License Header
 * Notice in each file and include the License file at
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the GPL Version 2 section of the License file that
 * accompanied this code. If applicable, add the following below the
 * License Header, with the fields enclosed by brackets [] replaced by
 * your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * If you wish your version of this file to be governed by only the CDDL
 * or only the GPL Version 2, indicate your decision by adding
 * "[Contributor] elects to include this software in this distribution
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
 * single choice of license, a recipient has the option to distribute
 * your version of this file under either the CDDL, the GPL Version 2 or
 * to extend the choice of license to its licensees as provided above.
 * However, if you add GPL Version 2 code and therefore, elected the GPL
 * Version 2 license, then the option applies only if the new code is
 * made subject to such option by the copyright holder.
 *
 * Contributor(s):
 *
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
 */
package org.netbeans.modules.jackpot30.indexer.usages;

import com.sun.source.util.TreePath;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.util.ElementFilter;
import org.apache.lucene.analysis.KeywordAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import org.netbeans.api.editor.mimelookup.MimePath;
import org.netbeans.api.java.source.CompilationController;
import org.netbeans.api.java.source.ElementHandle;
import org.netbeans.api.java.source.JavaSource;
import org.netbeans.api.java.source.Task;
import org.netbeans.junit.NbTestCase;
import org.netbeans.modules.jackpot30.backend.impl.spi.IndexAccessor;
import org.netbeans.modules.java.source.indexing.JavaCustomIndexer;
import org.netbeans.modules.java.source.parsing.JavacParser;
import org.netbeans.modules.java.source.parsing.JavacParserFactory;
import org.netbeans.modules.parsing.impl.indexing.CacheFolder;
import org.netbeans.modules.parsing.impl.indexing.FileObjectIndexable;
import org.netbeans.modules.parsing.impl.indexing.MimeTypes;
import org.netbeans.modules.parsing.impl.indexing.SPIAccessor;
import org.netbeans.spi.editor.mimelookup.MimeDataProvider;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.MIMEResolver;
import org.openide.util.Lookup;
import org.openide.util.lookup.Lookups;
import org.openide.util.lookup.ServiceProvider;

/**
 *
 * @author lahvac
 */
public class IndexerImplTest extends NbTestCase {

    public IndexerImplTest(String testName) {
        super(testName);
    }

    @Override
    protected void setUp() throws Exception {
        Set<String> mimeTypes = MimeTypes.getAllMimeTypes();
        if (mimeTypes == null) {
            mimeTypes = new HashSet<String>();
        } else {
            mimeTypes = new HashSet<String>(mimeTypes);
        }

        mimeTypes.add("text/x-java");
        MimeTypes.setAllMimeTypes(mimeTypes);

        org.netbeans.api.project.ui.OpenProjects.getDefault().getOpenProjects();
        clearWorkDir();
        CacheFolder.setCacheFolder(FileUtil.toFileObject(getWorkDir()));
        super.setUp();
    }

    public void testMethodSignatures() throws IOException {
        doMethodSignatureTest("package test; public class Test { public void test() {} }", "()V;");
        doMethodSignatureTest(
                "package test; public class Test { public <T extends String> void test(java.util.Map<java.util.List<String>, T> m, boolean p) {} }",
                "<T:Ljava/lang/String;>(Ljava/util/Map<Ljava/util/List<Ljava/lang/String;>;TT;>;Z)V;");
        doMethodSignatureTest(
                "package test; public class Test <T extends String> { public void test(java.util.Map<java.util.List<String>, T> m, boolean p) {} }",
                "(Ljava/util/Map<Ljava/util/List<Ljava/lang/String;>;TT;>;Z)V;");
        doMethodSignatureTest(
                "package test; public class Test { public void test() throws java.io.IOException {} }",
                "()V^Ljava/io/IOException;;");
        doMethodSignatureTest(
                "package test; public class Test { public void test(java.util.List<? extends String> l) {} }",
                "(Ljava/util/List<+Ljava/lang/String;>;)V;");
        doMethodSignatureTest(
                "package test; public class Test <T extends String> { public <P extends T> void test(P p) {} }",
                "<P:TT;>(TP;)V;");
    }

    protected void doMethodSignatureTest(String code, final String signature) throws IOException {
        FileObject testFile = FileUtil.createData(new File(getWorkDir(), "Test.java"));

        copyToFile(testFile, code);

        final boolean[] invoked = new boolean[1];

        JavaSource.forFileObject(testFile).runUserActionTask(new Task<CompilationController>() {
            @Override
            public void run(CompilationController parameter) throws Exception {
                parameter.toPhase(JavaSource.Phase.RESOLVED);

                ExecutableElement method = ElementFilter
                        .methodsIn(parameter.getTopLevelElements().get(0).getEnclosedElements()).iterator().next();

                assertEquals(signature, IndexerImpl.methodTypeSignature(parameter.getElements(), method));
                invoked[0] = true;
            }
        }, true);

        assertTrue(invoked[0]);
    }

    public void testOverriddenMethods() throws IOException {
        doOverriddenMethodsTest("package test; public class Test { public String toStr|ing() { return null; } }",
                "METHOD:java.lang.Object:toString:()Ljava/lang/String;");
        doOverriddenMethodsTest(
                "package test; public class Test extends A implements B { public void t|t() { } } class A implements B { public void tt() {} } interface B { public void tt(); }",
                "METHOD:test.A:tt:()V", "METHOD:test.B:tt:()V");
    }

    protected void doOverriddenMethodsTest(String code, final String... signature) throws IOException {
        final int pos = code.indexOf('|');

        code = code.replace("|", "");
        FileObject testFile = FileUtil.createData(new File(getWorkDir(), "Test.java"));

        copyToFile(testFile, code);

        final boolean[] invoked = new boolean[1];

        JavaSource.forFileObject(testFile).runUserActionTask(new Task<CompilationController>() {
            @Override
            public void run(CompilationController parameter) throws Exception {
                parameter.toPhase(JavaSource.Phase.RESOLVED);

                TreePath selected = parameter.getTreeUtilities().pathFor(pos);
                ExecutableElement method = (ExecutableElement) parameter.getTrees().getElement(selected);
                List<String> result = new ArrayList<String>();

                for (ExecutableElement ee : IndexerImpl.overrides(parameter.getTypes(), parameter.getElements(),
                        method)) {
                    result.add(Common.serialize(ElementHandle.create(ee)));
                }

                assertEquals(Arrays.asList(signature), result);
                invoked[0] = true;
            }
        }, true);

        assertTrue(invoked[0]);
    }

    public void testRepeatedIndexing() throws IOException {
        final FileObject root = FileUtil.toFileObject(getWorkDir());
        FileObject testFile = FileUtil.createData(root, "Test.java");
        copyToFile(testFile, "public class Test {}");

        Directory store = new RAMDirectory();
        IndexWriter iw = new IndexWriter(store, new KeywordAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED);
        IndexAccessor.current = new IndexAccessor(iw, root);

        iw.addDocument(fakeDocument(testFile));

        doIndex(root, testFile);

        iw.close();
        IndexReader ir = IndexReader.open(store);

        int expectedDocumentsCount = ir.numDocs();

        assertEquals(3 + 1, expectedDocumentsCount);

        store = new RAMDirectory();
        iw = new IndexWriter(store, new KeywordAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED);
        IndexAccessor.current = new IndexAccessor(iw, root);

        iw.addDocument(fakeDocument(testFile));

        doIndex(root, testFile);
        doIndex(root, testFile);

        iw.close();
        ir = IndexReader.open(store);

        assertEquals(expectedDocumentsCount, ir.numDocs());
    }

    public void testSubdirIndexing() throws IOException {
        final FileObject root = FileUtil.toFileObject(getWorkDir());
        FileObject aFile = FileUtil.createData(root, "a/A.java");
        copyToFile(aFile, "public class A {}");
        FileObject bFile = FileUtil.createData(root, "b/B.java");
        copyToFile(bFile, "public class B {}");

        Directory store = new RAMDirectory();
        IndexWriter iw = new IndexWriter(store, new KeywordAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED);
        IndexAccessor.current = new IndexAccessor(iw, root.getFileObject("a"));

        doIndex(root, aFile, bFile);

        iw.close();

        IndexReader ir = IndexReader.open(store);
        int maxDocs = ir.maxDoc();
        boolean foundA = false;

        for (int i = 0; i < maxDocs; i++) {
            Fieldable f = ir.document(i).getFieldable("file");

            if (f != null) {
                assertFalse(f.stringValue(), f.stringValue().contains("B"));
                if (f.stringValue().contains("A.java")) {
                    foundA = true;
                }
            }
        }

        assertTrue(foundA);
    }

    public void testTreePositions() throws IOException {
        doPositionTests("package test; public class Test { private Test() { ^Sy|stem.err.println(1); } }");
        doPositionTests("package test; public class Test { private Test() { System.^e|rr.println(1); } }");
        doPositionTests("package test; public class Test { private Test() { System.err.^p|rintln(1); } }");
    }

    private void doPositionTests(String code) throws IOException {
        final int caret = code.replace("^", "").indexOf('|');

        assertTrue("" + caret, caret != (-1));

        code = code.replace("|", "");

        final int expected = code.indexOf('^');

        assertTrue("" + expected, expected != (-1));

        FileObject testFile = FileUtil.createData(new File(getWorkDir(), "Test.java"));

        copyToFile(testFile, code.replace("^", ""));

        final boolean[] invoked = new boolean[1];

        JavaSource.forFileObject(testFile).runUserActionTask(new Task<CompilationController>() {
            @Override
            public void run(CompilationController parameter) throws Exception {
                parameter.toPhase(JavaSource.Phase.RESOLVED);

                TreePath tp = parameter.getTreeUtilities().pathFor(caret);

                assertEquals(expected, IndexerImpl.treePosition(parameter.getTrees(), tp));

                invoked[0] = true;
            }
        }, true);

        assertTrue(invoked[0]);
    }

    private void copyToFile(FileObject testFile, String code) throws IOException {
        OutputStream out = testFile.getOutputStream();

        try {
            out.write(code.getBytes());
        } finally {
            out.close();
        }
    }

    private Document fakeDocument(FileObject testFile) {
        //to test that unrelated document are not deleted:
        Document doc = new Document();

        doc.add(new Field("file", IndexAccessor.getCurrent().getPath(testFile.toURL()), Store.YES,
                Index.NOT_ANALYZED));

        return doc;
    }

    private void doIndex(final FileObject root, FileObject... testFiles)
            throws IOException, IllegalArgumentException {
        final boolean[] invoked = new boolean[1];

        for (FileObject testFile : testFiles) {
            JavaSource.forFileObject(testFile).runUserActionTask(new Task<CompilationController>() {
                @Override
                public void run(CompilationController parameter) throws Exception {
                    parameter.toPhase(JavaSource.Phase.RESOLVED);

                    new IndexerImpl(root.toURL()).process(parameter.getCompilationUnit(),
                            SPIAccessor.getInstance()
                                    .create(new FileObjectIndexable(root, parameter.getFileObject())),
                            Lookups.fixed(parameter.getTrees(), parameter.getElements(), parameter.getTypes()));
                    invoked[0] = true;
                }
            }, true);
        }

        assertTrue(invoked[0]);
    }

    @ServiceProvider(service = MimeDataProvider.class)
    public static final class JavacParserProvider implements MimeDataProvider {

        private Lookup javaLookup = Lookups.fixed(new JavacParserFactory(), new JavaCustomIndexer.Factory());

        public Lookup getLookup(MimePath mimePath) {
            if (mimePath.getPath().endsWith(JavacParser.MIME_TYPE)) {
                return javaLookup;
            }

            return Lookup.EMPTY;
        }

    }

    @ServiceProvider(service = MIMEResolver.class)
    public static final class JavaMimeResolver extends MIMEResolver {

        public JavaMimeResolver() {
            super(JavacParser.MIME_TYPE);
        }

        @Override
        public String findMIMEType(FileObject fo) {
            if ("java".equals(fo.getExt())) {
                return JavacParser.MIME_TYPE;
            }

            return null;
        }

    }
}