# HG changeset patch # User asaha # Date 1444849516 25200 # Node ID f55af75598d85f45f779f3e632152a067fb7efbc # Parent 5cc6fb646e805c169ccdcee398d55152455094fe# Parent 5909f5a549acc0b03d250437199aa7462f5825f4 Merge diff -r 5cc6fb646e80 -r f55af75598d8 src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java --- a/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java Wed Oct 14 11:57:56 2015 -0700 +++ b/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java Wed Oct 14 12:05:16 2015 -0700 @@ -124,19 +124,14 @@ * Returns the flags of a ClassSymbol in terms of javac's flags */ static long getFlags(ClassSymbol clazz) { - while (true) { - try { - return clazz.flags(); - } catch (CompletionFailure ex) { - /* Quietly ignore completion failures. - * Note that a CompletionFailure can only - * occur as a result of calling complete(), - * which will always remove the current - * completer, leaving it to be null or - * follow-up completer. Thus the loop - * is guaranteed to eventually terminate. - */ - } + try { + return clazz.flags(); + } catch (CompletionFailure ex) { + /* Quietly ignore completion failures and try again - the type + * for which the CompletionFailure was thrown shouldn't be completed + * again by the completer that threw the CompletionFailure. + */ + return getFlags(clazz); } } diff -r 5cc6fb646e80 -r f55af75598d8 src/share/classes/com/sun/tools/javadoc/MethodDocImpl.java --- a/src/share/classes/com/sun/tools/javadoc/MethodDocImpl.java Wed Oct 14 11:57:56 2015 -0700 +++ b/src/share/classes/com/sun/tools/javadoc/MethodDocImpl.java Wed Oct 14 12:05:16 2015 -0700 @@ -128,7 +128,7 @@ t.hasTag(CLASS); t = env.types.supertype(t)) { ClassSymbol c = (ClassSymbol)t.tsym; - for (Scope.Entry e = c.members().lookup(sym.name); e.scope != null; e = e.next()) { + for (Scope.Entry e = membersOf(c).lookup(sym.name); e.scope != null; e = e.next()) { if (sym.overrides(e.sym, origin, env.types, true)) { return TypeMaker.getType(env, t); } @@ -160,7 +160,7 @@ t.hasTag(CLASS); t = env.types.supertype(t)) { ClassSymbol c = (ClassSymbol)t.tsym; - for (Scope.Entry e = c.members().lookup(sym.name); e.scope != null; e = e.next()) { + for (Scope.Entry e = membersOf(c).lookup(sym.name); e.scope != null; e = e.next()) { if (sym.overrides(e.sym, origin, env.types, true)) { return env.getMethodDoc((MethodSymbol)e.sym); } @@ -169,6 +169,19 @@ return null; } + /**Retrieve members of c, ignoring any CompletionFailures that occur. */ + private Scope membersOf(ClassSymbol c) { + try { + return c.members(); + } catch (CompletionFailure cf) { + /* Quietly ignore completion failures and try again - the type + * for which the CompletionFailure was thrown shouldn't be completed + * again by the completer that threw the CompletionFailure. + */ + return membersOf(c); + } + } + /** * Tests whether this method overrides another. * The overridden method may be one declared in a superclass or diff -r 5cc6fb646e80 -r f55af75598d8 src/share/classes/com/sun/tools/javadoc/TypeMaker.java --- a/src/share/classes/com/sun/tools/javadoc/TypeMaker.java Wed Oct 14 11:57:56 2015 -0700 +++ b/src/share/classes/com/sun/tools/javadoc/TypeMaker.java Wed Oct 14 12:05:16 2015 -0700 @@ -28,6 +28,7 @@ import com.sun.javadoc.*; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.ClassSymbol; +import com.sun.tools.javac.code.Symbol.CompletionFailure; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Type.ArrayType; import com.sun.tools.javac.code.Type.ClassType; @@ -56,8 +57,21 @@ return getType(env, t, errorToClassDoc, true); } + public static com.sun.javadoc.Type getType(DocEnv env, Type t, + boolean errToClassDoc, boolean considerAnnotations) { + try { + return getTypeImpl(env, t, errToClassDoc, considerAnnotations); + } catch (CompletionFailure cf) { + /* Quietly ignore completion failures and try again - the type + * for which the CompletionFailure was thrown shouldn't be completed + * again by the completer that threw the CompletionFailure. + */ + return getType(env, t, errToClassDoc, considerAnnotations); + } + } + @SuppressWarnings("fallthrough") - public static com.sun.javadoc.Type getType(DocEnv env, Type t, + private static com.sun.javadoc.Type getTypeImpl(DocEnv env, Type t, boolean errToClassDoc, boolean considerAnnotations) { if (env.legacyDoclet) { t = env.types.erasure(t); diff -r 5cc6fb646e80 -r f55af75598d8 test/tools/javadoc/CompletionError.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javadoc/CompletionError.java Wed Oct 14 12:05:16 2015 -0700 @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2015, 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 8135307 + * @summary Check that CompletionFailures for missing classes are not incorrectly passed to + * the javadoc API clients. + * @modules jdk.javadoc + * @run main CompletionError + */ + +import java.io.File; +import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; + +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.ToolProvider; + +import com.sun.javadoc.*; +import com.sun.tools.javadoc.Main; + +public class CompletionError extends Doclet +{ + private static final String template = + "public class CompletionErrorAuxiliary #extends CompletionErrorMissing# #implements CompletionErrorIntfMissing# {" + + " #public CompletionErrorMissing tf;#" + + " #public CompletionErrorMissing tm() { return null; }#" + + " #public void tm(CompletionErrorMissing m) {}#" + + " #public void tm() throws CompletionErrorExcMissing {}#" + + " #public void tm() {}#" + + " public String toString() { return null; }" + + "}"; + + public static void main(String[] args) throws Exception { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + String[] templateParts = template.split("#"); + int sources = templateParts.length / 2; + for (int source = 0; source < sources; source++) { + StringBuilder testSource = new StringBuilder(); + for (int i = 0; i < templateParts.length; i += 2) { + testSource.append(templateParts[i]); + if (i == 2 * source) { + testSource.append(templateParts[i + 1]); + } + } + test = 0; + testsDone = false; + while (!testsDone) { + List fileObjects = + Arrays.asList(new JavaSource("CompletionErrorAuxiliary", testSource.toString()), + new JavaSource("CompletionErrorMissing", "public class CompletionErrorMissing {}"), + new JavaSource("CompletionErrorIntfMissing", "public interface CompletionErrorIntfMissing {}"), + new JavaSource("CompletionErrorExcMissing", "public class CompletionErrorExcMissing extends Exception {}")); + Boolean result = compiler.getTask(null, null, null, Arrays.asList("-d", "."), null, fileObjects).call(); + if (!result) + throw new Error(); + for (String delete : new String[] {"CompletionErrorMissing.class", "CompletionErrorIntfMissing.class", "CompletionErrorExcMissing.class"}) { + Files.delete(Paths.get(delete)); + } + // run javadoc: + if (Main.execute("javadoc", "CompletionError", CompletionError.class.getClassLoader(), + "-classpath", ".", + System.getProperty("test.src", ".") + File.separatorChar + "CompletionError.java") != 0) + throw new Error(); + } + } + } + + private static int test; + private static boolean testsDone; + + public static boolean start(com.sun.javadoc.RootDoc root) { + ClassDoc aux = root.classNamed("CompletionErrorAuxiliary"); + if (aux == null) + throw new AssertionError("Cannot find CompletionErrorAuxiliary"); + + FieldDoc tf = findField(aux, "tf"); + MethodDoc tm = findMethod(aux, "tm"); + MethodDoc cm = findMethod(aux, "toString"); + switch (test) { + case 0: aux.superclass(); break; + case 1: aux.superclassType(); break; + case 2: aux.interfaces(); break; + case 3: aux.interfaceTypes(); break; + case 4: if (tf != null) tf.type(); break; + case 5: if (tm != null) tm.overriddenClass(); break; + case 6: if (tm != null) tm.overriddenMethod(); break; + case 7: if (tm != null) tm.overriddenType(); break; + case 8: + if (tm != null) { + for (Parameter p : tm.parameters()) { + p.type(); + } + } + break; + case 9: if (tm != null) tm.receiverType(); break; + case 10: if (tm != null) tm.returnType(); break; + case 11: if (tm != null) tm.thrownExceptionTypes(); break; + case 12: if (tm != null) tm.thrownExceptions(); break; + case 13: + if (tm != null) { + for (TypeVariable tv : tm.typeParameters()) { + tv.bounds(); + } + } + break; + case 14: if (cm != null) cm.overriddenClass(); break; + case 15: if (cm != null) cm.overriddenMethod(); break; + case 16: if (cm != null) cm.overriddenType(); testsDone = true; break; + default: + throw new IllegalStateException("Unrecognized test!"); + } + test++; + return true; + } + + private static MethodDoc findMethod(ClassDoc cd, String name) { + for (MethodDoc m : cd.methods()) { + if (name.equals(m.name())) + return m; + } + + return null; + } + + private static FieldDoc findField(ClassDoc cd, String name) { + for (FieldDoc m : cd.fields()) { + if (name.equals(m.name())) + return m; + } + + return null; + } + + static class JavaSource extends SimpleJavaFileObject { + final String source; + + public JavaSource(String name, String source) { + super(URI.create("myfo:/" + name + ".java"), JavaFileObject.Kind.SOURCE); + this.source = source; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return source; + } + } +}