8205418: Assorted improvements to source code model
Improving tree positions, better error recovery, fixing Trees.getScope for possibly erroneous lambdas. Reviewed-by: jjg, mcimadamore, vromero
This commit is contained in:
parent
69191fc4cc
commit
eaf0364068
@ -1659,7 +1659,7 @@ public class Types {
|
|||||||
private TypeRelation isCastable = new TypeRelation() {
|
private TypeRelation isCastable = new TypeRelation() {
|
||||||
|
|
||||||
public Boolean visitType(Type t, Type s) {
|
public Boolean visitType(Type t, Type s) {
|
||||||
if (s.hasTag(ERROR))
|
if (s.hasTag(ERROR) || t.hasTag(NONE))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
switch (t.getTag()) {
|
switch (t.getTag()) {
|
||||||
|
@ -586,8 +586,11 @@ public class Attr extends JCTree.Visitor {
|
|||||||
class RecoveryInfo extends ResultInfo {
|
class RecoveryInfo extends ResultInfo {
|
||||||
|
|
||||||
public RecoveryInfo(final DeferredAttr.DeferredAttrContext deferredAttrContext) {
|
public RecoveryInfo(final DeferredAttr.DeferredAttrContext deferredAttrContext) {
|
||||||
super(KindSelector.VAL, Type.recoveryType,
|
this(deferredAttrContext, Type.recoveryType);
|
||||||
new Check.NestedCheckContext(chk.basicHandler) {
|
}
|
||||||
|
|
||||||
|
public RecoveryInfo(final DeferredAttr.DeferredAttrContext deferredAttrContext, Type pt) {
|
||||||
|
super(KindSelector.VAL, pt, new Check.NestedCheckContext(chk.basicHandler) {
|
||||||
@Override
|
@Override
|
||||||
public DeferredAttr.DeferredAttrContext deferredAttrContext() {
|
public DeferredAttr.DeferredAttrContext deferredAttrContext() {
|
||||||
return deferredAttrContext;
|
return deferredAttrContext;
|
||||||
@ -598,7 +601,9 @@ public class Attr extends JCTree.Visitor {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void report(DiagnosticPosition pos, JCDiagnostic details) {
|
public void report(DiagnosticPosition pos, JCDiagnostic details) {
|
||||||
chk.basicHandler.report(pos, details);
|
if (pt == Type.recoveryType) {
|
||||||
|
chk.basicHandler.report(pos, details);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -656,7 +661,7 @@ public class Attr extends JCTree.Visitor {
|
|||||||
}
|
}
|
||||||
if (tree == breakTree &&
|
if (tree == breakTree &&
|
||||||
resultInfo.checkContext.deferredAttrContext().mode == AttrMode.CHECK) {
|
resultInfo.checkContext.deferredAttrContext().mode == AttrMode.CHECK) {
|
||||||
throw new BreakAttr(copyEnv(env));
|
breakTreeFound(copyEnv(env));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} catch (CompletionFailure ex) {
|
} catch (CompletionFailure ex) {
|
||||||
@ -668,6 +673,10 @@ public class Attr extends JCTree.Visitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void breakTreeFound(Env<AttrContext> env) {
|
||||||
|
throw new BreakAttr(env);
|
||||||
|
}
|
||||||
|
|
||||||
Env<AttrContext> copyEnv(Env<AttrContext> env) {
|
Env<AttrContext> copyEnv(Env<AttrContext> env) {
|
||||||
Env<AttrContext> newEnv =
|
Env<AttrContext> newEnv =
|
||||||
env.dup(env.tree, env.info.dup(copyScope(env.info.scope)));
|
env.dup(env.tree, env.info.dup(copyScope(env.info.scope)));
|
||||||
@ -2506,8 +2515,7 @@ public class Attr extends JCTree.Visitor {
|
|||||||
//lambda only allowed in assignment or method invocation/cast context
|
//lambda only allowed in assignment or method invocation/cast context
|
||||||
log.error(that.pos(), Errors.UnexpectedLambda);
|
log.error(that.pos(), Errors.UnexpectedLambda);
|
||||||
}
|
}
|
||||||
result = that.type = types.createErrorType(pt());
|
resultInfo = recoveryInfo;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
//create an environment for attribution of the lambda expression
|
//create an environment for attribution of the lambda expression
|
||||||
final Env<AttrContext> localEnv = lambdaEnv(that, env);
|
final Env<AttrContext> localEnv = lambdaEnv(that, env);
|
||||||
@ -2595,6 +2603,10 @@ public class Attr extends JCTree.Visitor {
|
|||||||
attribTree(that.getBody(), localEnv, bodyResultInfo);
|
attribTree(that.getBody(), localEnv, bodyResultInfo);
|
||||||
} else {
|
} else {
|
||||||
JCBlock body = (JCBlock)that.body;
|
JCBlock body = (JCBlock)that.body;
|
||||||
|
if (body == breakTree &&
|
||||||
|
resultInfo.checkContext.deferredAttrContext().mode == AttrMode.CHECK) {
|
||||||
|
breakTreeFound(copyEnv(localEnv));
|
||||||
|
}
|
||||||
attribStats(body.stats, localEnv);
|
attribStats(body.stats, localEnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4126,8 +4138,8 @@ public class Attr extends JCTree.Visitor {
|
|||||||
typeargtypes,
|
typeargtypes,
|
||||||
noteWarner);
|
noteWarner);
|
||||||
|
|
||||||
DeferredAttr.DeferredTypeMap checkDeferredMap =
|
DeferredAttr.DeferredTypeMap<Void> checkDeferredMap =
|
||||||
deferredAttr.new DeferredTypeMap(DeferredAttr.AttrMode.CHECK, sym, env.info.pendingResolutionPhase);
|
deferredAttr.new DeferredTypeMap<>(DeferredAttr.AttrMode.CHECK, sym, env.info.pendingResolutionPhase);
|
||||||
|
|
||||||
argtypes = argtypes.map(checkDeferredMap);
|
argtypes = argtypes.map(checkDeferredMap);
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -28,6 +28,8 @@ package com.sun.tools.javac.comp;
|
|||||||
import com.sun.source.tree.LambdaExpressionTree.BodyKind;
|
import com.sun.source.tree.LambdaExpressionTree.BodyKind;
|
||||||
import com.sun.source.tree.NewClassTree;
|
import com.sun.source.tree.NewClassTree;
|
||||||
import com.sun.tools.javac.code.*;
|
import com.sun.tools.javac.code.*;
|
||||||
|
import com.sun.tools.javac.code.Type.ErrorType;
|
||||||
|
import com.sun.tools.javac.code.Type.MethodType;
|
||||||
import com.sun.tools.javac.code.Type.StructuralTypeMapping;
|
import com.sun.tools.javac.code.Type.StructuralTypeMapping;
|
||||||
import com.sun.tools.javac.code.Types.TypeMapping;
|
import com.sun.tools.javac.code.Types.TypeMapping;
|
||||||
import com.sun.tools.javac.comp.ArgumentAttr.LocalCacheContext;
|
import com.sun.tools.javac.comp.ArgumentAttr.LocalCacheContext;
|
||||||
@ -59,6 +61,7 @@ import java.util.WeakHashMap;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import com.sun.source.tree.MemberReferenceTree;
|
import com.sun.source.tree.MemberReferenceTree;
|
||||||
|
import com.sun.tools.javac.code.Type;
|
||||||
import com.sun.tools.javac.tree.JCTree.JCMemberReference.OverloadKind;
|
import com.sun.tools.javac.tree.JCTree.JCMemberReference.OverloadKind;
|
||||||
|
|
||||||
import static com.sun.tools.javac.code.TypeTag.*;
|
import static com.sun.tools.javac.code.TypeTag.*;
|
||||||
@ -1002,7 +1005,7 @@ public class DeferredAttr extends JCTree.Visitor {
|
|||||||
* where T is computed by retrieving the type that has already been
|
* where T is computed by retrieving the type that has already been
|
||||||
* computed for D during a previous deferred attribution round of the given kind.
|
* computed for D during a previous deferred attribution round of the given kind.
|
||||||
*/
|
*/
|
||||||
class DeferredTypeMap extends StructuralTypeMapping<Void> {
|
class DeferredTypeMap<T> extends StructuralTypeMapping<T> {
|
||||||
DeferredAttrContext deferredAttrContext;
|
DeferredAttrContext deferredAttrContext;
|
||||||
|
|
||||||
protected DeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) {
|
protected DeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) {
|
||||||
@ -1011,16 +1014,16 @@ public class DeferredAttr extends JCTree.Visitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type visitType(Type t, Void _unused) {
|
public Type visitType(Type t, T p) {
|
||||||
if (!t.hasTag(DEFERRED)) {
|
if (!t.hasTag(DEFERRED)) {
|
||||||
return super.visitType(t, null);
|
return super.visitType(t, p);
|
||||||
} else {
|
} else {
|
||||||
DeferredType dt = (DeferredType)t;
|
DeferredType dt = (DeferredType)t;
|
||||||
return typeOf(dt);
|
return typeOf(dt, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Type typeOf(DeferredType dt) {
|
protected Type typeOf(DeferredType dt, T p) {
|
||||||
switch (deferredAttrContext.mode) {
|
switch (deferredAttrContext.mode) {
|
||||||
case CHECK:
|
case CHECK:
|
||||||
return dt.tree.type == null ? Type.noType : dt.tree.type;
|
return dt.tree.type == null ? Type.noType : dt.tree.type;
|
||||||
@ -1039,17 +1042,35 @@ public class DeferredAttr extends JCTree.Visitor {
|
|||||||
* attribution round (as before), or (ii) by synthesizing a new type R for D
|
* attribution round (as before), or (ii) by synthesizing a new type R for D
|
||||||
* (the latter step is useful in a recovery scenario).
|
* (the latter step is useful in a recovery scenario).
|
||||||
*/
|
*/
|
||||||
public class RecoveryDeferredTypeMap extends DeferredTypeMap {
|
public class RecoveryDeferredTypeMap extends DeferredTypeMap<Type> {
|
||||||
|
|
||||||
public RecoveryDeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) {
|
public RecoveryDeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) {
|
||||||
super(mode, msym, phase != null ? phase : MethodResolutionPhase.BOX);
|
super(mode, msym, phase != null ? phase : MethodResolutionPhase.BOX);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Type typeOf(DeferredType dt) {
|
protected Type typeOf(DeferredType dt, Type pt) {
|
||||||
Type owntype = super.typeOf(dt);
|
Type owntype = super.typeOf(dt, pt);
|
||||||
return owntype == Type.noType ?
|
return owntype == Type.noType ?
|
||||||
recover(dt) : owntype;
|
recover(dt, pt) : owntype;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type visitMethodType(Type.MethodType t, Type pt) {
|
||||||
|
if (t.hasTag(METHOD) && deferredAttrContext.mode == AttrMode.CHECK) {
|
||||||
|
Type mtype = deferredAttrContext.msym.type;
|
||||||
|
mtype = mtype.hasTag(ERROR) ? ((ErrorType)mtype).getOriginalType() : null;
|
||||||
|
if (mtype != null && mtype.hasTag(METHOD)) {
|
||||||
|
List<Type> argtypes1 = map(t.getParameterTypes(), mtype.getParameterTypes());
|
||||||
|
Type restype1 = visit(t.getReturnType(), mtype.getReturnType());
|
||||||
|
List<Type> thrown1 = map(t.getThrownTypes(), mtype.getThrownTypes());
|
||||||
|
if (argtypes1 == t.getParameterTypes() &&
|
||||||
|
restype1 == t.getReturnType() &&
|
||||||
|
thrown1 == t.getThrownTypes()) return t;
|
||||||
|
else return new MethodType(argtypes1, restype1, thrown1, t.tsym);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.visitMethodType(t, pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1059,8 +1080,8 @@ public class DeferredAttr extends JCTree.Visitor {
|
|||||||
* representation. Remaining deferred types are attributed using
|
* representation. Remaining deferred types are attributed using
|
||||||
* a default expected type (j.l.Object).
|
* a default expected type (j.l.Object).
|
||||||
*/
|
*/
|
||||||
private Type recover(DeferredType dt) {
|
private Type recover(DeferredType dt, Type pt) {
|
||||||
dt.check(attr.new RecoveryInfo(deferredAttrContext) {
|
dt.check(attr.new RecoveryInfo(deferredAttrContext, pt != null ? pt : Type.recoveryType) {
|
||||||
@Override
|
@Override
|
||||||
protected Type check(DiagnosticPosition pos, Type found) {
|
protected Type check(DiagnosticPosition pos, Type found) {
|
||||||
return chk.checkNonVoid(pos, super.check(pos, found));
|
return chk.checkNonVoid(pos, super.check(pos, found));
|
||||||
@ -1068,6 +1089,16 @@ public class DeferredAttr extends JCTree.Visitor {
|
|||||||
});
|
});
|
||||||
return super.visit(dt);
|
return super.visit(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<Type> map(List<Type> ts, List<Type> pts) {
|
||||||
|
if (ts.nonEmpty()) {
|
||||||
|
List<Type> tail1 = map(ts.tail, pts != null ? pts.tail : null);
|
||||||
|
Type t = visit(ts.head, pts != null && pts.nonEmpty() ? pts.head : null);
|
||||||
|
if (tail1 != ts.tail || t != ts.head)
|
||||||
|
return tail1.prepend(t);
|
||||||
|
}
|
||||||
|
return ts;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -602,7 +602,7 @@ public class Infer {
|
|||||||
return mtype;
|
return mtype;
|
||||||
}
|
}
|
||||||
//where
|
//where
|
||||||
class ImplicitArgType extends DeferredAttr.DeferredTypeMap {
|
class ImplicitArgType extends DeferredAttr.DeferredTypeMap<Void> {
|
||||||
|
|
||||||
public ImplicitArgType(Symbol msym, Resolve.MethodResolutionPhase phase) {
|
public ImplicitArgType(Symbol msym, Resolve.MethodResolutionPhase phase) {
|
||||||
(rs.deferredAttr).super(AttrMode.SPECULATIVE, msym, phase);
|
(rs.deferredAttr).super(AttrMode.SPECULATIVE, msym, phase);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -210,7 +210,7 @@ public class Operators {
|
|||||||
* Report an operator lookup error.
|
* Report an operator lookup error.
|
||||||
*/
|
*/
|
||||||
private OperatorSymbol reportErrorIfNeeded(DiagnosticPosition pos, Tag tag, Type... args) {
|
private OperatorSymbol reportErrorIfNeeded(DiagnosticPosition pos, Tag tag, Type... args) {
|
||||||
if (Stream.of(args).noneMatch(Type::isErroneous)) {
|
if (Stream.of(args).noneMatch(t -> t.isErroneous() || t.hasTag(TypeTag.NONE))) {
|
||||||
Name opName = operatorName(tag);
|
Name opName = operatorName(tag);
|
||||||
JCDiagnostic.Error opError = (args.length) == 1 ?
|
JCDiagnostic.Error opError = (args.length) == 1 ?
|
||||||
Errors.OperatorCantBeApplied(opName, args[0]) :
|
Errors.OperatorCantBeApplied(opName, args[0]) :
|
||||||
|
@ -2560,8 +2560,8 @@ public class Resolve {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Type typeOf(DeferredType dt) {
|
protected Type typeOf(DeferredType dt, Type pt) {
|
||||||
Type res = super.typeOf(dt);
|
Type res = super.typeOf(dt, pt);
|
||||||
if (!res.isErroneous()) {
|
if (!res.isErroneous()) {
|
||||||
switch (TreeInfo.skipParens(dt.tree).getTag()) {
|
switch (TreeInfo.skipParens(dt.tree).getTag()) {
|
||||||
case LAMBDA:
|
case LAMBDA:
|
||||||
@ -3992,7 +3992,12 @@ public class Resolve {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Symbol access(Name name, TypeSymbol location) {
|
public Symbol access(Name name, TypeSymbol location) {
|
||||||
return types.createErrorType(name, location, syms.errSymbol.type).tsym;
|
Symbol sym = bestCandidate();
|
||||||
|
return types.createErrorType(name, location, sym != null ? sym.type : syms.errSymbol.type).tsym;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Symbol bestCandidate() {
|
||||||
|
return errCandidate().fst;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Pair<Symbol, JCDiagnostic> errCandidate() {
|
protected Pair<Symbol, JCDiagnostic> errCandidate() {
|
||||||
@ -4123,6 +4128,16 @@ public class Resolve {
|
|||||||
//conform to source order
|
//conform to source order
|
||||||
return details;
|
return details;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Symbol bestCandidate() {
|
||||||
|
Map<Symbol, JCDiagnostic> candidatesMap = mapCandidates();
|
||||||
|
Map<Symbol, JCDiagnostic> filteredCandidates = filterCandidates(candidatesMap);
|
||||||
|
if (filteredCandidates.size() == 1) {
|
||||||
|
return filteredCandidates.keySet().iterator().next();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -674,7 +674,7 @@ public class JavaTokenizer {
|
|||||||
scanNumber(pos, 10);
|
scanNumber(pos, 10);
|
||||||
} else if (reader.bp == reader.buflen || reader.ch == EOI && reader.bp + 1 == reader.buflen) { // JLS 3.5
|
} else if (reader.bp == reader.buflen || reader.ch == EOI && reader.bp + 1 == reader.buflen) { // JLS 3.5
|
||||||
tk = TokenKind.EOF;
|
tk = TokenKind.EOF;
|
||||||
pos = reader.buflen;
|
pos = reader.realLength;
|
||||||
} else {
|
} else {
|
||||||
String arg;
|
String arg;
|
||||||
|
|
||||||
|
@ -1516,6 +1516,7 @@ public class JavacParser implements Parser {
|
|||||||
ParensResult analyzeParens() {
|
ParensResult analyzeParens() {
|
||||||
int depth = 0;
|
int depth = 0;
|
||||||
boolean type = false;
|
boolean type = false;
|
||||||
|
ParensResult defaultResult = ParensResult.PARENS;
|
||||||
outer: for (int lookahead = 0 ; ; lookahead++) {
|
outer: for (int lookahead = 0 ; ; lookahead++) {
|
||||||
TokenKind tk = S.token(lookahead).kind;
|
TokenKind tk = S.token(lookahead).kind;
|
||||||
switch (tk) {
|
switch (tk) {
|
||||||
@ -1568,7 +1569,7 @@ public class JavacParser implements Parser {
|
|||||||
case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
|
case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
|
||||||
return ParensResult.CAST;
|
return ParensResult.CAST;
|
||||||
default:
|
default:
|
||||||
return ParensResult.PARENS;
|
return defaultResult;
|
||||||
}
|
}
|
||||||
case UNDERSCORE:
|
case UNDERSCORE:
|
||||||
case ASSERT:
|
case ASSERT:
|
||||||
@ -1580,6 +1581,8 @@ public class JavacParser implements Parser {
|
|||||||
} else if (peekToken(lookahead, RPAREN, ARROW)) {
|
} else if (peekToken(lookahead, RPAREN, ARROW)) {
|
||||||
// Identifier, ')' '->' -> implicit lambda
|
// Identifier, ')' '->' -> implicit lambda
|
||||||
return ParensResult.IMPLICIT_LAMBDA;
|
return ParensResult.IMPLICIT_LAMBDA;
|
||||||
|
} else if (depth == 0 && peekToken(lookahead, COMMA)) {
|
||||||
|
defaultResult = ParensResult.IMPLICIT_LAMBDA;
|
||||||
}
|
}
|
||||||
type = false;
|
type = false;
|
||||||
break;
|
break;
|
||||||
@ -1665,7 +1668,7 @@ public class JavacParser implements Parser {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
//this includes EOF
|
//this includes EOF
|
||||||
return ParensResult.PARENS;
|
return defaultResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3753,10 +3756,16 @@ public class JavacParser implements Parser {
|
|||||||
return defs;
|
return defs;
|
||||||
} else {
|
} else {
|
||||||
pos = token.pos;
|
pos = token.pos;
|
||||||
List<JCTree> err = isVoid
|
List<JCTree> err;
|
||||||
? List.of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
|
if (isVoid || typarams.nonEmpty()) {
|
||||||
List.nil(), List.nil(), null, null)))
|
JCMethodDecl m =
|
||||||
: null;
|
toP(F.at(pos).MethodDef(mods, name, type, typarams,
|
||||||
|
List.nil(), List.nil(), null, null));
|
||||||
|
attach(m, dc);
|
||||||
|
err = List.of(m);
|
||||||
|
} else {
|
||||||
|
err = List.nil();
|
||||||
|
}
|
||||||
return List.of(syntaxError(token.pos, err, Errors.Expected(LPAREN)));
|
return List.of(syntaxError(token.pos, err, Errors.Expected(LPAREN)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -70,6 +70,7 @@ public class UnicodeReader {
|
|||||||
/** A character buffer for saved chars.
|
/** A character buffer for saved chars.
|
||||||
*/
|
*/
|
||||||
protected char[] sbuf = new char[128];
|
protected char[] sbuf = new char[128];
|
||||||
|
protected int realLength;
|
||||||
protected int sp;
|
protected int sp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,6 +90,7 @@ public class UnicodeReader {
|
|||||||
protected UnicodeReader(ScannerFactory sf, char[] input, int inputLength) {
|
protected UnicodeReader(ScannerFactory sf, char[] input, int inputLength) {
|
||||||
log = sf.log;
|
log = sf.log;
|
||||||
names = sf.names;
|
names = sf.names;
|
||||||
|
realLength = inputLength;
|
||||||
if (inputLength == input.length) {
|
if (inputLength == input.length) {
|
||||||
if (input.length > 0 && Character.isWhitespace(input[input.length - 1])) {
|
if (input.length > 0 && Character.isWhitespace(input[input.length - 1])) {
|
||||||
inputLength--;
|
inputLength--;
|
||||||
|
@ -3,6 +3,6 @@ T8012003b.java:31:16: compiler.err.prob.found.req: (compiler.misc.stat.expr.expe
|
|||||||
T8012003b.java:32:22: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.conditional.target.cant.be.void))
|
T8012003b.java:32:22: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.conditional.target.cant.be.void))
|
||||||
T8012003b.java:33:12: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Integer, java.lang.String)))
|
T8012003b.java:33:12: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Integer, java.lang.String)))
|
||||||
T8012003b.java:34:12: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.mref: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer))
|
T8012003b.java:34:12: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.mref: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer))
|
||||||
T8012003b.java:35:12: compiler.err.invalid.mref: kindname.method, (compiler.misc.cant.resolve.location.args: kindname.method, k, , , (compiler.misc.location: kindname.class, T8012003b, null))
|
T8012003b.java:35:12: compiler.err.invalid.mref: kindname.method, (compiler.misc.cant.resolve.location.args: kindname.method, k, , java.lang.String, (compiler.misc.location: kindname.class, T8012003b, null))
|
||||||
- compiler.note.compressed.diags
|
- compiler.note.compressed.diags
|
||||||
6 errors
|
6 errors
|
||||||
|
155
test/langtools/tools/javac/api/TestGetScopeResult.java
Normal file
155
test/langtools/tools/javac/api/TestGetScopeResult.java
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, 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 8205418
|
||||||
|
* @summary Test the outcomes from Trees.getScope
|
||||||
|
* @modules jdk.compiler
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.lang.model.element.Element;
|
||||||
|
import javax.tools.JavaCompiler;
|
||||||
|
import javax.tools.SimpleJavaFileObject;
|
||||||
|
import javax.tools.StandardJavaFileManager;
|
||||||
|
import javax.tools.ToolProvider;
|
||||||
|
|
||||||
|
import com.sun.source.tree.CompilationUnitTree;
|
||||||
|
import com.sun.source.tree.LambdaExpressionTree;
|
||||||
|
import com.sun.source.tree.Scope;
|
||||||
|
import com.sun.source.util.JavacTask;
|
||||||
|
import com.sun.source.util.TreePath;
|
||||||
|
import com.sun.source.util.TreePathScanner;
|
||||||
|
import com.sun.source.util.Trees;
|
||||||
|
|
||||||
|
import static javax.tools.JavaFileObject.Kind.SOURCE;
|
||||||
|
|
||||||
|
public class TestGetScopeResult {
|
||||||
|
public static void main(String... args) throws IOException {
|
||||||
|
new TestGetScopeResult().run();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() throws IOException {
|
||||||
|
String[] simpleLambda = {
|
||||||
|
"s:java.lang.String",
|
||||||
|
"i:Test.I",
|
||||||
|
"super:java.lang.Object",
|
||||||
|
"this:Test"
|
||||||
|
};
|
||||||
|
doTest("class Test { void test() { I i = s -> { }; } interface I { public void test(String s); } }",
|
||||||
|
simpleLambda);
|
||||||
|
doTest("class Test { void test() { I i = s -> { }; } interface I { public int test(String s); } }",
|
||||||
|
simpleLambda);
|
||||||
|
doTest("class Test { void test() { I i = s -> { }; } interface I { public String test(String s); } }",
|
||||||
|
simpleLambda);
|
||||||
|
doTest("class Test { void test() { I i; inv(s -> { }); } void inv(I i) { } interface I { public void test(String s); } }",
|
||||||
|
simpleLambda);
|
||||||
|
doTest("class Test { void test() { I i; inv(s -> { }); } void inv(I i) { } interface I { public int test(String s); } }",
|
||||||
|
simpleLambda);
|
||||||
|
doTest("class Test { void test() { I i; inv(s -> { }); } void inv(I i) { } interface I { public String test(String s); } }",
|
||||||
|
simpleLambda);
|
||||||
|
String[] dualLambda = {
|
||||||
|
"s:java.lang.String",
|
||||||
|
"i:Test.I1",
|
||||||
|
"super:java.lang.Object",
|
||||||
|
"this:Test",
|
||||||
|
"s:java.lang.CharSequence",
|
||||||
|
"i:Test.I1",
|
||||||
|
"super:java.lang.Object",
|
||||||
|
"this:Test"
|
||||||
|
};
|
||||||
|
doTest("class Test { void test() { I1 i; inv(s -> { }, s -> { }); } void inv(I1 i, I2 i) { } interface I1 { public String test(String s); } interface I2 { public void test(CharSequence s); } }",
|
||||||
|
dualLambda);
|
||||||
|
doTest("class Test { void test() { I1 i; inv(s -> { }, s -> { }); } void inv(I1 i, I2 i) { } interface I1 { public String test(String s); } interface I2 { public int test(CharSequence s); } }",
|
||||||
|
dualLambda);
|
||||||
|
String[] brokenType = {
|
||||||
|
"s:<any>",
|
||||||
|
"u:Undefined",
|
||||||
|
"super:java.lang.Object",
|
||||||
|
"this:Test"
|
||||||
|
};
|
||||||
|
doTest("class Test { void test() { Undefined u = s -> { }; } }",
|
||||||
|
brokenType);
|
||||||
|
String[] multipleCandidates1 = {
|
||||||
|
"s:<any>",
|
||||||
|
"super:java.lang.Object",
|
||||||
|
"this:Test"
|
||||||
|
};
|
||||||
|
doTest("class Test { void test() { cand1(s -> { }); } void cand1(I1 i) { } void cand1(I2 i) { } interface I1 { public String test(String s); } interface I2 { public int test(CharSequence s); } }",
|
||||||
|
multipleCandidates1);
|
||||||
|
String[] multipleCandidates2 = {
|
||||||
|
"s:java.lang.String",
|
||||||
|
"super:java.lang.Object",
|
||||||
|
"this:Test"
|
||||||
|
};
|
||||||
|
doTest("class Test { void test() { cand1(s -> { }); } void cand1(I1 i) { } void cand1(I2 i, int i) { } interface I1 { public String test(String s); } interface I2 { public int test(CharSequence s); } }",
|
||||||
|
multipleCandidates2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doTest(String code, String... expected) throws IOException {
|
||||||
|
JavaCompiler c = ToolProvider.getSystemJavaCompiler();
|
||||||
|
try (StandardJavaFileManager fm = c.getStandardFileManager(null, null, null)) {
|
||||||
|
class MyFileObject extends SimpleJavaFileObject {
|
||||||
|
MyFileObject() {
|
||||||
|
super(URI.create("myfo:///Test.java"), SOURCE);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String getCharContent(boolean ignoreEncodingErrors) {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JavacTask t = (JavacTask) c.getTask(null, fm, null, null, null, List.of(new MyFileObject()));
|
||||||
|
CompilationUnitTree cut = t.parse().iterator().next();
|
||||||
|
t.analyze();
|
||||||
|
|
||||||
|
List<String> actual = new ArrayList<>();
|
||||||
|
|
||||||
|
new TreePathScanner<Void, Void>() {
|
||||||
|
@Override
|
||||||
|
public Void visitLambdaExpression(LambdaExpressionTree node, Void p) {
|
||||||
|
Scope scope = Trees.instance(t).getScope(new TreePath(getCurrentPath(), node.getBody()));
|
||||||
|
while (scope.getEnclosingClass() != null) {
|
||||||
|
for (Element el : scope.getLocalElements()) {
|
||||||
|
actual.add(el.getSimpleName() + ":" +el.asType().toString());
|
||||||
|
}
|
||||||
|
scope = scope.getEnclosingScope();
|
||||||
|
}
|
||||||
|
return super.visitLambdaExpression(node, p);
|
||||||
|
}
|
||||||
|
}.scan(cut, null);
|
||||||
|
|
||||||
|
List<String> expectedList = List.of(expected);
|
||||||
|
|
||||||
|
if (!expectedList.equals(actual)) {
|
||||||
|
throw new IllegalStateException("Unexpected scope content: " + actual);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,4 @@
|
|||||||
BadRecovery.java:17:9: compiler.err.cant.apply.symbol: kindname.method, m, BadRecovery.SAM1, @11, kindname.class, BadRecovery, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.arg.types.in.lambda))
|
BadRecovery.java:17:9: compiler.err.cant.apply.symbol: kindname.method, m, BadRecovery.SAM1, @11, kindname.class, BadRecovery, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.arg.types.in.lambda))
|
||||||
|
BadRecovery.java:17:38: compiler.err.cant.resolve.location.args: kindname.method, someMemberOfReceiver, , @60, (compiler.misc.location.1: kindname.variable, receiver, java.lang.Object)
|
||||||
BadRecovery.java:17:77: compiler.err.cant.resolve.location: kindname.variable, f, , , (compiler.misc.location: kindname.class, BadRecovery, null)
|
BadRecovery.java:17:77: compiler.err.cant.resolve.location: kindname.variable, f, , , (compiler.misc.location: kindname.class, BadRecovery, null)
|
||||||
2 errors
|
3 errors
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 7073631 7159445 7156633 8028235 8065753 8205913
|
* @bug 7073631 7159445 7156633 8028235 8065753 8205418 8205913
|
||||||
* @summary tests error and diagnostics positions
|
* @summary tests error and diagnostics positions
|
||||||
* @author Jan Lahoda
|
* @author Jan Lahoda
|
||||||
* @modules jdk.compiler/com.sun.tools.javac.api
|
* @modules jdk.compiler/com.sun.tools.javac.api
|
||||||
@ -51,6 +51,7 @@ import com.sun.source.tree.VariableTree;
|
|||||||
import com.sun.source.tree.WhileLoopTree;
|
import com.sun.source.tree.WhileLoopTree;
|
||||||
import com.sun.source.util.JavacTask;
|
import com.sun.source.util.JavacTask;
|
||||||
import com.sun.source.util.SourcePositions;
|
import com.sun.source.util.SourcePositions;
|
||||||
|
import com.sun.source.util.TreePath;
|
||||||
import com.sun.source.util.TreePathScanner;
|
import com.sun.source.util.TreePathScanner;
|
||||||
import com.sun.source.util.TreeScanner;
|
import com.sun.source.util.TreeScanner;
|
||||||
import com.sun.source.util.Trees;
|
import com.sun.source.util.Trees;
|
||||||
@ -1037,6 +1038,105 @@ public class JavacParserTest extends TestCase {
|
|||||||
assertEquals("the error message is not correct, actual: " + actualErrors, expectedErrors, actualErrors);
|
assertEquals("the error message is not correct, actual: " + actualErrors, expectedErrors, actualErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testTypeParamsWithoutMethod() throws IOException {
|
||||||
|
assert tool != null;
|
||||||
|
|
||||||
|
String code = "package test; class Test { /**javadoc*/ |public <T> |}";
|
||||||
|
String[] parts = code.split("\\|");
|
||||||
|
|
||||||
|
code = parts[0] + parts[1] + parts[2];
|
||||||
|
|
||||||
|
JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null,
|
||||||
|
null, Arrays.asList(new MyFileObject(code)));
|
||||||
|
Trees trees = Trees.instance(ct);
|
||||||
|
SourcePositions pos = trees.getSourcePositions();
|
||||||
|
CompilationUnitTree cut = ct.parse().iterator().next();
|
||||||
|
ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0);
|
||||||
|
ErroneousTree err = (ErroneousTree) clazz.getMembers().get(0);
|
||||||
|
MethodTree method = (MethodTree) err.getErrorTrees().get(0);
|
||||||
|
|
||||||
|
final int methodStart = parts[0].length();
|
||||||
|
final int methodEnd = parts[0].length() + parts[1].length();
|
||||||
|
assertEquals("testTypeParamsWithoutMethod",
|
||||||
|
methodStart, pos.getStartPosition(cut, method));
|
||||||
|
assertEquals("testTypeParamsWithoutMethod",
|
||||||
|
methodEnd, pos.getEndPosition(cut, method));
|
||||||
|
|
||||||
|
TreePath path2Method = new TreePath(new TreePath(new TreePath(cut), clazz), method);
|
||||||
|
String javadoc = trees.getDocComment(path2Method);
|
||||||
|
|
||||||
|
if (!"javadoc".equals(javadoc)) {
|
||||||
|
throw new AssertionError("Expected javadoc not found, actual javadoc: " + javadoc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testAnalyzeParensWithComma1() throws IOException {
|
||||||
|
assert tool != null;
|
||||||
|
|
||||||
|
String code = "package test; class Test { FI fi = |(s, |";
|
||||||
|
String[] parts = code.split("\\|", 3);
|
||||||
|
|
||||||
|
code = parts[0] + parts[1] + parts[2];
|
||||||
|
|
||||||
|
JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null,
|
||||||
|
null, Arrays.asList(new MyFileObject(code)));
|
||||||
|
Trees trees = Trees.instance(ct);
|
||||||
|
SourcePositions pos = trees.getSourcePositions();
|
||||||
|
CompilationUnitTree cut = ct.parse().iterator().next();
|
||||||
|
boolean[] found = new boolean[1];
|
||||||
|
|
||||||
|
new TreeScanner<Void, Void>() {
|
||||||
|
@Override
|
||||||
|
public Void visitLambdaExpression(LambdaExpressionTree tree, Void v) {
|
||||||
|
found[0] = true;
|
||||||
|
int lambdaStart = parts[0].length();
|
||||||
|
int lambdaEnd = parts[0].length() + parts[1].length();
|
||||||
|
assertEquals("testAnalyzeParensWithComma1",
|
||||||
|
lambdaStart, pos.getStartPosition(cut, tree));
|
||||||
|
assertEquals("testAnalyzeParensWithComma1",
|
||||||
|
lambdaEnd, pos.getEndPosition(cut, tree));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}.scan(cut, null);
|
||||||
|
|
||||||
|
assertTrue("testAnalyzeParensWithComma1", found[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testAnalyzeParensWithComma2() throws IOException {
|
||||||
|
assert tool != null;
|
||||||
|
|
||||||
|
String code = "package test; class Test { FI fi = |(s, o)|";
|
||||||
|
String[] parts = code.split("\\|", 3);
|
||||||
|
|
||||||
|
code = parts[0] + parts[1] + parts[2];
|
||||||
|
|
||||||
|
JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null,
|
||||||
|
null, Arrays.asList(new MyFileObject(code)));
|
||||||
|
Trees trees = Trees.instance(ct);
|
||||||
|
SourcePositions pos = trees.getSourcePositions();
|
||||||
|
CompilationUnitTree cut = ct.parse().iterator().next();
|
||||||
|
boolean[] found = new boolean[1];
|
||||||
|
|
||||||
|
new TreeScanner<Void, Void>() {
|
||||||
|
@Override
|
||||||
|
public Void visitLambdaExpression(LambdaExpressionTree tree, Void v) {
|
||||||
|
found[0] = true;
|
||||||
|
int lambdaStart = parts[0].length();
|
||||||
|
int lambdaEnd = parts[0].length() + parts[1].length();
|
||||||
|
assertEquals("testAnalyzeParensWithComma2",
|
||||||
|
lambdaStart, pos.getStartPosition(cut, tree));
|
||||||
|
assertEquals("testAnalyzeParensWithComma2",
|
||||||
|
lambdaEnd, pos.getEndPosition(cut, tree));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}.scan(cut, null);
|
||||||
|
|
||||||
|
assertTrue("testAnalyzeParensWithComma2", found[0]);
|
||||||
|
}
|
||||||
|
|
||||||
void run(String[] args) throws Exception {
|
void run(String[] args) throws Exception {
|
||||||
int passed = 0, failed = 0;
|
int passed = 0, failed = 0;
|
||||||
final Pattern p = (args != null && args.length > 0)
|
final Pattern p = (args != null && args.length > 0)
|
||||||
@ -1082,6 +1182,12 @@ abstract class TestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void assertTrue(String message, boolean bvalue) {
|
||||||
|
if (bvalue == false) {
|
||||||
|
fail(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void assertEquals(String message, int i, long l) {
|
void assertEquals(String message, int i, long l) {
|
||||||
if (i != l) {
|
if (i != l) {
|
||||||
fail(message + ":" + i + ":" + l);
|
fail(message + ":" + i + ":" + l);
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 8017216 8019422 8019421 8054956
|
* @bug 8017216 8019422 8019421 8054956 8205418
|
||||||
* @summary verify start and end positions
|
* @summary verify start and end positions
|
||||||
* @modules java.compiler
|
* @modules java.compiler
|
||||||
* jdk.compiler
|
* jdk.compiler
|
||||||
@ -44,6 +44,13 @@ import javax.tools.JavaFileManager;
|
|||||||
import javax.tools.JavaFileObject;
|
import javax.tools.JavaFileObject;
|
||||||
import javax.tools.SimpleJavaFileObject;
|
import javax.tools.SimpleJavaFileObject;
|
||||||
import javax.tools.ToolProvider;
|
import javax.tools.ToolProvider;
|
||||||
|
import com.sun.source.tree.CompilationUnitTree;
|
||||||
|
import com.sun.source.tree.Tree;
|
||||||
|
import com.sun.source.tree.Tree.Kind;
|
||||||
|
import com.sun.source.util.JavacTask;
|
||||||
|
import com.sun.source.util.SourcePositions;
|
||||||
|
import com.sun.source.util.TreeScanner;
|
||||||
|
import com.sun.source.util.Trees;
|
||||||
|
|
||||||
public class TreeEndPosTest {
|
public class TreeEndPosTest {
|
||||||
private static JavaFileManager getJavaFileManager(JavaCompiler compiler,
|
private static JavaFileManager getJavaFileManager(JavaCompiler compiler,
|
||||||
@ -99,6 +106,15 @@ public class TreeEndPosTest {
|
|||||||
js.endPos = end;
|
js.endPos = end;
|
||||||
return js;
|
return js;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JavaSource createFullJavaSource(String code) {
|
||||||
|
final String name = "Bug";
|
||||||
|
String[] parts = code.split("\\|", 3);
|
||||||
|
JavaSource js = new JavaSource(name + ".java", parts[0] + parts[1] + parts[2]);
|
||||||
|
js.startPos = parts[0].length();
|
||||||
|
js.endPos = parts[0].length() + parts[1].length();
|
||||||
|
return js;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String... args) throws IOException {
|
public static void main(String... args) throws IOException {
|
||||||
@ -107,6 +123,7 @@ public class TreeEndPosTest {
|
|||||||
testUnresolvableAnnotationAttribute();
|
testUnresolvableAnnotationAttribute();
|
||||||
testFinalVariableWithDefaultConstructor();
|
testFinalVariableWithDefaultConstructor();
|
||||||
testFinalVariableWithConstructor();
|
testFinalVariableWithConstructor();
|
||||||
|
testWholeTextSpan();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void testUninitializedVariable() throws IOException {
|
static void testUninitializedVariable() throws IOException {
|
||||||
@ -133,6 +150,10 @@ public class TreeEndPosTest {
|
|||||||
"{}"));
|
"{}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void testWholeTextSpan() throws IOException {
|
||||||
|
treeSpan(JavaSource.createFullJavaSource("|class X |"));
|
||||||
|
}
|
||||||
|
|
||||||
static void compile(JavaSource src) throws IOException {
|
static void compile(JavaSource src) throws IOException {
|
||||||
ByteArrayOutputStream ba = new ByteArrayOutputStream();
|
ByteArrayOutputStream ba = new ByteArrayOutputStream();
|
||||||
PrintWriter writer = new PrintWriter(ba);
|
PrintWriter writer = new PrintWriter(ba);
|
||||||
@ -169,4 +190,46 @@ public class TreeEndPosTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void treeSpan(JavaSource src) throws IOException {
|
||||||
|
ByteArrayOutputStream ba = new ByteArrayOutputStream();
|
||||||
|
PrintWriter writer = new PrintWriter(ba);
|
||||||
|
File tempDir = new File(".");
|
||||||
|
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||||
|
DiagnosticCollector dc = new DiagnosticCollector();
|
||||||
|
try (JavaFileManager javaFileManager = getJavaFileManager(compiler, dc)) {
|
||||||
|
List<String> options = new ArrayList<>();
|
||||||
|
options.add("-cp");
|
||||||
|
options.add(tempDir.getPath());
|
||||||
|
options.add("-d");
|
||||||
|
options.add(tempDir.getPath());
|
||||||
|
options.add("--should-stop=at=GENERATE");
|
||||||
|
|
||||||
|
List<JavaFileObject> sources = new ArrayList<>();
|
||||||
|
sources.add(src);
|
||||||
|
JavacTask task = (JavacTask) compiler.getTask(writer, javaFileManager,
|
||||||
|
dc, options, null,
|
||||||
|
sources);
|
||||||
|
SourcePositions sp = Trees.instance(task).getSourcePositions();
|
||||||
|
boolean[] found = new boolean[1];
|
||||||
|
new TreeScanner<Void, Void>() {
|
||||||
|
CompilationUnitTree cut;
|
||||||
|
@Override
|
||||||
|
public Void scan(Tree tree, Void p) {
|
||||||
|
if (tree == null)
|
||||||
|
return null;
|
||||||
|
if (tree.getKind() == Kind.COMPILATION_UNIT) {
|
||||||
|
cut = (CompilationUnitTree) tree;
|
||||||
|
}
|
||||||
|
found[0] |= (sp.getStartPosition(cut, tree) == src.startPos) &&
|
||||||
|
(sp.getEndPosition(cut, tree) == src.endPos);
|
||||||
|
return super.scan(tree, p);
|
||||||
|
}
|
||||||
|
}.scan(task.parse(), null);
|
||||||
|
|
||||||
|
if (!found[0]) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user