test/tools/javac/resolve/ResolveHarness.java

Thu, 31 Aug 2017 15:17:03 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:17:03 +0800
changeset 2525
2eb010b6cb22
parent 2395
9c577131ffa6
parent 0
959103a6100f
permissions
-rw-r--r--

merge

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

mercurial