Fri, 24 Apr 2020 03:58:51 +0100
Merge
mcimadamore@1114 | 1 | /* |
sogoel@2255 | 2 | * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. |
mcimadamore@1114 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
mcimadamore@1114 | 4 | * |
mcimadamore@1114 | 5 | * This code is free software; you can redistribute it and/or modify it |
mcimadamore@1114 | 6 | * under the terms of the GNU General Public License version 2 only, as |
mcimadamore@1114 | 7 | * published by the Free Software Foundation. |
mcimadamore@1114 | 8 | * |
mcimadamore@1114 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
mcimadamore@1114 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
mcimadamore@1114 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
mcimadamore@1114 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
mcimadamore@1114 | 13 | * accompanied this code). |
mcimadamore@1114 | 14 | * |
mcimadamore@1114 | 15 | * You should have received a copy of the GNU General Public License version |
mcimadamore@1114 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
mcimadamore@1114 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
mcimadamore@1114 | 18 | * |
mcimadamore@1114 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
mcimadamore@1114 | 20 | * or visit www.oracle.com if you need additional information or have any |
mcimadamore@1114 | 21 | * questions. |
mcimadamore@1114 | 22 | */ |
mcimadamore@1114 | 23 | |
mcimadamore@1114 | 24 | /* |
mcimadamore@1114 | 25 | * @test |
dlsmith@2395 | 26 | * @bug 7098660 8014649 8034223 |
dlsmith@2395 | 27 | * @summary Test harness for overload resolution/inference tests |
darcy@1466 | 28 | * @library /tools/javac/lib |
mcimadamore@1114 | 29 | * @build JavacTestingAbstractProcessor ResolveHarness |
mcimadamore@1114 | 30 | * @run main ResolveHarness |
mcimadamore@1114 | 31 | */ |
mcimadamore@1114 | 32 | |
mcimadamore@1114 | 33 | import com.sun.source.util.JavacTask; |
mcimadamore@1114 | 34 | import com.sun.tools.javac.api.ClientCodeWrapper.DiagnosticSourceUnwrapper; |
mcimadamore@1875 | 35 | import com.sun.tools.javac.code.Flags; |
mcimadamore@1875 | 36 | import com.sun.tools.javac.code.Symbol; |
mcimadamore@1114 | 37 | import com.sun.tools.javac.code.Type.MethodType; |
mcimadamore@1114 | 38 | import com.sun.tools.javac.util.JCDiagnostic; |
mcimadamore@1114 | 39 | |
mcimadamore@1114 | 40 | import java.io.File; |
mcimadamore@1114 | 41 | import java.util.Set; |
mcimadamore@1114 | 42 | import java.util.Arrays; |
mcimadamore@1114 | 43 | import java.util.ArrayList; |
mcimadamore@1114 | 44 | import java.util.Collections; |
mcimadamore@1114 | 45 | import java.util.HashMap; |
mcimadamore@1114 | 46 | import java.util.HashSet; |
mcimadamore@1114 | 47 | import java.util.List; |
mcimadamore@1779 | 48 | import java.util.Locale; |
mcimadamore@1114 | 49 | import java.util.Map; |
mcimadamore@1114 | 50 | |
mcimadamore@1114 | 51 | import javax.annotation.processing.AbstractProcessor; |
mcimadamore@1114 | 52 | import javax.annotation.processing.RoundEnvironment; |
mcimadamore@1114 | 53 | import javax.annotation.processing.SupportedAnnotationTypes; |
mcimadamore@1114 | 54 | import javax.lang.model.element.Element; |
mcimadamore@1114 | 55 | import javax.lang.model.element.TypeElement; |
mcimadamore@1114 | 56 | import javax.tools.Diagnostic; |
mcimadamore@1114 | 57 | import javax.tools.Diagnostic.Kind; |
mcimadamore@1114 | 58 | import javax.tools.DiagnosticListener; |
mcimadamore@1114 | 59 | import javax.tools.JavaCompiler; |
mcimadamore@1114 | 60 | import javax.tools.JavaFileObject; |
mcimadamore@1114 | 61 | import javax.tools.StandardJavaFileManager; |
mcimadamore@1114 | 62 | import javax.tools.ToolProvider; |
mcimadamore@1114 | 63 | |
mcimadamore@1114 | 64 | import static javax.tools.StandardLocation.*; |
mcimadamore@1114 | 65 | |
mcimadamore@1114 | 66 | public class ResolveHarness implements javax.tools.DiagnosticListener<JavaFileObject> { |
mcimadamore@1114 | 67 | |
mcimadamore@1114 | 68 | static int nerrors = 0; |
mcimadamore@1114 | 69 | |
mcimadamore@1114 | 70 | static final JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); |
mcimadamore@1114 | 71 | static final StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); |
mcimadamore@1114 | 72 | |
mcimadamore@1114 | 73 | public static void main(String[] args) throws Exception { |
mcimadamore@1114 | 74 | fm.setLocation(SOURCE_PATH, |
mcimadamore@1114 | 75 | Arrays.asList(new File(System.getProperty("test.src"), "tests"))); |
mcimadamore@1114 | 76 | for (JavaFileObject jfo : fm.list(SOURCE_PATH, "", Collections.singleton(JavaFileObject.Kind.SOURCE), true)) { |
mcimadamore@1114 | 77 | new ResolveHarness(jfo).check(); |
mcimadamore@1114 | 78 | } |
mcimadamore@1114 | 79 | if (nerrors > 0) { |
mcimadamore@1114 | 80 | throw new AssertionError("Errors were found"); |
mcimadamore@1114 | 81 | } |
mcimadamore@1114 | 82 | } |
mcimadamore@1114 | 83 | |
mcimadamore@1114 | 84 | |
mcimadamore@1114 | 85 | JavaFileObject jfo; |
mcimadamore@1114 | 86 | DiagnosticProcessor[] diagProcessors; |
mcimadamore@1114 | 87 | Map<ElementKey, Candidate> candidatesMap = new HashMap<ElementKey, Candidate>(); |
mcimadamore@1114 | 88 | Set<String> declaredKeys = new HashSet<>(); |
mcimadamore@1114 | 89 | List<Diagnostic<? extends JavaFileObject>> diags = new ArrayList<>(); |
mcimadamore@1114 | 90 | List<ElementKey> seenCandidates = new ArrayList<>(); |
mcimadamore@1779 | 91 | Map<String, String> predefTranslationMap = new HashMap<>(); |
mcimadamore@1114 | 92 | |
mcimadamore@1114 | 93 | protected ResolveHarness(JavaFileObject jfo) { |
mcimadamore@1114 | 94 | this.jfo = jfo; |
mcimadamore@1114 | 95 | this.diagProcessors = new DiagnosticProcessor[] { |
mcimadamore@1114 | 96 | new VerboseResolutionNoteProcessor(), |
mcimadamore@1114 | 97 | new VerboseDeferredInferenceNoteProcessor(), |
mcimadamore@1114 | 98 | new ErrorProcessor() |
mcimadamore@1114 | 99 | }; |
mcimadamore@1779 | 100 | predefTranslationMap.put("+", "_plus"); |
mcimadamore@1779 | 101 | predefTranslationMap.put("-", "_minus"); |
mcimadamore@1779 | 102 | predefTranslationMap.put("~", "_not"); |
mcimadamore@1779 | 103 | predefTranslationMap.put("++", "_plusplus"); |
mcimadamore@1779 | 104 | predefTranslationMap.put("--", "_minusminus"); |
mcimadamore@1779 | 105 | predefTranslationMap.put("!", "_bang"); |
mcimadamore@1779 | 106 | predefTranslationMap.put("*", "_mul"); |
mcimadamore@1779 | 107 | predefTranslationMap.put("/", "_div"); |
mcimadamore@1779 | 108 | predefTranslationMap.put("%", "_mod"); |
mcimadamore@1779 | 109 | predefTranslationMap.put("&", "_and"); |
mcimadamore@1779 | 110 | predefTranslationMap.put("|", "_or"); |
mcimadamore@1779 | 111 | predefTranslationMap.put("^", "_xor"); |
mcimadamore@1779 | 112 | predefTranslationMap.put("<<", "_lshift"); |
mcimadamore@1779 | 113 | predefTranslationMap.put(">>", "_rshift"); |
mcimadamore@1779 | 114 | predefTranslationMap.put("<<<", "_lshiftshift"); |
mcimadamore@1779 | 115 | predefTranslationMap.put(">>>", "_rshiftshift"); |
mcimadamore@1779 | 116 | predefTranslationMap.put("<", "_lt"); |
mcimadamore@1779 | 117 | predefTranslationMap.put(">", "_gt"); |
mcimadamore@1779 | 118 | predefTranslationMap.put("<=", "_lteq"); |
mcimadamore@1779 | 119 | predefTranslationMap.put(">=", "_gteq"); |
mcimadamore@1779 | 120 | predefTranslationMap.put("==", "_eq"); |
mcimadamore@1779 | 121 | predefTranslationMap.put("!=", "_neq"); |
mcimadamore@1779 | 122 | predefTranslationMap.put("&&", "_andand"); |
mcimadamore@1779 | 123 | predefTranslationMap.put("||", "_oror"); |
mcimadamore@1114 | 124 | } |
mcimadamore@1114 | 125 | |
mcimadamore@1114 | 126 | protected void check() throws Exception { |
mcimadamore@1114 | 127 | String[] options = { |
mcimadamore@1114 | 128 | "-XDshouldStopPolicy=ATTR", |
mcimadamore@1779 | 129 | "-XDverboseResolution=success,failure,applicable,inapplicable,deferred-inference,predef" |
mcimadamore@1114 | 130 | }; |
mcimadamore@1114 | 131 | |
mcimadamore@1114 | 132 | AbstractProcessor[] processors = { new ResolveCandidateFinder(), null }; |
mcimadamore@1114 | 133 | |
mcimadamore@1114 | 134 | @SuppressWarnings("unchecked") |
mcimadamore@1114 | 135 | DiagnosticListener<? super JavaFileObject>[] diagListeners = |
mcimadamore@1114 | 136 | new DiagnosticListener[] { new DiagnosticHandler(false), new DiagnosticHandler(true) }; |
mcimadamore@1114 | 137 | |
mcimadamore@1114 | 138 | for (int i = 0 ; i < options.length ; i ++) { |
mcimadamore@1114 | 139 | JavacTask ct = (JavacTask)comp.getTask(null, fm, diagListeners[i], |
mcimadamore@1114 | 140 | Arrays.asList(options[i]), null, Arrays.asList(jfo)); |
mcimadamore@1114 | 141 | if (processors[i] != null) { |
mcimadamore@1114 | 142 | ct.setProcessors(Collections.singleton(processors[i])); |
mcimadamore@1114 | 143 | } |
mcimadamore@1114 | 144 | ct.analyze(); |
mcimadamore@1114 | 145 | } |
mcimadamore@1114 | 146 | |
mcimadamore@1114 | 147 | //check diags |
mcimadamore@1114 | 148 | for (Diagnostic<? extends JavaFileObject> diag : diags) { |
mcimadamore@1114 | 149 | for (DiagnosticProcessor proc : diagProcessors) { |
mcimadamore@1114 | 150 | if (proc.matches(diag)) { |
mcimadamore@1114 | 151 | proc.process(diag); |
mcimadamore@1114 | 152 | break; |
mcimadamore@1114 | 153 | } |
mcimadamore@1114 | 154 | } |
mcimadamore@1114 | 155 | } |
mcimadamore@1114 | 156 | //check all candidates have been used up |
mcimadamore@1114 | 157 | for (Map.Entry<ElementKey, Candidate> entry : candidatesMap.entrySet()) { |
mcimadamore@1114 | 158 | if (!seenCandidates.contains(entry.getKey())) { |
mcimadamore@1875 | 159 | error("Redundant @Candidate annotation on method " + entry.getKey().elem + " sig = " + entry.getKey().elem.asType()); |
mcimadamore@1114 | 160 | } |
mcimadamore@1114 | 161 | } |
mcimadamore@1114 | 162 | } |
mcimadamore@1114 | 163 | |
mcimadamore@1114 | 164 | public void report(Diagnostic<? extends JavaFileObject> diagnostic) { |
mcimadamore@1114 | 165 | diags.add(diagnostic); |
mcimadamore@1114 | 166 | } |
mcimadamore@1114 | 167 | |
mcimadamore@1114 | 168 | Candidate getCandidateAtPos(Element methodSym, long line, long col) { |
mcimadamore@1114 | 169 | Candidate c = candidatesMap.get(new ElementKey(methodSym)); |
mcimadamore@1114 | 170 | if (c != null) { |
mcimadamore@1114 | 171 | Pos pos = c.pos(); |
mcimadamore@1114 | 172 | if (!pos.userDefined() || |
mcimadamore@1114 | 173 | (pos.line() == line && pos.col() == col)) { |
mcimadamore@1114 | 174 | seenCandidates.add(new ElementKey(methodSym)); |
mcimadamore@1114 | 175 | return c; |
mcimadamore@1114 | 176 | } |
mcimadamore@1114 | 177 | } else { |
mcimadamore@1114 | 178 | error("Missing @Candidate annotation on method " + methodSym); |
mcimadamore@1114 | 179 | } |
mcimadamore@1114 | 180 | return null; |
mcimadamore@1114 | 181 | } |
mcimadamore@1114 | 182 | |
mcimadamore@1114 | 183 | void checkSig(Candidate c, Element methodSym, MethodType mtype) { |
mcimadamore@1114 | 184 | if (c.sig().length() > 0 && !c.sig().equals(mtype.toString())) { |
mcimadamore@1114 | 185 | error("Inferred type mismatch for method: " + methodSym); |
mcimadamore@1114 | 186 | } |
mcimadamore@1114 | 187 | } |
mcimadamore@1114 | 188 | |
mcimadamore@1114 | 189 | protected void error(String msg) { |
mcimadamore@1114 | 190 | nerrors++; |
mcimadamore@1114 | 191 | System.err.printf("Error occurred while checking file: %s\nreason: %s\n", jfo.getName(), msg); |
mcimadamore@1114 | 192 | } |
mcimadamore@1114 | 193 | |
mcimadamore@1114 | 194 | /** |
mcimadamore@1114 | 195 | * Base class for diagnostic processor. It provides methods for matching and |
mcimadamore@1114 | 196 | * processing a given diagnostic object (overridden by subclasses). |
mcimadamore@1114 | 197 | */ |
mcimadamore@1114 | 198 | abstract class DiagnosticProcessor { |
mcimadamore@1114 | 199 | |
mcimadamore@1114 | 200 | List<String> codes; |
mcimadamore@1114 | 201 | Diagnostic.Kind kind; |
mcimadamore@1114 | 202 | |
mcimadamore@1114 | 203 | public DiagnosticProcessor(Kind kind, String... codes) { |
mcimadamore@1114 | 204 | this.codes = Arrays.asList(codes); |
mcimadamore@1114 | 205 | this.kind = kind; |
mcimadamore@1114 | 206 | } |
mcimadamore@1114 | 207 | |
mcimadamore@1114 | 208 | abstract void process(Diagnostic<? extends JavaFileObject> diagnostic); |
mcimadamore@1114 | 209 | |
mcimadamore@1114 | 210 | boolean matches(Diagnostic<? extends JavaFileObject> diagnostic) { |
mcimadamore@1114 | 211 | return (codes.isEmpty() || codes.contains(diagnostic.getCode())) && |
mcimadamore@1114 | 212 | diagnostic.getKind() == kind; |
mcimadamore@1114 | 213 | } |
mcimadamore@1114 | 214 | |
mcimadamore@1114 | 215 | JCDiagnostic asJCDiagnostic(Diagnostic<? extends JavaFileObject> diagnostic) { |
mcimadamore@1114 | 216 | if (diagnostic instanceof JCDiagnostic) { |
mcimadamore@1114 | 217 | return (JCDiagnostic)diagnostic; |
mcimadamore@1114 | 218 | } else if (diagnostic instanceof DiagnosticSourceUnwrapper) { |
mcimadamore@1114 | 219 | return ((DiagnosticSourceUnwrapper)diagnostic).d; |
mcimadamore@1114 | 220 | } else { |
mcimadamore@1114 | 221 | throw new AssertionError("Cannot convert diagnostic to JCDiagnostic: " + diagnostic.getClass().getName()); |
mcimadamore@1114 | 222 | } |
mcimadamore@1114 | 223 | } |
mcimadamore@1114 | 224 | |
mcimadamore@1114 | 225 | List<JCDiagnostic> subDiagnostics(Diagnostic<? extends JavaFileObject> diagnostic) { |
mcimadamore@1114 | 226 | JCDiagnostic diag = asJCDiagnostic(diagnostic); |
mcimadamore@1114 | 227 | if (diag instanceof JCDiagnostic.MultilineDiagnostic) { |
mcimadamore@1114 | 228 | return ((JCDiagnostic.MultilineDiagnostic)diag).getSubdiagnostics(); |
mcimadamore@1114 | 229 | } else { |
mcimadamore@1114 | 230 | throw new AssertionError("Cannot extract subdiagnostics: " + diag.getClass().getName()); |
mcimadamore@1114 | 231 | } |
mcimadamore@1114 | 232 | } |
mcimadamore@1114 | 233 | } |
mcimadamore@1114 | 234 | |
mcimadamore@1114 | 235 | /** |
mcimadamore@1114 | 236 | * Processor for verbose resolution notes generated by javac. The processor |
mcimadamore@1114 | 237 | * checks that the diagnostic is associated with a method declared by |
mcimadamore@1114 | 238 | * a class annotated with the special @TraceResolve marker annotation. If |
mcimadamore@1114 | 239 | * that's the case, all subdiagnostics (one for each resolution candidate) |
mcimadamore@1114 | 240 | * are checked against the corresponding @Candidate annotations, using |
mcimadamore@1114 | 241 | * a VerboseCandidateSubdiagProcessor. |
mcimadamore@1114 | 242 | */ |
mcimadamore@1114 | 243 | class VerboseResolutionNoteProcessor extends DiagnosticProcessor { |
mcimadamore@1114 | 244 | |
mcimadamore@1114 | 245 | VerboseResolutionNoteProcessor() { |
mcimadamore@1114 | 246 | super(Kind.NOTE, |
mcimadamore@1114 | 247 | "compiler.note.verbose.resolve.multi", |
mcimadamore@1114 | 248 | "compiler.note.verbose.resolve.multi.1"); |
mcimadamore@1114 | 249 | } |
mcimadamore@1114 | 250 | |
mcimadamore@1114 | 251 | @Override |
mcimadamore@1114 | 252 | void process(Diagnostic<? extends JavaFileObject> diagnostic) { |
mcimadamore@1114 | 253 | Element siteSym = getSiteSym(diagnostic); |
mcimadamore@1779 | 254 | if (siteSym.getSimpleName().length() != 0 && |
mcimadamore@1875 | 255 | ((Symbol)siteSym).outermostClass().getAnnotation(TraceResolve.class) == null) { |
mcimadamore@1114 | 256 | return; |
mcimadamore@1114 | 257 | } |
mcimadamore@1114 | 258 | int candidateIdx = 0; |
mcimadamore@1114 | 259 | for (JCDiagnostic d : subDiagnostics(diagnostic)) { |
mcimadamore@1114 | 260 | boolean isMostSpecific = candidateIdx++ == mostSpecific(diagnostic); |
mcimadamore@1114 | 261 | VerboseCandidateSubdiagProcessor subProc = |
mcimadamore@1114 | 262 | new VerboseCandidateSubdiagProcessor(isMostSpecific, phase(diagnostic), success(diagnostic)); |
mcimadamore@1114 | 263 | if (subProc.matches(d)) { |
mcimadamore@1114 | 264 | subProc.process(d); |
mcimadamore@1114 | 265 | } else { |
mcimadamore@1114 | 266 | throw new AssertionError("Bad subdiagnostic: " + d.getCode()); |
mcimadamore@1114 | 267 | } |
mcimadamore@1114 | 268 | } |
mcimadamore@1114 | 269 | } |
mcimadamore@1114 | 270 | |
mcimadamore@1114 | 271 | Element getSiteSym(Diagnostic<? extends JavaFileObject> diagnostic) { |
mcimadamore@1114 | 272 | return (Element)asJCDiagnostic(diagnostic).getArgs()[1]; |
mcimadamore@1114 | 273 | } |
mcimadamore@1114 | 274 | |
mcimadamore@1114 | 275 | int mostSpecific(Diagnostic<? extends JavaFileObject> diagnostic) { |
mcimadamore@1114 | 276 | return success(diagnostic) ? |
mcimadamore@1114 | 277 | (Integer)asJCDiagnostic(diagnostic).getArgs()[2] : -1; |
mcimadamore@1114 | 278 | } |
mcimadamore@1114 | 279 | |
mcimadamore@1114 | 280 | boolean success(Diagnostic<? extends JavaFileObject> diagnostic) { |
mcimadamore@1114 | 281 | return diagnostic.getCode().equals("compiler.note.verbose.resolve.multi"); |
mcimadamore@1114 | 282 | } |
mcimadamore@1114 | 283 | |
mcimadamore@1114 | 284 | Phase phase(Diagnostic<? extends JavaFileObject> diagnostic) { |
mcimadamore@1114 | 285 | return Phase.fromString(asJCDiagnostic(diagnostic).getArgs()[3].toString()); |
mcimadamore@1114 | 286 | } |
mcimadamore@1114 | 287 | } |
mcimadamore@1114 | 288 | |
mcimadamore@1114 | 289 | /** |
mcimadamore@1114 | 290 | * Processor for verbose resolution subdiagnostic notes generated by javac. |
mcimadamore@1114 | 291 | * The processor checks that the details of the overload candidate |
mcimadamore@1114 | 292 | * match against the info contained in the corresponding @Candidate |
mcimadamore@1114 | 293 | * annotation (if any). |
mcimadamore@1114 | 294 | */ |
mcimadamore@1114 | 295 | class VerboseCandidateSubdiagProcessor extends DiagnosticProcessor { |
mcimadamore@1114 | 296 | |
mcimadamore@1114 | 297 | boolean mostSpecific; |
mcimadamore@1114 | 298 | Phase phase; |
mcimadamore@1114 | 299 | boolean success; |
mcimadamore@1114 | 300 | |
mcimadamore@1114 | 301 | public VerboseCandidateSubdiagProcessor(boolean mostSpecific, Phase phase, boolean success) { |
mcimadamore@1114 | 302 | super(Kind.OTHER, |
mcimadamore@1114 | 303 | "compiler.misc.applicable.method.found", |
mcimadamore@1114 | 304 | "compiler.misc.applicable.method.found.1", |
mcimadamore@1114 | 305 | "compiler.misc.not.applicable.method.found"); |
mcimadamore@1114 | 306 | this.mostSpecific = mostSpecific; |
mcimadamore@1114 | 307 | this.phase = phase; |
mcimadamore@1114 | 308 | this.success = success; |
mcimadamore@1114 | 309 | } |
mcimadamore@1114 | 310 | |
mcimadamore@1114 | 311 | @Override |
mcimadamore@1114 | 312 | void process(Diagnostic<? extends JavaFileObject> diagnostic) { |
mcimadamore@1875 | 313 | Symbol methodSym = (Symbol)methodSym(diagnostic); |
mcimadamore@1875 | 314 | if ((methodSym.flags() & Flags.GENERATEDCONSTR) != 0) { |
mcimadamore@1875 | 315 | //skip resolution of default constructor (put there by javac) |
mcimadamore@1875 | 316 | return; |
mcimadamore@1875 | 317 | } |
mcimadamore@1114 | 318 | Candidate c = getCandidateAtPos(methodSym, |
mcimadamore@1114 | 319 | asJCDiagnostic(diagnostic).getLineNumber(), |
mcimadamore@1114 | 320 | asJCDiagnostic(diagnostic).getColumnNumber()); |
mcimadamore@1114 | 321 | if (c == null) { |
mcimadamore@1114 | 322 | return; //nothing to check |
mcimadamore@1114 | 323 | } |
mcimadamore@1114 | 324 | |
mcimadamore@1114 | 325 | if (c.applicable().length == 0 && c.mostSpecific()) { |
mcimadamore@1114 | 326 | error("Inapplicable method cannot be most specific " + methodSym); |
mcimadamore@1114 | 327 | } |
mcimadamore@1114 | 328 | |
mcimadamore@1114 | 329 | if (isApplicable(diagnostic) != Arrays.asList(c.applicable()).contains(phase)) { |
mcimadamore@1114 | 330 | error("Invalid candidate's applicability " + methodSym); |
mcimadamore@1114 | 331 | } |
mcimadamore@1114 | 332 | |
mcimadamore@1114 | 333 | if (success) { |
mcimadamore@1114 | 334 | for (Phase p : c.applicable()) { |
mcimadamore@1114 | 335 | if (phase.ordinal() < p.ordinal()) { |
mcimadamore@1114 | 336 | error("Invalid phase " + p + " on method " + methodSym); |
mcimadamore@1114 | 337 | } |
mcimadamore@1114 | 338 | } |
mcimadamore@1114 | 339 | } |
mcimadamore@1114 | 340 | |
mcimadamore@1114 | 341 | if (Arrays.asList(c.applicable()).contains(phase)) { //applicable |
mcimadamore@1114 | 342 | if (c.mostSpecific() != mostSpecific) { |
mcimadamore@1779 | 343 | error("Invalid most specific value for method " + methodSym + " " + new ElementKey(methodSym).key); |
mcimadamore@1114 | 344 | } |
mcimadamore@1114 | 345 | MethodType mtype = getSig(diagnostic); |
mcimadamore@1114 | 346 | if (mtype != null) { |
mcimadamore@1114 | 347 | checkSig(c, methodSym, mtype); |
mcimadamore@1114 | 348 | } |
mcimadamore@1114 | 349 | } |
mcimadamore@1114 | 350 | } |
mcimadamore@1114 | 351 | |
mcimadamore@1114 | 352 | boolean isApplicable(Diagnostic<? extends JavaFileObject> diagnostic) { |
mcimadamore@1114 | 353 | return !diagnostic.getCode().equals("compiler.misc.not.applicable.method.found"); |
mcimadamore@1114 | 354 | } |
mcimadamore@1114 | 355 | |
mcimadamore@1114 | 356 | Element methodSym(Diagnostic<? extends JavaFileObject> diagnostic) { |
mcimadamore@1114 | 357 | return (Element)asJCDiagnostic(diagnostic).getArgs()[1]; |
mcimadamore@1114 | 358 | } |
mcimadamore@1114 | 359 | |
mcimadamore@1114 | 360 | MethodType getSig(Diagnostic<? extends JavaFileObject> diagnostic) { |
mcimadamore@1114 | 361 | JCDiagnostic details = (JCDiagnostic)asJCDiagnostic(diagnostic).getArgs()[2]; |
mcimadamore@1114 | 362 | if (details == null) { |
mcimadamore@1114 | 363 | return null; |
mcimadamore@1114 | 364 | } else if (details instanceof JCDiagnostic) { |
mcimadamore@1114 | 365 | return details.getCode().equals("compiler.misc.full.inst.sig") ? |
mcimadamore@1114 | 366 | (MethodType)details.getArgs()[0] : null; |
mcimadamore@1114 | 367 | } else { |
mcimadamore@1114 | 368 | throw new AssertionError("Bad diagnostic arg: " + details); |
mcimadamore@1114 | 369 | } |
mcimadamore@1114 | 370 | } |
mcimadamore@1114 | 371 | } |
mcimadamore@1114 | 372 | |
mcimadamore@1114 | 373 | /** |
mcimadamore@1114 | 374 | * Processor for verbose deferred inference notes generated by javac. The |
mcimadamore@1114 | 375 | * processor checks that the inferred signature for a given generic method |
mcimadamore@1114 | 376 | * call corresponds to the one (if any) declared in the @Candidate annotation. |
mcimadamore@1114 | 377 | */ |
mcimadamore@1114 | 378 | class VerboseDeferredInferenceNoteProcessor extends DiagnosticProcessor { |
mcimadamore@1114 | 379 | |
mcimadamore@1114 | 380 | public VerboseDeferredInferenceNoteProcessor() { |
mcimadamore@1114 | 381 | super(Kind.NOTE, "compiler.note.deferred.method.inst"); |
mcimadamore@1114 | 382 | } |
mcimadamore@1114 | 383 | |
mcimadamore@1114 | 384 | @Override |
mcimadamore@1114 | 385 | void process(Diagnostic<? extends JavaFileObject> diagnostic) { |
mcimadamore@1114 | 386 | Element methodSym = methodSym(diagnostic); |
mcimadamore@1114 | 387 | Candidate c = getCandidateAtPos(methodSym, |
mcimadamore@1114 | 388 | asJCDiagnostic(diagnostic).getLineNumber(), |
mcimadamore@1114 | 389 | asJCDiagnostic(diagnostic).getColumnNumber()); |
mcimadamore@1114 | 390 | MethodType sig = sig(diagnostic); |
mcimadamore@1114 | 391 | if (c != null && sig != null) { |
mcimadamore@1114 | 392 | checkSig(c, methodSym, sig); |
mcimadamore@1114 | 393 | } |
mcimadamore@1114 | 394 | } |
mcimadamore@1114 | 395 | |
mcimadamore@1114 | 396 | Element methodSym(Diagnostic<? extends JavaFileObject> diagnostic) { |
mcimadamore@1114 | 397 | return (Element)asJCDiagnostic(diagnostic).getArgs()[0]; |
mcimadamore@1114 | 398 | } |
mcimadamore@1114 | 399 | |
mcimadamore@1114 | 400 | MethodType sig(Diagnostic<? extends JavaFileObject> diagnostic) { |
mcimadamore@1114 | 401 | return (MethodType)asJCDiagnostic(diagnostic).getArgs()[1]; |
mcimadamore@1114 | 402 | } |
mcimadamore@1114 | 403 | } |
mcimadamore@1114 | 404 | |
mcimadamore@1114 | 405 | /** |
mcimadamore@1114 | 406 | * Processor for all error diagnostics; if the error key is not declared in |
mcimadamore@1114 | 407 | * the test file header, the processor reports an error. |
mcimadamore@1114 | 408 | */ |
mcimadamore@1114 | 409 | class ErrorProcessor extends DiagnosticProcessor { |
mcimadamore@1114 | 410 | |
mcimadamore@1114 | 411 | public ErrorProcessor() { |
mcimadamore@1114 | 412 | super(Diagnostic.Kind.ERROR); |
mcimadamore@1114 | 413 | } |
mcimadamore@1114 | 414 | |
mcimadamore@1114 | 415 | @Override |
mcimadamore@1114 | 416 | void process(Diagnostic<? extends JavaFileObject> diagnostic) { |
mcimadamore@1114 | 417 | if (!declaredKeys.contains(diagnostic.getCode())) { |
mcimadamore@1114 | 418 | error("Unexpected compilation error key '" + diagnostic.getCode() + "'"); |
mcimadamore@1114 | 419 | } |
mcimadamore@1114 | 420 | } |
mcimadamore@1114 | 421 | } |
mcimadamore@1114 | 422 | |
mcimadamore@1114 | 423 | @SupportedAnnotationTypes({"Candidate","TraceResolve"}) |
mcimadamore@1114 | 424 | class ResolveCandidateFinder extends JavacTestingAbstractProcessor { |
mcimadamore@1114 | 425 | |
mcimadamore@1114 | 426 | @Override |
mcimadamore@1114 | 427 | public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { |
mcimadamore@1114 | 428 | if (roundEnv.processingOver()) |
mcimadamore@1114 | 429 | return true; |
mcimadamore@1114 | 430 | |
mcimadamore@1114 | 431 | TypeElement traceResolveAnno = elements.getTypeElement("TraceResolve"); |
mcimadamore@1114 | 432 | TypeElement candidateAnno = elements.getTypeElement("Candidate"); |
mcimadamore@1114 | 433 | |
mcimadamore@1114 | 434 | if (!annotations.contains(traceResolveAnno)) { |
mcimadamore@1114 | 435 | error("no @TraceResolve annotation found in test class"); |
mcimadamore@1114 | 436 | } |
mcimadamore@1114 | 437 | |
mcimadamore@1114 | 438 | if (!annotations.contains(candidateAnno)) { |
mcimadamore@1114 | 439 | error("no @candidate annotation found in test class"); |
mcimadamore@1114 | 440 | } |
mcimadamore@1114 | 441 | |
mcimadamore@1114 | 442 | for (Element elem: roundEnv.getElementsAnnotatedWith(traceResolveAnno)) { |
mcimadamore@1114 | 443 | TraceResolve traceResolve = elem.getAnnotation(TraceResolve.class); |
mcimadamore@1114 | 444 | declaredKeys.addAll(Arrays.asList(traceResolve.keys())); |
mcimadamore@1114 | 445 | } |
mcimadamore@1114 | 446 | |
mcimadamore@1114 | 447 | for (Element elem: roundEnv.getElementsAnnotatedWith(candidateAnno)) { |
mcimadamore@1114 | 448 | candidatesMap.put(new ElementKey(elem), elem.getAnnotation(Candidate.class)); |
mcimadamore@1114 | 449 | } |
mcimadamore@1114 | 450 | return true; |
mcimadamore@1114 | 451 | } |
mcimadamore@1114 | 452 | } |
mcimadamore@1114 | 453 | |
mcimadamore@1114 | 454 | class ElementKey { |
mcimadamore@1114 | 455 | |
mcimadamore@1114 | 456 | String key; |
mcimadamore@1114 | 457 | Element elem; |
mcimadamore@1114 | 458 | |
mcimadamore@1114 | 459 | public ElementKey(Element elem) { |
mcimadamore@1114 | 460 | this.elem = elem; |
mcimadamore@1114 | 461 | this.key = computeKey(elem); |
mcimadamore@1114 | 462 | } |
mcimadamore@1114 | 463 | |
mcimadamore@1114 | 464 | @Override |
mcimadamore@1114 | 465 | public boolean equals(Object obj) { |
mcimadamore@1114 | 466 | if (obj instanceof ElementKey) { |
mcimadamore@1114 | 467 | ElementKey other = (ElementKey)obj; |
mcimadamore@1114 | 468 | return other.key.equals(key); |
mcimadamore@1114 | 469 | } |
mcimadamore@1114 | 470 | return false; |
mcimadamore@1114 | 471 | } |
mcimadamore@1114 | 472 | |
mcimadamore@1114 | 473 | @Override |
mcimadamore@1114 | 474 | public int hashCode() { |
mcimadamore@1114 | 475 | return key.hashCode(); |
mcimadamore@1114 | 476 | } |
mcimadamore@1114 | 477 | |
mcimadamore@1114 | 478 | String computeKey(Element e) { |
mcimadamore@1875 | 479 | String simpleName = e.getSimpleName().toString(); |
mcimadamore@1875 | 480 | String opName = predefTranslationMap.get(simpleName); |
mcimadamore@1875 | 481 | String name = opName != null ? opName : simpleName; |
mcimadamore@1875 | 482 | return name + e.asType(); |
mcimadamore@1114 | 483 | } |
mcimadamore@1114 | 484 | |
mcimadamore@1114 | 485 | @Override |
mcimadamore@1114 | 486 | public String toString() { |
mcimadamore@1114 | 487 | return "Key{"+key+"}"; |
mcimadamore@1114 | 488 | } |
mcimadamore@1114 | 489 | } |
mcimadamore@1114 | 490 | |
mcimadamore@1114 | 491 | class DiagnosticHandler implements DiagnosticListener<JavaFileObject> { |
mcimadamore@1114 | 492 | |
mcimadamore@1114 | 493 | boolean shouldRecordDiags; |
mcimadamore@1114 | 494 | |
mcimadamore@1114 | 495 | DiagnosticHandler(boolean shouldRecordDiags) { |
mcimadamore@1114 | 496 | this.shouldRecordDiags = shouldRecordDiags; |
mcimadamore@1114 | 497 | } |
mcimadamore@1114 | 498 | |
mcimadamore@1114 | 499 | public void report(Diagnostic<? extends JavaFileObject> diagnostic) { |
mcimadamore@1114 | 500 | if (shouldRecordDiags) |
mcimadamore@1114 | 501 | diags.add(diagnostic); |
mcimadamore@1114 | 502 | } |
mcimadamore@1114 | 503 | |
mcimadamore@1114 | 504 | } |
mcimadamore@1114 | 505 | } |