| /* |
| * 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.refactoring.java.plugins; |
| |
| import com.sun.source.tree.Tree.Kind; |
| import com.sun.source.tree.*; |
| import com.sun.source.util.SourcePositions; |
| import com.sun.source.util.TreePath; |
| import com.sun.tools.javac.code.Flags; |
| import com.sun.tools.javac.tree.JCTree; |
| import java.io.IOException; |
| import java.util.*; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| import javax.lang.model.SourceVersion; |
| import javax.lang.model.element.Element; |
| import javax.lang.model.element.ElementKind; |
| import javax.lang.model.element.ExecutableElement; |
| import javax.lang.model.element.Modifier; |
| import javax.lang.model.element.TypeElement; |
| import javax.lang.model.element.VariableElement; |
| import javax.lang.model.type.*; |
| import javax.lang.model.util.Types; |
| import org.netbeans.api.java.classpath.ClassPath; |
| import org.netbeans.api.java.classpath.JavaClassPathConstants; |
| import org.netbeans.api.java.source.ClasspathInfo.PathKind; |
| import org.netbeans.api.java.source.*; |
| import org.netbeans.modules.refactoring.api.Problem; |
| import org.netbeans.modules.refactoring.java.RefactoringUtils; |
| import org.netbeans.modules.refactoring.java.api.JavaRefactoringUtils; |
| import org.openide.filesystems.FileObject; |
| import org.openide.filesystems.FileUtil; |
| import org.openide.util.Exceptions; |
| import org.openide.util.NbBundle; |
| |
| /** |
| * Utility class for java plugins. |
| */ |
| public final class JavaPluginUtils { |
| private static final Logger LOG = Logger.getLogger(JavaPluginUtils.class.getName()); |
| |
| public static Problem isSourceElement(Element el, CompilationInfo info) { |
| if (el == null) { |
| // XXX: shouldn't we create a problem ? How ? |
| return null; |
| } |
| Problem preCheckProblem; |
| Element typeElement; |
| if(el.getKind() != ElementKind.PACKAGE) { |
| typeElement = info.getElementUtilities().enclosingTypeElement(el); |
| if(typeElement == null) { |
| typeElement = el; |
| } |
| } else { |
| typeElement = el; |
| } |
| ElementHandle<Element> handle = null; |
| try { |
| handle = ElementHandle.create(typeElement); |
| } catch (IllegalArgumentException ex) { |
| LOG.log(Level.WARNING, "Cannot create handle for source element", ex); |
| } |
| if (handle == null || JavaRefactoringUtils.isFromLibrary(handle, info.getClasspathInfo())) { //NOI18N |
| preCheckProblem = new Problem(true, NbBundle.getMessage( |
| JavaPluginUtils.class, "ERR_CannotRefactorLibraryClass", |
| el.getKind()==ElementKind.PACKAGE?el:el.getEnclosingElement() |
| )); |
| return preCheckProblem; |
| } |
| FileObject file = SourceUtils.getFile(handle, info.getClasspathInfo()); |
| // RefactoringUtils.isFromLibrary already checked file for null |
| if (!RefactoringUtils.isFileInOpenProject(file)) { |
| preCheckProblem =new Problem(true, NbBundle.getMessage( |
| JavaPluginUtils.class, |
| "ERR_ProjectNotOpened", |
| FileUtil.getFileDisplayName(file))); |
| return preCheckProblem; |
| } |
| return null; |
| } |
| |
| public static Problem isSourceFile(FileObject fo, CompilationInfo info) { |
| Problem preCheckProblem; |
| if (fo == null || FileUtil.getArchiveFile(fo) != null) { //NOI18N |
| preCheckProblem = new Problem(true, NbBundle.getMessage( |
| JavaPluginUtils.class, "ERR_CannotRefactorLibraryClass", |
| FileUtil.getFileDisplayName(fo) |
| )); |
| return preCheckProblem; |
| } |
| // RefactoringUtils.isFromLibrary already checked file for null |
| if (!RefactoringUtils.isFileInOpenProject(fo)) { |
| preCheckProblem =new Problem(true, NbBundle.getMessage( |
| JavaPluginUtils.class, |
| "ERR_ProjectNotOpened", |
| FileUtil.getFileDisplayName(fo))); |
| return preCheckProblem; |
| } |
| return null; |
| } |
| |
| public static TreePath findMethod(TreePath path) { |
| while (path != null) { |
| if (path.getLeaf().getKind() == Kind.METHOD) { |
| return path; |
| } |
| |
| if (path.getLeaf().getKind() == Kind.BLOCK |
| && path.getParentPath() != null |
| && TreeUtilities.CLASS_TREE_KINDS.contains(path.getParentPath().getLeaf().getKind())) { |
| //initializer: |
| return path; |
| } |
| |
| path = path.getParentPath(); |
| } |
| |
| return null; |
| } |
| |
| public static TreePath findStatement(TreePath statementPath) { |
| while (statementPath != null |
| && (!StatementTree.class.isAssignableFrom(statementPath.getLeaf().getKind().asInterface()) |
| || (statementPath.getParentPath() != null |
| && statementPath.getParentPath().getLeaf().getKind() != Kind.BLOCK))) { |
| if (TreeUtilities.CLASS_TREE_KINDS.contains(statementPath.getLeaf().getKind())) { |
| return null; |
| } |
| |
| statementPath = statementPath.getParentPath(); |
| } |
| |
| return statementPath; |
| } |
| |
| public static boolean isParentOf(TreePath parent, TreePath path) { |
| Tree parentLeaf = parent.getLeaf(); |
| |
| while (path != null && path.getLeaf() != parentLeaf) { |
| path = path.getParentPath(); |
| } |
| |
| return path != null; |
| } |
| |
| public static boolean isParentOf(TreePath parent, List<? extends TreePath> candidates) { |
| for (TreePath tp : candidates) { |
| if (!isParentOf(parent, tp)) { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| public static Problem chainProblems(Problem result, Problem problem) { |
| if (result == null) { |
| return problem; |
| } |
| if (problem == null) { |
| return result; |
| } |
| Problem value; |
| if(problem.isFatal()) { |
| problem.setNext(result); |
| value = problem; |
| } else { |
| Problem next = value = result; |
| while (next.getNext() != null) { |
| next = next.getNext(); |
| } |
| next.setNext(problem); |
| } |
| return value; |
| } |
| |
| /** |
| * Convert typemirror of an anonymous class to supertype/iface |
| * |
| * @return typemirror of supertype/iface, initial tm if not anonymous |
| */ |
| public static TypeMirror convertIfAnonymous(TypeMirror tm) { |
| //anonymous class? |
| Set<ElementKind> fm = EnumSet.of(ElementKind.METHOD, ElementKind.FIELD); |
| if (tm instanceof DeclaredType) { |
| Element el = ((DeclaredType) tm).asElement(); |
| //XXX: the null check is needed for lambda type, not covered by test: |
| if (el != null && (el.getSimpleName().length() == 0 || fm.contains(el.getEnclosingElement().getKind()))) { |
| List<? extends TypeMirror> interfaces = ((TypeElement) el).getInterfaces(); |
| if (interfaces.isEmpty()) { |
| tm = ((TypeElement) el).getSuperclass(); |
| } else { |
| tm = interfaces.get(0); |
| } |
| } |
| } |
| return tm; |
| } |
| |
| public static TypeMirror resolveCapturedType(CompilationInfo info, TypeMirror tm) { |
| TypeMirror type = resolveCapturedTypeInt(info, tm); |
| |
| if (type.getKind() == TypeKind.WILDCARD) { |
| TypeMirror tmirr = ((WildcardType) type).getExtendsBound(); |
| if (tmirr != null) { |
| return tmirr; |
| } |
| else { //no extends, just '?' |
| return info.getElements().getTypeElement("java.lang.Object").asType(); // NOI18N |
| } |
| |
| } |
| |
| return type; |
| } |
| |
| private static TypeMirror resolveCapturedTypeInt(CompilationInfo info, TypeMirror tm) { |
| TypeMirror orig = SourceUtils.resolveCapturedType(tm); |
| |
| if (orig != null) { |
| if (orig.getKind() == TypeKind.WILDCARD) { |
| TypeMirror extendsBound = ((WildcardType) orig).getExtendsBound(); |
| TypeMirror rct = SourceUtils.resolveCapturedType(extendsBound != null ? extendsBound : ((WildcardType) orig).getSuperBound()); |
| if (rct != null) { |
| return rct; |
| } |
| } |
| return orig; |
| } |
| |
| if (tm.getKind() == TypeKind.DECLARED) { |
| DeclaredType dt = (DeclaredType) tm; |
| List<TypeMirror> typeArguments = new LinkedList<TypeMirror>(); |
| |
| for (TypeMirror t : dt.getTypeArguments()) { |
| typeArguments.add(resolveCapturedTypeInt(info, t)); |
| } |
| |
| final TypeMirror enclosingType = dt.getEnclosingType(); |
| if (enclosingType.getKind() == TypeKind.DECLARED) { |
| return info.getTypes().getDeclaredType((DeclaredType) enclosingType, (TypeElement) dt.asElement(), typeArguments.toArray(new TypeMirror[0])); |
| } else { |
| return info.getTypes().getDeclaredType((TypeElement) dt.asElement(), typeArguments.toArray(new TypeMirror[0])); |
| } |
| } |
| |
| if (tm.getKind() == TypeKind.ARRAY) { |
| ArrayType at = (ArrayType) tm; |
| |
| return info.getTypes().getArrayType(resolveCapturedTypeInt(info, at.getComponentType())); |
| } |
| |
| return tm; |
| } |
| |
| public static JavaSource createSource(final FileObject file, final ClasspathInfo cpInfo, final TreePathHandle tph) throws IllegalArgumentException { |
| JavaSource source; |
| if (file != null) { |
| final ClassPath mergedPlatformPath = RefactoringUtils.merge(cpInfo.getClassPath(PathKind.BOOT), ClassPath.getClassPath(file, ClassPath.BOOT)); |
| final ClassPath mergedModulePlatformPath = RefactoringUtils.merge(cpInfo.getClassPath(PathKind.MODULE_BOOT), ClassPath.getClassPath(file, JavaClassPathConstants.MODULE_BOOT_PATH)); |
| final ClassPath mergedCompilePath = RefactoringUtils.merge(cpInfo.getClassPath(PathKind.COMPILE), ClassPath.getClassPath(file, ClassPath.COMPILE)); |
| final ClassPath mergedModuleCompilePath = RefactoringUtils.merge(cpInfo.getClassPath(PathKind.MODULE_COMPILE), ClassPath.getClassPath(file, JavaClassPathConstants.MODULE_COMPILE_PATH)); |
| final ClassPath mergedModuleClassPath = RefactoringUtils.merge(cpInfo.getClassPath(PathKind.MODULE_CLASS), ClassPath.getClassPath(file, JavaClassPathConstants.MODULE_CLASS_PATH)); |
| final ClassPath mergedSourcePath = RefactoringUtils.merge(cpInfo.getClassPath(PathKind.SOURCE), ClassPath.getClassPath(file, ClassPath.SOURCE)); |
| final ClasspathInfo mergedInfo = new ClasspathInfo.Builder(mergedPlatformPath) |
| .setModuleBootPath(mergedModulePlatformPath) |
| .setClassPath(mergedCompilePath) |
| .setModuleCompilePath(mergedModuleCompilePath) |
| .setModuleClassPath(mergedModuleClassPath) |
| .setSourcePath(mergedSourcePath) |
| .build(); |
| source = JavaSource.create(mergedInfo, new FileObject[]{tph.getFileObject()}); |
| } else { |
| source = JavaSource.create(cpInfo); |
| } |
| return source; |
| } |
| |
| public static boolean hasGetter(CompilationInfo info, TypeElement typeElement, VariableElement field, Map<String, List<ExecutableElement>> methods, CodeStyle cs) { |
| CharSequence name = field.getSimpleName(); |
| assert name.length() > 0; |
| TypeMirror type = field.asType(); |
| boolean isStatic = field.getModifiers().contains(Modifier.STATIC); |
| String getterName = CodeStyleUtils.computeGetterName(name, type.getKind() == TypeKind.BOOLEAN, isStatic, cs); |
| Types types = info.getTypes(); |
| List<ExecutableElement> candidates = methods.get(getterName); |
| if (candidates != null) { |
| for (ExecutableElement candidate : candidates) { |
| if ((!candidate.getModifiers().contains(Modifier.ABSTRACT) || candidate.getEnclosingElement() == typeElement) |
| && candidate.getParameters().isEmpty() |
| && types.isSameType(candidate.getReturnType(), type)) |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| public static boolean hasSetter(CompilationInfo info, TypeElement typeElement, VariableElement field, Map<String, List<ExecutableElement>> methods, CodeStyle cs) { |
| CharSequence name = field.getSimpleName(); |
| assert name.length() > 0; |
| TypeMirror type = field.asType(); |
| boolean isStatic = field.getModifiers().contains(Modifier.STATIC); |
| String setterName = CodeStyleUtils.computeSetterName(name, isStatic, cs); |
| Types types = info.getTypes(); |
| List<ExecutableElement> candidates = methods.get(setterName); |
| if (candidates != null) { |
| for (ExecutableElement candidate : candidates) { |
| if ((!candidate.getModifiers().contains(Modifier.ABSTRACT) || candidate.getEnclosingElement() == typeElement) |
| && candidate.getReturnType().getKind() == TypeKind.VOID |
| && candidate.getParameters().size() == 1 |
| && types.isSameType(candidate.getParameters().get(0).asType(), type)) |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Works as TreeUtilities.isSynthetic, but treats implicit annotation parameter (value) as |
| * non-synthetic. See defect #270036 |
| */ |
| public static boolean isSyntheticPath(CompilationInfo ci, TreePath path) { |
| TreeUtilities tu = ci.getTreeUtilities(); |
| if (path == null) |
| throw new NullPointerException(); |
| |
| while (path != null) { |
| SYNT: if (isSynthetic(ci, path.getCompilationUnit(), path.getLeaf())) { |
| if (path.getLeaf().getKind() == Tree.Kind.ASSIGNMENT && |
| path.getParentPath() != null && path.getParentPath().getLeaf().getKind() == Tree.Kind.ANNOTATION) { |
| AssignmentTree aTree = (AssignmentTree)path.getLeaf(); |
| if (aTree.getVariable().getKind() == Tree.Kind.IDENTIFIER && |
| ((IdentifierTree)aTree.getVariable()).getName().contentEquals("value")) { // implicit value is not synthetic |
| break SYNT; |
| } |
| } |
| return true; |
| } |
| |
| path = path.getParentPath(); |
| } |
| |
| return false; |
| } |
| |
| //<editor-fold defaultstate="collapsed" desc="TODO: Copied from java.source.base TreeUtilities"> |
| static boolean isSynthetic(CompilationInfo info, CompilationUnitTree cut, Tree leaf) throws NullPointerException { |
| JCTree tree = (JCTree) leaf; |
| |
| if (tree.pos == (-1)) |
| return true; |
| |
| if (leaf.getKind() == Kind.METHOD) { |
| //check for synthetic constructor: |
| return (((JCTree.JCMethodDecl)leaf).mods.flags & Flags.GENERATEDCONSTR) != 0L; |
| } |
| |
| //check for synthetic superconstructor call: |
| if (leaf.getKind() == Kind.EXPRESSION_STATEMENT) { |
| ExpressionStatementTree est = (ExpressionStatementTree) leaf; |
| |
| if (est.getExpression().getKind() == Kind.METHOD_INVOCATION) { |
| MethodInvocationTree mit = (MethodInvocationTree) est.getExpression(); |
| |
| if (mit.getMethodSelect().getKind() == Kind.IDENTIFIER) { |
| IdentifierTree it = (IdentifierTree) mit.getMethodSelect(); |
| |
| if ("super".equals(it.getName().toString())) { |
| SourcePositions sp = info.getTrees().getSourcePositions(); |
| |
| return sp.getEndPosition(cut, leaf) == (-1); |
| } |
| } |
| } |
| } |
| |
| return false; |
| } |
| //</editor-fold> |
| |
| //<editor-fold defaultstate="collapsed" desc="TODO: Copy from org.netbeans.modules.java.hints.errors.Utilities"> |
| public static final String DEFAULT_NAME = "par"; // NOI18N |
| public static String makeNameUnique(CompilationInfo info, Scope s, String name) { |
| return makeNameUnique(info, s, name, Collections.EMPTY_LIST, null, null); |
| } |
| |
| public static String makeNameUnique(CompilationInfo info, Scope s, String name, List<String> definedIds) { |
| return makeNameUnique(info, s, name, definedIds, null, null); |
| } |
| |
| public static String makeNameUnique(CompilationInfo info, Scope s, String name, String prefix, String suffix) { |
| return makeNameUnique(info, s, name, Collections.EMPTY_LIST, prefix, suffix); |
| } |
| |
| public static String makeNameUnique(CompilationInfo info, Scope s, String name, List<String> definedIds, String prefix, String suffix) { |
| boolean cont; |
| String proposedName; |
| name = CodeStyleUtils.addPrefixSuffix(name, prefix, null); |
| int counter = 0; |
| do { |
| proposedName = name + (counter != 0 ? String.valueOf(counter) : "") + safeString(suffix); |
| |
| cont = false; |
| |
| if (s != null) { |
| for (String id : definedIds) { |
| if (proposedName.equals(id)) { |
| counter++; |
| cont = true; |
| break; |
| } |
| } |
| for (Element e : info.getElementUtilities().getLocalMembersAndVars(s, new VariablesFilter())) { |
| if (proposedName.equals(e.getSimpleName().toString())) { |
| counter++; |
| cont = true; |
| break; |
| } |
| } |
| } |
| } while(cont); |
| |
| return proposedName; |
| } |
| |
| private static String safeString(String str) { |
| return str == null ? "" : str; |
| } |
| |
| public static String getName(TypeMirror tm) { |
| if (tm.getKind().isPrimitive()) { |
| return "" + Character.toLowerCase(tm.getKind().name().charAt(0)); |
| } |
| |
| switch (tm.getKind()) { |
| case DECLARED: |
| DeclaredType dt = (DeclaredType) tm; |
| return firstToLower(dt.asElement().getSimpleName().toString()); |
| case ARRAY: |
| return getName(((ArrayType) tm).getComponentType()); |
| default: |
| return DEFAULT_NAME; |
| } |
| } |
| |
| public static String getName(ExpressionTree et) { |
| return getName((Tree) et); |
| } |
| |
| public static String getName(Tree et) { |
| return adjustName(getNameRaw(et)); |
| } |
| |
| private static String getNameRaw(Tree et) { |
| if (et == null) |
| return null; |
| |
| switch (et.getKind()) { |
| case IDENTIFIER: |
| return ((IdentifierTree) et).getName().toString(); |
| case METHOD_INVOCATION: |
| return getNameRaw(((MethodInvocationTree) et).getMethodSelect()); |
| case MEMBER_SELECT: |
| return ((MemberSelectTree) et).getIdentifier().toString(); |
| case NEW_CLASS: |
| return firstToLower(getNameRaw(((NewClassTree) et).getIdentifier())); |
| case PARAMETERIZED_TYPE: |
| return firstToLower(getNameRaw(((ParameterizedTypeTree) et).getType())); |
| case STRING_LITERAL: |
| String name = guessLiteralName((String) ((LiteralTree) et).getValue()); |
| if(name == null) { |
| return firstToLower(String.class.getSimpleName()); |
| } else { |
| return firstToLower(name); |
| } |
| case VARIABLE: |
| return ((VariableTree) et).getName().toString(); |
| default: |
| return null; |
| } |
| } |
| |
| static String adjustName(String name) { |
| if (name == null) { |
| return null; |
| } |
| |
| String shortName = null; |
| |
| if (name.startsWith("get") && name.length() > 3) { |
| shortName = name.substring(3); |
| } |
| |
| if (name.startsWith("is") && name.length() > 2) { |
| shortName = name.substring(2); |
| } |
| |
| if (shortName != null) { |
| return firstToLower(shortName); |
| } |
| |
| if (SourceVersion.isKeyword(name)) { |
| return "a" + Character.toUpperCase(name.charAt(0)) + name.substring(1); |
| } else { |
| return name; |
| } |
| } |
| |
| private static String firstToLower(String name) { |
| if (name.length() == 0) { |
| return null; |
| } |
| |
| StringBuilder result = new StringBuilder(); |
| boolean toLower = true; |
| char last = Character.toLowerCase(name.charAt(0)); |
| |
| for (int i = 1; i < name.length(); i++) { |
| if (toLower && (Character.isUpperCase(name.charAt(i)) || name.charAt(i) == '_')) { |
| result.append(Character.toLowerCase(last)); |
| } else { |
| result.append(last); |
| toLower = false; |
| } |
| last = name.charAt(i); |
| |
| } |
| |
| result.append(toLower ? Character.toLowerCase(last) : last); |
| |
| if (SourceVersion.isKeyword(result)) { |
| return "a" + name; |
| } else { |
| return result.toString(); |
| } |
| } |
| |
| private static String guessLiteralName(String str) { |
| if(str.isEmpty()) { |
| return null; |
| } |
| |
| StringBuilder sb = new StringBuilder(); |
| |
| for (int i = 0; i < str.length(); i++) { |
| char ch = str.charAt(i); |
| if(ch == ' ') { |
| sb.append('_'); |
| } else if (sb.length() == 0 ? Character.isJavaIdentifierStart(ch) : Character.isJavaIdentifierPart(ch)) { |
| sb.append(ch); |
| } |
| if (sb.length() > 40) { |
| break; |
| } |
| } |
| if (sb.length() == 0) { |
| return null; |
| } |
| else { |
| return sb.toString(); |
| } |
| } |
| |
| public static CompilationUnitTree createCompilationUnit(FileObject sourceRoot, String relativePath, Tree typeDecl, WorkingCopy workingCopy, TreeMaker make) { |
| GeneratorUtilities genUtils = GeneratorUtilities.get(workingCopy); |
| CompilationUnitTree newCompilation; |
| try { |
| newCompilation = genUtils.createFromTemplate(sourceRoot, relativePath, ElementKind.CLASS); |
| List<? extends Tree> typeDecls = newCompilation.getTypeDecls(); |
| if (typeDecls.isEmpty()) { |
| newCompilation = make.addCompUnitTypeDecl(newCompilation, typeDecl); |
| } else { |
| List<Tree> typeDeclarations = new LinkedList<Tree>(newCompilation.getTypeDecls()); |
| Tree templateClazz = typeDeclarations.remove(0); // TODO: Check for class with correct name, template could start with another type. |
| // mark the template CU as removed; any untransfered comments will be (?) lost. |
| workingCopy.getTreeMaker().asRemoved(templateClazz); |
| if (workingCopy.getTreeUtilities().getComments(typeDecl, true).isEmpty()) { |
| genUtils.copyComments(templateClazz, typeDecl, true); |
| } else if (workingCopy.getTreeUtilities().getComments(typeDecl, false).isEmpty()) { |
| genUtils.copyComments(templateClazz, typeDecl, false); |
| } |
| typeDeclarations.add(0, typeDecl); |
| newCompilation = make.CompilationUnit(newCompilation.getPackageAnnotations(), sourceRoot, relativePath, newCompilation.getImports(), typeDeclarations); |
| } |
| } catch (IOException ex) { |
| Exceptions.printStackTrace(ex); |
| newCompilation = make.CompilationUnit(sourceRoot, relativePath, null, Collections.singletonList(typeDecl)); |
| } |
| return newCompilation; |
| } |
| |
| public static final class VariablesFilter implements ElementUtilities.ElementAcceptor { |
| |
| private static final Set<ElementKind> ACCEPTABLE_KINDS = EnumSet.of(ElementKind.ENUM_CONSTANT, ElementKind.EXCEPTION_PARAMETER, ElementKind.FIELD, ElementKind.LOCAL_VARIABLE, ElementKind.PARAMETER); |
| |
| public boolean accept(Element e, TypeMirror type) { |
| return ACCEPTABLE_KINDS.contains(e.getKind()); |
| } |
| |
| } |
| //</editor-fold> |
| } |