blob: b70972a26ed6ded0349b796a8ec58bb87231b25e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.java.completion;
import com.sun.source.tree.*;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.util.*;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.logging.Logger;
import java.util.logging.Level;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.*;
import static javax.lang.model.element.ElementKind.*;
import static javax.lang.model.element.Modifier.*;
import javax.lang.model.type.*;
import javax.lang.model.util.Elements;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.annotations.common.NullAllowed;
import org.netbeans.api.java.lexer.JavaTokenId;
import org.netbeans.api.java.source.*;
import org.netbeans.api.java.source.JavaSource.Phase;
import org.netbeans.api.java.source.ClassIndex;
import org.netbeans.api.java.source.ClassIndex.Symbols;
import org.netbeans.api.java.source.support.ErrorAwareTreePathScanner;
import org.netbeans.api.java.source.support.ReferencesCount;
import org.netbeans.api.lexer.TokenSequence;
import org.netbeans.modules.java.completion.TreeShims;
import org.netbeans.modules.parsing.api.Source;
import org.openide.util.Pair;
/**
*
* @author Dusan Balek
*/
public final class JavaCompletionTask<T> extends BaseTask {
public static <I> JavaCompletionTask<I> create(final int caretOffset, @NonNull final ItemFactory<I> factory, @NonNull final Set<Options> options, @NullAllowed final Callable<Boolean> cancel) {
return new JavaCompletionTask<>(caretOffset, factory, cancel, options);
}
public static interface ItemFactory<T> {
T createKeywordItem(String kwd, String postfix, int substitutionOffset, boolean smartType);
T createPackageItem(String pkgFQN, int substitutionOffset, boolean inPackageStatement);
T createTypeItem(CompilationInfo info, TypeElement elem, DeclaredType type, int substitutionOffset, ReferencesCount referencesCount, boolean isDeprecated, boolean insideNew, boolean addTypeVars, boolean addSimpleName, boolean smartType, boolean autoImportEnclosingType);
T createTypeItem(ElementHandle<TypeElement> handle, EnumSet<ElementKind> kinds, int substitutionOffset, ReferencesCount referencesCount, Source source, boolean insideNew, boolean addTypeVars, boolean afterExtends);
T createArrayItem(CompilationInfo info, ArrayType type, int substitutionOffset, ReferencesCount referencesCount, Elements elements);
T createTypeParameterItem(TypeParameterElement elem, int substitutionOffset);
T createVariableItem(CompilationInfo info, VariableElement elem, TypeMirror type, int substitutionOffset, ReferencesCount referencesCount, boolean isInherited, boolean isDeprecated, boolean smartType, int assignToVarOffset);
T createVariableItem(CompilationInfo info, String varName, int substitutionOffset, boolean newVarName, boolean smartType);
T createExecutableItem(CompilationInfo info, ExecutableElement elem, ExecutableType type, int substitutionOffset, ReferencesCount referencesCount, boolean isInherited, boolean isDeprecated, boolean inImport, boolean addSemicolon, boolean smartType, int assignToVarOffset, boolean memberRef);
T createThisOrSuperConstructorItem(CompilationInfo info, ExecutableElement elem, ExecutableType type, int substitutionOffset, boolean isDeprecated, String name);
T createOverrideMethodItem(CompilationInfo info, ExecutableElement elem, ExecutableType type, int substitutionOffset, boolean implement);
T createGetterSetterMethodItem(CompilationInfo info, VariableElement elem, TypeMirror type, int substitutionOffset, String name, boolean setter);
T createDefaultConstructorItem(TypeElement elem, int substitutionOffset, boolean smartType);
T createParametersItem(CompilationInfo info, ExecutableElement elem, ExecutableType type, int substitutionOffset, boolean isDeprecated, int activeParamIndex, String name);
T createAnnotationItem(CompilationInfo info, TypeElement elem, DeclaredType type, int substitutionOffset, ReferencesCount referencesCount, boolean isDeprecated);
T createAttributeItem(CompilationInfo info, ExecutableElement elem, ExecutableType type, int substitutionOffset, boolean isDeprecated);
T createAttributeValueItem(CompilationInfo info, String value, String documentation, TypeElement element, int substitutionOffset, ReferencesCount referencesCount);
T createStaticMemberItem(CompilationInfo info, DeclaredType type, Element memberElem, TypeMirror memberType, boolean multipleVersions, int substitutionOffset, boolean isDeprecated, boolean addSemicolon);
T createStaticMemberItem(ElementHandle<TypeElement> handle, String name, int substitutionOffset, boolean addSemicolon, ReferencesCount referencesCount, Source source);
T createChainedMembersItem(CompilationInfo info, List<? extends Element> chainedElems, List<? extends TypeMirror> chainedTypes, int substitutionOffset, boolean isDeprecated, boolean addSemicolon);
T createInitializeAllConstructorItem(CompilationInfo info, boolean isDefault, Iterable<? extends VariableElement> fields, ExecutableElement superConstructor, TypeElement parent, int substitutionOffset);
}
public static interface TypeCastableItemFactory<T> extends ItemFactory<T> {
T createTypeCastableVariableItem(CompilationInfo info, VariableElement elem, TypeMirror type, TypeMirror castType, int substitutionOffset, ReferencesCount referencesCount, boolean isInherited, boolean isDeprecated, boolean smartType, int assignToVarOffset);
T createTypeCastableExecutableItem(CompilationInfo info, ExecutableElement elem, ExecutableType type, TypeMirror castType, int substitutionOffset, ReferencesCount referencesCount, boolean isInherited, boolean isDeprecated, boolean inImport, boolean addSemicolon, boolean smartType, int assignToVarOffset, boolean memberRef);
}
public static interface LambdaItemFactory<T> extends ItemFactory<T> {
T createLambdaItem(CompilationInfo info, TypeElement elem, DeclaredType type, int substitutionOffset, boolean addSemicolon);
}
public static interface ModuleItemFactory<T> extends ItemFactory<T> {
T createModuleItem(String moduleName, int substitutionOffset);
}
public static enum Options {
ALL_COMPLETION,
SKIP_ACCESSIBILITY_CHECK
}
private static final String ERROR = "<error>"; //NOI18N
private static final String INIT = "<init>"; //NOI18N
private static final String SPACE = " "; //NOI18N
private static final String COLON = ":"; //NOI18N
private static final String SEMI = ";"; //NOI18N
private static final String EMPTY = ""; //NOI18N
private static final String ABSTRACT_KEYWORD = "abstract"; //NOI18N
private static final String ASSERT_KEYWORD = "assert"; //NOI18N
private static final String BOOLEAN_KEYWORD = "boolean"; //NOI18N
private static final String BREAK_KEYWORD = "break"; //NOI18N
private static final String BYTE_KEYWORD = "byte"; //NOI18N
private static final String CASE_KEYWORD = "case"; //NOI18N
private static final String CATCH_KEYWORD = "catch"; //NOI18N
private static final String CHAR_KEYWORD = "char"; //NOI18N
private static final String CLASS_KEYWORD = "class"; //NOI18N
private static final String CONTINUE_KEYWORD = "continue"; //NOI18N
private static final String DEFAULT_KEYWORD = "default"; //NOI18N
private static final String DO_KEYWORD = "do"; //NOI18N
private static final String DOUBLE_KEYWORD = "double"; //NOI18N
private static final String ELSE_KEYWORD = "else"; //NOI18N
private static final String ENUM_KEYWORD = "enum"; //NOI18N
private static final String EXPORTS_KEYWORD = "exports"; //NOI18N
private static final String EXTENDS_KEYWORD = "extends"; //NOI18N
private static final String FALSE_KEYWORD = "false"; //NOI18N
private static final String FINAL_KEYWORD = "final"; //NOI18N
private static final String FINALLY_KEYWORD = "finally"; //NOI18N
private static final String FLOAT_KEYWORD = "float"; //NOI18N
private static final String FOR_KEYWORD = "for"; //NOI18N
private static final String IF_KEYWORD = "if"; //NOI18N
private static final String IMPLEMENTS_KEYWORD = "implements"; //NOI18N
private static final String IMPORT_KEYWORD = "import"; //NOI18N
private static final String INSTANCEOF_KEYWORD = "instanceof"; //NOI18N
private static final String INT_KEYWORD = "int"; //NOI18N
private static final String INTERFACE_KEYWORD = "interface"; //NOI18N
private static final String LONG_KEYWORD = "long"; //NOI18N
private static final String MODULE_KEYWORD = "module"; //NOI18N
private static final String NATIVE_KEYWORD = "native"; //NOI18N
private static final String NEW_KEYWORD = "new"; //NOI18N
private static final String NULL_KEYWORD = "null"; //NOI18N
private static final String OPEN_KEYWORD = "open"; //NOI18N
private static final String OPENS_KEYWORD = "opens"; //NOI18N
private static final String PACKAGE_KEYWORD = "package"; //NOI18N
private static final String PRIVATE_KEYWORD = "private"; //NOI18N
private static final String PROTECTED_KEYWORD = "protected"; //NOI18N
private static final String PROVIDES_KEYWORD = "provides"; //NOI18N
private static final String PUBLIC_KEYWORD = "public"; //NOI18N
private static final String RETURN_KEYWORD = "return"; //NOI18N
private static final String REQUIRES_KEYWORD = "requires"; //NOI18N
private static final String SHORT_KEYWORD = "short"; //NOI18N
private static final String STATIC_KEYWORD = "static"; //NOI18N
private static final String STRICT_KEYWORD = "strictfp"; //NOI18N
private static final String SUPER_KEYWORD = "super"; //NOI18N
private static final String SWITCH_KEYWORD = "switch"; //NOI18N
private static final String SYNCHRONIZED_KEYWORD = "synchronized"; //NOI18N
private static final String THIS_KEYWORD = "this"; //NOI18N
private static final String THROW_KEYWORD = "throw"; //NOI18N
private static final String THROWS_KEYWORD = "throws"; //NOI18N
private static final String TO_KEYWORD = "to"; //NOI18N
private static final String TRANSIENT_KEYWORD = "transient"; //NOI18N
private static final String TRANSITIVE_KEYWORD = "transitive"; //NOI18N
private static final String TRUE_KEYWORD = "true"; //NOI18N
private static final String TRY_KEYWORD = "try"; //NOI18N
private static final String USES_KEYWORD = "uses"; //NOI18N
private static final String VAR_KEYWORD = "var"; //NOI18N
private static final String VOID_KEYWORD = "void"; //NOI18N
private static final String VOLATILE_KEYWORD = "volatile"; //NOI18N
private static final String WHILE_KEYWORD = "while"; //NOI18N
private static final String WITH_KEYWORD = "with"; //NOI18N
private static final String YIELD_KEYWORD = "yield"; //NOI18N
private static final String JAVA_LANG_CLASS = "java.lang.Class"; //NOI18N
private static final String JAVA_LANG_OBJECT = "java.lang.Object"; //NOI18N
private static final String JAVA_LANG_ITERABLE = "java.lang.Iterable"; //NOI18N
private static final String[] PRIM_KEYWORDS = new String[]{
BOOLEAN_KEYWORD, BYTE_KEYWORD, CHAR_KEYWORD, DOUBLE_KEYWORD,
FLOAT_KEYWORD, INT_KEYWORD, LONG_KEYWORD, SHORT_KEYWORD
};
private static final String[] STATEMENT_KEYWORDS = new String[]{
DO_KEYWORD, IF_KEYWORD, FOR_KEYWORD, SWITCH_KEYWORD, SYNCHRONIZED_KEYWORD, TRY_KEYWORD,
VOID_KEYWORD, WHILE_KEYWORD
};
private static final String[] STATEMENT_SPACE_KEYWORDS = new String[]{
ASSERT_KEYWORD, NEW_KEYWORD, THROW_KEYWORD
};
private static final String[] BLOCK_KEYWORDS = new String[]{
ASSERT_KEYWORD, CLASS_KEYWORD, FINAL_KEYWORD, NEW_KEYWORD, STRICT_KEYWORD,
THROW_KEYWORD
};
private static final String[] MODULE_BODY_KEYWORDS = new String[]{
EXPORTS_KEYWORD, OPENS_KEYWORD, REQUIRES_KEYWORD, PROVIDES_KEYWORD, USES_KEYWORD
};
private static final String[] CLASS_BODY_KEYWORDS = new String[]{
ABSTRACT_KEYWORD, CLASS_KEYWORD, ENUM_KEYWORD, FINAL_KEYWORD,
INTERFACE_KEYWORD, NATIVE_KEYWORD, PRIVATE_KEYWORD, PROTECTED_KEYWORD,
PUBLIC_KEYWORD, STATIC_KEYWORD, STRICT_KEYWORD, SYNCHRONIZED_KEYWORD,
TRANSIENT_KEYWORD, VOID_KEYWORD, VOLATILE_KEYWORD
};
private static final SourceVersion SOURCE_VERSION_RELEASE_10;
private static final SourceVersion SOURCE_VERSION_RELEASE_11;
private static final SourceVersion SOURCE_VERSION_RELEASE_13;
static {
SourceVersion r10, r11, r13;
try {
r10 = SourceVersion.valueOf("RELEASE_10");
} catch (IllegalArgumentException ex) {
r10 = null;
}
try {
r11 = SourceVersion.valueOf("RELEASE_11");
} catch (IllegalArgumentException ex) {
r11 = null;
}
try {
r13 = SourceVersion.valueOf("RELEASE_13");
} catch (IllegalArgumentException ex) {
r13 = null;
}
SOURCE_VERSION_RELEASE_10 = r10;
SOURCE_VERSION_RELEASE_11 = r11;
SOURCE_VERSION_RELEASE_13 = r13;
}
private final ItemFactory<T> itemFactory;
private final Set<Options> options;
private ArrayList<T> results;
private boolean hasAdditionalClasses;
private boolean hasAdditionalMembers;
private int anchorOffset;
private JavaCompletionTask(final int caretOffset, final ItemFactory<T> factory, final Callable<Boolean> cancel, final Set<Options> options) {
super(caretOffset, cancel);
this.itemFactory = factory;
this.options = options;
}
public List<T> getResults() {
return results;
}
public boolean hasAdditionalClasses() {
return hasAdditionalClasses;
}
public boolean hasAdditionalMembers() {
return hasAdditionalMembers;
}
public int getAnchorOffset() {
return anchorOffset;
}
@Override
protected void resolve(CompilationController controller) throws IOException {
Env env = getCompletionEnvironment(controller, true);
if (env == null) {
return;
}
if (options.contains(JavaCompletionTask.Options.SKIP_ACCESSIBILITY_CHECK)) {
env.skipAccessibilityCheck();
}
results = new ArrayList<>();
anchorOffset = controller.getSnapshot().getOriginalOffset(env.getOffset());
TreePath path = env.getPath();
switch (path.getLeaf().getKind()) {
case COMPILATION_UNIT:
insideCompilationUnit(env);
break;
case MODULE:
insideModule(env);
break;
case EXPORTS:
insideExports(env);
break;
case OPENS:
insideOpens(env);
break;
case PROVIDES:
insideProvides(env);
break;
case REQUIRES:
insideRequires(env);
break;
case USES:
insideUses(env);
break;
case PACKAGE:
insidePackage(env);
break;
case IMPORT:
insideImport(env);
break;
case ANNOTATION_TYPE:
case CLASS:
case ENUM:
case INTERFACE:
insideClass(env);
break;
case VARIABLE:
insideVariable(env);
break;
case METHOD:
insideMethod(env);
break;
case MODIFIERS:
insideModifiers(env, path);
break;
case ANNOTATION:
case TYPE_ANNOTATION:
insideAnnotation(env);
break;
case ANNOTATED_TYPE:
insideAnnotatedType(env);
break;
case TYPE_PARAMETER:
insideTypeParameter(env);
break;
case PARAMETERIZED_TYPE:
insideParameterizedType(env, path);
break;
case UNBOUNDED_WILDCARD:
case EXTENDS_WILDCARD:
case SUPER_WILDCARD:
TreePath parentPath = path.getParentPath();
if (parentPath.getLeaf().getKind() == Tree.Kind.PARAMETERIZED_TYPE) {
insideParameterizedType(env, parentPath);
}
break;
case BLOCK:
insideBlock(env);
break;
case MEMBER_SELECT:
insideMemberSelect(env);
break;
case MEMBER_REFERENCE:
insideMemberReference(env);
break;
case LAMBDA_EXPRESSION:
insideLambdaExpression(env);
break;
case METHOD_INVOCATION:
insideMethodInvocation(env);
break;
case NEW_CLASS:
insideNewClass(env);
break;
case ASSERT:
case RETURN:
case THROW:
localResult(env);
addValueKeywords(env);
break;
case TRY:
insideTry(env);
break;
case CATCH:
insideCatch(env);
break;
case UNION_TYPE:
insideUnionType(env);
break;
case IF:
insideIf(env);
break;
case WHILE_LOOP:
insideWhile(env);
break;
case DO_WHILE_LOOP:
insideDoWhile(env);
break;
case FOR_LOOP:
insideFor(env);
break;
case ENHANCED_FOR_LOOP:
insideForEach(env);
break;
case SWITCH:
insideSwitch(env);
break;
case CASE:
insideCase(env);
break;
case LABELED_STATEMENT:
localResult(env);
addKeywordsForStatement(env);
break;
case PARENTHESIZED:
insideParens(env);
break;
case TYPE_CAST:
insideExpression(env, path);
break;
case INSTANCE_OF:
insideTypeCheck(env);
break;
case ARRAY_ACCESS:
insideArrayAccess(env);
break;
case NEW_ARRAY:
insideNewArray(env);
break;
case ASSIGNMENT:
insideAssignment(env);
break;
case MULTIPLY_ASSIGNMENT:
case DIVIDE_ASSIGNMENT:
case REMAINDER_ASSIGNMENT:
case PLUS_ASSIGNMENT:
case MINUS_ASSIGNMENT:
case LEFT_SHIFT_ASSIGNMENT:
case RIGHT_SHIFT_ASSIGNMENT:
case UNSIGNED_RIGHT_SHIFT_ASSIGNMENT:
case AND_ASSIGNMENT:
case XOR_ASSIGNMENT:
case OR_ASSIGNMENT:
insideCompoundAssignment(env);
break;
case PREFIX_INCREMENT:
case PREFIX_DECREMENT:
case UNARY_PLUS:
case UNARY_MINUS:
case BITWISE_COMPLEMENT:
case LOGICAL_COMPLEMENT:
localResult(env);
break;
case AND:
case CONDITIONAL_AND:
case CONDITIONAL_OR:
case DIVIDE:
case EQUAL_TO:
case GREATER_THAN:
case GREATER_THAN_EQUAL:
case LEFT_SHIFT:
case LESS_THAN:
case LESS_THAN_EQUAL:
case MINUS:
case MULTIPLY:
case NOT_EQUAL_TO:
case OR:
case PLUS:
case REMAINDER:
case RIGHT_SHIFT:
case UNSIGNED_RIGHT_SHIFT:
case XOR:
insideBinaryTree(env);
break;
case CONDITIONAL_EXPRESSION:
insideConditionalExpression(env);
break;
case EXPRESSION_STATEMENT:
insideExpressionStatement(env);
break;
case BREAK:
case CONTINUE:
insideBreakOrContinue(env);
break;
case STRING_LITERAL:
insideStringLiteral(env);
break;
default:
if (path.getLeaf().getKind().toString().equals(TreeShims.SWITCH_EXPRESSION)) {
insideSwitch(env);
}
break;
}
}
private void insideCompilationUnit(Env env) throws IOException {
int offset = env.getOffset();
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
Tree pkg = root.getPackageName();
if (pkg == null || offset <= sourcePositions.getStartPosition(root, root)) {
addKeywordsForCU(env);
return;
}
if (offset <= sourcePositions.getStartPosition(root, pkg)) {
addPackages(env, null, true);
} else {
TokenSequence<JavaTokenId> first = findFirstNonWhitespaceToken(env, (int) sourcePositions.getEndPosition(root, pkg), offset);
if (first != null && first.token().id() == JavaTokenId.SEMICOLON) {
addKeywordsForCU(env);
}
}
}
private void insideModule(Env env) throws IOException {
int offset = env.getOffset();
TreePath path = env.getPath();
CompilationController controller = env.getController();
int startPos = (int) env.getSourcePositions().getStartPosition(env.getRoot(), path.getLeaf());
String headerText = controller.getText().substring(startPos, offset);
int idx = headerText.indexOf('{'); //NOI18N
if (idx >= 0) {
addKeywordsForModuleBody(env);
} else if (!headerText.contains("module")) {
addKeyword(env, MODULE_KEYWORD, SPACE, false);
}
}
private void insideExports(Env env) throws IOException {
int offset = env.getOffset();
TreePath path = env.getPath();
ExportsTree exp = (ExportsTree) path.getLeaf();
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
if (exp.getModuleNames() != null) {
int startPos = (int) sourcePositions.getStartPosition(root, exp);
Tree lastModule = null;
for (Tree mdl : exp.getModuleNames()) {
int implPos = (int) sourcePositions.getEndPosition(root, mdl);
if (implPos == Diagnostic.NOPOS || offset <= implPos) {
break;
}
lastModule = mdl;
startPos = implPos;
}
if (lastModule != null) {
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, startPos, offset);
if (last != null && last.token().id() == JavaTokenId.COMMA) {
addModuleNames(env, null, true);
}
return;
}
}
Tree name = exp.getPackageName();
if (name != null) {
int extPos = (int) sourcePositions.getEndPosition(root, name);
if (extPos != Diagnostic.NOPOS && offset > extPos) {
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, extPos + 1, offset);
if (last != null && last.token().id() == JavaTokenId.TO) {
addModuleNames(env, null, true);
} else {
addKeyword(env, TO_KEYWORD, SPACE, false);
}
return;
}
}
addPackages(env, null, true);
}
private void insideOpens(Env env) throws IOException {
int offset = env.getOffset();
TreePath path = env.getPath();
OpensTree op = (OpensTree) path.getLeaf();
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
if (op.getModuleNames() != null) {
int startPos = (int) sourcePositions.getStartPosition(root, op);
Tree lastModule = null;
for (Tree mdl : op.getModuleNames()) {
int implPos = (int) sourcePositions.getEndPosition(root, mdl);
if (implPos == Diagnostic.NOPOS || offset <= implPos) {
break;
}
lastModule = mdl;
startPos = implPos;
}
if (lastModule != null) {
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, startPos, offset);
if (last != null && last.token().id() == JavaTokenId.COMMA) {
addModuleNames(env, null, true);
}
return;
}
}
Tree name = op.getPackageName();
if (name != null) {
int extPos = (int) sourcePositions.getEndPosition(root, name);
if (extPos != Diagnostic.NOPOS && offset > extPos) {
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, extPos + 1, offset);
if (last != null && last.token().id() == JavaTokenId.TO) {
addModuleNames(env, null, true);
} else {
addKeyword(env, TO_KEYWORD, SPACE, false);
}
return;
}
}
addPackages(env, null, true);
}
private void insideProvides(Env env) throws IOException {
int offset = env.getOffset();
TreePath path = env.getPath();
ProvidesTree prov = (ProvidesTree) path.getLeaf();
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
if (prov.getImplementationNames() != null) {
int startPos = (int) sourcePositions.getStartPosition(root, prov);
Tree lastImpl = null;
for (Tree impl : prov.getImplementationNames()) {
int implPos = (int) sourcePositions.getEndPosition(root, impl);
if (implPos == Diagnostic.NOPOS || offset <= implPos) {
break;
}
lastImpl = impl;
startPos = implPos;
}
if (lastImpl != null) {
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, startPos, offset);
if (last != null && last.token().id() != JavaTokenId.COMMA) {
return;
}
}
}
Tree serv = prov.getServiceName();
if (serv != null) {
int extPos = (int) sourcePositions.getEndPosition(root, serv);
if (extPos != Diagnostic.NOPOS && offset > extPos) {
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, extPos + 1, offset);
if (last != null && last.token().id() == JavaTokenId.WITH) {
CompilationController cc = env.getController();
cc.toPhase(Phase.RESOLVED);
Element el = cc.getTrees().getElement(new TreePath(path, serv));
options.add(Options.ALL_COMPLETION);
addTypes(env, EnumSet.of(CLASS), el != null && el.getKind().isInterface() ? (DeclaredType)el.asType() : null);
} else {
addKeyword(env, WITH_KEYWORD, SPACE, false);
}
return;
}
}
options.add(Options.ALL_COMPLETION);
addTypes(env, EnumSet.of(ANNOTATION_TYPE, CLASS, INTERFACE), null);
}
private void insideRequires(Env env) throws IOException {
int offset = env.getOffset();
TreePath path = env.getPath();
RequiresTree req = (RequiresTree) path.getLeaf();
Tree name = req.getModuleName();
if (name != null) {
int extPos = (int) env.getSourcePositions().getEndPosition(env.getRoot(), name);
if (extPos != Diagnostic.NOPOS && offset > extPos) {
return;
}
}
if (!req.isStatic()) {
addKeyword(env, STATIC_KEYWORD, SPACE, false);
}
if (!req.isTransitive()) {
addKeyword(env, TRANSITIVE_KEYWORD, SPACE, false);
}
addModuleNames(env, null, false);
}
private void insideUses(Env env) throws IOException {
int offset = env.getOffset();
TreePath path = env.getPath();
UsesTree uses = (UsesTree) path.getLeaf();
Tree name = uses.getServiceName();
if (name != null) {
int extPos = (int) env.getSourcePositions().getEndPosition(env.getRoot(), name);
if (extPos != Diagnostic.NOPOS && offset > extPos) {
return;
}
}
options.add(Options.ALL_COMPLETION);
addTypes(env, EnumSet.of(ANNOTATION_TYPE, CLASS, INTERFACE), null);
}
private void insidePackage(Env env) {
int offset = env.getOffset();
PackageTree pt = (PackageTree) env.getPath().getLeaf();
SourcePositions sourcePositions = env.getSourcePositions();
if (offset <= sourcePositions.getStartPosition(env.getRoot(), pt.getPackageName())) {
addPackages(env, null, true);
}
}
private void insideImport(Env env) throws IOException {
env.getController().toPhase(Phase.ELEMENTS_RESOLVED);
int offset = env.getOffset();
String prefix = env.getPrefix();
ImportTree im = (ImportTree) env.getPath().getLeaf();
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
if (offset <= sourcePositions.getStartPosition(root, im.getQualifiedIdentifier())) {
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, im, offset);
if (last != null && last.token().id() == JavaTokenId.IMPORT && Utilities.startsWith(STATIC_KEYWORD, prefix)) {
addKeyword(env, STATIC_KEYWORD, SPACE, false);
}
addPackages(env, null, false);
}
if (options.contains(Options.ALL_COMPLETION)) {
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE), null);
} else {
hasAdditionalClasses = true;
}
}
private void insideClass(Env env) throws IOException {
int offset = env.getOffset();
env.insideClass();
TreePath path = env.getPath();
ClassTree cls = (ClassTree) path.getLeaf();
CompilationController controller = env.getController();
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
int startPos = (int) sourcePositions.getEndPosition(root, cls.getModifiers());
if (startPos <= 0) {
startPos = (int) sourcePositions.getStartPosition(root, cls);
}
String headerText = controller.getText().substring(startPos, offset);
int idx = headerText.indexOf('{'); //NOI18N
if (idx >= 0) {
addKeywordsForClassBody(env);
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
addElementCreators(env);
return;
}
TreeUtilities tu = controller.getTreeUtilities();
Tree lastImpl = null;
for (Tree impl : cls.getImplementsClause()) {
int implPos = (int) sourcePositions.getEndPosition(root, impl);
if (implPos == Diagnostic.NOPOS || offset <= implPos) {
break;
}
lastImpl = impl;
startPos = implPos;
}
if (lastImpl != null) {
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, startPos, offset);
if (last != null && last.token().id() == JavaTokenId.COMMA) {
controller.toPhase(Phase.ELEMENTS_RESOLVED);
env.addToExcludes(controller.getTrees().getElement(path));
addTypes(env, EnumSet.of(INTERFACE, ANNOTATION_TYPE), null);
}
return;
}
Tree ext = cls.getExtendsClause();
if (ext != null) {
int extPos = (int) sourcePositions.getEndPosition(root, ext);
if (extPos != Diagnostic.NOPOS && offset > extPos) {
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, extPos + 1, offset);
if (last != null && last.token().id() == JavaTokenId.IMPLEMENTS) {
controller.toPhase(Phase.ELEMENTS_RESOLVED);
env.addToExcludes(controller.getTrees().getElement(path));
addTypes(env, EnumSet.of(INTERFACE, ANNOTATION_TYPE), null);
} else {
addKeyword(env, IMPLEMENTS_KEYWORD, SPACE, false);
}
return;
}
}
TypeParameterTree lastTypeParam = null;
for (TypeParameterTree tp : cls.getTypeParameters()) {
int tpPos = (int) sourcePositions.getEndPosition(root, tp);
if (tpPos == Diagnostic.NOPOS || offset <= tpPos) {
break;
}
lastTypeParam = tp;
startPos = tpPos;
}
if (lastTypeParam != null) {
TokenSequence<JavaTokenId> first = findFirstNonWhitespaceToken(env, startPos, offset);
if (first != null && (first.token().id() == JavaTokenId.GT
|| first.token().id() == JavaTokenId.GTGT
|| first.token().id() == JavaTokenId.GTGTGT)) {
first = nextNonWhitespaceToken(first);
if (first != null && first.offset() < offset) {
if (first.token().id() == JavaTokenId.EXTENDS) {
controller.toPhase(Phase.ELEMENTS_RESOLVED);
env.afterExtends();
env.addToExcludes(controller.getTrees().getElement(path));
addTypes(env, tu.isInterface(cls) ? EnumSet.of(INTERFACE, ANNOTATION_TYPE) : EnumSet.of(CLASS), null);
return;
}
if (first.token().id() == JavaTokenId.IMPLEMENTS) {
controller.toPhase(Phase.ELEMENTS_RESOLVED);
env.addToExcludes(controller.getTrees().getElement(path));
addTypes(env, EnumSet.of(INTERFACE, ANNOTATION_TYPE), null);
return;
}
}
if (!tu.isAnnotation(cls)) {
if (!tu.isEnum(cls)) {
addKeyword(env, EXTENDS_KEYWORD, SPACE, false);
}
if (!tu.isInterface(cls)) {
addKeyword(env, IMPLEMENTS_KEYWORD, SPACE, false);
}
}
} else {
if (lastTypeParam.getBounds().isEmpty()) {
addKeyword(env, EXTENDS_KEYWORD, SPACE, false);
}
}
return;
}
TokenSequence<JavaTokenId> lastNonWhitespaceToken = findLastNonWhitespaceToken(env, startPos, offset);
if (lastNonWhitespaceToken != null) {
switch (lastNonWhitespaceToken.token().id()) {
case EXTENDS:
controller.toPhase(Phase.ELEMENTS_RESOLVED);
env.afterExtends();
env.addToExcludes(controller.getTrees().getElement(path));
addTypes(env, tu.isInterface(cls) ? EnumSet.of(INTERFACE, ANNOTATION_TYPE) : EnumSet.of(CLASS), null);
break;
case IMPLEMENTS:
controller.toPhase(Phase.ELEMENTS_RESOLVED);
env.addToExcludes(controller.getTrees().getElement(path));
addTypes(env, EnumSet.of(INTERFACE, ANNOTATION_TYPE), null);
break;
case IDENTIFIER:
if (!tu.isAnnotation(cls)) {
if (!tu.isEnum(cls)) {
addKeyword(env, EXTENDS_KEYWORD, SPACE, false);
}
if (!tu.isInterface(cls)) {
addKeyword(env, IMPLEMENTS_KEYWORD, SPACE, false);
}
}
break;
}
return;
}
lastNonWhitespaceToken = findLastNonWhitespaceToken(env, (int) sourcePositions.getStartPosition(root, cls), offset);
if (lastNonWhitespaceToken != null && lastNonWhitespaceToken.token().id() == JavaTokenId.AT) {
addKeyword(env, INTERFACE_KEYWORD, SPACE, false);
addTypes(env, EnumSet.of(ANNOTATION_TYPE), null);
} else if (path.getParentPath().getLeaf().getKind() == Tree.Kind.COMPILATION_UNIT) {
addClassModifiers(env, cls.getModifiers().getFlags());
} else {
addMemberModifiers(env, cls.getModifiers().getFlags(), false);
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
}
}
private void insideVariable(Env env) throws IOException {
int offset = env.getOffset();
TreePath path = env.getPath();
VariableTree var = (VariableTree) path.getLeaf();
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
CompilationController controller = env.getController();
Tree type = var.getType();
int typePos = type.getKind() == Tree.Kind.ERRONEOUS && ((ErroneousTree) type).getErrorTrees().isEmpty()
? (int) sourcePositions.getEndPosition(root, type) : (int) sourcePositions.getStartPosition(root, type);
if (offset <= typePos) {
Tree parent = path.getParentPath().getLeaf();
if (parent.getKind() == Tree.Kind.CATCH) {
if (!options.contains(Options.ALL_COMPLETION)) {
TreeUtilities tu = controller.getTreeUtilities();
TreePath tryPath = tu.getPathElementOfKind(Tree.Kind.TRY, path);
Set<TypeMirror> exs = tu.getUncaughtExceptions(tryPath);
Elements elements = controller.getElements();
for (TypeMirror ex : exs) {
if (ex.getKind() == TypeKind.DECLARED && startsWith(env, ((DeclaredType) ex).asElement().getSimpleName().toString())
&& (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(((DeclaredType) ex).asElement()))
&& !Utilities.isExcluded(((TypeElement)((DeclaredType) ex).asElement()).getQualifiedName())) {
env.addToExcludes(((DeclaredType) ex).asElement());
results.add(itemFactory.createTypeItem(controller, (TypeElement) ((DeclaredType) ex).asElement(), (DeclaredType) ex, anchorOffset, env.getReferencesCount(), elements.isDeprecated(((DeclaredType) ex).asElement()), false, false, false, true, false));
}
}
}
TypeElement te = controller.getElements().getTypeElement("java.lang.Throwable"); //NOI18N
if (te != null) {
addTypes(env, EnumSet.of(CLASS, INTERFACE, TYPE_PARAMETER), controller.getTypes().getDeclaredType(te));
}
} else if (parent.getKind() == Tree.Kind.TRY) {
TypeElement te = controller.getElements().getTypeElement("java.lang.AutoCloseable"); //NOI18N
if (te != null) {
addTypes(env, EnumSet.of(CLASS, INTERFACE, TYPE_PARAMETER), controller.getTypes().getDeclaredType(te));
}
} else {
if (path.getParentPath().getLeaf().getKind() == Tree.Kind.LAMBDA_EXPRESSION) {
LambdaExpressionTree let = (LambdaExpressionTree) path.getParentPath().getLeaf();
if (let.getParameters().size() == 1) {
addVarTypeForLambdaParam(env);
} else if (isLambdaVarType(env, let)) {
addVarTypeForLambdaParam(env);
return;
}
}
boolean isLocal = !TreeUtilities.CLASS_TREE_KINDS.contains(parent.getKind());
addMemberModifiers(env, var.getModifiers().getFlags(), isLocal);
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
ModifiersTree mods = var.getModifiers();
if (mods.getFlags().isEmpty() && mods.getAnnotations().isEmpty()) {
addElementCreators(env);
}
}
return;
}
controller.toPhase(Phase.RESOLVED);
Tree init = unwrapErrTree(var.getInitializer());
if (init == null) {
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, (int) sourcePositions.getEndPosition(root, type), offset);
if (last == null || last.token().id() == JavaTokenId.COMMA) {
insideExpression(env, new TreePath(path, type));
} else if (last.token().id() == JavaTokenId.EQ) {
localResult(env);
addValueKeywords(env);
}
} else {
int pos = (int) sourcePositions.getStartPosition(root, init);
if (pos < 0) {
return;
}
if (offset <= pos) {
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, (int) sourcePositions.getEndPosition(root, type), offset);
if (last == null) {
insideExpression(env, new TreePath(path, type));
} else if (last.token().id() == JavaTokenId.EQ) {
localResult(env);
addValueKeywords(env);
}
} else {
insideExpression(env, new TreePath(path, init));
}
}
}
private void insideMethod(Env env) throws IOException {
int offset = env.getOffset();
TreePath path = env.getPath();
MethodTree mth = (MethodTree) path.getLeaf();
CompilationController controller = env.getController();
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
int startPos = (int) sourcePositions.getStartPosition(root, mth);
Tree lastTree = null;
int state = 0;
for (Tree thr : mth.getThrows()) {
int thrPos = (int) sourcePositions.getEndPosition(root, thr);
if (thrPos == Diagnostic.NOPOS || offset <= thrPos) {
break;
}
lastTree = thr;
startPos = thrPos;
state = 4;
}
if (lastTree == null) {
for (VariableTree param : mth.getParameters()) {
int parPos = (int) sourcePositions.getEndPosition(root, param);
if (parPos == Diagnostic.NOPOS || offset <= parPos) {
break;
}
lastTree = param;
startPos = parPos;
state = 3;
}
}
if (lastTree == null) {
Tree retType = mth.getReturnType();
if (retType != null) {
int retPos = (int) sourcePositions.getEndPosition(root, retType);
if (retPos != Diagnostic.NOPOS && offset > retPos) {
lastTree = retType;
startPos = retPos;
state = 2;
}
}
}
if (lastTree == null) {
for (TypeParameterTree tp : mth.getTypeParameters()) {
int tpPos = (int) sourcePositions.getEndPosition(root, tp);
if (tpPos == Diagnostic.NOPOS || offset <= tpPos) {
break;
}
lastTree = tp;
startPos = tpPos;
state = 1;
}
}
if (lastTree == null) {
Tree mods = mth.getModifiers();
if (mods != null) {
int modsPos = (int) sourcePositions.getEndPosition(root, mods);
if (modsPos != Diagnostic.NOPOS && offset > modsPos) {
lastTree = mods;
startPos = modsPos;
}
}
}
TokenSequence<JavaTokenId> lastToken = findLastNonWhitespaceToken(env, startPos, offset);
if (lastToken != null) {
switch (lastToken.token().id()) {
case LPAREN:
addMemberModifiers(env, Collections.<Modifier>emptySet(), true);
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
break;
case RPAREN:
Tree mthParent = path.getParentPath().getLeaf();
switch (mthParent.getKind()) {
case ANNOTATION_TYPE:
addKeyword(env, DEFAULT_KEYWORD, SPACE, false);
break;
default:
addKeyword(env, THROWS_KEYWORD, SPACE, false);
}
break;
case THROWS:
if (!options.contains(Options.ALL_COMPLETION) && mth.getBody() != null) {
controller.toPhase(Phase.RESOLVED);
Set<TypeMirror> exs = controller.getTreeUtilities().getUncaughtExceptions(new TreePath(path, mth.getBody()));
Elements elements = controller.getElements();
for (TypeMirror ex : exs) {
if (ex.getKind() == TypeKind.DECLARED && startsWith(env, ((DeclaredType) ex).asElement().getSimpleName().toString())
&& (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(((DeclaredType) ex).asElement()))
&& !Utilities.isExcluded(((TypeElement)((DeclaredType) ex).asElement()).getQualifiedName())) {
env.addToExcludes(((DeclaredType) ex).asElement());
results.add(itemFactory.createTypeItem(env.getController(), (TypeElement) ((DeclaredType) ex).asElement(), (DeclaredType) ex, anchorOffset, env.getReferencesCount(), elements.isDeprecated(((DeclaredType) ex).asElement()), false, false, false, true, false));
}
}
}
TypeElement te = controller.getElements().getTypeElement("java.lang.Throwable"); //NOI18N
if (te != null) {
addTypes(env, EnumSet.of(CLASS, INTERFACE, TYPE_PARAMETER), controller.getTypes().getDeclaredType(te));
}
break;
case DEFAULT:
addLocalConstantsAndTypes(env);
break;
case GT:
case GTGT:
case GTGTGT:
addPrimitiveTypeKeywords(env);
addKeyword(env, VOID_KEYWORD, SPACE, false);
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
break;
case COMMA:
switch (state) {
case 3:
addMemberModifiers(env, Collections.<Modifier>emptySet(), true);
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
break;
case 4:
if (!options.contains(Options.ALL_COMPLETION) && mth.getBody() != null) {
controller.toPhase(Phase.RESOLVED);
Set<TypeMirror> exs = controller.getTreeUtilities().getUncaughtExceptions(new TreePath(path, mth.getBody()));
Trees trees = controller.getTrees();
Types types = controller.getTypes();
for (ExpressionTree thr : mth.getThrows()) {
TypeMirror t = trees.getTypeMirror(new TreePath(path, thr));
for (Iterator<TypeMirror> it = exs.iterator(); it.hasNext();) {
if (types.isSubtype(it.next(), t)) {
it.remove();
}
}
if (thr == lastTree) {
break;
}
}
Elements elements = controller.getElements();
for (TypeMirror ex : exs) {
if (ex.getKind() == TypeKind.DECLARED && startsWith(env, ((DeclaredType) ex).asElement().getSimpleName().toString())
&& (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(((DeclaredType) ex).asElement()))
&& !Utilities.isExcluded(((TypeElement)((DeclaredType) ex).asElement()).getQualifiedName())) {
env.addToExcludes(((DeclaredType) ex).asElement());
results.add(itemFactory.createTypeItem(env.getController(), (TypeElement) ((DeclaredType) ex).asElement(), (DeclaredType) ex, anchorOffset, env.getReferencesCount(), elements.isDeprecated(((DeclaredType) ex).asElement()), false, false, false, true, false));
}
}
}
te = controller.getElements().getTypeElement("java.lang.Throwable"); //NOI18N
if (te != null) {
addTypes(env, EnumSet.of(CLASS, INTERFACE, TYPE_PARAMETER), controller.getTypes().getDeclaredType(te));
}
break;
}
break;
}
return;
}
switch (state) {
case 0:
addMemberModifiers(env, mth.getModifiers().getFlags(), false);
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
break;
case 1:
if (((TypeParameterTree) lastTree).getBounds().isEmpty()) {
addKeyword(env, EXTENDS_KEYWORD, SPACE, false);
}
break;
case 2:
insideExpression(env, new TreePath(path, lastTree));
break;
}
}
private void insideModifiers(Env env, TreePath modPath) throws IOException {
int offset = env.getOffset();
ModifiersTree mods = (ModifiersTree) modPath.getLeaf();
Set<Modifier> m = EnumSet.noneOf(Modifier.class);
TokenSequence<JavaTokenId> ts = env.getController().getTreeUtilities().tokensFor(mods, env.getSourcePositions());
JavaTokenId lastNonWhitespaceTokenId = null;
while (ts.moveNext() && ts.offset() < offset) {
lastNonWhitespaceTokenId = ts.token().id();
switch (lastNonWhitespaceTokenId) {
case PUBLIC:
m.add(PUBLIC);
break;
case PROTECTED:
m.add(PROTECTED);
break;
case PRIVATE:
m.add(PRIVATE);
break;
case STATIC:
m.add(STATIC);
break;
case DEFAULT:
m.add(DEFAULT);
break;
case ABSTRACT:
m.add(ABSTRACT);
break;
case FINAL:
m.add(FINAL);
break;
case SYNCHRONIZED:
m.add(SYNCHRONIZED);
break;
case NATIVE:
m.add(NATIVE);
break;
case STRICTFP:
m.add(STRICTFP);
break;
case TRANSIENT:
m.add(TRANSIENT);
break;
case VOLATILE:
m.add(VOLATILE);
break;
}
}
if (lastNonWhitespaceTokenId == JavaTokenId.AT) {
addKeyword(env, INTERFACE_KEYWORD, SPACE, false);
addTypes(env, EnumSet.of(ANNOTATION_TYPE), null);
return;
}
TreePath parentPath = modPath.getParentPath();
Tree parent = parentPath.getLeaf();
TreePath grandParentPath = parentPath.getParentPath();
Tree grandParent = grandParentPath != null ? grandParentPath.getLeaf() : null;
if (isTopLevelClass(parent, env.getRoot())) {
addClassModifiers(env, m);
} else if (parent.getKind() != Tree.Kind.VARIABLE || grandParent == null || TreeUtilities.CLASS_TREE_KINDS.contains(grandParent.getKind())) {
addMemberModifiers(env, m, false);
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
} else if (parent.getKind() == Tree.Kind.VARIABLE && grandParent.getKind() == Tree.Kind.METHOD) {
addMemberModifiers(env, m, true);
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
} else {
localResult(env);
addKeywordsForBlock(env);
}
}
private void insideAnnotation(Env env) throws IOException {
int offset = env.getOffset();
TreePath path = env.getPath();
AnnotationTree ann = (AnnotationTree) path.getLeaf();
CompilationController controller = env.getController();
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
int typeEndPos = (int) sourcePositions.getEndPosition(root, ann.getAnnotationType());
if (offset <= typeEndPos) {
TreePath parentPath = path.getParentPath();
if (parentPath.getLeaf().getKind() == Tree.Kind.MODIFIERS
&& (parentPath.getParentPath().getLeaf().getKind() != Tree.Kind.VARIABLE
|| parentPath.getParentPath().getParentPath().getLeaf().getKind() == Tree.Kind.CLASS)) {
addKeyword(env, INTERFACE_KEYWORD, SPACE, false);
}
if (!options.contains(Options.ALL_COMPLETION)) {
controller.toPhase(Phase.ELEMENTS_RESOLVED);
Set<? extends TypeMirror> smarts = getSmartTypes(env);
if (smarts != null) {
Elements elements = controller.getElements();
for (TypeMirror smart : smarts) {
if (smart.getKind() == TypeKind.DECLARED) {
TypeElement elem = (TypeElement) ((DeclaredType) smart).asElement();
if (elem.getKind() == ANNOTATION_TYPE && (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(elem)) && !Utilities.isExcluded(elem.getQualifiedName())) {
results.add(itemFactory.createTypeItem(env.getController(), elem, (DeclaredType) smart, anchorOffset, env.getReferencesCount(), elements.isDeprecated(elem), false, false, false, true, false));
}
}
}
}
}
addTypes(env, EnumSet.of(ANNOTATION_TYPE), null);
return;
}
TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, ann, offset);
if (ts == null || (ts.token().id() != JavaTokenId.LPAREN && ts.token().id() != JavaTokenId.COMMA)) {
return;
}
controller.toPhase(Phase.ELEMENTS_RESOLVED);
Trees trees = controller.getTrees();
Element annTypeElement = trees.getElement(new TreePath(path, ann.getAnnotationType()));
if (annTypeElement != null && annTypeElement.getKind() == ANNOTATION_TYPE) {
HashSet<String> names = new HashSet<>();
for (ExpressionTree arg : ann.getArguments()) {
if (arg.getKind() == Tree.Kind.ASSIGNMENT && sourcePositions.getEndPosition(root, ((AssignmentTree) arg).getExpression()) < offset) {
ExpressionTree var = ((AssignmentTree) arg).getVariable();
if (var.getKind() == Tree.Kind.IDENTIFIER) {
names.add(((IdentifierTree) var).getName().toString());
}
}
}
Elements elements = controller.getElements();
ExecutableElement valueElement = null;
for (Element e : ((TypeElement) annTypeElement).getEnclosedElements()) {
if (e.getKind() == METHOD) {
String name = e.getSimpleName().toString();
if ("value".equals(name)) { //NOI18N
valueElement = (ExecutableElement) e;
} else if (((ExecutableElement) e).getDefaultValue() == null) {
valueElement = null;
}
if (!names.contains(name) && startsWith(env, name) && (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(e))) {
results.add(itemFactory.createAttributeItem(env.getController(), (ExecutableElement) e, (ExecutableType) e.asType(), anchorOffset, elements.isDeprecated(e)));
}
}
}
if (valueElement != null && names.isEmpty()) {
Element el = null;
TreePath pPath = path.getParentPath();
if (pPath.getLeaf().getKind() == Tree.Kind.COMPILATION_UNIT) {
el = trees.getElement(pPath);
} else {
pPath = pPath.getParentPath();
Tree.Kind pKind = pPath.getLeaf().getKind();
if (TreeUtilities.CLASS_TREE_KINDS.contains(pKind) || pKind == Tree.Kind.METHOD || pKind == Tree.Kind.VARIABLE) {
el = trees.getElement(pPath);
}
}
if (el != null) {
AnnotationMirror annotation = null;
for (AnnotationMirror am : el.getAnnotationMirrors()) {
if (annTypeElement == am.getAnnotationType().asElement()) {
annotation = am;
break;
}
}
if (annotation != null) {
addAttributeValues(env, el, annotation, valueElement);
}
}
addLocalConstantsAndTypes(env);
}
}
}
private void insideAnnotatedType(Env env) throws IOException {
int offset = env.getOffset();
AnnotatedTypeTree att = (AnnotatedTypeTree) env.getPath().getLeaf();
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
int pos = (int) sourcePositions.getStartPosition(root, att.getUnderlyingType());
if (pos >= 0 && pos < offset) {
insideExpression(env, new TreePath(env.getPath(), att.getUnderlyingType()));
} else {
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
}
}
private void insideAnnotationAttribute(Env env, TreePath annotationPath, Name attributeName) throws IOException {
CompilationController controller = env.getController();
controller.toPhase(Phase.ELEMENTS_RESOLVED);
Trees trees = controller.getTrees();
AnnotationTree at = (AnnotationTree) annotationPath.getLeaf();
Element annTypeElement = trees.getElement(new TreePath(annotationPath, at.getAnnotationType()));
Element el = null;
TreePath pPath = annotationPath.getParentPath();
if (pPath.getLeaf().getKind() == Tree.Kind.COMPILATION_UNIT) {
el = trees.getElement(pPath);
} else {
pPath = pPath.getParentPath();
Tree.Kind pKind = pPath.getLeaf().getKind();
if (TreeUtilities.CLASS_TREE_KINDS.contains(pKind) || pKind == Tree.Kind.METHOD || pKind == Tree.Kind.VARIABLE) {
el = trees.getElement(pPath);
}
}
if (el != null && annTypeElement != null && annTypeElement.getKind() == ANNOTATION_TYPE) {
ExecutableElement memberElement = null;
for (Element e : ((TypeElement) annTypeElement).getEnclosedElements()) {
if (e.getKind() == METHOD && attributeName.contentEquals(e.getSimpleName())) {
memberElement = (ExecutableElement) e;
break;
}
}
if (memberElement != null) {
AnnotationMirror annotation = null;
for (AnnotationMirror am : el.getAnnotationMirrors()) {
if (annTypeElement == am.getAnnotationType().asElement()) {
annotation = am;
break;
}
}
if (annotation != null) {
addAttributeValues(env, el, annotation, memberElement);
}
}
}
}
private void insideTypeParameter(Env env) throws IOException {
int offset = env.getOffset();
TreePath path = env.getPath();
TypeParameterTree tp = (TypeParameterTree) path.getLeaf();
CompilationController controller = env.getController();
TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, tp, offset);
if (ts != null) {
switch (ts.token().id()) {
case EXTENDS:
controller.toPhase(Phase.ELEMENTS_RESOLVED);
addTypes(env, EnumSet.of(CLASS, INTERFACE, ANNOTATION_TYPE), null);
break;
case AMP:
controller.toPhase(Phase.ELEMENTS_RESOLVED);
addTypes(env, EnumSet.of(INTERFACE, ANNOTATION_TYPE), null);
break;
case IDENTIFIER:
if (ts.offset() == env.getSourcePositions().getStartPosition(env.getRoot(), tp)) {
addKeyword(env, EXTENDS_KEYWORD, SPACE, false);
}
break;
}
}
}
private void insideParameterizedType(Env env, TreePath ptPath) throws IOException {
int offset = env.getOffset();
ParameterizedTypeTree ta = (ParameterizedTypeTree) ptPath.getLeaf();
TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, ta, offset);
if (ts != null) {
switch (ts.token().id()) {
case EXTENDS:
case SUPER:
case LT:
case COMMA:
if (!options.contains(Options.ALL_COMPLETION)) {
CompilationController controller = env.getController();
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
int index = 0;
for (Tree arg : ta.getTypeArguments()) {
int parPos = (int) sourcePositions.getEndPosition(root, arg);
if (parPos == Diagnostic.NOPOS || offset <= parPos) {
break;
}
index++;
}
Elements elements = controller.getElements();
Types types = controller.getTypes();
TypeMirror tm = controller.getTrees().getTypeMirror(new TreePath(ptPath, ta.getType()));
List<? extends TypeMirror> bounds = null;
if (tm.getKind() == TypeKind.DECLARED) {
TypeElement te = (TypeElement) ((DeclaredType) tm).asElement();
List<? extends TypeParameterElement> typeParams = te.getTypeParameters();
if (index < typeParams.size()) {
TypeParameterElement typeParam = typeParams.get(index);
bounds = typeParam.getBounds();
}
}
Set<? extends TypeMirror> smarts = getSmartTypes(env);
if (smarts != null) {
for (TypeMirror smart : smarts) {
if (smart != null) {
if (smart.getKind() == TypeKind.DECLARED && types.isSubtype(tm, types.erasure(smart))) {
List<? extends TypeMirror> typeArgs = ((DeclaredType) smart).getTypeArguments();
if (index < typeArgs.size()) {
TypeMirror lowerBound = typeArgs.get(index);
TypeMirror upperBound = null;
if (lowerBound.getKind() == TypeKind.WILDCARD) {
upperBound = ((WildcardType) lowerBound).getSuperBound();
lowerBound = ((WildcardType) lowerBound).getExtendsBound();
}
if (lowerBound != null && lowerBound.getKind() == TypeKind.TYPEVAR) {
lowerBound = ((TypeVariable) lowerBound).getUpperBound();
}
if (upperBound != null && upperBound.getKind() == TypeKind.TYPEVAR) {
upperBound = ((TypeVariable) upperBound).getUpperBound();
}
if (upperBound != null && upperBound.getKind() == TypeKind.DECLARED) {
while (upperBound.getKind() == TypeKind.DECLARED) {
TypeElement elem = (TypeElement) ((DeclaredType) upperBound).asElement();
if (startsWith(env, elem.getSimpleName().toString()) && withinBounds(env, upperBound, bounds) && (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(elem)) && !Utilities.isExcluded(elem.getQualifiedName())) {
results.add(itemFactory.createTypeItem(env.getController(), elem, (DeclaredType) upperBound, anchorOffset, env.getReferencesCount(), elements.isDeprecated(elem), false, true, false, true, false));
}
env.addToExcludes(elem);
upperBound = elem.getSuperclass();
}
} else if (lowerBound != null && lowerBound.getKind() == TypeKind.DECLARED) {
for (DeclaredType subtype : getSubtypesOf(env, (DeclaredType) lowerBound)) {
TypeElement elem = (TypeElement) subtype.asElement();
if (withinBounds(env, subtype, bounds) && (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(elem)) && !Utilities.isExcluded(elem.getQualifiedName())) {
results.add(itemFactory.createTypeItem(env.getController(), elem, subtype, anchorOffset, env.getReferencesCount(), elements.isDeprecated(elem), false, true, false, true, false));
}
env.addToExcludes(elem);
}
}
}
}
}
}
} else if (bounds != null && !bounds.isEmpty()) {
TypeMirror lowerBound = bounds.get(0);
bounds = bounds.subList(0, bounds.size());
for (DeclaredType subtype : getSubtypesOf(env, (DeclaredType) lowerBound)) {
TypeElement elem = (TypeElement) subtype.asElement();
if (withinBounds(env, subtype, bounds) && (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(elem)) && !Utilities.isExcluded(elem.getQualifiedName())) {
results.add(itemFactory.createTypeItem(env.getController(), elem, subtype, anchorOffset, env.getReferencesCount(), elements.isDeprecated(elem), false, true, false, true, false));
}
env.addToExcludes(elem);
}
}
}
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
break;
case QUESTION:
addKeyword(env, EXTENDS_KEYWORD, SPACE, false);
addKeyword(env, SUPER_KEYWORD, SPACE, false);
break;
}
}
}
private void insideBlock(Env env) throws IOException {
int offset = env.getOffset();
BlockTree bl = (BlockTree) env.getPath().getLeaf();
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
int blockPos = (int) sourcePositions.getStartPosition(root, bl);
String text = env.getController().getText().substring(blockPos, offset);
if (text.indexOf('{') < 0) { //NOI18N
addMemberModifiers(env, Collections.singleton(STATIC), false);
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
return;
}
StatementTree last = null;
for (StatementTree stat : bl.getStatements()) {
int pos = (int) sourcePositions.getStartPosition(root, stat);
if (pos == Diagnostic.NOPOS || offset <= pos) {
break;
}
last = stat;
}
if (last == null) {
ExecutableElement enclMethod = env.getScope().getEnclosingMethod();
if (enclMethod != null && enclMethod.getKind() == ElementKind.CONSTRUCTOR) {
String prefix = env.getPrefix();
if (Utilities.startsWith(THIS_KEYWORD, prefix)) {
Element element = enclMethod.getEnclosingElement();
addThisOrSuperConstructor(env, element.asType(), element, THIS_KEYWORD, enclMethod);
}
if (Utilities.startsWith(SUPER_KEYWORD, prefix)) {
Element element = enclMethod.getEnclosingElement();
element = ((DeclaredType) ((TypeElement) element).getSuperclass()).asElement();
addThisOrSuperConstructor(env, element.asType(), element, SUPER_KEYWORD, enclMethod);
}
}
} else if (last.getKind() == Tree.Kind.TRY) {
if (((TryTree) last).getFinallyBlock() == null) {
addKeyword(env, CATCH_KEYWORD, null, true);
addKeyword(env, FINALLY_KEYWORD, null, true);
if (((TryTree) last).getCatches().isEmpty() && ((TryTree) last).getResources().isEmpty()) {
return;
}
}
} else if (last.getKind() == Tree.Kind.IF) {
if (((IfTree) last).getElseStatement() == null) {
addKeyword(env, ELSE_KEYWORD, null, true);
}
}
localResult(env);
addKeywordsForBlock(env);
String prefix = env.getPrefix();
if (SOURCE_VERSION_RELEASE_13 != null && env.getController().getSourceVersion().compareTo(SOURCE_VERSION_RELEASE_13) >= 0
&& Utilities.startsWith(YIELD_KEYWORD, prefix)) {
TreePath parentPath = env.getPath().getParentPath();
if (parentPath.getLeaf().getKind() == Tree.Kind.CASE && parentPath.getParentPath().getLeaf().getKind().toString().equals(TreeShims.SWITCH_EXPRESSION)) {
addKeyword(env, YIELD_KEYWORD, null, false);
}
}
}
@SuppressWarnings("fallthrough")
private void insideMemberSelect(Env env) throws IOException {
int offset = env.getOffset();
String prefix = env.getPrefix();
TreePath path = env.getPath();
MemberSelectTree fa = (MemberSelectTree) path.getLeaf();
CompilationController controller = env.getController();
CompilationUnitTree root = env.getRoot();
SourcePositions sourcePositions = env.getSourcePositions();
int expEndPos = (int) sourcePositions.getEndPosition(root, fa.getExpression());
boolean afterDot = false;
boolean afterLt = false;
int openLtNum = 0;
JavaTokenId lastNonWhitespaceTokenId = null;
TokenSequence<JavaTokenId> ts = controller.getTokenHierarchy().tokenSequence(JavaTokenId.language());
ts.move(expEndPos);
while (ts.moveNext()) {
if (ts.offset() >= offset) {
break;
}
switch (ts.token().id()) {
case DOUBLE_LITERAL:
case FLOAT_LITERAL:
case FLOAT_LITERAL_INVALID:
case LONG_LITERAL:
case ELLIPSIS:
if (ts.offset() != expEndPos || ts.token().text().charAt(0) != '.') {
break;
}
case DOT:
afterDot = true;
break;
case LT:
afterLt = true;
openLtNum++;
break;
case GT:
openLtNum--;
break;
case GTGT:
openLtNum -= 2;
break;
case GTGTGT:
openLtNum -= 3;
break;
}
switch (ts.token().id()) {
case WHITESPACE:
case LINE_COMMENT:
case BLOCK_COMMENT:
case JAVADOC_COMMENT:
break;
default:
lastNonWhitespaceTokenId = ts.token().id();
}
}
if (!afterDot) {
if (expEndPos <= offset) {
insideExpression(env, new TreePath(path, fa.getExpression()));
}
return;
}
if (openLtNum > 0) {
switch (lastNonWhitespaceTokenId) {
case QUESTION:
addKeyword(env, EXTENDS_KEYWORD, SPACE, false);
addKeyword(env, SUPER_KEYWORD, SPACE, false);
break;
case LT:
case COMMA:
case EXTENDS:
case SUPER:
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
break;
}
} else if (lastNonWhitespaceTokenId != JavaTokenId.STAR) {
controller.toPhase(Phase.RESOLVED);
if (withinModuleName(env)) {
String fqnPrefix = fa.getExpression().toString() + '.';
anchorOffset = (int) sourcePositions.getStartPosition(root, fa);
addModuleNames(env, fqnPrefix, true);
return;
}
TreePath parentPath = path.getParentPath();
Tree parent = parentPath != null ? parentPath.getLeaf() : null;
TreePath grandParentPath = parentPath != null ? parentPath.getParentPath() : null;
Tree grandParent = grandParentPath != null ? grandParentPath.getLeaf() : null;
ExpressionTree exp = fa.getExpression();
TreePath expPath = new TreePath(path, exp);
TypeMirror type = controller.getTrees().getTypeMirror(expPath);
if (type != null) {
Element el = controller.getTrees().getElement(expPath);
TreeUtilities tu = controller.getTreeUtilities();
EnumSet<ElementKind> kinds;
DeclaredType baseType = null;
Set<TypeMirror> exs = null;
boolean inImport = false;
boolean insideNew = false;
boolean srcOnly = false;
if (TreeUtilities.CLASS_TREE_KINDS.contains(parent.getKind()) && ((ClassTree) parent).getExtendsClause() == fa) {
kinds = EnumSet.of(CLASS);
env.afterExtends();
} else if (TreeUtilities.CLASS_TREE_KINDS.contains(parent.getKind()) && ((ClassTree) parent).getImplementsClause().contains(fa)) {
kinds = EnumSet.of(INTERFACE);
} else if (parent.getKind() == Tree.Kind.IMPORT) {
inImport = true;
kinds = ((ImportTree) parent).isStatic() ? EnumSet.of(CLASS, ENUM, INTERFACE, ANNOTATION_TYPE, FIELD, METHOD, ENUM_CONSTANT) : EnumSet.of(CLASS, ANNOTATION_TYPE, ENUM, INTERFACE);
} else if (parent.getKind() == Tree.Kind.NEW_CLASS && ((NewClassTree) parent).getIdentifier() == fa) {
insideNew = true;
kinds = EnumSet.of(CLASS, INTERFACE, ANNOTATION_TYPE);
if (grandParent.getKind() == Tree.Kind.THROW) {
TypeElement te = controller.getElements().getTypeElement("java.lang.Throwable"); //NOI18N
if (te != null) {
baseType = controller.getTypes().getDeclaredType(te);
}
}
} else if (parent.getKind() == Tree.Kind.PARAMETERIZED_TYPE && ((ParameterizedTypeTree) parent).getTypeArguments().contains(fa)) {
kinds = EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE);
} else if (parent.getKind() == Tree.Kind.ANNOTATION || parent.getKind() == Tree.Kind.TYPE_ANNOTATION) {
if (((AnnotationTree) parent).getAnnotationType() == fa) {
kinds = EnumSet.of(ANNOTATION_TYPE);
} else {
Iterator<? extends ExpressionTree> it = ((AnnotationTree) parent).getArguments().iterator();
if (it.hasNext()) {
ExpressionTree et = it.next();
if (et == fa || (et.getKind() == Tree.Kind.ASSIGNMENT && ((AssignmentTree) et).getExpression() == fa)) {
if (type.getKind() == TypeKind.ERROR && el.getKind().isClass()) {
el = controller.getElements().getPackageElement(((TypeElement) el).getQualifiedName());
}
if (el instanceof PackageElement) {
addPackageContent(env, (PackageElement) el, EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE), null, false, false);
} else if (type.getKind() == TypeKind.DECLARED) {
addMemberConstantsAndTypes(env, (DeclaredType) type, el);
}
return;
}
}
kinds = EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE, FIELD, METHOD, ENUM_CONSTANT);
}
} else if (parent.getKind() == Tree.Kind.ASSIGNMENT && ((AssignmentTree) parent).getExpression() == fa && grandParent != null && grandParent.getKind() == Tree.Kind.ANNOTATION) {
if (type.getKind() == TypeKind.ERROR && el.getKind().isClass()) {
el = controller.getElements().getPackageElement(((TypeElement) el).getQualifiedName());
}
if (el instanceof PackageElement) {
addPackageContent(env, (PackageElement) el, EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE), null, false, false);
} else if (type.getKind() == TypeKind.DECLARED) {
addMemberConstantsAndTypes(env, (DeclaredType) type, el);
}
return;
} else if (parent.getKind() == Tree.Kind.VARIABLE && ((VariableTree) parent).getType() == fa) {
if (grandParent.getKind() == Tree.Kind.CATCH) {
kinds = EnumSet.of(CLASS, INTERFACE);
if (!options.contains(Options.ALL_COMPLETION)) {
exs = controller.getTreeUtilities().getUncaughtExceptions(grandParentPath.getParentPath());
}
TypeElement te = controller.getElements().getTypeElement("java.lang.Throwable"); //NOI18N
if (te != null) {
baseType = controller.getTypes().getDeclaredType(te);
}
} else {
kinds = EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE);
}
} else if (parent.getKind() == Tree.Kind.METHOD && ((MethodTree) parent).getThrows().contains(fa)) {
Types types = controller.getTypes();
if (!options.contains(Options.ALL_COMPLETION) && ((MethodTree) parent).getBody() != null) {
controller.toPhase(Phase.RESOLVED);
exs = controller.getTreeUtilities().getUncaughtExceptions(new TreePath(path, ((MethodTree) parent).getBody()));
Trees trees = controller.getTrees();
for (ExpressionTree thr : ((MethodTree) parent).getThrows()) {
if (sourcePositions.getEndPosition(root, thr) >= offset) {
break;
}
TypeMirror t = trees.getTypeMirror(new TreePath(path, thr));
for (Iterator<TypeMirror> it = exs.iterator(); it.hasNext();) {
if (types.isSubtype(it.next(), t)) {
it.remove();
}
}
}
}
kinds = EnumSet.of(CLASS, INTERFACE);
TypeElement te = controller.getElements().getTypeElement("java.lang.Throwable"); //NOI18N
if (te != null) {
baseType = controller.getTypes().getDeclaredType(te);
}
} else if (parent.getKind() == Tree.Kind.METHOD && ((MethodTree) parent).getDefaultValue() == fa) {
if (type.getKind() == TypeKind.ERROR && el.getKind().isClass()) {
el = controller.getElements().getPackageElement(((TypeElement) el).getQualifiedName());
}
if (el instanceof PackageElement) {
addPackageContent(env, (PackageElement) el, EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE), null, false, false);
} else if (type.getKind() == TypeKind.DECLARED) {
addMemberConstantsAndTypes(env, (DeclaredType) type, el);
}
return;
} else if (parent.getKind() == Tree.Kind.TYPE_PARAMETER) {
TypeParameterTree tpt = (TypeParameterTree) parent;
Trees trees = controller.getTrees();
boolean first = true;
for (Tree bound : tpt.getBounds()) {
int pos = (int) sourcePositions.getEndPosition(root, bound);
if (offset <= pos) {
break;
}
first = false;
env.addToExcludes(trees.getElement(new TreePath(parentPath, bound)));
}
kinds = first ? EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE) : EnumSet.of(ANNOTATION_TYPE, INTERFACE);
} else if (parent.getKind() == Tree.Kind.AND) {
TypeMirror tm = controller.getTrees().getTypeMirror(new TreePath(path, ((BinaryTree) parent).getLeftOperand()));
if (tm != null && tm.getKind() == TypeKind.DECLARED) {
env.addToExcludes(((DeclaredType) tm).asElement());
kinds = EnumSet.of(INTERFACE, ANNOTATION_TYPE);
} else if (tm != null && tm.getKind() == TypeKind.INTERSECTION) {
for (TypeMirror bound : ((IntersectionType) tm).getBounds()) {
if (bound.getKind() == TypeKind.DECLARED) {
env.addToExcludes(((DeclaredType) bound).asElement());
}
}
kinds = EnumSet.of(INTERFACE, ANNOTATION_TYPE);
} else {
kinds = EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE, FIELD, METHOD, ENUM_CONSTANT);
}
} else if (afterLt) {
kinds = EnumSet.of(METHOD);
} else if (parent.getKind() == Tree.Kind.ENHANCED_FOR_LOOP && ((EnhancedForLoopTree) parent).getExpression() == fa) {
env.insideForEachExpression();
kinds = EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE, FIELD, METHOD, ENUM_CONSTANT);
} else if (tu.getPathElementOfKind(Tree.Kind.EXPORTS, path) != null) {
kinds = EnumSet.noneOf(ElementKind.class);
srcOnly = true;
} else if (tu.getPathElementOfKind(Tree.Kind.PROVIDES, path) != null) {
kinds = withinProvidesService(env) ? EnumSet.of(ANNOTATION_TYPE, CLASS, INTERFACE) : EnumSet.of(CLASS);
} else if (tu.getPathElementOfKind(Tree.Kind.USES, path) != null) {
kinds = EnumSet.of(ANNOTATION_TYPE, CLASS, INTERFACE);
} else {
kinds = EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE, FIELD, METHOD, ENUM_CONSTANT);
}
switch (type.getKind()) {
case TYPEVAR:
while (type != null && type.getKind() == TypeKind.TYPEVAR) {
type = ((TypeVariable) type).getUpperBound();
}
if (type == null) {
return;
}
type = controller.getTypes().capture(type);
case ARRAY:
case DECLARED:
case UNION:
case BOOLEAN:
case BYTE:
case CHAR:
case DOUBLE:
case FLOAT:
case INT:
case LONG:
case SHORT:
case VOID:
boolean b = exp.getKind() == Tree.Kind.PARENTHESIZED || exp.getKind() == Tree.Kind.TYPE_CAST;
while (b) {
if (exp.getKind() == Tree.Kind.PARENTHESIZED) {
exp = ((ParenthesizedTree) exp).getExpression();
expPath = new TreePath(expPath, exp);
} else if (exp.getKind() == Tree.Kind.TYPE_CAST) {
exp = ((TypeCastTree) exp).getExpression();
expPath = new TreePath(expPath, exp);
} else {
b = false;
}
}
el = controller.getTrees().getElement(expPath);
if (el != null && (el.getKind().isClass() || el.getKind().isInterface())) {
if (parent.getKind() == Tree.Kind.NEW_CLASS && ((NewClassTree) parent).getIdentifier() == fa && prefix != null) {
String typeName = controller.getElementUtilities().getElementName(el, true) + "." + prefix; //NOI18N
TypeMirror tm = controller.getTreeUtilities().parseType(typeName, env.getScope().getEnclosingClass());
if (tm != null && tm.getKind() == TypeKind.DECLARED) {
addMembers(env, tm, ((DeclaredType) tm).asElement(), EnumSet.of(CONSTRUCTOR), null, inImport, insideNew, false);
}
}
}
if (exs != null && !exs.isEmpty()) {
Elements elements = controller.getElements();
for (TypeMirror ex : exs) {
if (ex.getKind() == TypeKind.DECLARED) {
Element e = ((DeclaredType) ex).asElement();
if (e.getEnclosingElement() == el && startsWith(env, e.getSimpleName().toString()) && (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(e)) && !Utilities.isExcluded(((TypeElement)e).getQualifiedName())) {
env.addToExcludes(e);
results.add(itemFactory.createTypeItem(env.getController(), (TypeElement) e, (DeclaredType) ex, anchorOffset, null, elements.isDeprecated(e), insideNew, insideNew || env.isInsideClass(), true, true, false));
}
}
}
} else {
if (el == null) {
if (exp.getKind() == Tree.Kind.ARRAY_TYPE) {
TypeMirror tm = type;
while (tm.getKind() == TypeKind.ARRAY) {
tm = ((ArrayType) tm).getComponentType();
}
if (tm.getKind().isPrimitive()) {
el = controller.getTypes().boxedClass((PrimitiveType) tm);
} else if (tm.getKind() == TypeKind.DECLARED) {
el = ((DeclaredType) tm).asElement();
}
} else if (exp.getKind() == Tree.Kind.PRIMITIVE_TYPE) {
if (type.getKind().isPrimitive()) {
el = controller.getTypes().boxedClass((PrimitiveType) type);
} else if (type.getKind() == TypeKind.VOID) {
el = controller.getElements().getTypeElement("java.lang.Void"); //NOI18N
}
}
}
addMembers(env, type, el, kinds, baseType, inImport, insideNew, false);
}
break;
default:
el = controller.getTrees().getElement(expPath);
if (type.getKind() == TypeKind.ERROR && el != null && el.getKind().isClass()) {
el = controller.getElements().getPackageElement(((TypeElement) el).getQualifiedName());
}
if (el != null && el.getKind() == PACKAGE) {
if (parent.getKind() == Tree.Kind.NEW_CLASS && ((NewClassTree) parent).getIdentifier() == fa && prefix != null) {
String typeName = controller.getElementUtilities().getElementName(el, true) + "." + prefix; //NOI18N
TypeMirror tm = controller.getTreeUtilities().parseType(typeName, env.getScope().getEnclosingClass());
if (tm != null && tm.getKind() == TypeKind.DECLARED) {
addMembers(env, tm, ((DeclaredType) tm).asElement(), EnumSet.of(CONSTRUCTOR), null, inImport, insideNew, false);
}
}
if (exs != null && !exs.isEmpty()) {
Elements elements = controller.getElements();
for (TypeMirror ex : exs) {
if (ex.getKind() == TypeKind.DECLARED) {
Element e = ((DeclaredType) ex).asElement();
if (e.getEnclosingElement() == el && startsWith(env, e.getSimpleName().toString()) && (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(e)) && !Utilities.isExcluded(((TypeElement)e).getQualifiedName())) {
env.addToExcludes(e);
results.add(itemFactory.createTypeItem(env.getController(), (TypeElement) e, (DeclaredType) ex, anchorOffset, env.getReferencesCount(), elements.isDeprecated(e), false, env.isInsideClass(), true, true, false));
}
}
}
}
addPackageContent(env, (PackageElement) el, kinds, baseType, insideNew, srcOnly);
if (results.isEmpty() && ((PackageElement) el).getQualifiedName() == el.getSimpleName()) {
// no package content? Check for unimported class
ClassIndex ci = controller.getClasspathInfo().getClassIndex();
if (el.getEnclosedElements().isEmpty() && ci.getPackageNames(el.getSimpleName() + ".", true, EnumSet.allOf(ClassIndex.SearchScope.class)).isEmpty()) {
Trees trees = controller.getTrees();
Scope scope = env.getScope();
for (ElementHandle<TypeElement> teHandle : ci.getDeclaredTypes(el.getSimpleName().toString(), ClassIndex.NameKind.SIMPLE_NAME, EnumSet.allOf(ClassIndex.SearchScope.class))) {
TypeElement te = teHandle.resolve(controller);
if (te != null && trees.isAccessible(scope, te)) {
addMembers(env, te.asType(), te, kinds, baseType, inImport, insideNew, true);
}
}
}
}
}
}
} else if (parent.getKind() == Tree.Kind.COMPILATION_UNIT && ((CompilationUnitTree) parent).getPackageName() == fa) {
PackageElement pe = controller.getElements().getPackageElement(fullName(exp));
if (pe != null) {
addPackageContent(env, pe, EnumSet.of(ElementKind.PACKAGE), null, false, true);
}
}
}
}
private void insideMemberReference(Env env) throws IOException {
TreePath path = env.getPath();
MemberReferenceTree mr = (MemberReferenceTree) path.getLeaf();
TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, mr, env.getOffset());
if (ts != null) {
switch (ts.token().id()) {
case COLONCOLON:
case GT:
case GTGT:
case GTGTGT:
CompilationController controller = env.getController();
ExpressionTree exp = mr.getQualifierExpression();
TreePath expPath = new TreePath(path, exp);
Trees trees = controller.getTrees();
TypeMirror type = trees.getTypeMirror(expPath);
if (type != null && type.getKind() == TypeKind.TYPEVAR) {
while (type != null && type.getKind() == TypeKind.TYPEVAR) {
type = ((TypeVariable) type).getUpperBound();
}
if (type != null) {
type = controller.getTypes().capture(type);
}
}
if (type != null && (type.getKind() == TypeKind.DECLARED
|| type.getKind() == TypeKind.ARRAY || type.getKind() == TypeKind.TYPEVAR)) {
Element e = trees.getElement(expPath);
addMethodReferences(env, type, e);
if (e == null || e.getKind().isClass() || e.getKind().isInterface()) {
addKeyword(env, NEW_KEYWORD, SPACE, false);
}
}
break;
case LT:
case COMMA:
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
break;
}
}
}
private void insideLambdaExpression(Env env) throws IOException {
TreePath path = env.getPath();
LambdaExpressionTree let = (LambdaExpressionTree) path.getLeaf();
TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, let, env.getOffset());
if (ts != null) {
switch (ts.token().id()) {
case ARROW:
localResult(env);
addValueKeywords(env);
break;
case COMMA:
if (let.getParameters().isEmpty()
|| env.getController().getTrees().getSourcePositions().getStartPosition(path.getCompilationUnit(), let.getParameters().get(0).getType()) >= 0) {
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
addPrimitiveTypeKeywords(env);
addKeyword(env, FINAL_KEYWORD, SPACE, false);
}
else {
boolean isFirstParamVarType = isLambdaVarType(env, let);
if (isFirstParamVarType) {
addVarTypeForLambdaParam(env);
}
}
break;
}
}
}
private void insideMethodInvocation(Env env) throws IOException {
TreePath path = env.getPath();
MethodInvocationTree mi = (MethodInvocationTree) path.getLeaf();
int offset = env.getOffset();
TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, mi, offset);
if (ts == null || (ts.token().id() != JavaTokenId.LPAREN && ts.token().id() != JavaTokenId.COMMA)) {
SourcePositions sp = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
int lastTokenEndOffset = ts != null ? ts.offset() + ts.token().length() : -1;
for (ExpressionTree arg : mi.getArguments()) {
int pos = (int) sp.getEndPosition(root, arg);
if (lastTokenEndOffset == pos) {
insideExpression(env, new TreePath(path, arg));
break;
}
if (offset <= pos) {
break;
}
}
return;
}
String prefix = env.getPrefix();
if (prefix == null || prefix.length() == 0) {
addMethodArguments(env, mi);
}
addLocalMembersAndVars(env);
addValueKeywords(env);
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
addPrimitiveTypeKeywords(env);
}
private void insideNewClass(Env env) throws IOException {
TreePath path = env.getPath();
NewClassTree nc = (NewClassTree) path.getLeaf();
TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, nc, env.getOffset());
if (ts != null) {
switch (ts.token().id()) {
case NEW:
String prefix = env.getPrefix();
CompilationController controller = env.getController();
controller.toPhase(Phase.RESOLVED);
TypeElement tel = controller.getElements().getTypeElement("java.lang.Throwable"); //NOI18N
DeclaredType base = path.getParentPath().getLeaf().getKind() == Tree.Kind.THROW && tel != null
? controller.getTypes().getDeclaredType(tel) : null;
TypeElement toExclude = null;
if (nc.getIdentifier().getKind() == Tree.Kind.IDENTIFIER && prefix != null) {
TypeMirror tm = controller.getTreeUtilities().parseType(prefix, env.getScope().getEnclosingClass());
if (tm != null && tm.getKind() == TypeKind.DECLARED) {
TypeElement te = (TypeElement) ((DeclaredType) tm).asElement();
addMembers(env, tm, te, EnumSet.of(CONSTRUCTOR), base, false, true, false);
if ((te.getTypeParameters().isEmpty() || SourceVersion.RELEASE_5.compareTo(controller.getSourceVersion()) > 0)
&& !hasAccessibleInnerClassConstructor(te, env.getScope(), controller.getTrees())) {
toExclude = te;
}
}
}
boolean insideNew = true;
ExpressionTree encl = nc.getEnclosingExpression();
if (!options.contains(Options.ALL_COMPLETION)) {
Set<? extends TypeMirror> smarts = getSmartTypes(env);
if (smarts != null) {
Elements elements = env.getController().getElements();
for (TypeMirror smart : smarts) {
if (smart != null) {
if (smart.getKind() == TypeKind.DECLARED) {
if (encl == null) {
for (DeclaredType subtype : getSubtypesOf(env, (DeclaredType) smart)) {
TypeElement elem = (TypeElement) subtype.asElement();
if (toExclude != elem && (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(elem)) && !Utilities.isExcluded(elem.getQualifiedName())) {
results.add(itemFactory.createTypeItem(env.getController(), elem, (DeclaredType) SourceUtils.resolveCapturedType(controller, subtype), anchorOffset, env.getReferencesCount(), elements.isDeprecated(elem), true, true, false, true, false));
}
env.addToExcludes(elem);
}
}
} else if (smart.getKind() == TypeKind.ARRAY) {
insideNew = false;
try {
TypeMirror tm = smart;
while (tm.getKind() == TypeKind.ARRAY) {
tm = ((ArrayType) tm).getComponentType();
}
if (tm.getKind().isPrimitive() && startsWith(env, tm.toString())) {
results.add(itemFactory.createArrayItem(env.getController(), (ArrayType) smart, anchorOffset, env.getReferencesCount(), env.getController().getElements()));
} else if ((tm.getKind() == TypeKind.DECLARED || tm.getKind() == TypeKind.ERROR) && startsWith(env, ((DeclaredType) tm).asElement().getSimpleName().toString())) {
results.add(itemFactory.createArrayItem(env.getController(), (ArrayType) smart, anchorOffset, env.getReferencesCount(), env.getController().getElements()));
}
} catch (IllegalArgumentException iae) {
}
}
}
}
}
}
if (toExclude != null) {
env.addToExcludes(toExclude);
}
if (insideNew) {
env.insideNew();
}
if (encl == null) {
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE), base);
} else {
TypeMirror enclType = controller.getTrees().getTypeMirror(new TreePath(path, nc.getEnclosingExpression()));
if (enclType != null && enclType.getKind() == TypeKind.DECLARED) {
addMembers(env, enclType, ((DeclaredType) enclType).asElement(), EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE), base, false, insideNew, false);
}
}
break;
case LPAREN:
case COMMA:
case RPAREN:
prefix = env.getPrefix();
if (prefix == null || prefix.length() == 0) {
addConstructorArguments(env, nc);
}
addLocalMembersAndVars(env);
addValueKeywords(env);
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
addPrimitiveTypeKeywords(env);
break;
case GT:
case GTGT:
case GTGTGT:
controller = env.getController();
TypeMirror tm = controller.getTrees().getTypeMirror(new TreePath(path, nc.getIdentifier()));
addMembers(env, tm, ((DeclaredType) tm).asElement(), EnumSet.of(CONSTRUCTOR), null, false, false, false);
break;
}
}
}
private void insideTry(Env env) throws IOException {
CompilationController controller = env.getController();
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, env.getPath().getLeaf(), env.getOffset());
if (last != null && (last.token().id() == JavaTokenId.LPAREN || last.token().id() == JavaTokenId.SEMICOLON)) {
addKeyword(env, FINAL_KEYWORD, SPACE, false);
if (controller.getSourceVersion().compareTo(SourceVersion.RELEASE_9) >= 0) {
addEffectivelyFinalAutoCloseables(env);
}
TypeElement te = controller.getElements().getTypeElement("java.lang.AutoCloseable"); //NOI18N
if (te != null) {
addTypes(env, EnumSet.of(CLASS, INTERFACE, TYPE_PARAMETER), controller.getTypes().getDeclaredType(te));
}
}
}
private void insideCatch(Env env) throws IOException {
TreePath path = env.getPath();
CatchTree ct = (CatchTree) path.getLeaf();
CompilationController controller = env.getController();
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, ct, env.getOffset());
if (last != null && last.token().id() == JavaTokenId.LPAREN) {
addKeyword(env, FINAL_KEYWORD, SPACE, false);
if (!options.contains(Options.ALL_COMPLETION)) {
TreeUtilities tu = controller.getTreeUtilities();
TreePath tryPath = tu.getPathElementOfKind(Tree.Kind.TRY, path);
Set<TypeMirror> exs = tu.getUncaughtExceptions(tryPath != null ? tryPath : path.getParentPath());
Elements elements = controller.getElements();
for (TypeMirror ex : exs) {
if (ex.getKind() == TypeKind.DECLARED && startsWith(env, ((DeclaredType) ex).asElement().getSimpleName().toString())
&& (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(((DeclaredType) ex).asElement()))
&& !Utilities.isExcluded(((TypeElement)((DeclaredType) ex).asElement()).getQualifiedName())) {
env.addToExcludes(((DeclaredType) ex).asElement());
results.add(itemFactory.createTypeItem(env.getController(), (TypeElement) ((DeclaredType) ex).asElement(), (DeclaredType) ex, anchorOffset, env.getReferencesCount(), elements.isDeprecated(((DeclaredType) ex).asElement()), false, false, false, true, false));
}
}
}
TypeElement te = controller.getElements().getTypeElement("java.lang.Throwable"); //NOI18N
if (te != null) {
addTypes(env, EnumSet.of(CLASS, INTERFACE, TYPE_PARAMETER), controller.getTypes().getDeclaredType(te));
}
}
}
private void insideUnionType(Env env) throws IOException {
TreePath path = env.getPath();
UnionTypeTree dtt = (UnionTypeTree) path.getLeaf();
CompilationController controller = env.getController();
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, dtt, env.getOffset());
if (last != null && last.token().id() == JavaTokenId.BAR) {
if (!options.contains(Options.ALL_COMPLETION)) {
TreeUtilities tu = controller.getTreeUtilities();
TreePath tryPath = tu.getPathElementOfKind(Tree.Kind.TRY, path);
Set<TypeMirror> exs = tu.getUncaughtExceptions(tryPath);
if (!exs.isEmpty()) {
Trees trees = controller.getTrees();
Types types = controller.getTypes();
for (Tree t : dtt.getTypeAlternatives()) {
TypeMirror tm = trees.getTypeMirror(new TreePath(path, t));
if (tm != null && tm.getKind() != TypeKind.ERROR) {
for (Iterator<TypeMirror> it = exs.iterator(); it.hasNext();) {
if (types.isSubtype(tm, it.next())) {
it.remove();
}
}
}
}
Elements elements = controller.getElements();
for (TypeMirror ex : exs) {
if (ex.getKind() == TypeKind.DECLARED && startsWith(env, ((DeclaredType) ex).asElement().getSimpleName().toString())
&& (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(((DeclaredType) ex).asElement()))
&& !Utilities.isExcluded(((TypeElement)((DeclaredType) ex).asElement()).getQualifiedName())) {
env.addToExcludes(((DeclaredType) ex).asElement());
results.add(itemFactory.createTypeItem(env.getController(), (TypeElement) ((DeclaredType) ex).asElement(), (DeclaredType) ex, anchorOffset, env.getReferencesCount(), elements.isDeprecated(((DeclaredType) ex).asElement()), false, false, false, true, false));
}
}
}
}
TypeElement te = controller.getElements().getTypeElement("java.lang.Throwable"); //NOI18N
if (te != null) {
addTypes(env, EnumSet.of(CLASS, INTERFACE, TYPE_PARAMETER), controller.getTypes().getDeclaredType(te));
}
}
}
private void insideIf(Env env) throws IOException {
IfTree iff = (IfTree) env.getPath().getLeaf();
if (env.getSourcePositions().getEndPosition(env.getRoot(), iff.getCondition()) <= env.getOffset()) {
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, iff, env.getOffset());
if (last != null && (last.token().id() == JavaTokenId.RPAREN || last.token().id() == JavaTokenId.ELSE)) {
localResult(env);
addKeywordsForStatement(env);
}
}
}
private void insideWhile(Env env) throws IOException {
WhileLoopTree wlt = (WhileLoopTree) env.getPath().getLeaf();
if (env.getSourcePositions().getEndPosition(env.getRoot(), wlt.getCondition()) <= env.getOffset()) {
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, wlt, env.getOffset());
if (last != null && last.token().id() == JavaTokenId.RPAREN) {
localResult(env);
addKeywordsForStatement(env);
}
}
}
private void insideDoWhile(Env env) throws IOException {
DoWhileLoopTree dwlt = (DoWhileLoopTree) env.getPath().getLeaf();
if (env.getSourcePositions().getEndPosition(env.getRoot(), dwlt.getStatement()) <= env.getOffset()) {
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, dwlt, env.getOffset());
if (last != null && (last.token().id() == JavaTokenId.RBRACE || last.token().id() == JavaTokenId.SEMICOLON)) {
addKeyword(env, WHILE_KEYWORD, null, false);
}
}
}
private void insideFor(Env env) throws IOException {
int offset = env.getOffset();
TreePath path = env.getPath();
ForLoopTree fl = (ForLoopTree) path.getLeaf();
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
Tree lastTree = null;
int lastTreePos = offset;
for (Tree update : fl.getUpdate()) {
int pos = (int) sourcePositions.getEndPosition(root, update);
if (pos == Diagnostic.NOPOS || offset <= pos) {
break;
}
lastTree = update;
lastTreePos = pos;
}
if (lastTree == null) {
int pos = (int) sourcePositions.getEndPosition(root, fl.getCondition());
if (pos != Diagnostic.NOPOS && pos < offset) {
lastTree = fl.getCondition();
lastTreePos = pos;
}
}
if (lastTree == null) {
for (Tree init : fl.getInitializer()) {
int pos = (int) sourcePositions.getEndPosition(root, init);
if (pos == Diagnostic.NOPOS || offset <= pos) {
break;
}
lastTree = init;
lastTreePos = pos;
}
}
if (lastTree == null) {
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, fl, offset);
if (last != null && last.token().id() == JavaTokenId.LPAREN) {
addLocalFieldsAndVars(env);
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
addPrimitiveTypeKeywords(env);
}
} else {
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, lastTreePos, offset);
if (last != null && last.token().id() == JavaTokenId.SEMICOLON) {
localResult(env);
addValueKeywords(env);
} else if (last != null && last.token().id() == JavaTokenId.RPAREN) {
localResult(env);
addKeywordsForStatement(env);
} else {
switch (lastTree.getKind()) {
case VARIABLE:
Tree var = ((VariableTree) lastTree).getInitializer();
if (var != null) {
insideExpression(env, new TreePath(new TreePath(path, lastTree), var));
}
break;
case EXPRESSION_STATEMENT:
Tree exp = unwrapErrTree(((ExpressionStatementTree) lastTree).getExpression());
if (exp != null) {
insideExpression(env, new TreePath(new TreePath(path, lastTree), exp));
}
break;
default:
insideExpression(env, new TreePath(path, lastTree));
}
}
}
}
private void insideForEach(Env env) throws IOException {
int offset = env.getOffset();
TreePath path = env.getPath();
EnhancedForLoopTree efl = (EnhancedForLoopTree) path.getLeaf();
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
if (sourcePositions.getStartPosition(root, efl.getExpression()) >= offset) {
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, (int) sourcePositions.getEndPosition(root, efl.getVariable()), offset);
if (last != null && last.token().id() == JavaTokenId.COLON) {
env.insideForEachExpression();
addKeyword(env, NEW_KEYWORD, SPACE, false);
localResult(env);
}
return;
}
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, (int) sourcePositions.getEndPosition(root, efl.getExpression()), offset);
if (last != null && last.token().id() == JavaTokenId.RPAREN) {
addKeywordsForStatement(env);
} else {
env.insideForEachExpression();
addKeyword(env, NEW_KEYWORD, SPACE, false);
}
localResult(env);
}
private void insideSwitch(Env env) throws IOException {
int offset = env.getOffset();
TreePath path = env.getPath();
ExpressionTree exprTree = null;
if (path.getLeaf().getKind() == Tree.Kind.SWITCH) {
exprTree = ((SwitchTree) path.getLeaf()).getExpression();
} else {
List<? extends ExpressionTree> exprTrees = TreeShims.getExpressions(path.getLeaf());
if (!exprTrees.isEmpty()) {
exprTree = exprTrees.get(0);
}
}
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
if (sourcePositions.getStartPosition(root, exprTree) < offset) {
CaseTree lastCase = null;
for (CaseTree t : TreeShims.getCases(path.getLeaf())) {
int pos = (int) sourcePositions.getStartPosition(root, t);
if (pos == Diagnostic.NOPOS || offset <= pos) {
break;
}
lastCase = t;
}
if (lastCase != null) {
StatementTree last = null;
List<? extends StatementTree> statements = lastCase.getStatements();
if (statements == null) {
Tree caseBody = TreeShims.getBody(lastCase);
if (caseBody instanceof StatementTree) {
statements = Collections.singletonList((StatementTree) caseBody);
}
}
for (StatementTree stat : statements) {
int pos = (int) sourcePositions.getStartPosition(root, stat);
if (pos == Diagnostic.NOPOS || offset <= pos) {
break;
}
last = stat;
}
if (last != null) {
if (last.getKind() == Tree.Kind.TRY) {
if (((TryTree) last).getFinallyBlock() == null) {
addKeyword(env, CATCH_KEYWORD, null, false);
addKeyword(env, FINALLY_KEYWORD, null, false);
if (((TryTree) last).getCatches().isEmpty()) {
return;
}
}
} else if (last.getKind() == Tree.Kind.IF) {
if (((IfTree) last).getElseStatement() == null) {
addKeyword(env, ELSE_KEYWORD, null, false);
}
}
}
localResult(env);
addKeywordsForBlock(env);
String prefix = env.getPrefix();
if (SOURCE_VERSION_RELEASE_13 != null && (env.getController().getSourceVersion().compareTo(SOURCE_VERSION_RELEASE_13) >= 0
&& path.getLeaf().getKind().toString().equals(TreeShims.SWITCH_EXPRESSION) && Utilities.startsWith(YIELD_KEYWORD, prefix))) {
addKeyword(env, YIELD_KEYWORD, null, false);
}
} else {
TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, path.getLeaf(), offset);
if (ts != null && ts.token().id() == JavaTokenId.LBRACE) {
addKeyword(env, CASE_KEYWORD, SPACE, false);
addKeyword(env, DEFAULT_KEYWORD, COLON, false);
}
}
}
}
private void insideCase(Env env) throws IOException {
int offset = env.getOffset();
TreePath path = env.getPath();
CaseTree cst = (CaseTree) path.getLeaf();
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
CompilationController controller = env.getController();
TreePath parentPath = path.getParentPath();
ExpressionTree caseExpressionTree = null;
ExpressionTree caseErroneousTree = null;
List<? extends ExpressionTree> caseTreeList = TreeShims.getExpressions(cst);
if (!caseTreeList.isEmpty() && caseTreeList.size() == 1) {
caseExpressionTree = caseTreeList.get(0);
caseErroneousTree = caseTreeList.get(0);
} else if (caseTreeList.size() > 1) {
caseExpressionTree = caseTreeList.get(0);
for (ExpressionTree et : caseTreeList) {
if (et != null && et.getKind() == Tree.Kind.ERRONEOUS) {
caseErroneousTree = et;
break;
}
}
}
if (caseExpressionTree != null && ((sourcePositions.getStartPosition(root, caseExpressionTree) >= offset)
|| (caseErroneousTree != null && caseErroneousTree.getKind() == Tree.Kind.ERRONEOUS && ((ErroneousTree) caseErroneousTree).getErrorTrees().isEmpty() && sourcePositions.getEndPosition(root, caseErroneousTree) >= offset))) {
if (parentPath.getLeaf().getKind() == Tree.Kind.SWITCH || parentPath.getLeaf().getKind().toString().equals(TreeShims.SWITCH_EXPRESSION)) {
ExpressionTree exprTree = null;
if (parentPath.getLeaf().getKind() == Tree.Kind.SWITCH) {
exprTree = ((SwitchTree) parentPath.getLeaf()).getExpression();
} else {
List<? extends ExpressionTree> exprTrees = TreeShims.getExpressions(parentPath.getLeaf());
if (!exprTrees.isEmpty()) {
exprTree = exprTrees.get(0);
}
}
TypeMirror tm = controller.getTrees().getTypeMirror(new TreePath(parentPath, exprTree));
if (tm.getKind() == TypeKind.DECLARED && ((DeclaredType) tm).asElement().getKind() == ENUM) {
addEnumConstants(env, (TypeElement) ((DeclaredType) tm).asElement());
} else {
addLocalConstantsAndTypes(env);
}
}
} else {
TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, cst, offset);
if (ts != null && ts.token().id() != JavaTokenId.DEFAULT) {
localResult(env);
addKeywordsForBlock(env);
}
}
}
private void insideParens(Env env) throws IOException {
TreePath path = env.getPath();
ParenthesizedTree pa = (ParenthesizedTree) path.getLeaf();
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
Tree exp = unwrapErrTree(pa.getExpression());
if (exp == null || env.getOffset() <= sourcePositions.getStartPosition(root, exp)) {
if (!options.contains(Options.ALL_COMPLETION) && path.getParentPath().getLeaf().getKind() != Tree.Kind.SWITCH) {
Set<? extends TypeMirror> smarts = getSmartTypes(env);
if (smarts != null) {
Elements elements = env.getController().getElements();
for (TypeMirror smart : smarts) {
if (smart != null) {
if (smart.getKind() == TypeKind.DECLARED) {
for (DeclaredType subtype : getSubtypesOf(env, (DeclaredType) smart)) {
TypeElement elem = (TypeElement) subtype.asElement();
if ((Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(elem)) && !Utilities.isExcluded(elem.getQualifiedName())) {
results.add(itemFactory.createTypeItem(env.getController(), elem, subtype, anchorOffset, env.getReferencesCount(), elements.isDeprecated(elem), false, false, false, true, false));
}
env.addToExcludes(elem);
}
DeclaredType type = (DeclaredType) smart;
TypeElement element = (TypeElement) type.asElement();
if (elements.isFunctionalInterface(element)) {
addVarTypeForLambdaParam(env);
}
} else if (smart.getKind() == TypeKind.ARRAY) {
try {
TypeMirror tm = smart;
while (tm.getKind() == TypeKind.ARRAY) {
tm = ((ArrayType) tm).getComponentType();
}
if (tm.getKind().isPrimitive() && startsWith(env, tm.toString())) {
results.add(itemFactory.createArrayItem(env.getController(), (ArrayType) smart, anchorOffset, env.getReferencesCount(), env.getController().getElements()));
} else if ((tm.getKind() == TypeKind.DECLARED || tm.getKind() == TypeKind.ERROR) && startsWith(env, ((DeclaredType) tm).asElement().getSimpleName().toString())) {
results.add(itemFactory.createArrayItem(env.getController(), (ArrayType) smart, anchorOffset, env.getReferencesCount(), env.getController().getElements()));
}
} catch (IllegalArgumentException iae) {
}
}
}
}
}
}
addLocalMembersAndVars(env);
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
addPrimitiveTypeKeywords(env);
addValueKeywords(env);
} else {
insideExpression(env, new TreePath(path, exp));
}
}
private void insideTypeCheck(Env env) throws IOException {
InstanceOfTree iot = (InstanceOfTree) env.getPath().getLeaf();
TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, iot, env.getOffset());
if (ts != null && ts.token().id() == JavaTokenId.INSTANCEOF) {
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
}
}
private void insideArrayAccess(Env env) throws IOException {
int offset = env.getOffset();
ArrayAccessTree aat = (ArrayAccessTree) env.getPath().getLeaf();
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
int aaTextStart = (int) sourcePositions.getEndPosition(root, aat.getExpression());
if (aaTextStart != Diagnostic.NOPOS) {
Tree expr = unwrapErrTree(aat.getIndex());
if (expr == null || offset <= (int) sourcePositions.getStartPosition(root, expr)) {
String aatText = env.getController().getText().substring(aaTextStart, offset);
int bPos = aatText.indexOf('['); //NOI18N
if (bPos > -1) {
localResult(env);
addValueKeywords(env);
}
}
}
}
private void insideNewArray(Env env) throws IOException {
int offset = env.getOffset();
TreePath path = env.getPath();
NewArrayTree nat = (NewArrayTree) path.getLeaf();
if (nat.getInitializers() != null) { // UFFF!!!!
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
Tree last = null;
int lastPos = offset;
for (Tree init : nat.getInitializers()) {
int pos = (int) sourcePositions.getEndPosition(root, init);
if (pos == Diagnostic.NOPOS || offset <= pos) {
break;
}
last = init;
lastPos = pos;
}
if (last != null) {
TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, lastPos, offset);
if (ts != null && ts.token().id() == JavaTokenId.COMMA) {
TreePath parentPath = path.getParentPath();
TreePath gparentPath = parentPath.getParentPath();
if (gparentPath.getLeaf().getKind() == Tree.Kind.ANNOTATION && parentPath.getLeaf().getKind() == Tree.Kind.ASSIGNMENT) {
ExpressionTree var = ((AssignmentTree) parentPath.getLeaf()).getVariable();
if (var.getKind() == Tree.Kind.IDENTIFIER) {
insideAnnotationAttribute(env, gparentPath, ((IdentifierTree) var).getName());
addLocalConstantsAndTypes(env);
}
} else {
localResult(env);
addValueKeywords(env);
}
}
return;
}
}
TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, nat, offset);
switch (ts.token().id()) {
case LBRACKET:
case LBRACE:
TreePath parentPath = path.getParentPath();
TreePath gparentPath = parentPath.getParentPath();
if (gparentPath.getLeaf().getKind() == Tree.Kind.ANNOTATION && parentPath.getLeaf().getKind() == Tree.Kind.ASSIGNMENT) {
ExpressionTree var = ((AssignmentTree) parentPath.getLeaf()).getVariable();
if (var.getKind() == Tree.Kind.IDENTIFIER) {
insideAnnotationAttribute(env, gparentPath, ((IdentifierTree) var).getName());
addLocalConstantsAndTypes(env);
}
} else {
localResult(env);
addValueKeywords(env);
}
break;
case RBRACKET:
if (nat.getDimensions().size() > 0) {
insideExpression(env, path);
}
break;
}
}
private void insideAssignment(Env env) throws IOException {
int offset = env.getOffset();
TreePath path = env.getPath();
AssignmentTree as = (AssignmentTree) path.getLeaf();
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
int asTextStart = (int) sourcePositions.getEndPosition(root, as.getVariable());
if (asTextStart != Diagnostic.NOPOS) {
Tree expr = unwrapErrTree(as.getExpression());
if (expr == null || offset <= (int) sourcePositions.getStartPosition(root, expr)) {
CompilationController controller = env.getController();
String asText = controller.getText().substring(asTextStart, offset);
int eqPos = asText.indexOf('='); //NOI18N
if (eqPos > -1) {
TreePath parentPath = path.getParentPath();
if (parentPath.getLeaf().getKind() != Tree.Kind.ANNOTATION) {
localResult(env);
addValueKeywords(env);
} else if (as.getVariable().getKind() == Tree.Kind.IDENTIFIER) {
insideAnnotationAttribute(env, parentPath, ((IdentifierTree) as.getVariable()).getName());
addLocalConstantsAndTypes(env);
}
}
} else {
insideExpression(env, new TreePath(path, expr));
}
}
}
private void insideCompoundAssignment(Env env) throws IOException {
int offset = env.getOffset();
CompoundAssignmentTree cat = (CompoundAssignmentTree) env.getPath().getLeaf();
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
int catTextStart = (int) sourcePositions.getEndPosition(root, cat.getVariable());
if (catTextStart != Diagnostic.NOPOS) {
Tree expr = unwrapErrTree(cat.getExpression());
if (expr == null || offset <= (int) sourcePositions.getStartPosition(root, expr)) {
String catText = env.getController().getText().substring(catTextStart, offset);
int eqPos = catText.indexOf('='); //NOI18N
if (eqPos > -1) {
localResult(env);
addValueKeywords(env);
}
}
}
}
private void insideStringLiteral(Env env) throws IOException {
TreePath path = env.getPath();
TreePath parentPath = path.getParentPath();
TreePath grandParentPath = parentPath.getParentPath();
if (grandParentPath != null && grandParentPath.getLeaf().getKind() == Tree.Kind.ANNOTATION
&& parentPath.getLeaf().getKind() == Tree.Kind.ASSIGNMENT
&& ((AssignmentTree) parentPath.getLeaf()).getExpression() == path.getLeaf()) {
ExpressionTree var = ((AssignmentTree) parentPath.getLeaf()).getVariable();
if (var.getKind() == Tree.Kind.IDENTIFIER) {
insideAnnotationAttribute(env, grandParentPath, ((IdentifierTree) var).getName());
}
}
}
private void insideBinaryTree(Env env) throws IOException {
int offset = env.getOffset();
TreePath path = env.getPath();
BinaryTree bi = (BinaryTree) path.getLeaf();
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
int pos = (int) sourcePositions.getEndPosition(root, bi.getRightOperand());
if (pos != Diagnostic.NOPOS && pos < offset) {
return;
}
pos = (int) sourcePositions.getEndPosition(root, bi.getLeftOperand());
if (pos != Diagnostic.NOPOS) {
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, pos, offset);
if (last != null) {
CompilationController controller = env.getController();
controller.toPhase(Phase.RESOLVED);
TypeMirror tm = last.token().id() == JavaTokenId.AMP
? controller.getTrees().getTypeMirror(new TreePath(path, bi.getLeftOperand())) : null;
if (tm != null && tm.getKind() == TypeKind.DECLARED) {
env.addToExcludes(((DeclaredType) tm).asElement());
addTypes(env, EnumSet.of(INTERFACE, ANNOTATION_TYPE), null);
} else if (tm != null && tm.getKind() == TypeKind.INTERSECTION) {
for (TypeMirror bound : ((IntersectionType) tm).getBounds()) {
if (bound.getKind() == TypeKind.DECLARED) {
env.addToExcludes(((DeclaredType) bound).asElement());
}
}
addTypes(env, EnumSet.of(INTERFACE, ANNOTATION_TYPE), null);
} else {
localResult(env);
addValueKeywords(env);
}
}
}
}
private void insideConditionalExpression(Env env) throws IOException {
ConditionalExpressionTree co = (ConditionalExpressionTree) env.getPath().getLeaf();
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
int coTextStart = (int) sourcePositions.getStartPosition(root, co);
if (coTextStart != Diagnostic.NOPOS) {
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, coTextStart, env.getOffset());
if (last != null && (last.token().id() == JavaTokenId.QUESTION || last.token().id() == JavaTokenId.COLON)) {
localResult(env);
addValueKeywords(env);
}
}
}
@SuppressWarnings("fallthrough")
private void insideExpressionStatement(Env env) throws IOException {
TreePath path = env.getPath();
ExpressionStatementTree est = (ExpressionStatementTree) path.getLeaf();
CompilationController controller = env.getController();
Tree t = est.getExpression();
if (t.getKind() == Tree.Kind.ERRONEOUS) {
Iterator<? extends Tree> it = ((ErroneousTree) t).getErrorTrees().iterator();
if (it.hasNext()) {
t = it.next();
} else {
localResult(env);
Tree parentTree = path.getParentPath().getLeaf();
switch (parentTree.getKind()) {
case FOR_LOOP:
if (((ForLoopTree) parentTree).getStatement() == est) {
addKeywordsForStatement(env);
} else {
addValueKeywords(env);
}
break;
case ENHANCED_FOR_LOOP:
if (((EnhancedForLoopTree) parentTree).getStatement() == est) {
addKeywordsForStatement(env);
} else {
addValueKeywords(env);
}
break;
case VARIABLE:
addValueKeywords(env);
break;
case LAMBDA_EXPRESSION:
addValueKeywords(env);
break;
default:
addKeywordsForStatement(env);
break;
}
return;
}
}
TreePath tPath = new TreePath(path, t);
if (t.getKind() == Tree.Kind.MODIFIERS) {
insideModifiers(env, tPath);
} else if (t.getKind() == Tree.Kind.MEMBER_SELECT && ERROR.contentEquals(((MemberSelectTree) t).getIdentifier())) {
controller.toPhase(Phase.ELEMENTS_RESOLVED);
TreePath expPath = new TreePath(tPath, ((MemberSelectTree) t).getExpression());
TypeMirror type = controller.getTrees().getTypeMirror(expPath);
switch (type.getKind()) {
case TYPEVAR:
type = ((TypeVariable) type).getUpperBound();
if (type == null) {
return;
}
type = controller.getTypes().capture(type);
case ARRAY:
case DECLARED:
case BOOLEAN:
case BYTE:
case CHAR:
case DOUBLE:
case FLOAT:
case INT:
case LONG:
case SHORT:
case VOID:
addMembers(env, type, controller.getTrees().getElement(expPath), EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE, FIELD, METHOD, ENUM_CONSTANT), null, false, false, false);
break;
default:
Element el = controller.getTrees().getElement(expPath);
if (el instanceof PackageElement) {
addPackageContent(env, (PackageElement) el, EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE, FIELD, METHOD, ENUM_CONSTANT), null, false, false);
}
}
} else {
insideExpression(env, tPath);
}
}
private void insideExpression(Env env, TreePath exPath) throws IOException {
int offset = env.getOffset();
String prefix = env.getPrefix();
Tree et = exPath.getLeaf();
Tree parent = exPath.getParentPath().getLeaf();
final CompilationController controller = env.getController();
int endPos = (int) env.getSourcePositions().getEndPosition(env.getRoot(), et);
if (endPos != Diagnostic.NOPOS && endPos < offset) {
TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, endPos, offset);
if (last != null && last.token().id() != JavaTokenId.COMMA) {
return;
}
}
controller.toPhase(Phase.RESOLVED);
ElementKind varKind = ElementKind.LOCAL_VARIABLE;
Set<Modifier> varMods = EnumSet.noneOf(Modifier.class);
if (parent.getKind() == Tree.Kind.VARIABLE) {
varMods = ((VariableTree) parent).getModifiers().getFlags();
Element varEl = controller.getTrees().getElement(exPath.getParentPath());
if (varEl != null) {
varKind = varEl.getKind();
}
}
if (et.getKind() == Tree.Kind.ANNOTATED_TYPE) {
et = ((AnnotatedTypeTree) et).getUnderlyingType();
exPath = new TreePath(exPath, et);
}
if (parent.getKind() != Tree.Kind.PARENTHESIZED
&& (et.getKind() == Tree.Kind.PRIMITIVE_TYPE || et.getKind() == Tree.Kind.ARRAY_TYPE || et.getKind() == Tree.Kind.PARAMETERIZED_TYPE)) {
TypeMirror tm = controller.getTrees().getTypeMirror(exPath);
final Map<Name, ? extends Element> illegalForwardRefs = env.getForwardReferences();
Scope scope = env.getScope();
final ExecutableElement method = scope.getEnclosingMethod();
ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
return (method == null || method == e.getEnclosingElement() || e.getModifiers().contains(FINAL)
|| EnumSet.of(LOCAL_VARIABLE, PARAMETER, EXCEPTION_PARAMETER, RESOURCE_VARIABLE).contains(simplifyElementKind(e.getKind())) && controller.getSourceVersion().compareTo(SourceVersion.RELEASE_8) >= 0 && controller.getElementUtilities().isEffectivelyFinal((VariableElement)e))
&& !illegalForwardRefs.containsKey(e.getSimpleName());
}
};
for (String name : Utilities.varNamesSuggestions(tm, varKind, varMods, null, prefix, controller.getTypes(), controller.getElements(), controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor), CodeStyle.getDefault(controller.getDocument()))) {
results.add(itemFactory.createVariableItem(env.getController(), name, anchorOffset, true, false));
}
return;
}
if (et.getKind() == Tree.Kind.UNION_TYPE) {
for (Tree t : ((UnionTypeTree) et).getTypeAlternatives()) {
et = t;
exPath = new TreePath(exPath, t);
}
}
if (et.getKind() == Tree.Kind.IDENTIFIER) {
Element e = controller.getTrees().getElement(exPath);
if (e == null) {
return;
}
TypeMirror tm = controller.getTrees().getTypeMirror(exPath);
switch (simplifyElementKind(e.getKind())) {
case ANNOTATION_TYPE:
case CLASS:
case ENUM:
case INTERFACE:
case PACKAGE:
if (parent.getKind() != Tree.Kind.PARENTHESIZED
|| env.getController().getSourceVersion().compareTo(SourceVersion.RELEASE_8) >= 0) {
final Map<Name, ? extends Element> illegalForwardRefs = env.getForwardReferences();
Scope scope = env.getScope();
final ExecutableElement method = scope.getEnclosingMethod();
ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
return (method == null || method == e.getEnclosingElement() || e.getModifiers().contains(FINAL)
|| EnumSet.of(LOCAL_VARIABLE, PARAMETER, EXCEPTION_PARAMETER, RESOURCE_VARIABLE).contains(simplifyElementKind(e.getKind())) && controller.getSourceVersion().compareTo(SourceVersion.RELEASE_8) >= 0 && controller.getElementUtilities().isEffectivelyFinal((VariableElement)e))
&& !illegalForwardRefs.containsKey(e.getSimpleName());
}
};
for (String name : Utilities.varNamesSuggestions(tm, varKind, varMods, null, prefix, controller.getTypes(), controller.getElements(),
controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor), CodeStyle.getDefault(controller.getDocument()))) {
results.add(itemFactory.createVariableItem(env.getController(), name, anchorOffset, true, false));
}
}
VariableElement ve = getFieldOrVar(env, e.getSimpleName().toString());
if (ve != null) {
addKeyword(env, INSTANCEOF_KEYWORD, SPACE, false);
}
break;
case ENUM_CONSTANT:
case EXCEPTION_PARAMETER:
case FIELD:
case LOCAL_VARIABLE:
case RESOURCE_VARIABLE:
case PARAMETER:
if (tm != null && (tm.getKind() == TypeKind.DECLARED || tm.getKind() == TypeKind.ARRAY || tm.getKind() == TypeKind.ERROR)) {
addKeyword(env, INSTANCEOF_KEYWORD, SPACE, false);
}
TypeElement te = getTypeElement(env, e.getSimpleName().toString());
if (te != null) {
final Map<Name, ? extends Element> illegalForwardRefs = env.getForwardReferences();
Scope scope = env.getScope();
final ExecutableElement method = scope.getEnclosingMethod();
ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
return (method == null || method == e.getEnclosingElement() || e.getModifiers().contains(FINAL)
|| EnumSet.of(LOCAL_VARIABLE, PARAMETER, EXCEPTION_PARAMETER, RESOURCE_VARIABLE).contains(simplifyElementKind(e.getKind())) && controller.getSourceVersion().compareTo(SourceVersion.RELEASE_8) >= 0 && controller.getElementUtilities().isEffectivelyFinal((VariableElement)e))
&& !illegalForwardRefs.containsKey(e.getSimpleName());
}
};
for (String name : Utilities.varNamesSuggestions(controller.getTypes().getDeclaredType(te), varKind, varMods, null, prefix, controller.getTypes(),
controller.getElements(), controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor), CodeStyle.getDefault(controller.getDocument()))) {
results.add(itemFactory.createVariableItem(env.getController(), name, anchorOffset, true, false));
}
}
break;
}
return;
}
Tree exp = null;
if (et.getKind() == Tree.Kind.PARENTHESIZED) {
exp = ((ParenthesizedTree) et).getExpression();
} else if (et.getKind() == Tree.Kind.TYPE_CAST) {
if (env.getSourcePositions().getEndPosition(env.getRoot(), ((TypeCastTree) et).getType()) <= offset) {
exp = ((TypeCastTree) et).getType();
}
} else if (et.getKind() == Tree.Kind.ASSIGNMENT) {
Tree t = ((AssignmentTree) et).getExpression();
if (t.getKind() == Tree.Kind.PARENTHESIZED && env.getSourcePositions().getEndPosition(env.getRoot(), t) < offset) {
exp = ((ParenthesizedTree) t).getExpression();
}
}
if (exp != null) {
exPath = new TreePath(exPath, exp);
if (exp.getKind() == Tree.Kind.PRIMITIVE_TYPE || exp.getKind() == Tree.Kind.ARRAY_TYPE || exp.getKind() == Tree.Kind.PARAMETERIZED_TYPE) {
localResult(env);
addValueKeywords(env);
return;
}
Element e = controller.getTrees().getElement(exPath);
if (e == null) {
if (exp.getKind() == Tree.Kind.TYPE_CAST) {
addKeyword(env, INSTANCEOF_KEYWORD, SPACE, false);
}
return;
}
TypeMirror tm = controller.getTrees().getTypeMirror(exPath);
switch (simplifyElementKind(e.getKind())) {
case ANNOTATION_TYPE:
case CLASS:
case ENUM:
case INTERFACE:
case PACKAGE:
if (exp.getKind() == Tree.Kind.IDENTIFIER) {
VariableElement ve = getFieldOrVar(env, e.getSimpleName().toString());
if (ve != null) {
addKeyword(env, INSTANCEOF_KEYWORD, SPACE, false);
}
if (ve == null || tm == null || tm.getKind() != TypeKind.ERROR) {
localResult(env);
addValueKeywords(env);
}
} else if (exp.getKind() == Tree.Kind.MEMBER_SELECT) {
if (tm != null && (tm.getKind() == TypeKind.ERROR || tm.getKind() == TypeKind.PACKAGE)) {
addKeyword(env, INSTANCEOF_KEYWORD, SPACE, false);
}
localResult(env);
addValueKeywords(env);
} else if (exp.getKind() == Tree.Kind.PARENTHESIZED && tm != null && (tm.getKind() == TypeKind.DECLARED || tm.getKind() == TypeKind.ARRAY)) {
addKeyword(env, INSTANCEOF_KEYWORD, SPACE, false);
}
break;
case ENUM_CONSTANT:
case EXCEPTION_PARAMETER:
case FIELD:
case LOCAL_VARIABLE:
case RESOURCE_VARIABLE:
case PARAMETER:
if (tm != null && (tm.getKind() == TypeKind.DECLARED || tm.getKind() == TypeKind.ARRAY || tm.getKind() == TypeKind.ERROR)) {
addKeyword(env, INSTANCEOF_KEYWORD, SPACE, false);
}
TypeElement te = getTypeElement(env, e.getSimpleName().toString());
if (te != null || exp.getKind() == Tree.Kind.MEMBER_SELECT) {
localResult(env);
addValueKeywords(env);
}
break;
case CONSTRUCTOR:
case METHOD:
if (tm != null && (tm.getKind() == TypeKind.DECLARED || tm.getKind() == TypeKind.ARRAY || tm.getKind() == TypeKind.ERROR)) {
addKeyword(env, INSTANCEOF_KEYWORD, SPACE, false);
}
}
return;
}
Element e = controller.getTrees().getElement(exPath);
TypeMirror tm = controller.getTrees().getTypeMirror(exPath);
if (e == null) {
if (tm != null && (tm.getKind() == TypeKind.DECLARED || tm.getKind() == TypeKind.ARRAY)) {
addKeyword(env, INSTANCEOF_KEYWORD, SPACE, false);
}
return;
}
switch (simplifyElementKind(e.getKind())) {
case ANNOTATION_TYPE:
case CLASS:
case ENUM:
case INTERFACE:
case PACKAGE:
final Map<Name, ? extends Element> illegalForwardRefs = env.getForwardReferences();
Scope scope = env.getScope();
final ExecutableElement method = scope.getEnclosingMethod();
ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
return (method == null || method == e.getEnclosingElement() || e.getModifiers().contains(FINAL)
|| EnumSet.of(LOCAL_VARIABLE, PARAMETER, EXCEPTION_PARAMETER, RESOURCE_VARIABLE).contains(simplifyElementKind(e.getKind())) && controller.getSourceVersion().compareTo(SourceVersion.RELEASE_8) >= 0 && controller.getElementUtilities().isEffectivelyFinal((VariableElement)e))
&& !illegalForwardRefs.containsKey(e.getSimpleName());
}
};
for (String name : Utilities.varNamesSuggestions(tm, varKind, varMods, null, prefix, controller.getTypes(), controller.getElements(), controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor), CodeStyle.getDefault(controller.getDocument()))) {
results.add(itemFactory.createVariableItem(env.getController(), name, anchorOffset, true, false));
}
break;
case ENUM_CONSTANT:
case EXCEPTION_PARAMETER:
case FIELD:
case LOCAL_VARIABLE:
case RESOURCE_VARIABLE:
case PARAMETER:
case CONSTRUCTOR:
case METHOD:
if (tm != null && (tm.getKind() == TypeKind.DECLARED || tm.getKind() == TypeKind.ARRAY || tm.getKind() == TypeKind.ERROR)) {
addKeyword(env, INSTANCEOF_KEYWORD, SPACE, false);
}
}
}
private void insideBreakOrContinue(Env env) throws IOException {
TreePath path = env.getPath();
TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, path.getLeaf(), env.getOffset());
if (ts != null && (ts.token().id() == JavaTokenId.BREAK || ts.token().id() == JavaTokenId.CONTINUE)) {
while (path != null) {
if (path.getLeaf().getKind() == Tree.Kind.LABELED_STATEMENT) {
results.add(itemFactory.createVariableItem(env.getController(), ((LabeledStatementTree) path.getLeaf()).getLabel().toString(), anchorOffset, false, false));
}
path = path.getParentPath();
}
}
}
private void localResult(Env env) throws IOException {
addLocalMembersAndVars(env);
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
addPrimitiveTypeKeywords(env);
}
private void addLocalConstantsAndTypes(final Env env) throws IOException {
final String prefix = env.getPrefix();
final CompilationController controller = env.getController();
final Elements elements = controller.getElements();
final Types types = controller.getTypes();
final Trees trees = controller.getTrees();
final Scope scope = env.getScope();
Set<? extends TypeMirror> smartTypes = null;
boolean smartType = false;
if (!options.contains(Options.ALL_COMPLETION)) {
smartTypes = getSmartTypes(env);
if (smartTypes != null) {
for (TypeMirror st : smartTypes) {
if (st.getKind() == TypeKind.BOOLEAN) {
smartType = true;
}
if (st.getKind().isPrimitive()) {
st = types.boxedClass((PrimitiveType) st).asType();
}
if (st.getKind() == TypeKind.DECLARED) {
final DeclaredType type = (DeclaredType) st;
final TypeElement element = (TypeElement) type.asElement();
if (element.getKind() == ANNOTATION_TYPE && (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(element))) {
results.add(itemFactory.createAnnotationItem(env.getController(), element, type, anchorOffset, env.getReferencesCount(), elements.isDeprecated(element)));
}
if (JAVA_LANG_CLASS.contentEquals(element.getQualifiedName())) {
addTypeDotClassMembers(env, type);
}
if (startsWith(env, element.getSimpleName().toString(), prefix)) {
final boolean isStatic = element.getKind().isClass() || element.getKind().isInterface();
ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
return (e.getKind() == ENUM_CONSTANT || e.getKind() == FIELD && ((VariableElement) e).getConstantValue() != null)
&& (!isStatic || e.getModifiers().contains(STATIC))
&& trees.isAccessible(scope, e, (DeclaredType) t)
&& types.isAssignable(((VariableElement) e).asType(), type);
}
};
for (Element ee : controller.getElementUtilities().getMembers(type, acceptor)) {
if (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(ee)) {
results.add(itemFactory.createStaticMemberItem(env.getController(), type, ee, asMemberOf(ee, type, types), false, anchorOffset, elements.isDeprecated(ee), false));
}
}
}
}
}
}
}
if (env.getPath().getLeaf().getKind() != Tree.Kind.CASE) {
if (Utilities.startsWith(FALSE_KEYWORD, prefix)) {
results.add(itemFactory.createKeywordItem(FALSE_KEYWORD, null, anchorOffset, smartType));
}
if (Utilities.startsWith(TRUE_KEYWORD, prefix)) {
results.add(itemFactory.createKeywordItem(TRUE_KEYWORD, null, anchorOffset, smartType));
}
}
final TypeElement enclClass = scope.getEnclosingClass();
for (Element e : getLocalMembersAndVars(env)) {
switch (simplifyElementKind(e.getKind())) {
case FIELD:
if (((VariableElement) e).getConstantValue() != null) {
TypeMirror tm = asMemberOf(e, enclClass != null ? enclClass.asType() : null, types);
results.add(itemFactory.createVariableItem(env.getController(), (VariableElement) e, tm, anchorOffset, null, env.getScope().getEnclosingClass() != e.getEnclosingElement(), elements.isDeprecated(e), isOfSmartType(env, tm, smartTypes), env.assignToVarPos()));
}
break;
case LOCAL_VARIABLE:
case RESOURCE_VARIABLE:
case EXCEPTION_PARAMETER:
case PARAMETER:
case ENUM_CONSTANT:
if (((VariableElement) e).getConstantValue() != null) {
results.add(itemFactory.createVariableItem(env.getController(), (VariableElement) e, e.asType(), anchorOffset, null, env.getScope().getEnclosingClass() != e.getEnclosingElement(), elements.isDeprecated(e), isOfSmartType(env, e.asType(), smartTypes), env.assignToVarPos()));
}
break;
}
}
addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
}
private void addLocalMembersAndVars(final Env env) throws IOException {
final CompilationController controller = env.getController();
final Elements elements = controller.getElements();
final Types types = controller.getTypes();
final Trees trees = controller.getTrees();
final Scope scope = env.getScope();
Iterable<? extends Element> locals = getLocalMembersAndVars(env);
Set<? extends TypeMirror> smartTypes = null;
if (!options.contains(Options.ALL_COMPLETION)) {
smartTypes = getSmartTypes(env);
if (smartTypes != null) {
for (TypeMirror st : smartTypes) {
if (st.getKind().isPrimitive()) {
st = types.boxedClass((PrimitiveType) st).asType();
}
if (st.getKind() == TypeKind.DECLARED) {
final DeclaredType type = (DeclaredType) st;
final TypeElement element = (TypeElement) type.asElement();
if (JAVA_LANG_CLASS.contentEquals(element.getQualifiedName())) {
addTypeDotClassMembers(env, type);
} else if (controller.getSourceVersion().compareTo(SourceVersion.RELEASE_8) >= 0
&& elements.isFunctionalInterface(element) && itemFactory instanceof LambdaItemFactory) {
results.add(((LambdaItemFactory<T>)itemFactory).createLambdaItem(env.getController(), element, type, anchorOffset, env.addSemicolon()));
}
final boolean startsWith = startsWith(env, element.getSimpleName().toString());
final boolean withinScope = withinScope(env, element);
if (withinScope && scope.getEnclosingClass() == element) {
continue;
}
final boolean isStatic = element.getKind().isClass() || element.getKind().isInterface();
final Set<? extends TypeMirror> finalSmartTypes = smartTypes;
ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
return (startsWith || startsWith(env, e.getSimpleName().toString()))
&& (!e.getSimpleName().contentEquals(CLASS_KEYWORD) && (!withinScope && (!isStatic || e.getModifiers().contains(STATIC))) || withinScope && e.getSimpleName().contentEquals(THIS_KEYWORD))
&& trees.isAccessible(scope, e, (DeclaredType) t)
&& (e.getKind().isField() && isOfSmartType(env, ((VariableElement) e).asType(), finalSmartTypes) || e.getKind() == METHOD && isOfSmartType(env, ((ExecutableElement) e).getReturnType(), finalSmartTypes));
}
};
for (Element ee : controller.getElementUtilities().getMembers(type, acceptor)) {
if (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(ee)) {
results.add(itemFactory.createStaticMemberItem(env.getController(), type, ee, asMemberOf(ee, type, types), false, anchorOffset, elements.isDeprecated(ee), env.addSemicolon()));
}
}
}
}
}
} else {
addChainedMembers(env, locals);
addAllStaticMemberNames(env);
}
final TypeElement enclClass = scope.getEnclosingClass();
for (Element e : locals) {
switch (simplifyElementKind(e.getKind())) {
case ENUM_CONSTANT:
case EXCEPTION_PARAMETER:
case LOCAL_VARIABLE:
case RESOURCE_VARIABLE:
case PARAMETER:
results.add(itemFactory.createVariableItem(env.getController(), (VariableElement) e, e.asType(), anchorOffset, null, env.getScope().getEnclosingClass() != e.getEnclosingElement(), elements.isDeprecated(e), isOfSmartType(env, e.asType(), smartTypes), env.assignToVarPos()));
break;
case FIELD:
String name = e.getSimpleName().toString();
if (THIS_KEYWORD.equals(name) || SUPER_KEYWORD.equals(name)) {
results.add(itemFactory.createKeywordItem(name, null, anchorOffset, isOfSmartType(env, e.asType(), smartTypes)));
} else {
TypeMirror tm = asMemberOf(e, enclClass != null ? enclClass.asType() : null, types);
results.add(itemFactory.createVariableItem(env.getController(), (VariableElement) e, tm, anchorOffset, null, env.getScope().getEnclosingClass() != e.getEnclosingElement(), elements.isDeprecated(e), isOfSmartType(env, tm, smartTypes), env.assignToVarPos()));
}
break;
case METHOD:
ExecutableType et = (ExecutableType) asMemberOf(e, enclClass != null ? enclClass.asType() : null, types);
if (e.getEnclosingElement() != enclClass && conflictsWithLocal(e.getSimpleName(), enclClass, locals)) {
results.add(itemFactory.createStaticMemberItem(env.getController(), (DeclaredType)e.getEnclosingElement().asType(), e, et, false, anchorOffset, elements.isDeprecated(e), env.addSemicolon()));
} else {
results.add(itemFactory.createExecutableItem(env.getController(), (ExecutableElement) e, et, anchorOffset, null, env.getScope().getEnclosingClass() != e.getEnclosingElement(), elements.isDeprecated(e), false, env.addSemicolon(), isOfSmartType(env, getCorrectedReturnType(env, et, (ExecutableElement) e, enclClass != null ? enclClass.asType() : null), smartTypes), env.assignToVarPos(), false));
}
break;
}
}
}
private void addLocalFieldsAndVars(final Env env) throws IOException {
final CompilationController controller = env.getController();
final Elements elements = controller.getElements();
final Types types = controller.getTypes();
final Scope scope = env.getScope();
Set<? extends TypeMirror> smartTypes = options.contains(Options.ALL_COMPLETION) ? null : getSmartTypes(env);
final TypeElement enclClass = scope.getEnclosingClass();
for (Element e : getLocalMembersAndVars(env)) {
switch (simplifyElementKind(e.getKind())) {
case ENUM_CONSTANT:
case EXCEPTION_PARAMETER:
case LOCAL_VARIABLE:
case RESOURCE_VARIABLE:
case PARAMETER:
results.add(itemFactory.createVariableItem(env.getController(), (VariableElement) e, e.asType(), anchorOffset, null, env.getScope().getEnclosingClass() != e.getEnclosingElement(), elements.isDeprecated(e), isOfSmartType(env, e.asType(), smartTypes), env.assignToVarPos()));
break;
case FIELD:
String name = e.getSimpleName().toString();
if (THIS_KEYWORD.equals(name) || SUPER_KEYWORD.equals(name)) {
results.add(itemFactory.createKeywordItem(name, null, anchorOffset, isOfSmartType(env, e.asType(), smartTypes)));
} else {
TypeMirror tm = asMemberOf(e, enclClass != null ? enclClass.asType() : null, types);
results.add(itemFactory.createVariableItem(env.getController(), (VariableElement) e, tm, anchorOffset, null, env.getScope().getEnclosingClass() != e.getEnclosingElement(), elements.isDeprecated(e), isOfSmartType(env, tm, smartTypes), env.assignToVarPos()));
}
break;
}
}
}
private void addEffectivelyFinalAutoCloseables(final Env env) throws IOException {
final CompilationController controller = env.getController();
final Elements elements = controller.getElements();
final TypeElement te = elements.getTypeElement("java.lang.AutoCloseable"); //NOI18N
if (te != null) {
final Types types = controller.getTypes();
final ElementUtilities eu = controller.getElementUtilities();
final Scope scope = env.getScope();
final Set<? extends TypeMirror> smartTypes = options.contains(Options.ALL_COMPLETION) ? null : getSmartTypes(env);
final TypeElement enclClass = scope.getEnclosingClass();
for (Element e : getLocalMembersAndVars(env)) {
switch (simplifyElementKind(e.getKind())) {
case EXCEPTION_PARAMETER:
case LOCAL_VARIABLE:
case RESOURCE_VARIABLE:
case PARAMETER:
if (types.isSubtype(e.asType(), te.asType()) && eu.isEffectivelyFinal((VariableElement) e)) {
results.add(itemFactory.createVariableItem(env.getController(), (VariableElement) e, e.asType(), anchorOffset, null, env.getScope().getEnclosingClass() != e.getEnclosingElement(), elements.isDeprecated(e), isOfSmartType(env, e.asType(), smartTypes), env.assignToVarPos()));
}
break;
case FIELD:
if (types.isSubtype(e.asType(), te.asType())) {
String name = e.getSimpleName().toString();
if (THIS_KEYWORD.equals(name) || SUPER_KEYWORD.equals(name)) {
results.add(itemFactory.createKeywordItem(name, null, anchorOffset, isOfSmartType(env, e.asType(), smartTypes)));
} else {
TypeMirror tm = asMemberOf(e, enclClass != null ? enclClass.asType() : null, types);
results.add(itemFactory.createVariableItem(env.getController(), (VariableElement) e, tm, anchorOffset, null, env.getScope().getEnclosingClass() != e.getEnclosingElement(), elements.isDeprecated(e), isOfSmartType(env, tm, smartTypes), env.assignToVarPos()));
}
}
break;
}
}
}
}
@SuppressWarnings("fallthrough")
private Iterable<? extends Element> getLocalMembersAndVars(final Env env) throws IOException {
final String prefix = env.getPrefix();
final CompilationController controller = env.getController();
final Elements elements = controller.getElements();
final Trees trees = controller.getTrees();
final TreeUtilities tu = controller.getTreeUtilities();
final ElementUtilities eu = controller.getElementUtilities();
final Scope scope = env.getScope();
final TypeElement enclClass = scope.getEnclosingClass();
final boolean enclStatic = enclClass != null && enclClass.getModifiers().contains(Modifier.STATIC);
final boolean ctxStatic = enclClass != null && (tu.isStaticContext(scope) || (env.getPath().getLeaf().getKind() == Tree.Kind.BLOCK && ((BlockTree) env.getPath().getLeaf()).isStatic()));
final Map<Name, ? extends Element> illegalForwardRefs = env.getForwardReferences();
final ExecutableElement method = scope.getEnclosingMethod() != null && scope.getEnclosingMethod().getEnclosingElement() == enclClass ? scope.getEnclosingMethod() : null;
ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
boolean isStatic = ctxStatic || (t != null && t.getKind() == TypeKind.DECLARED && ((DeclaredType) t).asElement() != enclClass && enclStatic);
switch (simplifyElementKind(e.getKind())) {
case CONSTRUCTOR:
return false;
case LOCAL_VARIABLE:
case RESOURCE_VARIABLE:
case EXCEPTION_PARAMETER:
case PARAMETER:
return startsWith(env, e.getSimpleName().toString()) &&
(method == e.getEnclosingElement() ||
e.getModifiers().contains(Modifier.FINAL) ||
env.getController().getSourceVersion().compareTo(SourceVersion.RELEASE_8) >= 0 && eu.isEffectivelyFinal((VariableElement)e)
|| (method == null && (e.getEnclosingElement().getKind() == INSTANCE_INIT
|| e.getEnclosingElement().getKind() == STATIC_INIT
|| e.getEnclosingElement().getKind() == CONSTRUCTOR
|| e.getEnclosingElement().getKind() == METHOD && e.getEnclosingElement().getEnclosingElement().getKind() == FIELD)))
&& (!illegalForwardRefs.containsKey(e.getSimpleName()) || illegalForwardRefs.get(e.getSimpleName()).getEnclosingElement() != e.getEnclosingElement());
case FIELD:
if (e.getSimpleName().contentEquals(THIS_KEYWORD) || e.getSimpleName().contentEquals(SUPER_KEYWORD)) {
return Utilities.startsWith(e.getSimpleName().toString(), prefix) && !isStatic;
}
case ENUM_CONSTANT:
return startsWith(env, e.getSimpleName().toString())
&& !illegalForwardRefs.containsValue(e)
&& (!isStatic || e.getModifiers().contains(STATIC))
&& (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(e))
&& trees.isAccessible(scope, e, (DeclaredType) t);
case METHOD:
String sn = e.getSimpleName().toString();
return startsWith(env, sn)
&& (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(e))
&& (!isStatic || e.getModifiers().contains(STATIC))
&& trees.isAccessible(scope, e, (DeclaredType) t)
&& (!Utilities.isExcludeMethods() || !Utilities.isExcluded(eu.getElementName(e.getEnclosingElement(), true) + "." + sn)); //NOI18N
}
return false;
}
};
return controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor);
}
private void addTypeDotClassMembers(Env env, DeclaredType type) throws IOException {
final CompilationController controller = env.getController();
final Elements elements = controller.getElements();
final Types types = controller.getTypes();
Iterator<? extends TypeMirror> it = type.getTypeArguments().iterator();
TypeMirror tm = it.hasNext() ? it.next() : elements.getTypeElement(JAVA_LANG_OBJECT).asType();
Iterable<DeclaredType> dts = null;
if (tm.getKind() == TypeKind.WILDCARD) {
TypeMirror bound = ((WildcardType) tm).getSuperBound();
if (bound != null) {
if (bound.getKind() == TypeKind.DECLARED) {
dts = getSupertypesOf(env, (DeclaredType) bound);
}
} else {
bound = ((WildcardType) tm).getExtendsBound();
if (bound != null) {
if (bound.getKind() == TypeKind.DECLARED) {
if (JAVA_LANG_OBJECT.contentEquals(((TypeElement) ((DeclaredType) bound).asElement()).getQualifiedName())) {
dts = Collections.singleton((DeclaredType) elements.getTypeElement(JAVA_LANG_OBJECT).asType());
} else {
dts = getSubtypesOf(env, (DeclaredType) bound);
}
}
} else {
dts = Collections.singleton((DeclaredType) elements.getTypeElement(JAVA_LANG_OBJECT).asType());
}
}
} else if (tm.getKind() == TypeKind.DECLARED) {
dts = Collections.singleton((DeclaredType) tm);
}
if (dts != null) {
ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
return e.getKind() == FIELD && e.getSimpleName().contentEquals(CLASS_KEYWORD);
}
};
for (DeclaredType dt : dts) {
if (startsWith(env, dt.asElement().getSimpleName().toString())) {
for (Element ee : controller.getElementUtilities().getMembers(dt, acceptor)) {
results.add(itemFactory.createStaticMemberItem(env.getController(), dt, ee, asMemberOf(ee, dt, types), false, anchorOffset, elements.isDeprecated(ee), env.addSemicolon()));
}
}
}
}
}
@SuppressWarnings("fallthrough")
private void addChainedMembers(final Env env, final Iterable<? extends Element> locals) throws IOException {
final Set<? extends TypeMirror> smartTypes = getSmartTypes(env);
if (smartTypes != null && !smartTypes.isEmpty()) {
final CompilationController controller = env.getController();
final Scope scope = env.getScope();
final TypeElement enclClass = scope.getEnclosingClass();
final Elements elements = controller.getElements();
final Types types = controller.getTypes();
final Trees trees = controller.getTrees();
final ElementUtilities eu = controller.getElementUtilities();
for (Element localElement : locals) {
TypeMirror localElementType = null;
TypeMirror type = null;
switch (simplifyElementKind(localElement.getKind())) {
case EXCEPTION_PARAMETER:
case LOCAL_VARIABLE:
case RESOURCE_VARIABLE:
case PARAMETER:
case ENUM_CONSTANT:
type = localElementType = localElement.asType();
break;
case FIELD:
String name = localElement.getSimpleName().toString();
if (!THIS_KEYWORD.equals(name) && !SUPER_KEYWORD.equals(name)) {
type = localElementType = asMemberOf(localElement, enclClass != null ? enclClass.asType() : null, types);
}
break;
case METHOD:
localElementType = asMemberOf(localElement, enclClass != null ? enclClass.asType() : null, types);
type = ((ExecutableType) localElementType).getReturnType();
break;
}
if (type != null && type.getKind() == TypeKind.DECLARED && !isOfSmartType(env, type, smartTypes)) {
ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
switch (e.getKind()) {
case FIELD:
if (e.getSimpleName().contentEquals(THIS_KEYWORD) || e.getSimpleName().contentEquals(SUPER_KEYWORD)) {
return false;
}
case ENUM_CONSTANT:
return trees.isAccessible(scope, e, (DeclaredType) t)
&& isOfSmartType(env, asMemberOf(e, t, types), smartTypes);
case METHOD:
return trees.isAccessible(scope, e, (DeclaredType) t)
&& isOfSmartType(env, ((ExecutableType) asMemberOf(e, t, types)).getReturnType(), smartTypes);
}
return false;
}
};
for (Element e : eu.getMembers(type, acceptor)) {
if (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(e)) {
List<Element> chainedElements = new ArrayList<>(2);
chainedElements.add(localElement);
chainedElements.add(e);
List<TypeMirror> chainedTypes = new ArrayList<>(2);
chainedTypes.add(localElementType);
chainedTypes.add(asMemberOf(e, type, types));
results.add(itemFactory.createChainedMembersItem(env.getController(), chainedElements, chainedTypes, anchorOffset, elements.isDeprecated(localElement) || elements.isDeprecated(e), env.addSemicolon()));
}
}
}
}
}
}
private void addAllStaticMemberNames(final Env env) {
String prefix = env.getPrefix();
if (prefix != null && prefix.length() > 0) {
CompilationController controller = env.getController();
Set<? extends Element> excludes = env.getExcludes();
Set<ElementHandle<Element>> excludeHandles = null;
if (excludes != null) {
excludeHandles = new HashSet<>(excludes.size());
for (Element el : excludes) {
excludeHandles.add(ElementHandle.create(el));
}
}
ClassIndex.NameKind kind = Utilities.isCaseSensitive() ? ClassIndex.NameKind.PREFIX : ClassIndex.NameKind.CASE_INSENSITIVE_PREFIX;
Iterable<Symbols> declaredSymbols = controller.getClasspathInfo().getClassIndex().getDeclaredSymbols(prefix, kind, EnumSet.allOf(ClassIndex.SearchScope.class));
for (Symbols symbols : declaredSymbols) {
if (Utilities.isExcluded(symbols.getEnclosingType().getQualifiedName())
|| excludeHandles != null && excludeHandles.contains(symbols.getEnclosingType())
|| isAnnonInner(symbols.getEnclosingType())) {
continue;
}
for (String name : symbols.getSymbols()) {
if (!Utilities.isExcludeMethods() || !Utilities.isExcluded(symbols.getEnclosingType().getQualifiedName() + '.' + name)) {
results.add(itemFactory.createStaticMemberItem(symbols.getEnclosingType(), name, anchorOffset, env.addSemicolon(), env.getReferencesCount(), controller.getSnapshot().getSource()));
}
}
}
}
}
@SuppressWarnings("fallthrough")
private void addMemberConstantsAndTypes(final Env env, final TypeMirror type, final Element elem) throws IOException {
Set<? extends TypeMirror> smartTypes = options.contains(Options.ALL_COMPLETION) ? null : getSmartTypes(env);
final CompilationController controller = env.getController();
final Elements elements = controller.getElements();
final Types types = controller.getTypes();
final Trees trees = controller.getTrees();
TypeElement typeElem = type.getKind() == TypeKind.DECLARED ? (TypeElement) ((DeclaredType) type).asElement() : null;
final boolean isStatic = elem != null && (elem.getKind().isClass() || elem.getKind().isInterface() || elem.getKind() == TYPE_PARAMETER);
final boolean isSuperCall = elem != null && elem.getKind().isField() && elem.getSimpleName().contentEquals(SUPER_KEYWORD);
final Scope scope = env.getScope();
TypeElement enclClass = scope.getEnclosingClass();
final TypeMirror enclType = enclClass != null ? enclClass.asType() : null;
ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
if (!startsWith(env, e.getSimpleName().toString())
|| (isStatic && !e.getModifiers().contains(STATIC))) {
return false;
}
switch (e.getKind()) {
case FIELD:
if (((VariableElement) e).getConstantValue() == null && !CLASS_KEYWORD.contentEquals(e.getSimpleName())) {
return false;
}
case ENUM_CONSTANT:
return (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(e)) && trees.isAccessible(scope, e, (DeclaredType) (isSuperCall && enclType != null ? enclType : t));
case CLASS:
case ENUM:
case INTERFACE:
return (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(e)) && !Utilities.isExcluded(((TypeElement)e).getQualifiedName()) && trees.isAccessible(scope, e, (DeclaredType) t);
}
return false;
}
};
for (Element e : controller.getElementUtilities().getMembers(type, acceptor)) {
switch (e.getKind()) {
case FIELD:
case ENUM_CONSTANT:
String name = e.getSimpleName().toString();
if (CLASS_KEYWORD.equals(name)) {
results.add(itemFactory.createKeywordItem(name, null, anchorOffset, false));
} else {
TypeMirror tm = asMemberOf(e, type, types);
results.add(itemFactory.createVariableItem(env.getController(), (VariableElement) e, tm, anchorOffset, null, typeElem != e.getEnclosingElement(), elements.isDeprecated(e), isOfSmartType(env, tm, smartTypes), env.assignToVarPos()));
}
break;
case CLASS:
case ENUM:
case INTERFACE:
DeclaredType dt = (DeclaredType) asMemberOf(e, type, types);
results.add(itemFactory.createTypeItem(env.getController(), (TypeElement) e, dt, anchorOffset, null, elements.isDeprecated(e), false, env.isInsideClass(), true, false, false));
break;
}
}
}
private void addMethodReferences(final Env env, final TypeMirror type, final Element elem) throws IOException {
Set<? extends TypeMirror> smartTypes = getSmartTypes(env);
final String prefix = env.getPrefix();
final CompilationController controller = env.getController();
final Elements elements = controller.getElements();
final Types types = controller.getTypes();
final TreeUtilities tu = controller.getTreeUtilities();
final ElementUtilities eu = controller.getElementUtilities();
TypeElement typeElem = type.getKind() == TypeKind.DECLARED ? (TypeElement) ((DeclaredType) type).asElement() : null;
final boolean isThisCall = elem != null && elem.getKind().isField() && elem.getSimpleName().contentEquals(THIS_KEYWORD);
final boolean isSuperCall = elem != null && elem.getKind().isField() && elem.getSimpleName().contentEquals(SUPER_KEYWORD);
final Scope scope = env.getScope();
if ((isThisCall || isSuperCall) && tu.isStaticContext(scope)) {
return;
}
ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
switch (e.getKind()) {
case METHOD:
String sn = e.getSimpleName().toString();
return startsWith(env, sn, prefix)
&& (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(e))
&& env.isAccessible(scope, e, t, isSuperCall)
&& (!Utilities.isExcludeMethods() || !Utilities.isExcluded(eu.getElementName(e.getEnclosingElement(), true) + "." + sn)); //NOI18N
}
return false;
}
};
for (Element e : eu.getMembers(type, acceptor)) {
switch (e.getKind()) {
case METHOD:
ExecutableType et = (ExecutableType) asMemberOf(e, type, types);
results.add(itemFactory.createExecutableItem(env.getController(), (ExecutableElement) e, et, anchorOffset, null, typeElem != e.getEnclosingElement(), elements.isDeprecated(e), false, false, isOfSmartType(env, et, smartTypes), env.assignToVarPos(), true));
break;
}
}
}
private void addMembers(final Env env, final TypeMirror type, final Element elem, final EnumSet<ElementKind> kinds, final DeclaredType baseType, final boolean inImport, final boolean insideNew, final boolean autoImport) throws IOException {
Set<? extends TypeMirror> smartTypes = getSmartTypes(env);
final TreePath path = env.getPath();
TypeMirror actualType = type;
if (path != null && path.getLeaf().getKind() == Tree.Kind.MEMBER_SELECT) {
actualType = adjustType(env, type, elem, new TreePath(path, ((MemberSelectTree)path.getLeaf()).getExpression()));
}
final CompilationController controller = env.getController();
final Trees trees = controller.getTrees();
final Elements elements = controller.getElements();
final ElementUtilities eu = controller.getElementUtilities();
final Types types = controller.getTypes();
final TreeUtilities tu = controller.getTreeUtilities();
TypeElement typeElem = actualType.getKind() == TypeKind.DECLARED ? (TypeElement) ((DeclaredType) actualType).asElement() : null;
final boolean isStatic = elem != null && (elem.getKind().isClass() || elem.getKind().isInterface() || elem.getKind() == TYPE_PARAMETER) && elem.asType().getKind() != TypeKind.ERROR;
final boolean isThisCall = elem != null && elem.getKind().isField() && elem.getSimpleName().contentEquals(THIS_KEYWORD);
final boolean isSuperCall = elem != null && elem.getKind().isField() && elem.getSimpleName().contentEquals(SUPER_KEYWORD);
final Scope scope = env.getScope();
if ((isThisCall || isSuperCall) && tu.isStaticContext(scope)) {
return;
}
final boolean[] ctorSeen = {false};
final boolean[] nestedClassSeen = {false};
final TypeElement enclClass = scope.getEnclosingClass();
ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
switch (simplifyElementKind(e.getKind())) {
case FIELD:
if (!startsWith(env, e.getSimpleName().toString())) {
return false;
}
if (e.getSimpleName().contentEquals(THIS_KEYWORD) || e.getSimpleName().contentEquals(SUPER_KEYWORD)) {
TypeElement cls = enclClass;
while (cls != null) {
if (cls == elem) {
return isOfKindAndType(asMemberOf(e, t, types), e, kinds, baseType, scope, trees, types);
}
TypeElement outer = eu.enclosingTypeElement(cls);
cls = !cls.getModifiers().contains(STATIC) ? outer : null;
}
return false;
}
if (isStatic) {
if (!e.getModifiers().contains(STATIC)
|| e.getSimpleName().contentEquals(CLASS_KEYWORD) && elem.getKind() == ElementKind.TYPE_PARAMETER) {
return false;
}
} else {
if (!options.contains(Options.ALL_COMPLETION) && e.getModifiers().contains(STATIC)) {
if ((Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(e))
&& isOfKindAndType(asMemberOf(e, t, types), e, kinds, baseType, scope, trees, types)
&& env.isAccessible(scope, e, t, isSuperCall)
&& ((isStatic && !inImport) || !e.getSimpleName().contentEquals(CLASS_KEYWORD))) {
hasAdditionalMembers = true;
}
return false;
}
}
return (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(e))
&& isOfKindAndType(asMemberOf(e, t, types), e, kinds, baseType, scope, trees, types)
&& env.isAccessible(scope, e, t, isSuperCall)
&& ((isStatic && !inImport) || !e.getSimpleName().contentEquals(CLASS_KEYWORD));
case ENUM_CONSTANT:
case EXCEPTION_PARAMETER:
case LOCAL_VARIABLE:
case RESOURCE_VARIABLE:
case PARAMETER:
return startsWith(env, e.getSimpleName().toString())
&& (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(e))
&& isOfKindAndType(asMemberOf(e, t, types), e, kinds, baseType, scope, trees, types)
&& env.isAccessible(scope, e, t, isSuperCall);
case METHOD:
String sn = e.getSimpleName().toString();
if (isStatic) {
if (!e.getModifiers().contains(STATIC)) {
return false;
}
} else {
if (!options.contains(Options.ALL_COMPLETION) && e.getModifiers().contains(STATIC)) {
if (startsWith(env, sn)
&& (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(e))
&& isOfKindAndType(((ExecutableType) asMemberOf(e, t, types)).getReturnType(), e, kinds, baseType, scope, trees, types)
&& env.isAccessible(scope, e, t, isSuperCall)
&& (!Utilities.isExcludeMethods() || !Utilities.isExcluded(eu.getElementName(e.getEnclosingElement(), true) + "." + sn))) { //NOI18N
hasAdditionalMembers = true;
}
return false;
}
}
return startsWith(env, sn)
&& (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(e))
&& isOfKindAndType(((ExecutableType) asMemberOf(e, t, types)).getReturnType(), e, kinds, baseType, scope, trees, types)
&& env.isAccessible(scope, e, t, isSuperCall)
&& (!Utilities.isExcludeMethods() || !Utilities.isExcluded(eu.getElementName(e.getEnclosingElement(), true) + "." + sn)); //NOI18N
case CLASS:
case ENUM:
case INTERFACE:
case ANNOTATION_TYPE:
if (!e.getModifiers().contains(STATIC)) {
nestedClassSeen[0] = true;
}
return startsWith(env, e.getSimpleName().toString())
&& (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(e))
&& !Utilities.isExcluded(((TypeElement)e).getQualifiedName())
&& isOfKindAndType(e.asType(), e, kinds, baseType, scope, trees, types)
&& (!env.isAfterExtends() || containsAccessibleNonFinalType(e, scope, trees))
&& env.isAccessible(scope, e, t, isSuperCall) && isStatic;
case CONSTRUCTOR:
ctorSeen[0] = true;
return (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(e))
&& isOfKindAndType(e.getEnclosingElement().asType(), e, kinds, baseType, scope, trees, types)
&& (env.isAccessible(scope, e, t, isSuperCall || insideNew) || (elem.getModifiers().contains(ABSTRACT) && !e.getModifiers().contains(PRIVATE)))
&& isStatic;
}
return false;
}
};
boolean addCast = actualType != type && elem instanceof VariableElement && !elem.getKind().isField();
for (Element e : controller.getElementUtilities().getMembers(actualType, acceptor)) {
switch (simplifyElementKind(e.getKind())) {
case ENUM_CONSTANT:
case EXCEPTION_PARAMETER:
case FIELD:
case LOCAL_VARIABLE:
case RESOURCE_VARIABLE:
case PARAMETER:
String name = e.getSimpleName().toString();
if (THIS_KEYWORD.equals(name) || CLASS_KEYWORD.equals(name) || SUPER_KEYWORD.equals(name)) {
if (!env.isExcludedKW(name)) {
results.add(itemFactory.createKeywordItem(name, null, anchorOffset, isOfSmartType(env, e.asType(), smartTypes)));
env.addExcludedKW(name);
}
} else {
TypeMirror tm = asMemberOf(e, actualType, types);
if (addCast && itemFactory instanceof TypeCastableItemFactory) {
results.add(((TypeCastableItemFactory<T>)itemFactory).createTypeCastableVariableItem(env.getController(), (VariableElement) e, tm, actualType, anchorOffset, autoImport ? env.getReferencesCount() : null, typeElem != e.getEnclosingElement(), elements.isDeprecated(e), isOfSmartType(env, tm, smartTypes), env.assignToVarPos()));
} else {
results.add(itemFactory.createVariableItem(env.getController(), (VariableElement) e, tm, anchorOffset, autoImport ? env.getReferencesCount() : null, typeElem != e.getEnclosingElement(), elements.isDeprecated(e), isOfSmartType(env, tm, smartTypes), env.assignToVarPos()));
}
}
break;
case CONSTRUCTOR:
ExecutableType et = (ExecutableType) asMemberOf(e, actualType, types);
results.add(itemFactory.createExecutableItem(env.getController(), (ExecutableElement) e, et, anchorOffset, autoImport ? env.getReferencesCount() : null, typeElem != e.getEnclosingElement(), elements.isDeprecated(e), inImport, false, isOfSmartType(env, actualType, smartTypes), env.assignToVarPos(), false));
break;
case METHOD:
et = (ExecutableType) asMemberOf(e, actualType, types);
if (addCast && itemFactory instanceof TypeCastableItemFactory
&& !types.isSubtype(type, e.getEnclosingElement().asType())
&& type.getKind() == TypeKind.DECLARED && !eu.alreadyDefinedIn(e.getSimpleName(), et, (TypeElement)((DeclaredType)type).asElement())) {
results.add(((TypeCastableItemFactory<T>)itemFactory).createTypeCastableExecutableItem(env.getController(), (ExecutableElement) e, et, actualType, anchorOffset, autoImport ? env.getReferencesCount() : null, typeElem != e.getEnclosingElement(), elements.isDeprecated(e), inImport, env.addSemicolon(), isOfSmartType(env, getCorrectedReturnType(env, et, (ExecutableElement) e, actualType), smartTypes), env.assignToVarPos(), false));
} else {
results.add(itemFactory.createExecutableItem(env.getController(), (ExecutableElement) e, et, anchorOffset, autoImport ? env.getReferencesCount() : null, typeElem != e.getEnclosingElement(), elements.isDeprecated(e), inImport, env.addSemicolon(), isOfSmartType(env, getCorrectedReturnType(env, et, (ExecutableElement) e, actualType), smartTypes), env.assignToVarPos(), false));
}
break;
case CLASS:
case ENUM:
case INTERFACE:
case ANNOTATION_TYPE:
DeclaredType dt = (DeclaredType) asMemberOf(e, actualType, types);
results.add(itemFactory.createTypeItem(env.getController(), (TypeElement) e, dt, anchorOffset, null, elements.isDeprecated(e), insideNew, insideNew || env.isInsideClass(), true, isOfSmartType(env, dt, smartTypes), autoImport));
break;
}
}
if (!ctorSeen[0] && kinds.contains(CONSTRUCTOR) && elem.getKind().isInterface()) {
results.add(itemFactory.createDefaultConstructorItem((TypeElement) elem, anchorOffset, isOfSmartType(env, actualType, smartTypes)));
}
if (isStatic && enclClass != null && elem.getKind().isInterface() && env.getController().getSourceVersion().compareTo(SourceVersion.RELEASE_8) >= 0) {
for (TypeMirror iface : enclClass.getInterfaces()) {
if (((DeclaredType) iface).asElement() == elem) {
results.add(itemFactory.createKeywordItem(SUPER_KEYWORD, null, anchorOffset, isOfSmartType(env, actualType, smartTypes)));
break;
}
}
}
if (!isStatic && nestedClassSeen[0]) {
addKeyword(env, NEW_KEYWORD, SPACE, false);
}
}
private void addThisOrSuperConstructor(final Env env, final TypeMirror type, final Element elem, final String name, final ExecutableElement toExclude) throws IOException {
final CompilationController controller = env.getController();
final Elements elements = controller.getElements();
final Types types = controller.getTypes();
final Trees trees = controller.getTrees();
final Scope scope = env.getScope();
ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
switch (e.getKind()) {
case CONSTRUCTOR:
return toExclude != e && (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(e))
&& (trees.isAccessible(scope, e, (DeclaredType) t) || (elem.getModifiers().contains(ABSTRACT) && !e.getModifiers().contains(PRIVATE)));
}
return false;
}
};
for (Element e : controller.getElementUtilities().getMembers(type, acceptor)) {
if (e.getKind() == CONSTRUCTOR) {
ExecutableType et = (ExecutableType) asMemberOf(e, type, types);
results.add(itemFactory.createThisOrSuperConstructorItem(env.getController(), (ExecutableElement) e, et, anchorOffset, elements.isDeprecated(e), name));
}
}
}
private void addEnumConstants(Env env, TypeElement elem) {
Elements elements = env.getController().getElements();
Trees trees = env.getController().getTrees();
TreePath path = env.getPath().getParentPath();
Set<Element> alreadyUsed = new HashSet<>();
List<? extends CaseTree> caseTrees = null;
if (path != null && path.getLeaf().getKind() == Tree.Kind.SWITCH) {
SwitchTree st = (SwitchTree) path.getLeaf();
caseTrees = st.getCases();
} else if (path != null && path.getLeaf().getKind().toString().equals(TreeShims.SWITCH_EXPRESSION)) {
caseTrees = TreeShims.getCases(path.getLeaf());
}
if (caseTrees != null) {
for (CaseTree ct : caseTrees) {
for (ExpressionTree et : TreeShims.getExpressions(ct)) {
Element e = et != null ? trees.getElement(new TreePath(path, et)) : null;
if (e != null && e.getKind() == ENUM_CONSTANT) {
alreadyUsed.add(e);
}
}
}
}
for (Element e : elem.getEnclosedElements()) {
if (e.getKind() == ENUM_CONSTANT && !alreadyUsed.contains(e)) {
String name = e.getSimpleName().toString();
if (startsWith(env, name) && (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(e))) {
results.add(itemFactory.createVariableItem(env.getController(), (VariableElement) e, e.asType(), anchorOffset, null, false, elements.isDeprecated(e), false, env.assignToVarPos()));
}
}
}
}
private void addPackageContent(final Env env, PackageElement pe, EnumSet<ElementKind> kinds, DeclaredType baseType, boolean insideNew, boolean srcOnly) throws IOException {
Set<? extends TypeMirror> smartTypes = options.contains(Options.ALL_COMPLETION) ? null : getSmartTypes(env);
CompilationController controller = env.getController();
Elements elements = controller.getElements();
Types types = controller.getTypes();
Trees trees = controller.getTrees();
ElementUtilities eu = controller.getElementUtilities();
Scope scope = env.getScope();
for (Element e : pe.getEnclosedElements()) {
if (e.getKind().isClass() || e.getKind().isInterface()) {
String name = e.getSimpleName().toString();
if ((env.getExcludes() == null || !env.getExcludes().contains(e))
&& startsWith(env, name) && (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(e))
&& trees.isAccessible(scope, (TypeElement) e)
&& isOfKindAndType(e.asType(), e, kinds, baseType, scope, trees, types)
&& !Utilities.isExcluded(eu.getElementName(e, true))) {
results.add(itemFactory.createTypeItem(env.getController(), (TypeElement) e, (DeclaredType) e.asType(), anchorOffset, null, elements.isDeprecated(e), insideNew, insideNew || env.isInsideClass(), true, isOfSmartType(env, e.asType(), smartTypes), false));
}
}
}
String pkgName = pe.getQualifiedName() + "."; //NOI18N
addPackages(env, pkgName, srcOnly);
}
private void addPackages(Env env, String fqnPrefix, boolean srcOnly) {
if (fqnPrefix == null) {
fqnPrefix = EMPTY;
}
String prefix = env.getPrefix() != null ? fqnPrefix + env.getPrefix() : fqnPrefix;
CompilationController controller = env.getController();
Elements elements = controller.getElements();
Element el = controller.getTrees().getElement(new TreePath(controller.getCompilationUnit()));
ModuleElement moduleElement = el != null ? controller.getElements().getModuleOf(el) : null;
Set<String> seenPkgs = new HashSet<>();
EnumSet<ClassIndex.SearchScope> scope = srcOnly ? EnumSet.of(ClassIndex.SearchScope.SOURCE) : EnumSet.allOf(ClassIndex.SearchScope.class);
for (String pkgName : env.getController().getClasspathInfo().getClassIndex().getPackageNames(fqnPrefix, false, scope)) {
if (startsWith(env, pkgName, prefix) && !Utilities.isExcluded(pkgName + ".")
&& (moduleElement != null ? elements.getPackageElement(moduleElement, pkgName) : elements.getPackageElement(pkgName)) != null) { //NOI18N
if (fqnPrefix != null) {
pkgName = pkgName.substring(fqnPrefix.length());
}
int idx = pkgName.indexOf('.');
if (idx > 0) {
pkgName = pkgName.substring(0, idx);
}
if (seenPkgs.add(pkgName)) {
results.add(itemFactory.createPackageItem(pkgName, anchorOffset, srcOnly));
}
}
}
}
private void addModuleNames(Env env, String fqnPrefix, boolean srcOnly) {
if (fqnPrefix == null) {
fqnPrefix = EMPTY;
}
srcOnly = false;
String prefix = env.getPrefix() != null ? fqnPrefix + env.getPrefix() : fqnPrefix;
for (String name : SourceUtils.getModuleNames(env.getController(), srcOnly ? EnumSet.of(ClassIndex.SearchScope.SOURCE) : EnumSet.allOf(ClassIndex.SearchScope.class))) {
if (startsWith(env, name, prefix) && itemFactory instanceof ModuleItemFactory) {
results.add(((ModuleItemFactory<T>)itemFactory).createModuleItem(name, anchorOffset));
}
}
}
private void addTypes(Env env, EnumSet<ElementKind> kinds, DeclaredType baseType) throws IOException {
if (options.contains(Options.ALL_COMPLETION)) {
if (baseType == null) {
addAllTypes(env, kinds);
} else {
Elements elements = env.getController().getElements();
Set<? extends Element> excludes = env.getExcludes();
for (DeclaredType subtype : getSubtypesOf(env, baseType)) {
TypeElement elem = (TypeElement) subtype.asElement();
if ((excludes == null || !excludes.contains(elem)) && (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(elem)) && !Utilities.isExcluded(elem.getQualifiedName()) && (!env.isAfterExtends() || !elem.getModifiers().contains(Modifier.FINAL))) {
results.add(itemFactory.createTypeItem(env.getController(), elem, subtype, anchorOffset, env.getReferencesCount(), elements.isDeprecated(elem), env.isInsideNew(), env.isInsideNew() || env.isInsideClass(), false, true, false));
}
}
}
} else {
addLocalAndImportedTypes(env, kinds, baseType);
hasAdditionalClasses = true;
}
addPackages(env, null, kinds.isEmpty());
}
private void addLocalAndImportedTypes(final Env env, final EnumSet<ElementKind> kinds, final DeclaredType baseType) throws IOException {
final CompilationController controller = env.getController();
final Trees trees = controller.getTrees();
final Elements elements = controller.getElements();
final Types types = controller.getTypes();
final TreeUtilities tu = controller.getTreeUtilities();
final Scope scope = env.getScope();
final ExecutableElement enclMethod = scope.getEnclosingMethod();
final TypeElement enclClass = scope.getEnclosingClass();
final boolean isStatic = enclClass == null ? false
: (tu.isStaticContext(scope) || (env.getPath().getLeaf().getKind() == Tree.Kind.BLOCK && ((BlockTree) env.getPath().getLeaf()).isStatic()));
ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
if ((env.getExcludes() == null || !env.getExcludes().contains(e)) && (e.getKind().isClass() || e.getKind().isInterface() || e.getKind() == TYPE_PARAMETER) && (!env.isAfterExtends() || containsAccessibleNonFinalType(e, scope, trees))) {
String name = e.getSimpleName().toString();
return name.length() > 0 && !Character.isDigit(name.charAt(0)) && startsWith(env, name)
&& (!isStatic || e.getModifiers().contains(STATIC) || e.getEnclosingElement() == enclMethod)
&& (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(e))
&& (e.getKind() == TYPE_PARAMETER || !Utilities.isExcluded(((TypeElement)e).getQualifiedName()))
&& isOfKindAndType(e.asType(), e, kinds, baseType, scope, trees, types);
}
return false;
}
};
for (Element e : controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor)) {
switch (e.getKind()) {
case CLASS:
case ENUM:
case INTERFACE:
case ANNOTATION_TYPE:
results.add(itemFactory.createTypeItem(env.getController(), (TypeElement) e, (DeclaredType) e.asType(), anchorOffset, null, elements.isDeprecated(e), env.isInsideNew(), env.isInsideNew() || env.isInsideClass(), false, false, false));
env.addToExcludes(e);
break;
case TYPE_PARAMETER:
results.add(itemFactory.createTypeParameterItem((TypeParameterElement) e, anchorOffset));
break;
}
}
acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
if ((e.getKind().isClass() || e.getKind().isInterface())) {
return (env.getExcludes() == null || !env.getExcludes().contains(e)) && startsWith(env, e.getSimpleName().toString())
&& (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(e))
&& !Utilities.isExcluded(((TypeElement)e).getQualifiedName()) && trees.isAccessible(scope, (TypeElement) e)
&& isOfKindAndType(e.asType(), e, kinds, baseType, scope, trees, types) && (!env.isAfterExtends() || containsAccessibleNonFinalType(e, scope, trees));
}
return false;
}
};
for (TypeElement e : controller.getElementUtilities().getGlobalTypes(acceptor)) {
results.add(itemFactory.createTypeItem(env.getController(), e, (DeclaredType) e.asType(), anchorOffset, null, elements.isDeprecated(e), env.isInsideNew(), env.isInsideNew() || env.isInsideClass(), false, false, false));
}
}
private void addAllTypes(Env env, EnumSet<ElementKind> kinds) {
String prefix = env.getPrefix();
CompilationController controller = env.getController();
Set<? extends Element> excludes = env.getExcludes();
Set<ElementHandle<Element>> excludeHandles = null;
if (excludes != null) {
excludeHandles = new HashSet<>(excludes.size());
for (Element el : excludes) {
excludeHandles.add(ElementHandle.create(el));
}
}
if (!kinds.contains(ElementKind.CLASS) && !kinds.contains(ElementKind.INTERFACE)) {
Set<ElementHandle<TypeElement>> declaredTypes = controller.getClasspathInfo().getClassIndex().getDeclaredTypes(EMPTY, ClassIndex.NameKind.PREFIX, EnumSet.allOf(ClassIndex.SearchScope.class));
Map<String, ElementHandle<TypeElement>> removed = new HashMap<>(declaredTypes.size());
Set<String> doNotRemove = new HashSet<>();
for (ElementHandle<TypeElement> name : declaredTypes) {
if (excludeHandles != null && excludeHandles.contains(name) || isAnnonInner(name)) {
continue;
}
if (!kinds.contains(name.getKind()) && !doNotRemove.contains(name.getQualifiedName())) {
removed.put(name.getQualifiedName(), name);
continue;
}
String qName = name.getQualifiedName();
String sName = null;
int idx;
while ((idx = qName.lastIndexOf('.')) > 0) {
if (sName == null) {
sName = qName.substring(idx + 1);
if (sName.length() <= 0 || !startsWith(env, sName, prefix)) {
break;
}
results.add(itemFactory.createTypeItem(name, kinds, anchorOffset, env.getReferencesCount(), controller.getSnapshot().getSource(), env.isInsideNew(), env.isInsideNew() || env.isInsideClass(), env.isAfterExtends()));
}
qName = qName.substring(0, idx);
doNotRemove.add(qName);
ElementHandle<TypeElement> r = removed.remove(qName);
if (r != null) {
results.add(itemFactory.createTypeItem(r, kinds, anchorOffset, env.getReferencesCount(), controller.getSnapshot().getSource(), env.isInsideNew(), env.isInsideNew() || env.isInsideClass(), env.isAfterExtends()));
}
}
}
} else {
String subwordsPattern = null;
if (prefix != null && !env.isCamelCasePrefix() && Utilities.isSubwordSensitive()) {
subwordsPattern = Utilities.createSubwordsPattern(prefix);
}
ClassIndex.NameKind kind = env.isCamelCasePrefix()
? Utilities.isCaseSensitive() ? ClassIndex.NameKind.CAMEL_CASE : ClassIndex.NameKind.CAMEL_CASE_INSENSITIVE
: subwordsPattern != null ? ClassIndex.NameKind.REGEXP
: Utilities.isCaseSensitive() ? ClassIndex.NameKind.PREFIX : ClassIndex.NameKind.CASE_INSENSITIVE_PREFIX;
Set<ElementHandle<TypeElement>> declaredTypes = controller.getClasspathInfo().getClassIndex().getDeclaredTypes(subwordsPattern != null ? subwordsPattern : prefix != null ? prefix : EMPTY, kind, EnumSet.allOf(ClassIndex.SearchScope.class));
results.ensureCapacity(results.size() + declaredTypes.size());
for (ElementHandle<TypeElement> name : declaredTypes) {
if (excludeHandles != null && excludeHandles.contains(name) || isAnnonInner(name)) {
continue;
}
results.add(itemFactory.createTypeItem(name, kinds, anchorOffset, env.getReferencesCount(), controller.getSnapshot().getSource(), env.isInsideNew(), env.isInsideNew() || env.isInsideClass(), env.isAfterExtends()));
}
}
}
private Set<DeclaredType> getSupertypesOf(Env env, DeclaredType type) {
LinkedList<DeclaredType> bases = new LinkedList<>();
bases.add(type);
HashSet<DeclaredType> ret = new HashSet<>();
while (!bases.isEmpty()) {
DeclaredType head = bases.remove();
TypeElement elem = (TypeElement) head.asElement();
if (startsWith(env, elem.getSimpleName().toString())) {
ret.add(head);
}
TypeMirror sup = elem.getSuperclass();
if (sup.getKind() == TypeKind.DECLARED) {
bases.add((DeclaredType) sup);
}
for (TypeMirror iface : elem.getInterfaces()) {
if (iface.getKind() == TypeKind.DECLARED) {
bases.add((DeclaredType) iface);
}
}
}
return ret;
}
private List<DeclaredType> getSubtypesOf(Env env, DeclaredType baseType) throws IOException {
if (((TypeElement) baseType.asElement()).getQualifiedName().contentEquals(JAVA_LANG_OBJECT)) {
return Collections.emptyList();
}
LinkedList<DeclaredType> subtypes = new LinkedList<>();
String prefix = env.getPrefix();
CompilationController controller = env.getController();
Types types = controller.getTypes();
Trees trees = controller.getTrees();
Scope scope = env.getScope();
if (prefix != null && prefix.length() > 2 && baseType.getTypeArguments().isEmpty()) {
String subwordsPattern = null;
if (!env.isCamelCasePrefix() && Utilities.isSubwordSensitive()) {
subwordsPattern = Utilities.createSubwordsPattern(prefix);
}
ClassIndex.NameKind kind = env.isCamelCasePrefix()
? Utilities.isCaseSensitive() ? ClassIndex.NameKind.CAMEL_CASE : ClassIndex.NameKind.CAMEL_CASE_INSENSITIVE
: subwordsPattern != null ? ClassIndex.NameKind.REGEXP
: Utilities.isCaseSensitive() ? ClassIndex.NameKind.PREFIX : ClassIndex.NameKind.CASE_INSENSITIVE_PREFIX;
for (ElementHandle<TypeElement> handle : controller.getClasspathInfo().getClassIndex().getDeclaredTypes(subwordsPattern != null ? subwordsPattern : prefix, kind, EnumSet.allOf(ClassIndex.SearchScope.class))) {
TypeElement te = handle.resolve(controller);
if (te != null && trees.isAccessible(scope, te) && types.isSubtype(types.getDeclaredType(te), baseType)) {
subtypes.add(types.getDeclaredType(te));
}
}
} else {
HashSet<TypeElement> elems = new HashSet<>();
LinkedList<DeclaredType> bases = new LinkedList<>();
bases.add(baseType);
ClassIndex index = controller.getClasspathInfo().getClassIndex();
while (!bases.isEmpty()) {
DeclaredType head = bases.remove();
TypeElement elem = (TypeElement) head.asElement();
if (!elems.add(elem)) {
continue;
}
if (startsWith(env, elem.getSimpleName().toString())) {
subtypes.add(head);
}
List<? extends TypeMirror> tas = head.getTypeArguments();
boolean isRaw = !tas.iterator().hasNext();
subtypes:
for (ElementHandle<TypeElement> eh : index.getElements(ElementHandle.create(elem), EnumSet.of(ClassIndex.SearchKind.IMPLEMENTORS), EnumSet.allOf(ClassIndex.SearchScope.class))) {
TypeElement e = eh.resolve(controller);
if (e != null) {
if (trees.isAccessible(scope, e)) {
if (isRaw) {
DeclaredType dt = types.getDeclaredType(e);
bases.add(dt);
} else {
HashMap<Element, TypeMirror> map = new HashMap<>();
TypeMirror sup = e.getSuperclass();
if (sup.getKind() == TypeKind.DECLARED && ((DeclaredType) sup).asElement() == elem) {
DeclaredType dt = (DeclaredType) sup;
Iterator<? extends TypeMirror> ittas = tas.iterator();
Iterator<? extends TypeMirror> it = dt.getTypeArguments().iterator();
while (it.hasNext() && ittas.hasNext()) {
TypeMirror basetm = ittas.next();
TypeMirror stm = it.next();
if (basetm != stm) {
if (stm.getKind() == TypeKind.TYPEVAR) {
map.put(((TypeVariable) stm).asElement(), basetm);
} else {
continue subtypes;
}
}
}
if (it.hasNext() != ittas.hasNext()) {
continue;
}
} else {
for (TypeMirror tm : e.getInterfaces()) {
if (((DeclaredType) tm).asElement() == elem) {
DeclaredType dt = (DeclaredType) tm;
Iterator<? extends TypeMirror> ittas = tas.iterator();
Iterator<? extends TypeMirror> it = dt.getTypeArguments().iterator();
while (it.hasNext() && ittas.hasNext()) {
TypeMirror basetm = ittas.next();
TypeMirror stm = it.next();
if (basetm != stm) {
if (stm.getKind() == TypeKind.TYPEVAR) {
map.put(((TypeVariable) stm).asElement(), basetm);
} else {
continue subtypes;
}
}
}
if (it.hasNext() != ittas.hasNext()) {
continue subtypes;
}
break;
}
}
}
bases.add(getDeclaredType(e, map, types));
}
}
} else {
Logger.getLogger("global").log(Level.FINE, String.format("Cannot resolve: %s on bootpath: %s classpath: %s sourcepath: %s\n", eh.toString(),
controller.getClasspathInfo().getClassPath(ClasspathInfo.PathKind.BOOT),
controller.getClasspathInfo().getClassPath(ClasspathInfo.PathKind.COMPILE),
controller.getClasspathInfo().getClassPath(ClasspathInfo.PathKind.SOURCE)));
}
}
}
}
return subtypes;
}
@SuppressWarnings("fallthrough")
private void addMethodArguments(Env env, MethodInvocationTree mit) throws IOException {
final CompilationController controller = env.getController();
TreePath path = env.getPath();
CompilationUnitTree root = env.getRoot();
SourcePositions sourcePositions = env.getSourcePositions();
List<Tree> argTypes = getArgumentsUpToPos(env, mit.getArguments(), (int) sourcePositions.getEndPosition(root, mit.getMethodSelect()), env.getOffset(), true);
if (argTypes != null) {
controller.toPhase(Phase.RESOLVED);
TypeMirror[] types = new TypeMirror[argTypes.size()];
int j = 0;
for (Tree t : argTypes) {
types[j++] = controller.getTrees().getTypeMirror(new TreePath(path, t));
}
List<Pair<ExecutableElement, ExecutableType>> methods = null;
String name = null;
Tree mid = mit.getMethodSelect();
path = new TreePath(path, mid);
switch (mid.getKind()) {
case MEMBER_SELECT: {
ExpressionTree exp = ((MemberSelectTree) mid).getExpression();
path = new TreePath(path, exp);
final Trees trees = controller.getTrees();
final TypeMirror type = trees.getTypeMirror(path);
final Element element = trees.getElement(path);
final boolean isStatic = element != null && (element.getKind().isClass() || element.getKind().isInterface() || element.getKind() == TYPE_PARAMETER);
final boolean isSuperCall = element != null && element.getKind().isField() && element.getSimpleName().contentEquals(SUPER_KEYWORD);
final Scope scope = env.getScope();
TypeElement enclClass = scope.getEnclosingClass();
final TypeMirror enclType = enclClass != null ? enclClass.asType() : null;
ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
return (!isStatic || e.getModifiers().contains(STATIC) || e.getKind() == CONSTRUCTOR) && (t.getKind() != TypeKind.DECLARED || trees.isAccessible(scope, e, (DeclaredType) (isSuperCall && enclType != null ? enclType : t)));
}
};
methods = getMatchingExecutables(type, controller.getElementUtilities().getMembers(type, acceptor), ((MemberSelectTree) mid).getIdentifier().toString(), types, controller.getTypes());
break;
}
case IDENTIFIER: {
final Scope scope = env.getScope();
final TreeUtilities tu = controller.getTreeUtilities();
final Trees trees = controller.getTrees();
final TypeElement enclClass = scope.getEnclosingClass();
final boolean isStatic = enclClass != null ? (tu.isStaticContext(scope) || (env.getPath().getLeaf().getKind() == Tree.Kind.BLOCK && ((BlockTree) env.getPath().getLeaf()).isStatic())) : false;
final Map<Name, ? extends Element> illegalForwardRefs = env.getForwardReferences();
final ExecutableElement method = scope.getEnclosingMethod();
ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
switch (simplifyElementKind(e.getKind())) {
case LOCAL_VARIABLE:
case RESOURCE_VARIABLE:
case EXCEPTION_PARAMETER:
case PARAMETER:
return (method == e.getEnclosingElement() || e.getModifiers().contains(FINAL)
|| controller.getSourceVersion().compareTo(SourceVersion.RELEASE_8) >= 0 && controller.getElementUtilities().isEffectivelyFinal((VariableElement)e))
&& (!illegalForwardRefs.containsKey(e.getSimpleName()) || illegalForwardRefs.get(e.getSimpleName()).getEnclosingElement() != e.getEnclosingElement());
case FIELD:
if (illegalForwardRefs.containsValue(e)) {
return false;
}
if (e.getSimpleName().contentEquals(THIS_KEYWORD) || e.getSimpleName().contentEquals(SUPER_KEYWORD)) {
return !isStatic;
}
default:
return (!isStatic || e.getModifiers().contains(STATIC)) && trees.isAccessible(scope, e, (DeclaredType) t);
}
}
};
name = ((IdentifierTree) mid).getName().toString();
if (SUPER_KEYWORD.equals(name) && enclClass != null) {
TypeMirror superclass = enclClass.getSuperclass();
methods = getMatchingExecutables(superclass, controller.getElementUtilities().getMembers(superclass, acceptor), INIT, types, controller.getTypes());
} else if (THIS_KEYWORD.equals(name) && enclClass != null) {
TypeMirror thisclass = enclClass.asType();
methods = getMatchingExecutables(thisclass, controller.getElementUtilities().getMembers(thisclass, acceptor), INIT, types, controller.getTypes());
} else {
methods = getMatchingExecutables(enclClass != null ? enclClass.asType() : null, controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor), name, types, controller.getTypes());
name = null;
}
break;
}
}
if (methods != null) {
Elements elements = controller.getElements();
for (Pair<ExecutableElement, ExecutableType> method : methods) {
if (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(method.first())) {
results.add(itemFactory.createParametersItem(env.getController(), method.first(), method.second(), anchorOffset, elements.isDeprecated(method.first()), types.length, name));
}
}
}
}
}
private void addConstructorArguments(Env env, NewClassTree nct) throws IOException {
CompilationController controller = env.getController();
TreePath path = env.getPath();
CompilationUnitTree root = env.getRoot();
SourcePositions sourcePositions = env.getSourcePositions();
List<Tree> argTypes = getArgumentsUpToPos(env, nct.getArguments(), (int) sourcePositions.getEndPosition(root, nct.getIdentifier()), env.getOffset(), true);
if (argTypes != null) {
controller.toPhase(Phase.RESOLVED);
TypeMirror[] types = new TypeMirror[argTypes.size()];
int j = 0;
for (Tree t : argTypes) {
types[j++] = controller.getTrees().getTypeMirror(new TreePath(path, t));
}
path = new TreePath(path, nct.getIdentifier());
final Trees trees = controller.getTrees();
final TypeMirror type = trees.getTypeMirror(path);
final Element el = trees.getElement(path);
final Scope scope = env.getScope();
final boolean isAnonymous = nct.getClassBody() != null || (el != null && (el.getKind().isInterface() || el.getModifiers().contains(ABSTRACT)));
ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
return e.getKind() == CONSTRUCTOR && (trees.isAccessible(scope, e, (DeclaredType) t) || isAnonymous && e.getModifiers().contains(PROTECTED));
}
};
List<Pair<ExecutableElement, ExecutableType>> ctors = getMatchingExecutables(type, controller.getElementUtilities().getMembers(type, acceptor), INIT, types, controller.getTypes());
Elements elements = controller.getElements();
for (Pair<ExecutableElement, ExecutableType> ctor : ctors) {
if (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(ctor.first())) {
results.add(itemFactory.createParametersItem(env.getController(), ctor.first(), ctor.second(), anchorOffset, elements.isDeprecated(ctor.first()), types.length, null));
}
}
}
}
private void addAttributeValues(Env env, Element element, AnnotationMirror annotation, ExecutableElement member) throws IOException {
CompilationController controller = env.getController();
TreeUtilities tu = controller.getTreeUtilities();
ElementUtilities eu = controller.getElementUtilities();
for (javax.annotation.processing.Completion completion : SourceUtils.getAttributeValueCompletions(controller, element, annotation, member, env.getPrefix())) {
String value = completion.getValue().trim();
if (value.length() > 0 && startsWith(env, value)) {
TypeMirror type = member.getReturnType();
TypeElement typeElement = null;
while (type.getKind() == TypeKind.ARRAY) {
type = ((ArrayType) type).getComponentType();
}
if (type.getKind() == TypeKind.DECLARED) {
CharSequence fqn = ((TypeElement) ((DeclaredType) type).asElement()).getQualifiedName();
if (JAVA_LANG_CLASS.contentEquals(fqn)) {
String name = value.endsWith(".class") ? value.substring(0, value.length() - 6) : value; //NOI18N
TypeMirror tm = tu.parseType(name, eu.outermostTypeElement(element));
typeElement = tm != null && tm.getKind() == TypeKind.DECLARED ? (TypeElement) ((DeclaredType) tm).asElement() : null;
if (typeElement != null && startsWith(env, typeElement.getSimpleName().toString())) {
env.addToExcludes(typeElement);
}
}
}
results.add(itemFactory.createAttributeValueItem(env.getController(), value, completion.getMessage(), typeElement, anchorOffset, env.getReferencesCount()));
}
}
}
private void addKeyword(Env env, String kw, String postfix, boolean smartType) {
if (Utilities.startsWith(kw, env.getPrefix())) {
results.add(itemFactory.createKeywordItem(kw, postfix, anchorOffset, smartType));
}
}
private void addKeywordsForCU(Env env) {
List<String> kws = new ArrayList<>();
int offset = env.getOffset();
String prefix = env.getPrefix();
CompilationUnitTree cu = env.getRoot();
boolean pkgInfo = env.getController().getTreeUtilities().isPackageInfo(cu);
boolean mdlInfo = env.getController().getTreeUtilities().isModuleInfo(cu);
SourcePositions sourcePositions = env.getSourcePositions();
if (!pkgInfo && !mdlInfo) {
kws.add(ABSTRACT_KEYWORD);
kws.add(CLASS_KEYWORD);
kws.add(ENUM_KEYWORD);
kws.add(FINAL_KEYWORD);
kws.add(INTERFACE_KEYWORD);
}
boolean beforeAnyClass = true;
boolean beforePublicClass = true;
for (Tree t : cu.getTypeDecls()) {
if (TreeUtilities.CLASS_TREE_KINDS.contains(t.getKind())) {
int pos = (int) sourcePositions.getEndPosition(cu, t);
if (pos != Diagnostic.NOPOS && offset >= pos) {
beforeAnyClass = false;
if (((ClassTree) t).getModifiers().getFlags().contains(Modifier.PUBLIC)) {
beforePublicClass = false;
break;
}
}
} else if (t.getKind() == Tree.Kind.MODULE) {
int pos = (int) sourcePositions.getEndPosition(cu, t);
if (pos != Diagnostic.NOPOS && offset >= pos) {
beforeAnyClass = false;
}
}
}
if (beforePublicClass && !pkgInfo && !mdlInfo) {
kws.add(PUBLIC_KEYWORD);
}
if (beforeAnyClass) {
if (mdlInfo) {
kws.add(MODULE_KEYWORD);
kws.add(OPEN_KEYWORD);
}
kws.add(IMPORT_KEYWORD);
Tree firstImport = null;
for (Tree t : cu.getImports()) {
firstImport = t;
break;
}
Tree pd = cu.getPackageName();
if (!mdlInfo && ((pd != null && offset <= sourcePositions.getStartPosition(cu, cu))
|| (pd == null && (firstImport == null || sourcePositions.getStartPosition(cu, firstImport) >= offset)))) {
kws.add(PACKAGE_KEYWORD);
}
}
for (String kw : kws) {
if (Utilities.startsWith(kw, prefix)) {
results.add(itemFactory.createKeywordItem(kw, SPACE, anchorOffset, false));
}
}
}
private void addKeywordsForModuleBody(Env env) {
String prefix = env.getPrefix();
for (String kw : MODULE_BODY_KEYWORDS) {
if (Utilities.startsWith(kw, prefix)) {
results.add(itemFactory.createKeywordItem(kw, SPACE, anchorOffset, false));
}
}
}
private void addKeywordsForClassBody(Env env) {
String prefix = env.getPrefix();
for (String kw : CLASS_BODY_KEYWORDS) {
if (Utilities.startsWith(kw, prefix)) {
results.add(itemFactory.createKeywordItem(kw, SPACE, anchorOffset, false));
}
}
if (env.getController().getSourceVersion().compareTo(SourceVersion.RELEASE_8) >= 0
&& Utilities.startsWith(DEFAULT_KEYWORD, prefix)
&& env.getController().getTreeUtilities().getPathElementOfKind(Tree.Kind.INTERFACE, env.getPath()) != null) {
results.add(itemFactory.createKeywordItem(DEFAULT_KEYWORD, SPACE, anchorOffset, false));
}
addPrimitiveTypeKeywords(env);
}
private void addKeywordsForBlock(Env env) {
String prefix = env.getPrefix();
for (String kw : STATEMENT_KEYWORDS) {
if (Utilities.startsWith(kw, prefix)) {
results.add(itemFactory.createKeywordItem(kw, null, anchorOffset, false));
}
}
for (String kw : BLOCK_KEYWORDS) {
if (Utilities.startsWith(kw, prefix)) {
results.add(itemFactory.createKeywordItem(kw, SPACE, anchorOffset, false));
}
}
if (Utilities.startsWith(RETURN_KEYWORD, prefix)) {
TreePath tp = env.getController().getTreeUtilities().getPathElementOfKind(EnumSet.of(Tree.Kind.METHOD, Tree.Kind.LAMBDA_EXPRESSION), env.getPath());
String postfix = SPACE;
if (tp != null) {
if (tp.getLeaf().getKind() == Tree.Kind.METHOD) {
Tree rt = ((MethodTree) tp.getLeaf()).getReturnType();
if (rt == null || (rt.getKind() == Tree.Kind.PRIMITIVE_TYPE && ((PrimitiveTypeTree) rt).getPrimitiveTypeKind() == TypeKind.VOID)) {
postfix = SEMI;
}
} else {
TypeMirror tm = env.getController().getTrees().getTypeMirror(tp);
if (tm != null && tm.getKind() == TypeKind.DECLARED) {
ExecutableType dt = env.getController().getTypeUtilities().getDescriptorType((DeclaredType) tm);
if (dt != null && dt.getReturnType().getKind() == TypeKind.VOID) {
postfix = SEMI;
}
}
}
}
results.add(itemFactory.createKeywordItem(RETURN_KEYWORD, postfix, anchorOffset, false));
}
boolean caseAdded = false;
boolean breakAdded = false;
boolean continueAdded = false;
TreePath tp = env.getPath();
while (tp != null) {
switch (tp.getLeaf().getKind()) {
case SWITCH:
CaseTree lastCase = null;
CompilationUnitTree root = env.getRoot();
SourcePositions sourcePositions = env.getSourcePositions();
for (CaseTree t : ((SwitchTree) tp.getLeaf()).getCases()) {
if (sourcePositions.getStartPosition(root, t) >= env.getOffset()) {
break;
}
lastCase = t;
}
if (!caseAdded && (lastCase == null || lastCase.getExpression() != null)) {
caseAdded = true;
if (Utilities.startsWith(CASE_KEYWORD, prefix)) {
results.add(itemFactory.createKeywordItem(CASE_KEYWORD, SPACE, anchorOffset, false));
}
if (Utilities.startsWith(DEFAULT_KEYWORD, prefix)) {
results.add(itemFactory.createKeywordItem(DEFAULT_KEYWORD, COLON, anchorOffset, false));
}
}
if (!breakAdded && Utilities.startsWith(BREAK_KEYWORD, prefix)) {
breakAdded = true;
results.add(itemFactory.createKeywordItem(BREAK_KEYWORD, withinLabeledStatement(env) ? null : SEMI, anchorOffset, false));
}
break;
case DO_WHILE_LOOP:
case ENHANCED_FOR_LOOP:
case FOR_LOOP:
case WHILE_LOOP:
if (!breakAdded && Utilities.startsWith(BREAK_KEYWORD, prefix)) {
breakAdded = true;
results.add(itemFactory.createKeywordItem(BREAK_KEYWORD, withinLabeledStatement(env) ? null : SEMI, anchorOffset, false));
}
if (!continueAdded && Utilities.startsWith(CONTINUE_KEYWORD, prefix)) {
continueAdded = true;
results.add(itemFactory.createKeywordItem(CONTINUE_KEYWORD, withinLabeledStatement(env) ? null : SEMI, anchorOffset, false));
}
break;
}
tp = tp.getParentPath();
}
if (SOURCE_VERSION_RELEASE_10 != null &&
env.getController().getSourceVersion().compareTo(SOURCE_VERSION_RELEASE_10) >= 0 &&
Utilities.startsWith(VAR_KEYWORD, prefix)) {
results.add(itemFactory.createKeywordItem(VAR_KEYWORD, SPACE, anchorOffset, false));
}
}
@SuppressWarnings("fallthrough")
private void addKeywordsForStatement(Env env) {
String prefix = env.getPrefix();
for (String kw : STATEMENT_KEYWORDS) {
if (Utilities.startsWith(kw, prefix)) {
results.add(itemFactory.createKeywordItem(kw, null, anchorOffset, false));
}
}
for (String kw : STATEMENT_SPACE_KEYWORDS) {
if (Utilities.startsWith(kw, prefix)) {
results.add(itemFactory.createKeywordItem(kw, SPACE, anchorOffset, false));
}
}
if (Utilities.startsWith(RETURN_KEYWORD, prefix)) {
TreePath tp = env.getController().getTreeUtilities().getPathElementOfKind(EnumSet.of(Tree.Kind.METHOD, Tree.Kind.LAMBDA_EXPRESSION), env.getPath());
String postfix = SPACE;
if (tp != null) {
if (tp.getLeaf().getKind() == Tree.Kind.METHOD) {
Tree rt = ((MethodTree) tp.getLeaf()).getReturnType();
if (rt == null || (rt.getKind() == Tree.Kind.PRIMITIVE_TYPE && ((PrimitiveTypeTree) rt).getPrimitiveTypeKind() == TypeKind.VOID)) {
postfix = SEMI;
}
} else {
TypeMirror tm = env.getController().getTrees().getTypeMirror(tp);
if (tm != null && tm.getKind() == TypeKind.DECLARED) {
ExecutableType dt = env.getController().getTypeUtilities().getDescriptorType((DeclaredType) tm);
if (dt != null && dt.getReturnType().getKind() == TypeKind.VOID) {
postfix = SEMI;
}
}
}
}
results.add(itemFactory.createKeywordItem(RETURN_KEYWORD, postfix, anchorOffset, false));
}
TreePath tp = env.getPath();
boolean cAdded = false;
boolean bAdded = false;
while (tp != null && !(cAdded && bAdded)) {
switch (tp.getLeaf().getKind()) {
case DO_WHILE_LOOP:
case ENHANCED_FOR_LOOP:
case FOR_LOOP:
case WHILE_LOOP:
if (!cAdded && Utilities.startsWith(CONTINUE_KEYWORD, prefix)) {
results.add(itemFactory.createKeywordItem(CONTINUE_KEYWORD, SEMI, anchorOffset, false));
cAdded = true;
}
case SWITCH:
if (!bAdded && Utilities.startsWith(BREAK_KEYWORD, prefix)) {
results.add(itemFactory.createKeywordItem(BREAK_KEYWORD, SEMI, anchorOffset, false));
bAdded = true;
}
break;
}
tp = tp.getParentPath();
}
}
private void addValueKeywords(Env env) throws IOException {
String prefix = env.getPrefix();
boolean smartType = false;
if (!options.contains(Options.ALL_COMPLETION)) {
Set<? extends TypeMirror> smartTypes = getSmartTypes(env);
if (smartTypes != null && !smartTypes.isEmpty()) {
for (TypeMirror st : smartTypes) {
if (st.getKind() == TypeKind.BOOLEAN) {
smartType = true;
break;
}
}
}
}
if (Utilities.startsWith(FALSE_KEYWORD, prefix)) {
results.add(itemFactory.createKeywordItem(FALSE_KEYWORD, null, anchorOffset, smartType));
}
if (Utilities.startsWith(TRUE_KEYWORD, prefix)) {
results.add(itemFactory.createKeywordItem(TRUE_KEYWORD, null, anchorOffset, smartType));
}
boolean isVar = env.getPath().getLeaf().getKind() == Tree.Kind.VARIABLE &&
env.getController().getTreeUtilities().isSynthetic(new TreePath(env.getPath(), ((VariableTree) env.getPath().getLeaf()).getType()));
if (Utilities.startsWith(NULL_KEYWORD, prefix) && !isVar) {
results.add(itemFactory.createKeywordItem(NULL_KEYWORD, null, anchorOffset, false));
}
if (Utilities.startsWith(NEW_KEYWORD, prefix)) {
results.add(itemFactory.createKeywordItem(NEW_KEYWORD, SPACE, anchorOffset, false));
}
}
private void addPrimitiveTypeKeywords(Env env) {
String prefix = env.getPrefix();
for (String kw : PRIM_KEYWORDS) {
if (Utilities.startsWith(kw, prefix)) {
results.add(itemFactory.createKeywordItem(kw, null, anchorOffset, false));
}
}
}
private void addClassModifiers(Env env, Set<Modifier> modifiers) {
String prefix = env.getPrefix();
List<String> kws = new ArrayList<>();
if (!modifiers.contains(PUBLIC) && !modifiers.contains(PRIVATE)) {
kws.add(PUBLIC_KEYWORD);
}
if (!modifiers.contains(FINAL) && !modifiers.contains(ABSTRACT)) {
kws.add(ABSTRACT_KEYWORD);
kws.add(FINAL_KEYWORD);
}
kws.add(CLASS_KEYWORD);
kws.add(INTERFACE_KEYWORD);
kws.add(ENUM_KEYWORD);
for (String kw : kws) {
if (Utilities.startsWith(kw, prefix)) {
results.add(itemFactory.createKeywordItem(kw, SPACE, anchorOffset, false));
}
}
}
private void addMemberModifiers(Env env, Set<Modifier> modifiers, boolean isLocal) {
String prefix = env.getPrefix();
List<String> kws = new ArrayList<>();
if (isLocal) {
if (!modifiers.contains(FINAL)) {
kws.add(FINAL_KEYWORD);
}
} else {
if (!modifiers.contains(PUBLIC) && !modifiers.contains(PROTECTED) && !modifiers.contains(PRIVATE)) {
kws.add(PUBLIC_KEYWORD);
kws.add(PROTECTED_KEYWORD);
kws.add(PRIVATE_KEYWORD);
}
if (env.getController().getSourceVersion().compareTo(SourceVersion.RELEASE_8) >= 0
&& env.getController().getTreeUtilities().getPathElementOfKind(Tree.Kind.INTERFACE, env.getPath()) != null
&& !modifiers.contains(STATIC) && !modifiers.contains(ABSTRACT) && !modifiers.contains(DEFAULT)) {
kws.add(DEFAULT_KEYWORD);
}
if (!modifiers.contains(FINAL) && !modifiers.contains(ABSTRACT) && !modifiers.contains(VOLATILE)) {
kws.add(FINAL_KEYWORD);
}
if (!modifiers.contains(FINAL) && !modifiers.contains(ABSTRACT) && !modifiers.contains(DEFAULT)
&& !modifiers.contains(NATIVE) && !modifiers.contains(SYNCHRONIZED)) {
kws.add(ABSTRACT_KEYWORD);
}
if (!modifiers.contains(STATIC) && !modifiers.contains(DEFAULT)) {
kws.add(STATIC_KEYWORD);
}
if (!modifiers.contains(ABSTRACT) && !modifiers.contains(NATIVE)) {
kws.add(NATIVE_KEYWORD);
}
if (!modifiers.contains(STRICTFP)) {
kws.add(STRICT_KEYWORD);
}
if (!modifiers.contains(SYNCHRONIZED) && !modifiers.contains(ABSTRACT)) {
kws.add(SYNCHRONIZED_KEYWORD);
}
if (!modifiers.contains(TRANSIENT)) {
kws.add(TRANSIENT_KEYWORD);
}
if (!modifiers.contains(FINAL) && !modifiers.contains(VOLATILE)) {
kws.add(VOLATILE_KEYWORD);
}
kws.add(VOID_KEYWORD);
kws.add(CLASS_KEYWORD);
kws.add(INTERFACE_KEYWORD);
kws.add(ENUM_KEYWORD);
}
for (String kw : kws) {
if (Utilities.startsWith(kw, prefix)) {
results.add(itemFactory.createKeywordItem(kw, SPACE, anchorOffset, false));
}
}
for (String kw : PRIM_KEYWORDS) {
if (Utilities.startsWith(kw, prefix)) {
results.add(itemFactory.createKeywordItem(kw, SPACE, anchorOffset, false));
}
}
}
private void addElementCreators(Env env) throws IOException {
final CompilationController controller = env.getController();
controller.toPhase(Phase.ELEMENTS_RESOLVED);
final TreeUtilities tu = controller.getTreeUtilities();
final TreePath clsPath = tu.getPathElementOfKind(TreeUtilities.CLASS_TREE_KINDS, env.getPath());
if (clsPath == null) {
return;
}
final ClassTree cls = (ClassTree) clsPath.getLeaf();
final CompilationUnitTree root = env.getRoot();
final SourcePositions sourcePositions = env.getSourcePositions();
Tree currentMember = null;
int nextMemberPos = (int) Diagnostic.NOPOS;
for (Tree member : cls.getMembers()) {
int pos = (int) sourcePositions.getStartPosition(root, member);
if (pos >= caretOffset) {
nextMemberPos = pos;
break;
}
pos = (int) sourcePositions.getEndPosition(root, member);
if (caretOffset < pos) {
currentMember = member;
nextMemberPos = pos;
break;
}
}
if (nextMemberPos > caretOffset) {
String text = controller.getText().substring(caretOffset, nextMemberPos);
int idx = text.indexOf('\n'); // NOI18N
if (idx >= 0) {
text = text.substring(0, idx);
}
if (text.trim().length() > 0) {
return;
}
}
final Trees trees = controller.getTrees();
final ElementUtilities eu = controller.getElementUtilities();
final TypeElement te = (TypeElement) trees.getElement(clsPath);
if (te == null || te.getKind() == ElementKind.ANNOTATION_TYPE) {
return;
}
final String prefix = env.getPrefix();
final Types types = controller.getTypes();
DeclaredType clsType = (DeclaredType) te.asType();
if (te.getKind().isClass() || te.getKind().isInterface() && SourceVersion.RELEASE_8.compareTo(controller.getSourceVersion()) <= 0) {
for (ExecutableElement ee : eu.findUnimplementedMethods(te)) {
if (startsWith(env, ee.getSimpleName().toString())) {
TypeMirror tm = asMemberOf(ee, clsType, types);
if (tm.getKind() == TypeKind.EXECUTABLE) {
results.add(itemFactory.createOverrideMethodItem(env.getController(), ee, (ExecutableType) tm, anchorOffset, true));
}
}
}
}
if (te.getKind().isClass() || te.getKind().isInterface()) {
for (ExecutableElement ee : eu.findOverridableMethods(te)) {
if (startsWith(env, ee.getSimpleName().toString())) {
TypeMirror tm = asMemberOf(ee, clsType, types);
if (tm.getKind() == TypeKind.EXECUTABLE) {
results.add(itemFactory.createOverrideMethodItem(env.getController(), ee, (ExecutableType) tm, anchorOffset, false));
}
}
}
}
if (!te.getKind().isClass()) {
return;
}
if (prefix == null || startsWith(env, "get") || startsWith(env, "set") || startsWith(env, "is")
|| startsWith(env, prefix, "get") || startsWith(env, prefix, "set") || startsWith(env, prefix, "is")) {
CodeStyle codeStyle = CodeStyle.getDefault(controller.getDocument());
for (VariableElement variableElement : ElementFilter.fieldsIn(controller.getElements().getAllMembers(te))) {
Name name = variableElement.getSimpleName();
if (!name.contentEquals(ERROR)) {
boolean isStatic = variableElement.getModifiers().contains(Modifier.STATIC);
String setterName = CodeStyleUtils.computeSetterName(name, isStatic, codeStyle);
String getterName = CodeStyleUtils.computeGetterName(name, variableElement.asType().getKind() == TypeKind.BOOLEAN, isStatic, codeStyle);
if ((prefix == null || startsWith(env, getterName)) && !eu.hasGetter(te, variableElement, codeStyle)) {
results.add(itemFactory.createGetterSetterMethodItem(env.getController(), variableElement, asMemberOf(variableElement, clsType, types), anchorOffset, getterName, false));
}
if ((prefix == null || startsWith(env, setterName)) && !(variableElement.getModifiers().contains(Modifier.FINAL) || eu.hasSetter(te, variableElement, codeStyle))) {
results.add(itemFactory.createGetterSetterMethodItem(env.getController(), variableElement, asMemberOf(variableElement, clsType, types), anchorOffset, setterName, true));
}
}
}
}
if (startsWith(env, te.getSimpleName().toString())) {
final Set<? extends VariableElement> uninitializedFields = tu.getUninitializedFields(clsPath);
final List<ExecutableElement> constructors = ElementFilter.constructorsIn(te.getEnclosedElements());
if (currentMember != null && currentMember.getKind() == Tree.Kind.VARIABLE) {
Element e = trees.getElement(new TreePath(clsPath, currentMember));
if (e.getKind().isField()) {
uninitializedFields.remove((VariableElement) e);
}
}
Element dctor2generate = null;
Map<ExecutableElement, boolean[]> ctors2generate = new LinkedHashMap<>();
final Set<VariableElement> uninitializedFinalFields = new LinkedHashSet<>();
for (VariableElement ve : uninitializedFields) {
if (ve.getModifiers().contains(Modifier.FINAL)) {
uninitializedFinalFields.add(ve);
}
}
int ufSize = uninitializedFields.size();
int uffSize = uninitializedFinalFields.size();
if (cls.getKind() != Tree.Kind.ENUM && te.getSuperclass().getKind() == TypeKind.DECLARED) {
DeclaredType superType = (DeclaredType) te.getSuperclass();
Scope scope = env.getScope();
for (ExecutableElement ctor : ElementFilter.constructorsIn(superType.asElement().getEnclosedElements())) {
if (trees.isAccessible(scope, ctor, superType)) {
if (dctor2generate == null || ((ExecutableElement) dctor2generate).getParameters().size() > ctor.getParameters().size()) {
dctor2generate = ctor;
}
ctors2generate.put(ctor, new boolean[]{uffSize > 0 && uffSize < ufSize, ufSize > 0});
}
}
} else {
dctor2generate = te;
ctors2generate.put(null, new boolean[]{uffSize > 0 && uffSize < ufSize, ufSize > 0});
}
for (ExecutableElement ee : constructors) {
if (!eu.isSynthetic(ee)) {
List<? extends VariableElement> parameters = ee.getParameters();
if (parameters.isEmpty()) {
dctor2generate = null;
}
for (Map.Entry<ExecutableElement, boolean[]> entry : ctors2generate.entrySet()) {
List<? extends VariableElement> params = entry.getKey() != null ? entry.getKey().getParameters() : Collections.<VariableElement>emptyList();
int paramSize = params.size();
if (uffSize > 0 && uffSize < ufSize && parameters.size() == paramSize + uffSize) {
Iterator<? extends VariableElement> proposed = uninitializedFinalFields.iterator();
Iterator<? extends VariableElement> original = parameters.iterator();
boolean same = true;
while (same && proposed.hasNext() && original.hasNext()) {
same &= types.isSameType(proposed.next().asType(), original.next().asType());
}
if (same) {
proposed = params.iterator();
while (same && proposed.hasNext() && original.hasNext()) {
same &= types.isSameType(proposed.next().asType(), original.next().asType());
}
if (same) {
entry.getValue()[0] = false;
}
}
}
if (parameters.size() == paramSize + ufSize) {
Iterator<? extends VariableElement> proposed = uninitializedFields.iterator();
Iterator<? extends VariableElement> original = parameters.iterator();
boolean same = true;
while (same && proposed.hasNext() && original.hasNext()) {
same &= types.isSameType(proposed.next().asType(), original.next().asType());
}
if (same) {
proposed = params.iterator();
while (same && proposed.hasNext() && original.hasNext()) {
same &= types.isSameType(proposed.next().asType(), original.next().asType());
}
if (same) {
entry.getValue()[1] = false;
}
}
}
}
}
}
if (dctor2generate != null) {
results.add(itemFactory.createInitializeAllConstructorItem(env.getController(), true, uninitializedFinalFields, dctor2generate.getKind() == CONSTRUCTOR ? (ExecutableElement) dctor2generate : null, te, anchorOffset));
}
for (Map.Entry<ExecutableElement, boolean[]> entry : ctors2generate.entrySet()) {
if (entry.getValue()[0]) {
results.add(itemFactory.createInitializeAllConstructorItem(env.getController(), false, uninitializedFinalFields, entry.getKey(), te, anchorOffset));
}
if (entry.getValue()[1]) {
results.add(itemFactory.createInitializeAllConstructorItem(env.getController(), false, uninitializedFields, entry.getKey(), te, anchorOffset));
}
}
}
}
private TypeElement getTypeElement(Env env, final String simpleName) throws IOException {
if (simpleName == null || simpleName.length() == 0) {
return null;
}
final CompilationController controller = env.getController();
final TreeUtilities tu = controller.getTreeUtilities();
final Trees trees = controller.getTrees();
final Scope scope = env.getScope();
final TypeElement enclClass = scope.getEnclosingClass();
final boolean isStatic = enclClass == null ? false
: (tu.isStaticContext(scope) || (env.getPath().getLeaf().getKind() == Tree.Kind.BLOCK && ((BlockTree) env.getPath().getLeaf()).isStatic()));
ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
return (e.getKind().isClass() || e.getKind().isInterface())
&& e.getSimpleName().contentEquals(simpleName)
&& (!isStatic || e.getModifiers().contains(STATIC))
&& trees.isAccessible(scope, e, (DeclaredType) t);
}
};
for (Element e : controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor)) {
return (TypeElement) e;
}
acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
return e.getSimpleName().contentEquals(simpleName)
&& trees.isAccessible(scope, (TypeElement) e);
}
};
for (TypeElement e : controller.getElementUtilities().getGlobalTypes(acceptor)) {
if (simpleName.contentEquals(e.getSimpleName())) {
return e;
}
}
return null;
}
@SuppressWarnings("fallthrough")
private VariableElement getFieldOrVar(Env env, final String simpleName) throws IOException {
if (simpleName == null || simpleName.length() == 0) {
return null;
}
final CompilationController controller = env.getController();
final Scope scope = env.getScope();
final TypeElement enclClass = scope.getEnclosingClass();
final boolean isStatic = enclClass == null ? false
: (controller.getTreeUtilities().isStaticContext(scope) || (env.getPath().getLeaf().getKind() == Tree.Kind.BLOCK && ((BlockTree) env.getPath().getLeaf()).isStatic()));
final Map<Name, ? extends Element> illegalForwardRefs = env.getForwardReferences();
final ExecutableElement method = scope.getEnclosingMethod();
ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
if (!e.getSimpleName().contentEquals(simpleName)) {
return false;
}
switch (simplifyElementKind(e.getKind())) {
case LOCAL_VARIABLE:
case RESOURCE_VARIABLE:
if (isStatic && (e.getSimpleName().contentEquals(THIS_KEYWORD) || e.getSimpleName().contentEquals(SUPER_KEYWORD))) {
return false;
}
case EXCEPTION_PARAMETER:
case PARAMETER:
return (method == e.getEnclosingElement() || e.getModifiers().contains(FINAL)
|| controller.getSourceVersion().compareTo(SourceVersion.RELEASE_8) >= 0 && controller.getElementUtilities().isEffectivelyFinal((VariableElement)e))
&& (!illegalForwardRefs.containsKey(e.getSimpleName()) || illegalForwardRefs.get(e.getSimpleName()).getEnclosingElement() != e.getEnclosingElement());
case FIELD:
if (e.getSimpleName().contentEquals(THIS_KEYWORD) || e.getSimpleName().contentEquals(SUPER_KEYWORD)) {
return !isStatic;
}
case ENUM_CONSTANT:
return !illegalForwardRefs.containsValue(e);
}
return false;
}
};
for (Element e : controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor)) {
return (VariableElement) e;
}
return null;
}
private TypeMirror getCorrectedReturnType(Env env, ExecutableType et, ExecutableElement el, TypeMirror site) {
TypeMirror type = et.getReturnType();
if (site != null && site.getKind() == TypeKind.DECLARED) {
if ("getClass".contentEquals(el.getSimpleName()) && et.getParameterTypes().isEmpty() //NOI18N
&& type.getKind() == TypeKind.DECLARED
&& JAVA_LANG_CLASS.contentEquals(((TypeElement) ((DeclaredType) type).asElement()).getQualifiedName())
&& ((TypeElement) ((DeclaredType) type).asElement()).getTypeParameters().size() == 1) {
Types types = env.getController().getTypes();
type = types.getDeclaredType((TypeElement) ((DeclaredType) type).asElement(), types.getWildcardType(site, null));
}
}
return type;
}
private boolean isOfSmartType(Env env, TypeMirror type, Set<? extends TypeMirror> smartTypes) {
if (smartTypes == null || smartTypes.isEmpty()) {
return false;
}
if (env.isInsideForEachExpression()) {
if (type.getKind() == TypeKind.ARRAY) {
type = ((ArrayType) type).getComponentType();
} else if (type.getKind() == TypeKind.DECLARED) {
Elements elements = env.getController().getElements();
Types types = env.getController().getTypes();
TypeElement iterableTE = elements.getTypeElement(JAVA_LANG_ITERABLE); //NOI18N
DeclaredType iterable = iterableTE != null ? types.getDeclaredType(iterableTE) : null;
if (iterable != null && types.isSubtype(type, iterable)) {
Iterator<? extends TypeMirror> it = ((DeclaredType) type).getTypeArguments().iterator();
type = it.hasNext() ? it.next() : elements.getTypeElement(JAVA_LANG_OBJECT).asType(); //NOI18N
} else {
return false;
}
} else {
return false;
}
} else if (type.getKind() == TypeKind.EXECUTABLE) {
Types types = env.getController().getTypes();
TypeUtilities tu = env.getController().getTypeUtilities();
for (TypeMirror smartType : smartTypes) {
if (smartType.getKind() == TypeKind.DECLARED) {
ExecutableType descriptorType = tu.getDescriptorType((DeclaredType) smartType);
if (descriptorType != null && types.isSubsignature((ExecutableType) type, descriptorType)
&& types.isSubtype(((ExecutableType) type).getReturnType(), descriptorType.getReturnType())) {
return true;
}
}
}
return false;
}
for (TypeMirror smartType : smartTypes) {
if (type.getKind() == TypeKind.DECLARED){
smartType = inferDeclaredType(env.getController().getTypes(), (DeclaredType) type, smartType);
}
if (SourceUtils.checkTypesAssignable(env.getController(), type, smartType)) {
return true;
}
}
return false;
}
private boolean isTopLevelClass(Tree tree, CompilationUnitTree root) {
if (TreeUtilities.CLASS_TREE_KINDS.contains(tree.getKind()) || (tree.getKind() == Tree.Kind.EXPRESSION_STATEMENT && ((ExpressionStatementTree) tree).getExpression().getKind() == Tree.Kind.ERRONEOUS)) {
for (Tree t : root.getTypeDecls()) {
if (tree == t) {
return true;
}
}
}
return tree.getKind() == Kind.COMPILATION_UNIT;
}
private static boolean isAnnonInner(ElementHandle<TypeElement> elem) {
String name = elem.getQualifiedName();
int idx = name.lastIndexOf('.'); //NOI18N
String simpleName = idx > -1 ? name.substring(idx + 1) : name;
return simpleName.length() == 0 || Character.isDigit(simpleName.charAt(0));
}
private boolean isOfKindAndType(TypeMirror type, Element e, EnumSet<ElementKind> kinds, TypeMirror base, Scope scope, Trees trees, Types types) {
if (type.getKind() != TypeKind.ERROR && kinds.contains(e.getKind())) {
if (base == null) {
return true;
}
if (types.isSubtype(type, base)) {
return true;
}
}
if ((e.getKind().isClass() || e.getKind().isInterface())
&& (kinds.contains(ANNOTATION_TYPE) || kinds.contains(CLASS) || kinds.contains(ENUM) || kinds.contains(INTERFACE))) {
DeclaredType dt = (DeclaredType) e.asType();
for (Element ee : e.getEnclosedElements()) {
if (trees.isAccessible(scope, ee, dt) && isOfKindAndType(ee.asType(), ee, kinds, base, scope, trees, types)) {
return true;
}
}
}
return false;
}
private boolean containsAccessibleNonFinalType(Element e, Scope scope, Trees trees) {
if (e.getKind().isClass() || e.getKind().isInterface()) {
if (!e.getModifiers().contains(Modifier.FINAL)) {
return true;
}
DeclaredType dt = (DeclaredType) e.asType();
for (Element ee : e.getEnclosedElements()) {
if (trees.isAccessible(scope, ee, dt) && containsAccessibleNonFinalType(ee, scope, trees)) {
return true;
}
}
}
return false;
}
private Set<? extends TypeMirror> getSmartTypes(Env env) throws IOException {
Set<? extends TypeMirror> smartTypes = env.getSmartTypes();
if (smartTypes == null) {
CompilationController controller = env.getController();
controller.toPhase(JavaSource.Phase.RESOLVED);
smartTypes = getSmartTypesImpl(env);
if (smartTypes != null) {
Iterator<? extends TypeMirror> it = smartTypes.iterator();
TypeMirror err = null;
if (it.hasNext()) {
err = it.next();
if (it.hasNext() || err.getKind() != TypeKind.ERROR) {
err = null;
}
}
if (err != null) {
HashSet<TypeMirror> st = new HashSet<>();
Types types = controller.getTypes();
TypeElement te = (TypeElement) ((DeclaredType) err).asElement();
if (te.getQualifiedName() == te.getSimpleName()) {
ClassIndex ci = controller.getClasspathInfo().getClassIndex();
for (ElementHandle<TypeElement> eh : ci.getDeclaredTypes(te.getSimpleName().toString(), ClassIndex.NameKind.SIMPLE_NAME, EnumSet.allOf(ClassIndex.SearchScope.class))) {
te = eh.resolve(controller);
if (te != null) {
st.add(types.erasure(te.asType()));
}
}
}
smartTypes = st;
}
}
env.setSmartTypes(smartTypes);
}
return smartTypes;
}
@SuppressWarnings("fallthrough")
private Set<? extends TypeMirror> getSmartTypesImpl(Env env) throws IOException {
int offset = env.getOffset();
final CompilationController controller = env.getController();
TreeUtilities tu = controller.getTreeUtilities();
TreePath path = tu.pathFor(offset);
Tree lastTree = null;
int dim = 0;
while (path != null) {
Tree tree = path.getLeaf();
switch (tree.getKind()) {
case VARIABLE:
TypeMirror type = controller.getTrees().getTypeMirror(path);
if (type == null) {
return null;
}
while (dim-- > 0) {
if (type.getKind() == TypeKind.ARRAY) {
type = ((ArrayType) type).getComponentType();
} else {
return null;
}
}
return type != null ? Collections.singleton(type) : null;
case ASSIGNMENT:
type = controller.getTrees().getTypeMirror(new TreePath(path, ((AssignmentTree) tree).getVariable()));
if (type == null) {
return null;
}
TreePath parentPath = path.getParentPath();
if (parentPath != null && parentPath.getLeaf().getKind() == Tree.Kind.ANNOTATION && type.getKind() == TypeKind.EXECUTABLE) {
type = ((ExecutableType) type).getReturnType();
while (dim-- > 0) {
if (type.getKind() == TypeKind.ARRAY) {
type = ((ArrayType) type).getComponentType();
} else {
return null;
}
}
if (type.getKind() == TypeKind.ARRAY) {
type = ((ArrayType) type).getComponentType();
}
}
return type != null ? Collections.singleton(type) : null;
case RETURN:
TreePath methodOrLambdaPath = tu.getPathElementOfKind(EnumSet.of(Tree.Kind.METHOD, Tree.Kind.LAMBDA_EXPRESSION), path);
if (methodOrLambdaPath == null) {
return null;
}
if (methodOrLambdaPath.getLeaf().getKind() == Tree.Kind.METHOD) {
Tree retTree = ((MethodTree) methodOrLambdaPath.getLeaf()).getReturnType();
if (retTree == null) {
return null;
}
type = controller.getTrees().getTypeMirror(new TreePath(methodOrLambdaPath, retTree));
if (type == null && JavaSource.Phase.RESOLVED.compareTo(controller.getPhase()) > 0) {
controller.toPhase(Phase.RESOLVED);
type = controller.getTrees().getTypeMirror(new TreePath(methodOrLambdaPath, retTree));
}
return type != null ? Collections.singleton(type) : null;
} else {
type = controller.getTrees().getTypeMirror(methodOrLambdaPath);
if (type != null && type.getKind() == TypeKind.DECLARED) {
ExecutableType descType = controller.getTypeUtilities().getDescriptorType((DeclaredType) type);
if (descType != null) {
return Collections.singleton(descType.getReturnType());
}
}
}
break;
case THROW:
TreePath methodPath = tu.getPathElementOfKind(Tree.Kind.METHOD, path);
if (methodPath == null) {
return null;
}
HashSet<TypeMirror> ret = new HashSet<>();
Trees trees = controller.getTrees();
for (ExpressionTree thr : ((MethodTree) methodPath.getLeaf()).getThrows()) {
type = trees.getTypeMirror(new TreePath(methodPath, thr));
if (type == null && JavaSource.Phase.RESOLVED.compareTo(controller.getPhase()) > 0) {
controller.toPhase(Phase.RESOLVED);
type = trees.getTypeMirror(new TreePath(methodPath, thr));
}
if (type != null) {
ret.add(type);
}
}
return ret;
case TRY:
TryTree tt = (TryTree) tree;
BlockTree tryBlock = tt.getBlock();
SourcePositions sourcePositions = env.getSourcePositions();
if (tryBlock != null && sourcePositions.getStartPosition(env.getRoot(), tryBlock) <= offset) {
return null;
}
TypeElement te = controller.getElements().getTypeElement("java.lang.AutoCloseable"); //NOI18N
return te != null ? Collections.singleton(controller.getTypes().getDeclaredType(te)) : null;
case IF:
IfTree iff = (IfTree) tree;
return iff.getCondition() == lastTree ? Collections.<TypeMirror>singleton(controller.getTypes().getPrimitiveType(TypeKind.BOOLEAN)) : null;
case WHILE_LOOP:
WhileLoopTree wl = (WhileLoopTree) tree;
return wl.getCondition() == lastTree ? Collections.<TypeMirror>singleton(controller.getTypes().getPrimitiveType(TypeKind.BOOLEAN)) : null;
case DO_WHILE_LOOP:
DoWhileLoopTree dwl = (DoWhileLoopTree) tree;
return dwl.getCondition() == lastTree ? Collections.<TypeMirror>singleton(controller.getTypes().getPrimitiveType(TypeKind.BOOLEAN)) : null;
case FOR_LOOP:
ForLoopTree fl = (ForLoopTree) tree;
Tree cond = fl.getCondition();
if (lastTree != null) {
if (cond instanceof ErroneousTree) {
Iterator<? extends Tree> itt = ((ErroneousTree) cond).getErrorTrees().iterator();
if (itt.hasNext()) {
cond = itt.next();
}
}
return cond == lastTree ? Collections.<TypeMirror>singleton(controller.getTypes().getPrimitiveType(TypeKind.BOOLEAN)) : null;
}
sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
if (cond != null && sourcePositions.getEndPosition(root, cond) < offset) {
return null;
}
Tree lastInit = null;
for (Tree init : fl.getInitializer()) {
if (sourcePositions.getEndPosition(root, init) >= offset) {
return null;
}
lastInit = init;
}
String text;
if (lastInit == null) {
text = controller.getText().substring((int) sourcePositions.getStartPosition(root, fl), offset).trim();
int idx = text.indexOf('('); //NOI18N
if (idx >= 0) {
text = text.substring(idx + 1);
}
} else {
text = controller.getText().substring((int) sourcePositions.getEndPosition(root, lastInit), offset).trim();
}
return ";".equals(text) ? Collections.<TypeMirror>singleton(controller.getTypes().getPrimitiveType(TypeKind.BOOLEAN)) : null; //NOI18N
case ENHANCED_FOR_LOOP:
EnhancedForLoopTree efl = (EnhancedForLoopTree) tree;
Tree expr = efl.getExpression();
if (lastTree != null) {
if (expr instanceof ErroneousTree) {
Iterator<? extends Tree> itt = ((ErroneousTree) expr).getErrorTrees().iterator();
if (itt.hasNext()) {
expr = itt.next();
}
}
if (expr != lastTree) {
return null;
}
} else {
sourcePositions = env.getSourcePositions();
root = env.getRoot();
if (efl.getVariable() == null || sourcePositions.getEndPosition(root, efl.getVariable()) > offset) {
text = controller.getText().substring((int) sourcePositions.getStartPosition(root, efl), offset).trim();
int idx = text.indexOf('('); //NOI18N
if (idx >= 0) {
text = text.substring(idx + 1);
}
} else {
text = controller.getText().substring((int) sourcePositions.getEndPosition(root, efl.getVariable()), offset).trim();
}
if (!":".equals(text)) {
return null;
}
}
TypeMirror var = efl.getVariable() != null ? controller.getTrees().getTypeMirror(new TreePath(path, efl.getVariable())) : null;
return var != null ? Collections.singleton(var) : null;
case SWITCH:
SwitchTree sw = (SwitchTree) tree;
if (sw.getExpression() != lastTree && sw.getExpression().getKind() != Tree.Kind.ERRONEOUS) {
return null;
}
ret = new HashSet<>();
Types types = controller.getTypes();
ret.add(controller.getTypes().getPrimitiveType(TypeKind.INT));
te = controller.getElements().getTypeElement("java.lang.Enum"); //NOI18N
if (te != null) {
ret.add(types.getDeclaredType(te));
}
if (controller.getSourceVersion().compareTo(SourceVersion.RELEASE_7) >= 0) {
te = controller.getElements().getTypeElement("java.lang.String"); //NOI18N
if (te != null) {
ret.add(types.getDeclaredType(te));
}
}
return ret;
case METHOD_INVOCATION:
MethodInvocationTree mi = (MethodInvocationTree) tree;
sourcePositions = env.getSourcePositions();
root = env.getRoot();
List<Tree> argTypes = getArgumentsUpToPos(env, mi.getArguments(), (int) sourcePositions.getEndPosition(root, mi.getMethodSelect()), lastTree != null ? (int) sourcePositions.getStartPosition(root, lastTree) : offset, true);
if (argTypes != null) {
TypeMirror[] args = new TypeMirror[argTypes.size()];
int j = 0;
for (Tree t : argTypes) {
args[j++] = controller.getTrees().getTypeMirror(new TreePath(path, t));
}
TypeMirror[] targs = null;
if (!mi.getTypeArguments().isEmpty()) {
targs = new TypeMirror[mi.getTypeArguments().size()];
j = 0;
for (Tree t : mi.getTypeArguments()) {
TypeMirror ta = controller.getTrees().getTypeMirror(new TreePath(path, t));
if (ta == null) {
return null;
}
targs[j++] = ta;
}
}
Tree mid = mi.getMethodSelect();
path = new TreePath(path, mid);
TypeMirror typeMirror = controller.getTrees().getTypeMirror(path);
final ExecutableType midTM = typeMirror != null && typeMirror.getKind() == TypeKind.EXECUTABLE ? (ExecutableType) typeMirror : null;
final ExecutableElement midEl = midTM == null ? null : (ExecutableElement) controller.getTrees().getElement(path);
switch (mid.getKind()) {
case MEMBER_SELECT: {
String name = ((MemberSelectTree) mid).getIdentifier().toString();
ExpressionTree exp = ((MemberSelectTree) mid).getExpression();
path = new TreePath(path, exp);
final TypeMirror tm = controller.getTrees().getTypeMirror(path);
final Element el = controller.getTrees().getElement(path);
final Trees trs = controller.getTrees();
if (el != null && tm.getKind() == TypeKind.DECLARED) {
final boolean isStatic = el.getKind().isClass() || el.getKind().isInterface() || el.getKind() == TYPE_PARAMETER;
final boolean isSuperCall = el.getKind().isField() && el.getSimpleName().contentEquals(SUPER_KEYWORD);
final Scope scope = env.getScope();
TypeElement enclClass = scope.getEnclosingClass();
final TypeMirror enclType = enclClass != null ? enclClass.asType() : null;
ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
return e.getKind() == METHOD && (!isStatic || e.getModifiers().contains(STATIC)) && trs.isAccessible(scope, e, (DeclaredType) (isSuperCall && enclType != null ? enclType : t));
}
};
return getMatchingArgumentTypes(tm, controller.getElementUtilities().getMembers(tm, acceptor), name, args, targs, midEl, midTM, controller.getTypes(), controller.getTypeUtilities());
}
return null;
}
case IDENTIFIER: {
String name = ((IdentifierTree) mid).getName().toString();
final Scope scope = env.getScope();
final Trees trs = controller.getTrees();
final TypeElement enclClass = scope.getEnclosingClass();
final boolean isStatic = enclClass != null ? (tu.isStaticContext(scope) || (env.getPath().getLeaf().getKind() == Tree.Kind.BLOCK && ((BlockTree) env.getPath().getLeaf()).isStatic())) : false;
if (SUPER_KEYWORD.equals(name) && enclClass != null) {
ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
return e.getKind() == CONSTRUCTOR && trs.isAccessible(scope, e, (DeclaredType) t);
}
};
TypeMirror superclass = enclClass.getSuperclass();
return getMatchingArgumentTypes(superclass, controller.getElementUtilities().getMembers(superclass, acceptor), INIT, args, targs, midEl, midTM, controller.getTypes(), controller.getTypeUtilities());
}
ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
return e.getKind() == METHOD && (!isStatic || e.getModifiers().contains(STATIC)) && trs.isAccessible(scope, e, (DeclaredType) t);
}
};
return getMatchingArgumentTypes(enclClass != null ? enclClass.asType() : null, controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor), THIS_KEYWORD.equals(name) ? INIT : name, args, targs, midEl, midTM, controller.getTypes(), controller.getTypeUtilities());
}
}
}
break;
case NEW_CLASS:
NewClassTree nc = (NewClassTree) tree;
sourcePositions = env.getSourcePositions();
root = env.getRoot();
int idEndPos = (int) sourcePositions.getEndPosition(root, nc.getIdentifier());
if (idEndPos < 0) {
idEndPos = (int) sourcePositions.getStartPosition(root, nc);
}
if (idEndPos < 0 || idEndPos >= offset || controller.getText().substring(idEndPos, offset).indexOf('(') < 0) {
break;
}
argTypes = getArgumentsUpToPos(env, nc.getArguments(), idEndPos, lastTree != null ? (int) sourcePositions.getStartPosition(root, lastTree) : offset, true);
if (argTypes != null) {
trees = controller.getTrees();
TypeMirror[] args = new TypeMirror[argTypes.size()];
int j = 0;
for (Tree t : argTypes) {
args[j++] = trees.getTypeMirror(new TreePath(path, t));
}
TypeMirror[] targs = null;
if (!nc.getTypeArguments().isEmpty()) {
targs = new TypeMirror[nc.getTypeArguments().size()];
j = 0;
for (Tree t : nc.getTypeArguments()) {
TypeMirror ta = trees.getTypeMirror(new TreePath(path, t));
if (ta == null) {
return null;
}
targs[j++] = ta;
}
}
Element elem = controller.getTrees().getElement(path);
ExecutableElement ncElem = elem != null && elem.getKind() == CONSTRUCTOR ? (ExecutableElement) elem : null;
TypeMirror ncTM = ncElem != null ? ncElem.asType() : null;
ExecutableType ncType = ncTM != null && ncTM.getKind() == TypeKind.EXECUTABLE ? (ExecutableType) ncTM : null;
Tree mid = nc.getIdentifier();
path = new TreePath(path, mid);
TypeMirror tm = trees.getTypeMirror(path);
if (tm != null && tm.getKind() == TypeKind.ERROR && path.getLeaf().getKind() == Tree.Kind.PARAMETERIZED_TYPE) {
path = new TreePath(path, ((ParameterizedTypeTree) path.getLeaf()).getType());
tm = trees.getTypeMirror(path);
}
final Element el = controller.getTrees().getElement(path);
final Trees trs = controller.getTrees();
if (el != null && tm.getKind() == TypeKind.DECLARED) {
final Scope scope = env.getScope();
final boolean isAnonymous = nc.getClassBody() != null || el.getKind().isInterface() || el.getModifiers().contains(ABSTRACT);
ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
@Override
public boolean accept(Element e, TypeMirror t) {
return e.getKind() == CONSTRUCTOR && (trs.isAccessible(scope, e, (DeclaredType) t) || isAnonymous && e.getModifiers().contains(PROTECTED));
}
};
return getMatchingArgumentTypes(tm, controller.getElementUtilities().getMembers(tm, acceptor), INIT, args, targs, ncElem, ncType, controller.getTypes(), controller.getTypeUtilities());
}
return null;
}
break;
case NEW_ARRAY:
NewArrayTree nat = (NewArrayTree) tree;
Tree arrayType = nat.getType();
if (arrayType == null) {
dim++;
break;
}
sourcePositions = env.getSourcePositions();
root = env.getRoot();
int typeEndPos = (int) sourcePositions.getEndPosition(root, arrayType);
if (typeEndPos > offset) {
break;
}
text = controller.getText().substring(typeEndPos, offset);
if (text.indexOf('{') >= 0) {
type = controller.getTrees().getTypeMirror(new TreePath(path, arrayType));
while (dim-- > 0) {
if (type.getKind() == TypeKind.ARRAY) {
type = ((ArrayType) type).getComponentType();
} else {
return null;
}
}
return type != null ? Collections.singleton(type) : null;
}
if (text.trim().endsWith("[")) //NOI18N
{
return Collections.singleton(controller.getTypes().getPrimitiveType(TypeKind.INT));
}
return null;
case LAMBDA_EXPRESSION:
LambdaExpressionTree let = (LambdaExpressionTree) tree;
int pos = (int) env.getSourcePositions().getStartPosition(env.getRoot(), let.getBody());
if (offset <= pos && findLastNonWhitespaceToken(env, tree, offset).token().id() != JavaTokenId.ARROW
|| lastTree != null && lastTree.getKind() == Tree.Kind.BLOCK) {
break;
}
type = controller.getTrees().getTypeMirror(path);
if (type != null && type.getKind() == TypeKind.DECLARED) {
ExecutableType descType = controller.getTypeUtilities().getDescriptorType((DeclaredType) type);
if (descType != null) {
return Collections.singleton(descType.getReturnType());
}
}
break;
case CASE:
CaseTree ct = (CaseTree) tree;
ExpressionTree exp = ct.getExpression();
if (exp != null && env.getSourcePositions().getEndPosition(env.getRoot(), exp) >= offset) {
parentPath = path.getParentPath();
if (parentPath.getLeaf().getKind() == Tree.Kind.SWITCH) {
exp = ((SwitchTree) parentPath.getLeaf()).getExpression();
type = controller.getTrees().getTypeMirror(new TreePath(parentPath, exp));
return type != null ? Collections.singleton(type) : null;
}
}
return null;
case ANNOTATION:
AnnotationTree ann = (AnnotationTree) tree;
pos = (int) env.getSourcePositions().getStartPosition(env.getRoot(), ann.getAnnotationType());
if (offset <= pos) {
break;
}
pos = (int) env.getSourcePositions().getEndPosition(env.getRoot(), ann.getAnnotationType());
if (offset < pos) {
break;
}
text = controller.getText().substring(pos, offset).trim();
if ("(".equals(text) || text.endsWith("{") || text.endsWith(",")) { //NOI18N
TypeElement el = (TypeElement) controller.getTrees().getElement(new TreePath(path, ann.getAnnotationType()));
if (el != null) {
for (Element ee : el.getEnclosedElements()) {
if (ee.getKind() == METHOD && "value".contentEquals(ee.getSimpleName())) {
type = ((ExecutableElement) ee).getReturnType();
while (dim-- > 0) {
if (type.getKind() == TypeKind.ARRAY) {
type = ((ArrayType) type).getComponentType();
} else {
return null;
}
}
if (type.getKind() == TypeKind.ARRAY) {
type = ((ArrayType) type).getComponentType();
}
return type != null ? Collections.singleton(type) : null;
}
}
}
}
return null;
case REMAINDER_ASSIGNMENT:
case AND_ASSIGNMENT:
case XOR_ASSIGNMENT:
case OR_ASSIGNMENT:
case LEFT_SHIFT_ASSIGNMENT:
case RIGHT_SHIFT_ASSIGNMENT:
case UNSIGNED_RIGHT_SHIFT_ASSIGNMENT:
CompoundAssignmentTree cat = (CompoundAssignmentTree) tree;
pos = (int) env.getSourcePositions().getEndPosition(env.getRoot(), cat.getVariable());
if (offset <= pos) {
break;
}
ret = new HashSet<>();
types = controller.getTypes();
ret.add(types.getPrimitiveType(TypeKind.BYTE));
ret.add(types.getPrimitiveType(TypeKind.CHAR));
ret.add(types.getPrimitiveType(TypeKind.INT));
ret.add(types.getPrimitiveType(TypeKind.LONG));
ret.add(types.getPrimitiveType(TypeKind.SHORT));
return ret;
case LEFT_SHIFT:
case RIGHT_SHIFT:
case UNSIGNED_RIGHT_SHIFT:
case AND:
case OR:
case XOR:
case REMAINDER:
BinaryTree bt = (BinaryTree) tree;
pos = (int) env.getSourcePositions().getEndPosition(env.getRoot(), bt.getLeftOperand());
if (offset <= pos) {
break;
}
case BITWISE_COMPLEMENT:
ret = new HashSet<>();
types = controller.getTypes();
ret.add(types.getPrimitiveType(TypeKind.BYTE));
ret.add(types.getPrimitiveType(TypeKind.CHAR));
ret.add(types.getPrimitiveType(TypeKind.INT));
ret.add(types.getPrimitiveType(TypeKind.LONG));
ret.add(types.getPrimitiveType(TypeKind.SHORT));
return ret;
case CONDITIONAL_AND:
case CONDITIONAL_OR:
bt = (BinaryTree) tree;
pos = (int) env.getSourcePositions().getEndPosition(env.getRoot(), bt.getLeftOperand());
if (offset <= pos) {
break;
}
case LOGICAL_COMPLEMENT:
return Collections.singleton(controller.getTypes().getPrimitiveType(TypeKind.BOOLEAN));
case PLUS:
case EQUAL_TO:
case NOT_EQUAL_TO:
bt = (BinaryTree) tree;
pos = (int) env.getSourcePositions().getEndPosition(env.getRoot(), bt.getLeftOperand());
if (offset <= pos) {
break;
}
TypeMirror tm = controller.getTrees().getTypeMirror(new TreePath(path, bt.getLeftOperand()));
if (tm == null) {
return null;
}
if (tm.getKind().isPrimitive()) {
ret = new HashSet<>();
types = controller.getTypes();
ret.add(types.getPrimitiveType(TypeKind.BYTE));
ret.add(types.getPrimitiveType(TypeKind.CHAR));
ret.add(types.getPrimitiveType(TypeKind.DOUBLE));
ret.add(types.getPrimitiveType(TypeKind.FLOAT));
ret.add(types.getPrimitiveType(TypeKind.INT));
ret.add(types.getPrimitiveType(TypeKind.LONG));
ret.add(types.getPrimitiveType(TypeKind.SHORT));
return ret;
}
return Collections.singleton(tm);
case PLUS_ASSIGNMENT:
cat = (CompoundAssignmentTree) tree;
pos = (int) env.getSourcePositions().getEndPosition(env.getRoot(), cat.getVariable());
if (offset <= pos) {
break;
}
tm = controller.getTrees().getTypeMirror(new TreePath(path, cat.getVariable()));
if (tm == null) {
return null;
}
if (tm.getKind().isPrimitive()) {
ret = new HashSet<>();
types = controller.getTypes();
ret.add(types.getPrimitiveType(TypeKind.BYTE));
ret.add(types.getPrimitiveType(TypeKind.CHAR));
ret.add(types.getPrimitiveType(TypeKind.DOUBLE));
ret.add(types.getPrimitiveType(TypeKind.FLOAT));
ret.add(types.getPrimitiveType(TypeKind.INT));
ret.add(types.getPrimitiveType(TypeKind.LONG));
ret.add(types.getPrimitiveType(TypeKind.SHORT));
return ret;
}
return Collections.singleton(tm);
case MULTIPLY_ASSIGNMENT:
case DIVIDE_ASSIGNMENT:
case MINUS_ASSIGNMENT:
cat = (CompoundAssignmentTree) tree;
pos = (int) env.getSourcePositions().getEndPosition(env.getRoot(), cat.getVariable());
if (offset <= pos) {
break;
}
ret = new HashSet<>();
types = controller.getTypes();
ret.add(types.getPrimitiveType(TypeKind.BYTE));
ret.add(types.getPrimitiveType(TypeKind.CHAR));
ret.add(types.getPrimitiveType(TypeKind.DOUBLE));
ret.add(types.getPrimitiveType(TypeKind.FLOAT));
ret.add(types.getPrimitiveType(TypeKind.INT));
ret.add(types.getPrimitiveType(TypeKind.LONG));
ret.add(types.getPrimitiveType(TypeKind.SHORT));
return ret;
case DIVIDE:
case GREATER_THAN:
case GREATER_THAN_EQUAL:
case LESS_THAN:
case LESS_THAN_EQUAL:
case MINUS:
case MULTIPLY:
bt = (BinaryTree) tree;
pos = (int) env.getSourcePositions().getEndPosition(env.getRoot(), bt.getLeftOperand());
if (offset <= pos) {
break;
}
case PREFIX_INCREMENT:
case PREFIX_DECREMENT:
case UNARY_PLUS:
case UNARY_MINUS:
ret = new HashSet<>();
types = controller.getTypes();
ret.add(types.getPrimitiveType(TypeKind.BYTE));
ret.add(types.getPrimitiveType(TypeKind.CHAR));
ret.add(types.getPrimitiveType(TypeKind.DOUBLE));
ret.add(types.getPrimitiveType(TypeKind.FLOAT));
ret.add(types.getPrimitiveType(TypeKind.INT));
ret.add(types.getPrimitiveType(TypeKind.LONG));
ret.add(types.getPrimitiveType(TypeKind.SHORT));
return ret;
case EXPRESSION_STATEMENT:
exp = ((ExpressionStatementTree) tree).getExpression();
if (exp.getKind() == Tree.Kind.PARENTHESIZED) {
text = controller.getText().substring((int) env.getSourcePositions().getStartPosition(env.getRoot(), exp), offset).trim();
if (text.endsWith(")")) //NOI18N
{
return null;
}
}
break;
case BLOCK:
return null;
}
lastTree = tree;
path = path.getParentPath();
}
return null;
}
private List<Pair<ExecutableElement, ExecutableType>> getMatchingExecutables(TypeMirror type, Iterable<? extends Element> elements, String name, TypeMirror[] argTypes, Types types) {
List<Pair<ExecutableElement, ExecutableType>> ret = new ArrayList<>();
for (Element e : elements) {
if ((e.getKind() == CONSTRUCTOR || e.getKind() == METHOD) && name.contentEquals(e.getSimpleName())) {
List<? extends VariableElement> params = ((ExecutableElement) e).getParameters();
int parSize = params.size();
boolean varArgs = ((ExecutableElement) e).isVarArgs();
if (!varArgs && (parSize < argTypes.length)) {
continue;
}
ExecutableType eType = (ExecutableType) asMemberOf(e, type, types);
if (parSize == 0) {
ret.add(Pair.of((ExecutableElement) e, eType));
} else {
Iterator<? extends TypeMirror> parIt = eType.getParameterTypes().iterator();
TypeMirror param = null;
for (int i = 0; i <= argTypes.length; i++) {
if (parIt.hasNext()) {
param = parIt.next();
if (!parIt.hasNext() && param.getKind() == TypeKind.ARRAY) {
param = ((ArrayType) param).getComponentType();
}
} else if (!varArgs) {
break;
}
if (i == argTypes.length) {
ret.add(Pair.of((ExecutableElement) e, eType));
break;
}
if (argTypes[i] == null || !types.isAssignable(argTypes[i], param)) {
break;
}
}
}
}
}
return ret;
}
private Set<TypeMirror> getMatchingArgumentTypes(TypeMirror type, Iterable<? extends Element> elements, String name, TypeMirror[] argTypes, TypeMirror[] typeArgTypes, ExecutableElement prototypeSym, ExecutableType prototype, Types types, TypeUtilities tu) {
Set<TypeMirror> ret = new HashSet<>();
List<TypeMirror> tatList = typeArgTypes != null ? Arrays.asList(typeArgTypes) : null;
for (Element e : elements) {
if ((e.getKind() == CONSTRUCTOR || e.getKind() == METHOD) && name.contentEquals(e.getSimpleName())) {
List<? extends VariableElement> params = ((ExecutableElement) e).getParameters();
int parSize = params.size();
boolean varArgs = ((ExecutableElement) e).isVarArgs();
if (!varArgs && (parSize <= argTypes.length)) {
continue;
}
ExecutableType meth = e == prototypeSym && prototype != null ? prototype : (ExecutableType) asMemberOf(e, type, types);
Iterator<? extends TypeMirror> parIt = meth.getParameterTypes().iterator();
TypeMirror param = null;
Map<TypeVariable, TypeMirror> table = new HashMap<>();
for (int i = 0; i <= argTypes.length; i++) {
if (parIt.hasNext()) {
param = parIt.next();
} else if (!varArgs) {
break;
}
if (tatList != null && param.getKind() == TypeKind.DECLARED && tatList.size() == meth.getTypeVariables().size()) {
param = tu.substitute(param, meth.getTypeVariables(), tatList);
}
if (i == argTypes.length) {
TypeMirror toAdd = null;
if (i < parSize) {
toAdd = param;
}
if (varArgs && !parIt.hasNext() && param.getKind() == TypeKind.ARRAY) {
toAdd = ((ArrayType) param).getComponentType();
}
while (toAdd != null && toAdd.getKind() == TypeKind.TYPEVAR) {
toAdd = ((TypeVariable) toAdd).getUpperBound();
}
if (toAdd != null && ret.add(toAdd)) {
TypeMirror toRemove = null;
for (TypeMirror tm : ret) {
if (tm != toAdd) {
TypeMirror tmErasure = types.erasure(tm);
TypeMirror toAddErasure = types.erasure(toAdd);
if (types.isSubtype(toAddErasure, tmErasure)) {
toRemove = toAdd;
break;
} else if (types.isSubtype(tmErasure, toAddErasure)) {
toRemove = tm;
break;
}
}
}
if (toRemove != null && !toRemove.getKind().isPrimitive()
&& !"java.lang.String".equals(toRemove.toString()) && !"char[]".equals(toRemove.toString())) //NOI18N
{
ret.remove(toRemove);
}
}
break;
}
if (argTypes[i] == null) {
break;
}
if (varArgs && !parIt.hasNext() && param.getKind() == TypeKind.ARRAY) {
if (types.isAssignable(argTypes[i], param)) {
varArgs = false;
} else if (argTypes[i].getKind() != TypeKind.ERROR && !types.isAssignable(argTypes[i], ((ArrayType) param).getComponentType())) {
break;
}
} else if (argTypes[i].getKind() != TypeKind.ERROR && !types.isAssignable(argTypes[i], param)) {
if (tatList == null && param.getKind() == TypeKind.DECLARED && argTypes[i].getKind() == TypeKind.DECLARED
&& types.isAssignable(types.erasure(argTypes[i]), types.erasure(param))) {
Iterator<? extends TypeMirror> argTypeTAs = ((DeclaredType) argTypes[i]).getTypeArguments().iterator();
for (Iterator<? extends TypeMirror> it = ((DeclaredType) param).getTypeArguments().iterator(); it.hasNext();) {
TypeMirror paramTA = it.next();
if (argTypeTAs.hasNext() && paramTA.getKind() == TypeKind.TYPEVAR) {
table.put((TypeVariable) paramTA, argTypeTAs.next());
} else {
break;
}
}
if (table.size() == meth.getTypeVariables().size()) {
tatList = new ArrayList<>(meth.getTypeVariables().size());
for (TypeVariable tv : meth.getTypeVariables()) {
tatList.add(table.get(tv));
}
}
continue;
}
break;
}
}
}
}
return ret.isEmpty() ? null : ret;
}
private TypeMirror adjustType(Env env, TypeMirror original, Element element, TreePath path) {
if (element instanceof VariableElement && !element.getKind().isField() && itemFactory instanceof TypeCastableItemFactory) {
final Trees trees = env.getController().getTrees();
final Types types = env.getController().getTypes();
final TypeUtilities tu = env.getController().getTypeUtilities();
Tree last = null;
while (path != null) {
if (path.getLeaf().getKind() == Tree.Kind.IF) {
IfTree ifTree = (IfTree) path.getLeaf();
if (ifTree.getThenStatement() == last) {
Tree cond = ifTree.getCondition();
while (cond.getKind() == Tree.Kind.PARENTHESIZED) {
cond = ((ParenthesizedTree)cond).getExpression();
}
if (cond.getKind() == Tree.Kind.INSTANCE_OF) {
InstanceOfTree instTree = (InstanceOfTree) cond;
if (element == trees.getElement(new TreePath(path, instTree.getExpression()))) {
TypeMirror tm = trees.getTypeMirror(new TreePath(path, instTree.getType()));
if (tm != null && tu.isCastable(original, tm)) {
Boolean used = new ErrorAwareTreePathScanner<Boolean, Element>() {
@Override
public Boolean reduce(Boolean r1, Boolean r2) {
return r1 == Boolean.TRUE ? r1 : r2;
}
@Override
public Boolean visitAssignment(AssignmentTree tree, Element e) {
return e == trees.getElement(new TreePath(getCurrentPath(), tree.getVariable()))
? Boolean.TRUE : super.visitAssignment(tree, e);
}
@Override
public Boolean visitCompoundAssignment(CompoundAssignmentTree tree, Element e) {
return e == trees.getElement(new TreePath(getCurrentPath(), tree.getVariable()))
? Boolean.TRUE : super.visitCompoundAssignment(tree, e);
}
}.scan(new TreePath(path, ifTree.getThenStatement()), element);
if (used != Boolean.TRUE) {
if (original.getKind() == TypeKind.DECLARED) {
return inferDeclaredType(types, (DeclaredType)original, tm);
}
return tm;
}
}
}
}
}
}
last = path.getLeaf();
path = path.getParentPath();
}
}
return original;
}
private TypeMirror inferDeclaredType(Types types, DeclaredType original, TypeMirror type) {
if (type != null && type.getKind() == TypeKind.DECLARED) {
Element el = ((DeclaredType)type).asElement();
if (el.getKind().isClass() || el.getKind().isInterface()) {
List<? extends TypeParameterElement> typeParams = ((TypeElement)el).getTypeParameters();
if (!typeParams.isEmpty() && !original.getTypeArguments().isEmpty()) {
for (TypeMirror typeArgument : ((DeclaredType)type).getTypeArguments()) {
if (typeArgument.getKind() == TypeKind.WILDCARD) {
typeArgument = ((WildcardType)typeArgument).getExtendsBound();
}
if (typeArgument == null || typeArgument.getKind() != TypeKind.TYPEVAR) {
return type;
}
}
if (el == original.asElement()) {
return original;
}
Map<Element, TypeMirror> map = new HashMap<>();
TypeMirror sup = ((TypeElement)el).getSuperclass();
TypeMirror infSup = inferDeclaredType(types, original, sup);
if (sup != infSup) {
Iterator<? extends TypeMirror> supTP = ((DeclaredType)sup).getTypeArguments().iterator();
Iterator<? extends TypeMirror> infTP = ((DeclaredType)infSup).getTypeArguments().iterator();
while (supTP.hasNext() && infTP.hasNext()) {
final TypeMirror next = supTP.next();
if (next.getKind() == TypeKind.TYPEVAR) {
map.put(((TypeVariable)next).asElement(), infTP.next());
}
}
assert !supTP.hasNext() && !infTP.hasNext();
}
for (TypeMirror iface : ((TypeElement)el).getInterfaces()) {
TypeMirror infIface = inferDeclaredType(types, original, iface);
if (iface != infIface) {
Iterator<? extends TypeMirror> ifaceTP = ((DeclaredType)iface).getTypeArguments().iterator();
Iterator<? extends TypeMirror> infTP = ((DeclaredType)infIface).getTypeArguments().iterator();
while (ifaceTP.hasNext() && infTP.hasNext()) {
final TypeMirror next = ifaceTP.next();
if (next.getKind() == TypeKind.TYPEVAR) {
map.put(((TypeVariable)next).asElement(), infTP.next());
}
}
assert !ifaceTP.hasNext() && !infTP.hasNext();
}
}
TypeMirror[] targs = new TypeMirror[typeParams.size()];
int i = 0;
for (TypeParameterElement typeParam : typeParams) {
TypeMirror val = map.get(typeParam);
targs[i++] = val != null ? val : typeParam.getBounds().get(0);
}
return types.getDeclaredType((TypeElement)el, targs);
}
}
}
return type;
}
private boolean withinScope(Env env, TypeElement e) throws IOException {
for (Element encl = env.getScope().getEnclosingClass(); encl != null; encl = encl.getEnclosingElement()) {
if (e == encl) {
return true;
}
}
return false;
}
private boolean withinLabeledStatement(Env env) {
TreePath path = env.getPath();
while (path != null) {
if (path.getLeaf().getKind() == Tree.Kind.LABELED_STATEMENT) {
return true;
}
path = path.getParentPath();
}
return false;
}
private boolean withinModuleName(Env env) {
TreePath path = env.getPath();
Tree last = null;
while (path != null) {
Tree tree = path.getLeaf();
if (last != null
&& (tree.getKind() == Tree.Kind.EXPORTS && ((ExportsTree)tree).getModuleNames() != null && ((ExportsTree)tree).getModuleNames().contains(last)
|| tree.getKind() == Tree.Kind.REQUIRES && ((RequiresTree)tree).getModuleName() == last)) {
return true;
}
path = path.getParentPath();
last = tree;
}
return false;
}
private boolean withinProvidesService(Env env) {
TreePath path = env.getPath();
Tree last = null;
while (path != null) {
Tree tree = path.getLeaf();
if (last != null && tree.getKind() == Tree.Kind.PROVIDES && ((ProvidesTree)tree).getServiceName() == last) {
return true;
}
path = path.getParentPath();
last = tree;
}
return false;
}
private boolean hasAccessibleInnerClassConstructor(Element e, Scope scope, Trees trees) {
DeclaredType dt = (DeclaredType) e.asType();
for (TypeElement inner : ElementFilter.typesIn(e.getEnclosedElements())) {
if (trees.isAccessible(scope, inner, dt)) {
DeclaredType innerType = (DeclaredType) inner.asType();
for (ExecutableElement ctor : ElementFilter.constructorsIn(inner.getEnclosedElements())) {
if (trees.isAccessible(scope, ctor, innerType)) {
return true;
}
}
}
}
return false;
}
private boolean conflictsWithLocal(Name name, TypeElement enclClass, Iterable<? extends Element> locals) {
for (ExecutableElement local : ElementFilter.methodsIn(locals)) {
if (local.getEnclosingElement() == enclClass && name.contentEquals(local.getSimpleName())) {
return true;
}
}
return false;
}
private String fullName(Tree tree) {
switch (tree.getKind()) {
case IDENTIFIER:
return ((IdentifierTree) tree).getName().toString();
case MEMBER_SELECT:
String sname = fullName(((MemberSelectTree) tree).getExpression());
return sname == null ? null : sname + '.' + ((MemberSelectTree) tree).getIdentifier();
default:
return null;
}
}
private DeclaredType getDeclaredType(TypeElement e, HashMap<? extends Element, ? extends TypeMirror> map, Types types) {
List<? extends TypeParameterElement> tpes = e.getTypeParameters();
TypeMirror[] targs = new TypeMirror[tpes.size()];
int i = 0;
for (Iterator<? extends TypeParameterElement> it = tpes.iterator(); it.hasNext();) {
TypeParameterElement tpe = it.next();
TypeMirror t = map.get(tpe);
targs[i++] = t != null ? t : tpe.asType();
}
Element encl = e.getEnclosingElement();
if ((encl.getKind().isClass() || encl.getKind().isInterface()) && !((TypeElement) encl).getTypeParameters().isEmpty()) {
return types.getDeclaredType(getDeclaredType((TypeElement) encl, map, types), e, targs);
}
return types.getDeclaredType(e, targs);
}
private boolean startsWith(Env env, String theString) {
String prefix = env.getPrefix();
return startsWith(env, theString, prefix);
}
private boolean startsWith(Env env, String theString, String prefix) {
return env.isCamelCasePrefix() ? Utilities.isCaseSensitive()
? Utilities.startsWithCamelCase(theString, prefix)
: Utilities.startsWithCamelCase(theString, prefix) || Utilities.startsWith(theString, prefix)
: Utilities.startsWith(theString, prefix);
}
private boolean withinBounds(Env env, TypeMirror type, List<? extends TypeMirror> bounds) {
if (bounds != null) {
Types types = env.getController().getTypes();
for (TypeMirror bound : bounds) {
if (!types.isSubtype(type, bound)) {
return false;
}
}
}
return true;
}
private void addVarTypeForLambdaParam(final Env env) throws IOException {
if (SOURCE_VERSION_RELEASE_11 == null || env.getController().getSourceVersion().compareTo(SOURCE_VERSION_RELEASE_11) < 0) {
return;
}
results.add(itemFactory.createKeywordItem(VAR_KEYWORD, SPACE, anchorOffset, false));
}
/**
*
* @param env : env
* @param tree : Lambda expression tree
* @return true if first param of lambda expr is of 'var' type
*/
private boolean isLambdaVarType(Env env, Tree tree) {
if (tree.getKind() != Tree.Kind.LAMBDA_EXPRESSION) {
return false;
}
LambdaExpressionTree let = (LambdaExpressionTree) tree;
if (let.getParameters().isEmpty()) {
return false;
}
boolean isFirstParamVarType = false;
VariableTree firstParamTree = let.getParameters().get(0);
int firstParamStartPos = (int) env.getSourcePositions().getStartPosition(env.getRoot(), firstParamTree);
TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, let, env.getOffset());
ts.move(firstParamStartPos);
ts.movePrevious();
//TreeUtilities.isVarType() API can't be used as FirstParamTree might not be complete.
while (ts.token().id() != JavaTokenId.COMMA && !isFirstParamVarType && ts.moveNext()) {
isFirstParamVarType = ts.token().id() == JavaTokenId.VAR;
}
return isFirstParamVarType;
}
private static ElementKind simplifyElementKind(ElementKind kind) {
if (TreeShims.BINDING_VARIABLE.equals(kind.name())) {
return ElementKind.LOCAL_VARIABLE;
}
return kind;
}
}