/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 6550655
* @summary javac crashes when compiling against an annotated class
*/
import java.io.File;
import java.net.URI;
import java.util.Arrays;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticListener;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
public class T6550655 {
JavaCompiler javacTool;
File testDir;
TestKind testKind;
EnumActionKind actionKind;
String testSource = "enum E { NORTH, SOUTH, WEST, EAST; }\n" +
"@I(val = E.NORTH)class A {}\n" +
"@interface I { E val(); }";
T6550655(JavaCompiler javacTool, File testDir, TestKind testKind, EnumActionKind actionKind) {
this.javacTool = javacTool;
this.testDir = testDir;
this.testKind = testKind;
this.actionKind = actionKind;
}
void test() {
testDir.mkdirs();
compile(null, new JavaSource("Test.java", testSource));
actionKind.doAction(this);
compile(new DiagnosticChecker(), testKind.source);
}
void compile(DiagnosticChecker dc, JavaSource... sources) {
try {
CompilationTask ct = javacTool.getTask(null, null, dc,
Arrays.asList("-d", testDir.getAbsolutePath(), "-cp", testDir.getAbsolutePath()),
null, Arrays.asList(sources));
ct.call();
}
catch (Exception e) {
error("Internal compilation error");
}
}
void replaceEnum(String newSource) {
compile(null, new JavaSource("Replace.java", newSource));
};
void removeEnum() {
File enumClass = new File(testDir, "E.class");
if (!enumClass.exists()) {
error("Expected file E.class does not exists in folder " + testDir);
}
enumClass.delete();
};
void error(String msg) {
System.err.println(msg);
nerrors++;
}
class DiagnosticChecker implements DiagnosticListener<JavaFileObject> {
String[][] expectedKeys = new String[][] {
// DIRECT, INDIRECT
{/*REPLACE1*/ "compiler.err.cant.resolve.location" , "compiler.warn.unknown.enum.constant" },
{/*REPLACE2*/ "compiler.err.cant.resolve.location.args", "compiler.warn.annotation.method.not.found" },
{/*REMOVE*/ "compiler.err.cant.resolve" , "compiler.warn.unknown.enum.constant.reason" } };
String keyToIgnore = "compiler.err.attribute.value.must.be.constant";
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
String expectedCode = expectedKeys[actionKind.ordinal()][testKind.ordinal()];
if (!diagnostic.getCode().equals(keyToIgnore) &&
!diagnostic.getCode().equals(expectedCode)) {
error("Unexpected diagnostic" +
"\nfound " + diagnostic.getCode() +
"\nexpected " + expectedCode +
"\ntestKind " + testKind +
"\nactionKind " + actionKind);
}
}
}
//global declarations
enum EnumActionKind {
REPLACE1("enum E { SOUTH, WEST, EAST; }") {
@Override
void doAction(T6550655 test) {
test.replaceEnum(optionalSource);
}
},
REPLACE2("@interface I { E valNew() default E.EAST; }") {
@Override
void doAction(T6550655 test) {
test.replaceEnum(optionalSource);
}
},
REMOVE(null) {
@Override
void doAction(T6550655 test) { test.removeEnum(); }
};
String optionalSource;
private EnumActionKind(String optionalSource) {
this.optionalSource = optionalSource;
}
abstract void doAction(T6550655 test);
}
enum TestKind {
DIRECT("@I(val = E.NORTH)class C1 {}"),
INDIRECT("class C2 { A a; }");
JavaSource source;
private TestKind(final String code) {
this.source = new JavaSource("Test.java", code);
}
}
public static void main(String[] args) throws Exception {
String SCRATCH_DIR = System.getProperty("user.dir");
JavaCompiler javacTool = ToolProvider.getSystemJavaCompiler();
int n = 0;
for (TestKind testKind : TestKind.values()) {
for (EnumActionKind actionKind : EnumActionKind.values()) {
File testDir = new File(SCRATCH_DIR, "test"+n);
new T6550655(javacTool, testDir, testKind, actionKind).test();
n++;
}
}
if (nerrors > 0) {
throw new AssertionError("Some errors have been detected");
}
}
static class JavaSource extends SimpleJavaFileObject {
String source;
public JavaSource(String filename, String source) {
super(URI.create("myfo:/" + filename), JavaFileObject.Kind.SOURCE);
this.source = source;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return source;
}
}
static int nerrors = 0;
}