Java tutorial
/* * 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; } } }