blob: 22a9970a5ad40a2c9a25752b5591bb81328f6a73 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
*
* 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 org.netbeans.modules.java.hints.test.api;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.util.TreePath;
import java.io.ByteArrayOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import javax.swing.text.Document;
import org.junit.Assert;
import org.junit.Test;
import org.netbeans.api.java.source.ClasspathInfo.PathKind;
import org.netbeans.api.java.source.CompilationInfo;
import org.netbeans.api.java.source.JavaSource;
import org.netbeans.spi.editor.hints.ChangeInfo;
import org.netbeans.spi.editor.hints.ErrorDescription;
import org.netbeans.spi.editor.hints.Fix;
import org.netbeans.spi.java.hints.ErrorDescriptionFactory;
import org.netbeans.spi.java.hints.Hint;
import org.netbeans.spi.java.hints.HintContext;
import org.netbeans.spi.java.hints.JavaFix;
import org.netbeans.spi.java.hints.JavaFix.TransformationContext;
import org.netbeans.spi.java.hints.TriggerTreeKind;
import org.openide.cookies.EditorCookie;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataObject;
/**
*
* @author lahvac
*/
public class HintTestTest {
public HintTestTest() {
}
@Test
public void testNonJavaChanges() throws Exception {
HintTest.create()
.input("package test;\n" +
"public class Test { }\n")
.input("test/test.txt", "1\n2\n", false)
.run(NonJavaChanges.class)
.findWarning("1:13-1:17:verifier:Test")
.applyFix()
.assertVerbatimOutput("test/test.txt", "2\n3\n");
}
@Test
public void test220070() throws Exception {
HintTest.create()
.input("package test;\n" +
"public class Test { }\n")
.input("test/test.txt", "1\n2\n", false)
.run(NonJavaChanges.class)
.findWarning("1:13-1:17:verifier:Test")
.applyFix()
.assertOutput("test/test.txt", "2\r3\r");
}
@Test
public void testNonJavaChangesOpenedInEditor() throws Exception {
HintTest ht = HintTest.create()
.input("package test;\n" +
"public class Test { }\n")
.input("test/test.txt", "1\n2\n", false);
FileObject resource = ht.getSourceRoot().getFileObject("test/test.txt");
DataObject od = DataObject.find(resource);
EditorCookie ec = od.getLookup().lookup(EditorCookie.class);
Document doc = ec.openDocument();
doc.remove(0, doc.getLength());
doc.insertString(0, "5\n6\n", null);
ht.run(NonJavaChanges.class)
.findWarning("1:13-1:17:verifier:Test")
.applyFix(false)
.assertVerbatimOutput("test/test.txt", "6\n7\n");
Assert.assertEquals("1\n2\n", resource.asText("UTF-8"));
Assert.assertEquals("6\n7\n", doc.getText(0, doc.getLength()));
}
@Hint(displayName="testingNonJavaChanges", description="testingNonJavaChanges", category="test")
public static final class NonJavaChanges {
@TriggerTreeKind(Kind.CLASS)
public static ErrorDescription hint(HintContext ctx) {
return ErrorDescriptionFactory.forName(ctx, ctx.getPath(), "Test", new TestingNonJavaChangesFix(ctx.getInfo(), ctx.getPath()).toEditorFix());
}
}
private static final class TestingNonJavaChangesFix extends JavaFix {
public TestingNonJavaChangesFix(CompilationInfo info, TreePath tp) {
super(info, tp);
}
@Override protected String getText() {
return "Test";
}
@Override protected void performRewrite(TransformationContext ctx) {
try {
FileObject resource = ctx.getWorkingCopy().getFileObject().getParent().getFileObject("test.txt");
Assert.assertNotNull(resource);
Reader r = new InputStreamReader(ctx.getResourceContent(resource), "UTF-8");
ByteArrayOutputStream outData = new ByteArrayOutputStream();
Writer w = new OutputStreamWriter(outData, "UTF-8");
int read;
while ((read = r.read()) != -1) {
if (read != '\n') read++;
w.write(read);
}
r.close();
w.close();
OutputStream out = ctx.getResourceOutput(resource);
out.write(outData.toByteArray());
out.close();
} catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
}
@Test
public void testMeaningfullSourcePath() throws Exception {
HintTest.create()
.input("package test;\n" +
"public class Test { }\n")
.run(MeaningfullSourcePath.class)
.assertWarnings();
}
@Hint(displayName="meaningfullSourcePath", description="meaningfullSourcePath", category="test")
public static final class MeaningfullSourcePath {
@TriggerTreeKind(Kind.CLASS)
public static ErrorDescription hint(HintContext ctx) {
if (ctx.getInfo().getClasspathInfo().getClassPath(PathKind.SOURCE).findOwnerRoot(ctx.getInfo().getFileObject()) == null) {
return ErrorDescriptionFactory.forTree(ctx, ctx.getPath(), "Broken Source Path");
}
return null;
}
}
@Test
public void testCompilationClassPath() throws Exception {
HintTest.create()
.input("package test;\n" +
"public class Test { }\n")
.classpath(FileUtil.getArchiveRoot(JavaSource.class.getProtectionDomain().getCodeSource().getLocation()))
.run(CompilationClassPath.class)
.assertWarnings();
}
@Hint(displayName="compilationClassPath", description="compilationClassPath", category="test")
public static final class CompilationClassPath {
@TriggerTreeKind(Kind.CLASS)
public static ErrorDescription hint(HintContext ctx) {
FileObject clazz = ctx.getInfo().getClasspathInfo().getClassPath(PathKind.COMPILE).findResource("org/netbeans/api/java/source/JavaSource.class");
if (clazz == null) {
return ErrorDescriptionFactory.forTree(ctx, ctx.getPath(), "Broken Compilation ClassPath");
}
return null;
}
}
@Test
public void testHintThrowsException() throws Exception {
HintTest ht = HintTest.create()
.input("package test;\n" +
"public class Test { }\n");
try {
ht.run(HintThrowsException.class);
Assert.fail("No exception thrown");
} catch (Exception ex) {
//ok
Assert.assertEquals(IllegalStateException.class, ex.getClass());
Assert.assertNotNull(ex.getCause());
Assert.assertEquals(NullPointerException.class, ex.getCause().getClass());
Assert.assertEquals("a", ex.getCause().getMessage());
}
}
@Hint(displayName="hintThrowsException", description="hintThrowsException", category="test")
public static final class HintThrowsException {
@TriggerTreeKind(Kind.CLASS)
public static ErrorDescription hint(HintContext ctx) {
throw new NullPointerException("a");
}
}
@Test
public void testNonJavaFix() throws Exception {
HintTest ht = HintTest.create()
.input("package test;\n" +
"public class Test { }\n");
try {
ht.run(NonJavaFix.class)
.findWarning("1:0-1:21:verifier:Test")
.applyFix();
Assert.fail("No exception thrown");
} catch (AssertionError ae) {
//ok
Assert.assertEquals("The fix must be a JavaFix", ae.getMessage());
}
}
@Hint(displayName="nonJavaFix", description="nonJavaFix", category="test")
public static final class NonJavaFix {
@TriggerTreeKind(Kind.CLASS)
public static ErrorDescription hint(HintContext ctx) {
return ErrorDescriptionFactory.forTree(ctx, ctx.getPath(), "Test", new Fix() {
@Override public String getText() {
return "Fix";
}
@Override public ChangeInfo implement() throws Exception {
return null;
}
});
}
}
@Test
public void testNotRepeatableJavaFix() throws Exception {
HintTest ht = HintTest.create()
.input("package test;\n" +
"public class Test { }\n");
try {
ht.run(NotRepeatableJavaFix.class)
.findWarning("1:0-1:21:verifier:Test")
.applyFix();
Assert.fail("No exception thrown");
} catch (AssertionError ae) {
//ok
Assert.assertTrue(ae.getMessage().startsWith("The fix must be repeatable"));
}
}
@Hint(displayName="notRepeatableJavaFix", description="notRepeatableJavaFix", category="test")
public static final class NotRepeatableJavaFix {
@TriggerTreeKind(Kind.CLASS)
public static ErrorDescription hint(HintContext ctx) {
Fix f = new JavaFix(ctx.getInfo(), ctx.getPath()) {
private boolean wasRun;
@Override protected String getText() {
return "Fix";
}
@Override protected void performRewrite(TransformationContext ctx) throws Exception {
if (wasRun) return ;
ctx.getWorkingCopy().rewrite(ctx.getPath().getLeaf(), ctx.getWorkingCopy().getTreeMaker().setLabel(ctx.getPath().getLeaf(), "Nue"));
wasRun = true;
}
}.toEditorFix();
return ErrorDescriptionFactory.forTree(ctx, ctx.getPath(), "Test", f);
}
}
@Test
public void testNonJavaChangesOpenedInEditor214197() throws Exception {
HintTest ht = HintTest.create()
.input("package test;\n" +
"public class Test { }\n")
.input("test/test.txt", "1\n#foobar\n\n2", false);
FileObject resource = ht.getSourceRoot().getFileObject("test/test.txt");
DataObject od = DataObject.find(resource);
EditorCookie ec = od.getLookup().lookup(EditorCookie.class);
Document doc = ec.openDocument();
doc.remove(0, doc.getLength());
doc.insertString(0, "5\n6\n", null);
ht.run(NonJavaChanges.class)
.findWarning("1:13-1:17:verifier:Test")
.applyFix(false)
.assertVerbatimOutput("test/test.txt", "6\n7\n");
Assert.assertEquals("1\n#foobar\n\n2", resource.asText("UTF-8"));
Assert.assertEquals("6\n7\n", doc.getText(0, doc.getLength()));
}
@Test
public void testModuleBootPath() throws Exception {
HintTest.create()
.sourceLevel("9")
.input("module-info.java",
"module m1 {}\n")
.run(ModuleBootPath.class)
.assertWarnings("0:0-0:12:verifier:Test");
}
@Hint(displayName="testModuleBootPath", description="testModuleBootPath", category="test")
public static final class ModuleBootPath {
@TriggerTreeKind(Kind.MODULE)
public static ErrorDescription hint(HintContext ctx) {
return ErrorDescriptionFactory.forTree(ctx, ctx.getPath(), "Test");
}
}
}