mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-16 14:23:28 +07:00
java property index
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,15 +17,12 @@ package com.intellij.codeInspection.dataFlow
|
||||
|
||||
import com.intellij.lang.LighterAST
|
||||
import com.intellij.lang.LighterASTNode
|
||||
import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import com.intellij.psi.impl.source.JavaLightStubBuilder
|
||||
import com.intellij.psi.impl.source.PsiFileImpl
|
||||
import com.intellij.psi.impl.source.PsiMethodImpl
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType.*
|
||||
import com.intellij.psi.impl.source.tree.LightTreeUtil
|
||||
import com.intellij.psi.impl.source.tree.RecursiveLighterASTNodeWalkingVisitor
|
||||
import com.intellij.psi.util.PsiUtil
|
||||
import com.intellij.psi.stub.JavaStubImplUtil
|
||||
import com.intellij.util.gist.GistManager
|
||||
import java.util.*
|
||||
|
||||
@@ -96,18 +93,4 @@ private fun createData(body: LighterASTNode,
|
||||
return MethodData(nullity, purity, contracts, notNullParams, body.startOffset, body.endOffset)
|
||||
}
|
||||
|
||||
fun getIndexedData(method: PsiMethodImpl): MethodData? = gist.getFileData(method.containingFile)?.get(methodIndex(method))
|
||||
|
||||
private fun methodIndex(method: PsiMethodImpl): Int? {
|
||||
val file = method.containingFile as PsiFileImpl
|
||||
if (file.elementTypeForStubBuilder == null) return null
|
||||
|
||||
val stubTree = try {
|
||||
file.stubTree ?: file.calcStubTree()
|
||||
} catch (e: ProcessCanceledException) {
|
||||
throw e
|
||||
} catch (e: RuntimeException) {
|
||||
throw RuntimeException("While inferring contract for " + PsiUtil.getMemberQualifiedName(method), e)
|
||||
}
|
||||
return stubTree.plainList.filter { it.stubType == JavaElementType.METHOD }.map { it.psi }.indexOf(method)
|
||||
}
|
||||
fun getIndexedData(method: PsiMethodImpl): MethodData? = gist.getFileData(method.containingFile)?.get(JavaStubImplUtil.getMethodStubIndex(method))
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -73,13 +73,12 @@ public class PreferByKindWeigher extends LookupElementWeigher {
|
||||
psiElement(PsiReferenceExpression.class).withParent(PsiResourceExpression.class)));
|
||||
|
||||
private final CompletionType myCompletionType;
|
||||
@NotNull
|
||||
private final PsiElement myPosition;
|
||||
private final Set<PsiField> myNonInitializedFields;
|
||||
private final Condition<PsiClass> myRequiredSuper;
|
||||
private final ExpectedTypeInfo[] myExpectedTypes;
|
||||
|
||||
public PreferByKindWeigher(CompletionType completionType, @NotNull final PsiElement position, ExpectedTypeInfo[] expectedTypes) {
|
||||
public PreferByKindWeigher(CompletionType completionType, final PsiElement position, ExpectedTypeInfo[] expectedTypes) {
|
||||
super("kind");
|
||||
myCompletionType = completionType;
|
||||
myPosition = position;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -15,5 +15,6 @@
|
||||
<orderEntry type="module" module-name="projectModel-impl" />
|
||||
<orderEntry type="module" module-name="java-indexing-api" exported="" />
|
||||
<orderEntry type="library" name="Guava" level="project" />
|
||||
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed 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 com.intellij.psi.impl
|
||||
|
||||
import com.intellij.ide.highlighter.JavaFileType
|
||||
import com.intellij.lang.LighterASTNode
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import com.intellij.psi.JavaTokenType
|
||||
import com.intellij.psi.PsiField
|
||||
import com.intellij.psi.impl.cache.RecordUtil
|
||||
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes
|
||||
import com.intellij.psi.impl.source.JavaLightStubBuilder
|
||||
import com.intellij.psi.impl.source.JavaLightTreeUtil
|
||||
import com.intellij.psi.impl.source.PsiMethodImpl
|
||||
import com.intellij.psi.impl.source.tree.ElementType
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType
|
||||
import com.intellij.psi.impl.source.tree.LightTreeUtil
|
||||
import com.intellij.psi.impl.source.tree.RecursiveLighterASTNodeWalkingVisitor
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.stub.JavaStubImplUtil
|
||||
import com.intellij.psi.util.PropertyUtil
|
||||
import com.intellij.psi.util.PropertyUtilBase
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import com.intellij.util.indexing.*
|
||||
import com.intellij.util.io.DataExternalizer
|
||||
import com.intellij.util.io.EnumeratorIntegerDescriptor
|
||||
import com.intellij.util.io.EnumeratorStringDescriptor
|
||||
import com.intellij.util.io.KeyDescriptor
|
||||
import java.io.DataInput
|
||||
import java.io.DataOutput
|
||||
|
||||
private val indexId = ID.create<Int, PropertyIndexValue>("java.simple.property")
|
||||
private val log = Logger.getInstance(JavaSimplePropertyIndex::class.java)
|
||||
|
||||
fun getFieldOfGetter(method: PsiMethodImpl): PsiField? = resolveFieldFromIndexValue(method, true)
|
||||
|
||||
fun getFieldOfSetter(method: PsiMethodImpl): PsiField? = resolveFieldFromIndexValue(method, false)
|
||||
|
||||
private fun resolveFieldFromIndexValue(method: PsiMethodImpl, isGetter: Boolean): PsiField? {
|
||||
val id = JavaStubImplUtil.getMethodStubIndex(method)
|
||||
if (id != -1) {
|
||||
val values = FileBasedIndex.getInstance().getValues(indexId, id, GlobalSearchScope.fileScope(method.containingFile))
|
||||
when (values.size) {
|
||||
0 -> return null
|
||||
1 -> {
|
||||
val indexValue = values[0]
|
||||
if (isGetter != indexValue.getter) return null
|
||||
val psiClass = method.containingClass
|
||||
val project = psiClass!!.project
|
||||
val expr = JavaPsiFacade.getElementFactory(project).createExpressionFromText(indexValue.propertyRefText, psiClass)
|
||||
return PropertyUtil.getSimplyReturnedField(expr)
|
||||
}
|
||||
else -> {
|
||||
log.error("multiple index values for method $method")
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
data class PropertyIndexValue(val propertyRefText: String, val getter: Boolean)
|
||||
|
||||
class JavaSimplePropertyIndex : FileBasedIndexExtension<Int, PropertyIndexValue>(), PsiDependentIndex {
|
||||
override fun getIndexer(): DataIndexer<Int, PropertyIndexValue, FileContent> = DataIndexer { inputData ->
|
||||
val result = ContainerUtil.newHashMap<Int, PropertyIndexValue>()
|
||||
val tree = (inputData as FileContentImpl).lighterASTForPsiDependentIndex
|
||||
|
||||
object : RecursiveLighterASTNodeWalkingVisitor(tree) {
|
||||
var methodIndex = 0
|
||||
|
||||
override fun visitNode(element: LighterASTNode) {
|
||||
if (JavaLightStubBuilder.isCodeBlockWithoutStubs(element)) return
|
||||
|
||||
if (element.tokenType === JavaElementType.METHOD) {
|
||||
extractProperty(element)?.let { result.put(methodIndex, it) }
|
||||
methodIndex++
|
||||
}
|
||||
|
||||
super.visitNode(element)
|
||||
}
|
||||
|
||||
private fun extractProperty(method: LighterASTNode): PropertyIndexValue? {
|
||||
var isConstructor = true
|
||||
var isGetter = true
|
||||
|
||||
var isBooleanReturnType = false
|
||||
var isVoidReturnType = false
|
||||
var setterParameterName: String? = null
|
||||
|
||||
var refText: String? = null
|
||||
|
||||
for (child in tree.getChildren(method)) {
|
||||
when (child.tokenType) {
|
||||
JavaElementType.TYPE -> {
|
||||
val children = tree.getChildren(child)
|
||||
if (children.size != 1) return null
|
||||
val typeElement = children[0]
|
||||
if (typeElement.tokenType == JavaTokenType.VOID_KEYWORD) isVoidReturnType = true
|
||||
if (typeElement.tokenType == JavaTokenType.BOOLEAN_KEYWORD) isBooleanReturnType = true
|
||||
isConstructor = false
|
||||
}
|
||||
JavaElementType.PARAMETER_LIST -> {
|
||||
if (isGetter) {
|
||||
if (LightTreeUtil.firstChildOfType(tree, child, JavaElementType.PARAMETER) != null) return null
|
||||
} else {
|
||||
val parameters = LightTreeUtil.getChildrenOfType(tree, child, JavaElementType.PARAMETER)
|
||||
if (parameters.size != 1) return null
|
||||
setterParameterName = JavaLightTreeUtil.getNameIdentifierText(tree, parameters[0])
|
||||
if (setterParameterName == null) return null
|
||||
}
|
||||
}
|
||||
JavaElementType.CODE_BLOCK -> {
|
||||
refText = if (isGetter) getGetterPropertyRefText(child) else getSetterPropertyRefText(child, setterParameterName!!)
|
||||
if (refText == null) return null
|
||||
}
|
||||
JavaTokenType.IDENTIFIER -> {
|
||||
if (isConstructor) return null
|
||||
val name = RecordUtil.intern(tree.charTable, child)
|
||||
val flavour = PropertyUtil.getMethodNameGetterFlavour(name)
|
||||
when (flavour) {
|
||||
PropertyUtilBase.GetterFlavour.NOT_A_GETTER -> {
|
||||
if (PropertyUtil.isSetterName(name)) {
|
||||
isGetter = false
|
||||
}
|
||||
else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
PropertyUtilBase.GetterFlavour.BOOLEAN -> if (!isBooleanReturnType) return null
|
||||
else -> { }
|
||||
}
|
||||
if (isVoidReturnType && isGetter) return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return refText?.let { PropertyIndexValue(it, isGetter) }
|
||||
}
|
||||
|
||||
private fun getSetterPropertyRefText(codeBlock: LighterASTNode, setterParameterName: String): String? {
|
||||
val assignment = tree
|
||||
.getChildren(codeBlock)
|
||||
.singleOrNull { ElementType.JAVA_STATEMENT_BIT_SET.contains(it.tokenType) }
|
||||
?.takeIf { it.tokenType == JavaElementType.EXPRESSION_STATEMENT }
|
||||
?.let { LightTreeUtil.firstChildOfType(tree, it, JavaElementType.ASSIGNMENT_EXPRESSION) }
|
||||
if (assignment == null || LightTreeUtil.firstChildOfType(tree, assignment, JavaTokenType.EQ) == null) return null
|
||||
val operands = LightTreeUtil.getChildrenOfType(tree, assignment, ElementType.EXPRESSION_BIT_SET)
|
||||
if (operands.size != 2 || LightTreeUtil.toFilteredString(tree, operands[1], null) != setterParameterName) return null
|
||||
val lhsText = LightTreeUtil.toFilteredString(tree, operands[0], null)
|
||||
if (lhsText == setterParameterName) return null
|
||||
return lhsText
|
||||
}
|
||||
|
||||
private fun getGetterPropertyRefText(codeBlock: LighterASTNode): String? = tree
|
||||
.getChildren(codeBlock)
|
||||
.singleOrNull { ElementType.JAVA_STATEMENT_BIT_SET.contains(it.tokenType) }
|
||||
?.takeIf { it.tokenType == JavaElementType.RETURN_STATEMENT}
|
||||
?.let { LightTreeUtil.firstChildOfType(tree, it, ElementType.EXPRESSION_BIT_SET) }
|
||||
?.let { LightTreeUtil.toFilteredString(tree, it, null) }
|
||||
|
||||
}.visitNode(tree.root)
|
||||
result
|
||||
}
|
||||
|
||||
override fun getKeyDescriptor(): KeyDescriptor<Int> = EnumeratorIntegerDescriptor.INSTANCE
|
||||
|
||||
override fun getValueExternalizer(): DataExternalizer<PropertyIndexValue> = object: DataExternalizer<PropertyIndexValue> {
|
||||
override fun save(out: DataOutput, value: PropertyIndexValue?) {
|
||||
value!!
|
||||
EnumeratorStringDescriptor.INSTANCE.save(out, value.propertyRefText)
|
||||
out.writeBoolean(value.getter)
|
||||
}
|
||||
|
||||
override fun read(input: DataInput): PropertyIndexValue = PropertyIndexValue(EnumeratorStringDescriptor.INSTANCE.read(input), input.readBoolean())
|
||||
}
|
||||
|
||||
override fun getName(): ID<Int, PropertyIndexValue> = indexId
|
||||
|
||||
override fun getInputFilter(): FileBasedIndex.InputFilter = object : DefaultFileTypeSpecificInputFilter(JavaFileType.INSTANCE) {
|
||||
override fun acceptInput(file: VirtualFile): Boolean = JavaStubElementTypes.JAVA_FILE.shouldBuildStubFor(file)
|
||||
}
|
||||
|
||||
override fun dependsOnFileContent(): Boolean = true
|
||||
|
||||
override fun getVersion(): Int = 0
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed 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 com.intellij.psi.util;
|
||||
|
||||
import com.intellij.lang.jvm.JvmModifier;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.JavaSimplePropertyIndexKt;
|
||||
import com.intellij.psi.impl.source.PsiMethodImpl;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
/**
|
||||
* @author Mike
|
||||
*/
|
||||
public class PropertyUtil extends PropertyUtilBase {
|
||||
private PropertyUtil() {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiField getFieldOfGetter(PsiMethod method) {
|
||||
return getFieldOfGetter(method, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiField getFieldOfGetter(PsiMethod method, boolean useIndex) {
|
||||
PsiField field = useIndex && method instanceof PsiMethodImpl && method.isPhysical()
|
||||
? JavaSimplePropertyIndexKt.getFieldOfGetter((PsiMethodImpl)method)
|
||||
: getSimplyReturnedField(getGetterReturnExpression(method));
|
||||
if (field == null || !checkFieldLocation(method, field)) return null;
|
||||
final PsiType returnType = method.getReturnType();
|
||||
return returnType != null && field.getType().equals(returnType) ? field : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiField getSimplyReturnedField(@Nullable PsiExpression value) {
|
||||
if (!(value instanceof PsiReferenceExpression)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final PsiReferenceExpression reference = (PsiReferenceExpression)value;
|
||||
if (hasSubstantialQualifier(reference)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final PsiElement referent = reference.resolve();
|
||||
if (!(referent instanceof PsiField)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (PsiField)referent;
|
||||
}
|
||||
|
||||
private static boolean hasSubstantialQualifier(PsiReferenceExpression reference) {
|
||||
final PsiExpression qualifier = reference.getQualifierExpression();
|
||||
if (qualifier == null) return false;
|
||||
|
||||
if (qualifier instanceof PsiThisExpression || qualifier instanceof PsiSuperExpression) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (qualifier instanceof PsiReferenceExpression) {
|
||||
return !(((PsiReferenceExpression)qualifier).resolve() instanceof PsiClass);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isSimpleGetter(PsiMethod method) {
|
||||
//noinspection TestOnlyProblems
|
||||
return isSimpleGetter(method, true);
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
public static boolean isSimpleGetter(PsiMethod method, boolean useIndex) {
|
||||
return getFieldOfGetter(method, useIndex) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiField getFieldOfSetter(@Nullable PsiMethod method) {
|
||||
return getFieldOfSetter(method, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiField getFieldOfSetter(@Nullable PsiMethod method, boolean useIndex) {
|
||||
if (method == null) {
|
||||
return null;
|
||||
}
|
||||
final PsiParameterList parameterList = method.getParameterList();
|
||||
if (parameterList.getParametersCount() != 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PsiField field;
|
||||
if (useIndex && method instanceof PsiMethodImpl && method.isPhysical()) {
|
||||
field = JavaSimplePropertyIndexKt.getFieldOfSetter((PsiMethodImpl)method);
|
||||
}
|
||||
else {
|
||||
@NonNls final String name = method.getName();
|
||||
if (!name.startsWith("set")) {
|
||||
return null;
|
||||
}
|
||||
if (method.hasModifierProperty(PsiModifier.SYNCHRONIZED)) {
|
||||
return null;
|
||||
}
|
||||
final PsiCodeBlock body = method.getBody();
|
||||
if (body == null) {
|
||||
return null;
|
||||
}
|
||||
final PsiStatement[] statements = body.getStatements();
|
||||
if (statements.length != 1) {
|
||||
return null;
|
||||
}
|
||||
final PsiStatement statement = statements[0];
|
||||
if (!(statement instanceof PsiExpressionStatement)) {
|
||||
return null;
|
||||
}
|
||||
final PsiExpressionStatement possibleAssignmentStatement = (PsiExpressionStatement)statement;
|
||||
final PsiExpression possibleAssignment = possibleAssignmentStatement.getExpression();
|
||||
if (!(possibleAssignment instanceof PsiAssignmentExpression)) {
|
||||
return null;
|
||||
}
|
||||
final PsiAssignmentExpression assignment = (PsiAssignmentExpression)possibleAssignment;
|
||||
if (!JavaTokenType.EQ.equals(assignment.getOperationTokenType())) {
|
||||
return null;
|
||||
}
|
||||
final PsiExpression lhs = assignment.getLExpression();
|
||||
if (!(lhs instanceof PsiReferenceExpression)) {
|
||||
return null;
|
||||
}
|
||||
final PsiReferenceExpression reference = (PsiReferenceExpression)lhs;
|
||||
final PsiExpression qualifier = reference.getQualifierExpression();
|
||||
if (qualifier instanceof PsiReferenceExpression) {
|
||||
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)qualifier;
|
||||
final PsiElement target = referenceExpression.resolve();
|
||||
if (!(target instanceof PsiClass)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else if (qualifier != null && !(qualifier instanceof PsiThisExpression) && !(qualifier instanceof PsiSuperExpression)) {
|
||||
return null;
|
||||
}
|
||||
final PsiElement referent = reference.resolve();
|
||||
if (referent == null) {
|
||||
return null;
|
||||
}
|
||||
if (!(referent instanceof PsiField)) {
|
||||
return null;
|
||||
}
|
||||
field = (PsiField)referent;
|
||||
|
||||
final PsiExpression rhs = assignment.getRExpression();
|
||||
if (!(rhs instanceof PsiReferenceExpression)) {
|
||||
return null;
|
||||
}
|
||||
final PsiReferenceExpression rReference = (PsiReferenceExpression)rhs;
|
||||
final PsiExpression rQualifier = rReference.getQualifierExpression();
|
||||
if (rQualifier != null) {
|
||||
return null;
|
||||
}
|
||||
final PsiElement rReferent = rReference.resolve();
|
||||
if (rReferent == null) {
|
||||
return null;
|
||||
}
|
||||
if (!(rReferent instanceof PsiParameter)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return field != null && field.getType().equals(parameterList.getParameters()[0].getType()) && checkFieldLocation(method, field)
|
||||
? field
|
||||
: null;
|
||||
}
|
||||
|
||||
public static boolean isSimpleSetter(PsiMethod method) {
|
||||
//noinspection TestOnlyProblems
|
||||
return isSimpleSetter(method, true);
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
public static boolean isSimpleSetter(PsiMethod method, boolean useIndex) {
|
||||
return getFieldOfSetter(method, useIndex) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiMethod getReversePropertyMethod(PsiMethod propertyMethod) {
|
||||
if (propertyMethod == null) {
|
||||
return null;
|
||||
}
|
||||
final PsiClass aClass = propertyMethod.getContainingClass();
|
||||
if (aClass == null) {
|
||||
return null;
|
||||
}
|
||||
final String methodName = propertyMethod.getName();
|
||||
final String prefix;
|
||||
if (methodName.startsWith("get")) {
|
||||
prefix = "get";
|
||||
}
|
||||
else if (methodName.startsWith(IS_PREFIX)) {
|
||||
prefix = IS_PREFIX;
|
||||
}
|
||||
else if (methodName.startsWith("set")) {
|
||||
prefix = "set";
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
final String name = methodName.substring(prefix.length());
|
||||
final PsiField field = prefix.equals("set") ? getFieldOfSetter(propertyMethod) : getFieldOfGetter(propertyMethod);
|
||||
if (field == null) {
|
||||
return null;
|
||||
}
|
||||
if (prefix.equals("set")) {
|
||||
final PsiMethod result = findPropertyMethod(aClass, "get", name, field);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
return findPropertyMethod(aClass, IS_PREFIX, name, field);
|
||||
}
|
||||
else {
|
||||
return findPropertyMethod(aClass, "set", name, field);
|
||||
}
|
||||
}
|
||||
|
||||
private static PsiMethod findPropertyMethod(@NotNull PsiClass aClass,
|
||||
@NotNull String prefix,
|
||||
@NotNull String propertyName,
|
||||
@NotNull PsiField field1) {
|
||||
final PsiMethod[] methods = aClass.findMethodsByName(prefix + propertyName, true);
|
||||
for (PsiMethod method : methods) {
|
||||
final PsiField field2 = prefix.equals("set") ? getFieldOfSetter(method) : getFieldOfGetter(method);
|
||||
if (field1.equals(field2)) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean checkFieldLocation(PsiMethod method, PsiField field) {
|
||||
return PsiResolveHelper.SERVICE.getInstance(method.getProject()).isAccessible(field, method, null) &&
|
||||
(!method.hasModifier(JvmModifier.STATIC) || field.hasModifier(JvmModifier.STATIC)) &&
|
||||
InheritanceUtil.isInheritorOrSelf(method.getContainingClass(), field.getContainingClass(), true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,101 +35,14 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.beans.Introspector;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Mike
|
||||
*/
|
||||
public class PropertyUtil {
|
||||
@NonNls private static final String IS_PREFIX = "is";
|
||||
public class PropertyUtilBase {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.util.PropertyUtil");
|
||||
|
||||
private PropertyUtil() {
|
||||
}
|
||||
|
||||
@Contract("null -> false")
|
||||
public static boolean isSimplePropertyGetter(@Nullable PsiMethod method) {
|
||||
return hasGetterName(method) && method.getParameterList().getParametersCount() == 0;
|
||||
}
|
||||
|
||||
@SuppressWarnings("HardCodedStringLiteral")
|
||||
public static boolean hasGetterName(final PsiMethod method) {
|
||||
if (method == null) return false;
|
||||
|
||||
if (method.isConstructor()) return false;
|
||||
|
||||
String methodName = method.getName();
|
||||
int methodNameLength = methodName.length();
|
||||
if (methodName.startsWith("get") && methodNameLength > "get".length()) {
|
||||
if (Character.isLowerCase(methodName.charAt("get".length()))
|
||||
&& (methodNameLength == "get".length() + 1 || Character.isLowerCase(methodName.charAt("get".length() + 1)))) {
|
||||
return false;
|
||||
}
|
||||
PsiType returnType = method.getReturnType();
|
||||
if (returnType != null && PsiType.VOID.equals(returnType)) return false;
|
||||
}
|
||||
else if (methodName.startsWith(IS_PREFIX) && methodNameLength > IS_PREFIX.length()) {
|
||||
if (Character.isLowerCase(methodName.charAt(IS_PREFIX.length()))
|
||||
&& (methodNameLength == IS_PREFIX.length() + 1 || Character.isLowerCase(methodName.charAt(IS_PREFIX.length() + 1)))) {
|
||||
return false;
|
||||
}
|
||||
PsiType returnType = method.getReturnType();
|
||||
return isBoolean(returnType);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("HardCodedStringLiteral")
|
||||
public static boolean isSimplePropertySetter(@Nullable PsiMethod method) {
|
||||
if (method == null) return false;
|
||||
|
||||
if (method.isConstructor()) return false;
|
||||
|
||||
String methodName = method.getName();
|
||||
|
||||
if (!(methodName.startsWith("set") && methodName.length() > "set".length())) return false;
|
||||
if (Character.isLowerCase(methodName.charAt("set".length()))
|
||||
&& (methodName.length() == "set".length() + 1 || Character.isLowerCase(methodName.charAt("set".length() + 1)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (method.getParameterList().getParametersCount() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiType returnType = method.getReturnType();
|
||||
|
||||
if (returnType == null || PsiType.VOID.equals(returnType)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Comparing.equal(PsiUtil.resolveClassInType(TypeConversionUtil.erasure(returnType)), method.getContainingClass());
|
||||
}
|
||||
|
||||
@NonNls protected static final String IS_PREFIX = "is";
|
||||
@Nullable
|
||||
public static String getPropertyName(@NotNull PsiMethod method) {
|
||||
if (isSimplePropertyGetter(method)) {
|
||||
return getPropertyNameByGetter(method);
|
||||
}
|
||||
if (isSimplePropertySetter(method)) {
|
||||
return getPropertyNameBySetter(method);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getPropertyNameByGetter(PsiMethod getterMethod) {
|
||||
@NonNls String methodName = getterMethod.getName();
|
||||
if (methodName.startsWith("get")) return StringUtil.decapitalize(methodName.substring(3));
|
||||
if (methodName.startsWith("is")) return StringUtil.decapitalize(methodName.substring(2));
|
||||
return methodName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getPropertyNameBySetter(@NotNull PsiMethod setterMethod) {
|
||||
String methodName = setterMethod.getName();
|
||||
return Introspector.decapitalize(methodName.substring(3));
|
||||
public static String getPropertyName(@NonNls @NotNull String methodName) {
|
||||
return StringUtil.getPropertyName(methodName);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -207,6 +120,92 @@ public class PropertyUtil {
|
||||
return ContainerUtil.concat(getGetters(psiClass, propertyName), getSetters(psiClass, propertyName));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String[] getReadableProperties(@NotNull PsiClass aClass, boolean includeSuperClass) {
|
||||
List<String> result = new ArrayList<>();
|
||||
|
||||
PsiMethod[] methods = includeSuperClass ? aClass.getAllMethods() : aClass.getMethods();
|
||||
|
||||
for (PsiMethod method : methods) {
|
||||
if (CommonClassNames.JAVA_LANG_OBJECT.equals(method.getContainingClass().getQualifiedName())) continue;
|
||||
|
||||
if (isSimplePropertyGetter(method)) {
|
||||
result.add(getPropertyName(method));
|
||||
}
|
||||
}
|
||||
|
||||
return ArrayUtil.toStringArray(result);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String[] getWritableProperties(@NotNull PsiClass aClass, boolean includeSuperClass) {
|
||||
List<String> result = new ArrayList<>();
|
||||
|
||||
PsiMethod[] methods = includeSuperClass ? aClass.getAllMethods() : aClass.getMethods();
|
||||
|
||||
for (PsiMethod method : methods) {
|
||||
if (CommonClassNames.JAVA_LANG_OBJECT.equals(method.getContainingClass().getQualifiedName())) continue;
|
||||
|
||||
if (isSimplePropertySetter(method)) {
|
||||
result.add(getPropertyName(method));
|
||||
}
|
||||
}
|
||||
|
||||
return ArrayUtil.toStringArray(result);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiType getPropertyType(final PsiMember member) {
|
||||
if (member instanceof PsiField) {
|
||||
return ((PsiField)member).getType();
|
||||
}
|
||||
if (member instanceof PsiMethod) {
|
||||
final PsiMethod psiMethod = (PsiMethod)member;
|
||||
if (isSimplePropertyGetter(psiMethod)) {
|
||||
return psiMethod.getReturnType();
|
||||
}
|
||||
else if (isSimplePropertySetter(psiMethod)) {
|
||||
return psiMethod.getParameterList().getParameters()[0].getType();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
public static PsiMethod findPropertySetter(PsiClass aClass,
|
||||
@NotNull String propertyName,
|
||||
boolean isStatic,
|
||||
boolean checkSuperClasses) {
|
||||
if (aClass == null) return null;
|
||||
String setterName = suggestSetterName(propertyName);
|
||||
PsiMethod[] methods = aClass.findMethodsByName(setterName, checkSuperClasses);
|
||||
|
||||
for (PsiMethod method : methods) {
|
||||
if (method.hasModifierProperty(PsiModifier.STATIC) != isStatic) continue;
|
||||
|
||||
if (isSimplePropertySetter(method)) {
|
||||
if (getPropertyNameBySetter(method).equals(propertyName)) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiField findPropertyField(PsiClass aClass, String propertyName, boolean isStatic) {
|
||||
PsiField[] fields = aClass.getAllFields();
|
||||
|
||||
for (PsiField field : fields) {
|
||||
if (field.hasModifierProperty(PsiModifier.STATIC) != isStatic) continue;
|
||||
if (propertyName.equals(suggestPropertyName(field))) return field;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiMethod findPropertyGetter(PsiClass aClass,
|
||||
@NotNull String propertyName,
|
||||
@@ -249,28 +248,6 @@ public class PropertyUtil {
|
||||
return isSimplePropertyGetter(method) || isSimplePropertySetter(method);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiMethod findPropertySetter(PsiClass aClass,
|
||||
@NotNull String propertyName,
|
||||
boolean isStatic,
|
||||
boolean checkSuperClasses) {
|
||||
if (aClass == null) return null;
|
||||
String setterName = suggestSetterName(propertyName);
|
||||
PsiMethod[] methods = aClass.findMethodsByName(setterName, checkSuperClasses);
|
||||
|
||||
for (PsiMethod method : methods) {
|
||||
if (method.hasModifierProperty(PsiModifier.STATIC) != isStatic) continue;
|
||||
|
||||
if (isSimplePropertySetter(method)) {
|
||||
if (getPropertyNameBySetter(method).equals(propertyName)) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiMethod findPropertySetterWithType(String propertyName, boolean isStatic, PsiType type, Iterator<PsiMethod> methods) {
|
||||
while (methods.hasNext()) {
|
||||
@@ -287,21 +264,158 @@ public class PropertyUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiField findPropertyField(PsiClass aClass, String propertyName, boolean isStatic) {
|
||||
PsiField[] fields = aClass.getAllFields();
|
||||
public enum GetterFlavour {
|
||||
BOOLEAN,
|
||||
GENERIC,
|
||||
NOT_A_GETTER
|
||||
}
|
||||
|
||||
for (PsiField field : fields) {
|
||||
if (field.hasModifierProperty(PsiModifier.STATIC) != isStatic) continue;
|
||||
if (propertyName.equals(suggestPropertyName(field))) return field;
|
||||
@NotNull
|
||||
public static GetterFlavour getMethodNameGetterFlavour(@NotNull String methodName) {
|
||||
if (checkPrefix(methodName, "get")) {
|
||||
return GetterFlavour.GENERIC;
|
||||
}
|
||||
else if (checkPrefix(methodName, IS_PREFIX)) {
|
||||
return GetterFlavour.BOOLEAN;
|
||||
}
|
||||
return GetterFlavour.NOT_A_GETTER;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@Contract("null -> false")
|
||||
public static boolean isSimplePropertyGetter(@Nullable PsiMethod method) {
|
||||
return hasGetterName(method) && method.getParameterList().getParametersCount() == 0;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("HardCodedStringLiteral")
|
||||
public static boolean hasGetterName(final PsiMethod method) {
|
||||
if (method == null) return false;
|
||||
|
||||
if (method.isConstructor()) return false;
|
||||
|
||||
String methodName = method.getName();
|
||||
GetterFlavour flavour = getMethodNameGetterFlavour(methodName);
|
||||
switch (flavour) {
|
||||
case GENERIC:
|
||||
PsiType returnType = method.getReturnType();
|
||||
return returnType == null || !PsiType.VOID.equals(returnType);
|
||||
case BOOLEAN:
|
||||
return isBoolean(method.getReturnType());
|
||||
case NOT_A_GETTER:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static boolean isBoolean(@Nullable PsiType propertyType) {
|
||||
return PsiType.BOOLEAN.equals(propertyType);
|
||||
}
|
||||
|
||||
|
||||
public static String suggestPropertyName(@NotNull PsiField field) {
|
||||
return suggestPropertyName(field, field.getName());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String suggestPropertyName(@NotNull PsiField field, @NotNull String fieldName) {
|
||||
JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(field.getProject());
|
||||
VariableKind kind = codeStyleManager.getVariableKind(field);
|
||||
String name = codeStyleManager.variableNameToPropertyName(fieldName, kind);
|
||||
if (!field.hasModifierProperty(PsiModifier.STATIC) && isBoolean(field.getType())) {
|
||||
if (name.startsWith(IS_PREFIX) && name.length() > IS_PREFIX.length() && Character.isUpperCase(name.charAt(IS_PREFIX.length()))) {
|
||||
name = Introspector.decapitalize(name.substring(IS_PREFIX.length()));
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public static String suggestGetterName(PsiField field) {
|
||||
String propertyName = suggestPropertyName(field);
|
||||
return suggestGetterName(propertyName, field.getType());
|
||||
}
|
||||
|
||||
public static String suggestSetterName(PsiField field) {
|
||||
String propertyName = suggestPropertyName(field);
|
||||
return suggestSetterName(propertyName);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getPropertyName(@NonNls @NotNull String methodName) {
|
||||
return StringUtil.getPropertyName(methodName);
|
||||
public static String getPropertyName(final PsiMember member) {
|
||||
if (member instanceof PsiMethod) {
|
||||
return getPropertyName((PsiMethod)member);
|
||||
}
|
||||
if (member instanceof PsiField) {
|
||||
return member.getName();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("HardCodedStringLiteral")
|
||||
public static boolean isSimplePropertySetter(@Nullable PsiMethod method) {
|
||||
if (method == null) return false;
|
||||
|
||||
if (method.isConstructor()) return false;
|
||||
|
||||
String methodName = method.getName();
|
||||
|
||||
if (!isSetterName(methodName)) return false;
|
||||
|
||||
if (method.getParameterList().getParametersCount() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiType returnType = method.getReturnType();
|
||||
|
||||
if (returnType == null || PsiType.VOID.equals(returnType)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Comparing.equal(PsiUtil.resolveClassInType(TypeConversionUtil.erasure(returnType)), method.getContainingClass());
|
||||
}
|
||||
|
||||
public static boolean isSetterName(@NotNull String methodName) {
|
||||
return checkPrefix(methodName, "set");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getPropertyName(@NotNull PsiMethod method) {
|
||||
if (isSimplePropertyGetter(method)) {
|
||||
return getPropertyNameByGetter(method);
|
||||
}
|
||||
if (isSimplePropertySetter(method)) {
|
||||
return getPropertyNameBySetter(method);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getPropertyNameByGetter(PsiMethod getterMethod) {
|
||||
@NonNls String methodName = getterMethod.getName();
|
||||
if (methodName.startsWith("get")) return StringUtil.decapitalize(methodName.substring(3));
|
||||
if (methodName.startsWith("is")) return StringUtil.decapitalize(methodName.substring(2));
|
||||
return methodName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getPropertyNameBySetter(@NotNull PsiMethod setterMethod) {
|
||||
String methodName = setterMethod.getName();
|
||||
return Introspector.decapitalize(methodName.substring(3));
|
||||
}
|
||||
|
||||
private static boolean checkPrefix(@NotNull String methodName, @NotNull String prefix) {
|
||||
boolean hasPrefix = methodName.startsWith(prefix) && methodName.length() > prefix.length();
|
||||
return hasPrefix && !(Character.isLowerCase(methodName.charAt(prefix.length())) &&
|
||||
(methodName.length() == prefix.length() + 1 || Character.isLowerCase(methodName.charAt(prefix.length() + 1))));
|
||||
}
|
||||
|
||||
@NonNls
|
||||
@NotNull
|
||||
public static String[] suggestGetterNames(@NotNull String propertyName) {
|
||||
final String str = StringUtil.capitalizeWithJavaBeanConvention(StringUtil.sanitizeJavaIdentifier(propertyName));
|
||||
return new String[]{IS_PREFIX + str, "get" + str};
|
||||
}
|
||||
|
||||
public static String suggestGetterName(@NonNls @NotNull String propertyName, @Nullable PsiType propertyType) {
|
||||
@@ -326,16 +440,6 @@ public class PropertyUtil {
|
||||
return name.toString();
|
||||
}
|
||||
|
||||
private static boolean isBoolean(@Nullable PsiType propertyType) {
|
||||
return PsiType.BOOLEAN.equals(propertyType);
|
||||
}
|
||||
|
||||
@NonNls
|
||||
@NotNull
|
||||
public static String[] suggestGetterNames(@NotNull String propertyName) {
|
||||
final String str = StringUtil.capitalizeWithJavaBeanConvention(StringUtil.sanitizeJavaIdentifier(propertyName));
|
||||
return new String[]{IS_PREFIX + str, "get" + str};
|
||||
}
|
||||
|
||||
public static String suggestSetterName(@NonNls @NotNull String propertyName) {
|
||||
return suggestSetterName(propertyName, "set");
|
||||
@@ -351,40 +455,6 @@ public class PropertyUtil {
|
||||
return name.toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String[] getReadableProperties(@NotNull PsiClass aClass, boolean includeSuperClass) {
|
||||
List<String> result = new ArrayList<>();
|
||||
|
||||
PsiMethod[] methods = includeSuperClass ? aClass.getAllMethods() : aClass.getMethods();
|
||||
|
||||
for (PsiMethod method : methods) {
|
||||
if (CommonClassNames.JAVA_LANG_OBJECT.equals(method.getContainingClass().getQualifiedName())) continue;
|
||||
|
||||
if (isSimplePropertyGetter(method)) {
|
||||
result.add(getPropertyName(method));
|
||||
}
|
||||
}
|
||||
|
||||
return ArrayUtil.toStringArray(result);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String[] getWritableProperties(@NotNull PsiClass aClass, boolean includeSuperClass) {
|
||||
List<String> result = new ArrayList<>();
|
||||
|
||||
PsiMethod[] methods = includeSuperClass ? aClass.getAllMethods() : aClass.getMethods();
|
||||
|
||||
for (PsiMethod method : methods) {
|
||||
if (CommonClassNames.JAVA_LANG_OBJECT.equals(method.getContainingClass().getQualifiedName())) continue;
|
||||
|
||||
if (isSimplePropertySetter(method)) {
|
||||
result.add(getPropertyName(method));
|
||||
}
|
||||
}
|
||||
|
||||
return ArrayUtil.toStringArray(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Consider using {@link com.intellij.codeInsight.generation.GenerateMembersUtil#generateGetterPrototype(com.intellij.psi.PsiField)} or
|
||||
* {@link com.intellij.codeInsight.generation.GenerateMembersUtil#generateSimpleGetterPrototype(com.intellij.psi.PsiField)}
|
||||
@@ -498,61 +568,6 @@ public class PropertyUtil {
|
||||
NullableNotNullManager.getInstance(field.getProject()).copyNullableOrNotNullAnnotation(field, listOwner);
|
||||
}
|
||||
|
||||
public static String suggestPropertyName(@NotNull PsiField field) {
|
||||
return suggestPropertyName(field, field.getName());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String suggestPropertyName(@NotNull PsiField field, @NotNull String fieldName) {
|
||||
JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(field.getProject());
|
||||
VariableKind kind = codeStyleManager.getVariableKind(field);
|
||||
String name = codeStyleManager.variableNameToPropertyName(fieldName, kind);
|
||||
if (!field.hasModifierProperty(PsiModifier.STATIC) && isBoolean(field.getType())) {
|
||||
if (name.startsWith(IS_PREFIX) && name.length() > IS_PREFIX.length() && Character.isUpperCase(name.charAt(IS_PREFIX.length()))) {
|
||||
name = Introspector.decapitalize(name.substring(IS_PREFIX.length()));
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public static String suggestGetterName(PsiField field) {
|
||||
String propertyName = suggestPropertyName(field);
|
||||
return suggestGetterName(propertyName, field.getType());
|
||||
}
|
||||
|
||||
public static String suggestSetterName(PsiField field) {
|
||||
String propertyName = suggestPropertyName(field);
|
||||
return suggestSetterName(propertyName);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getPropertyName(final PsiMember member) {
|
||||
if (member instanceof PsiMethod) {
|
||||
return getPropertyName((PsiMethod)member);
|
||||
}
|
||||
if (member instanceof PsiField) {
|
||||
return member.getName();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiType getPropertyType(final PsiMember member) {
|
||||
if (member instanceof PsiField) {
|
||||
return ((PsiField)member).getType();
|
||||
}
|
||||
if (member instanceof PsiMethod) {
|
||||
final PsiMethod psiMethod = (PsiMethod)member;
|
||||
if (isSimplePropertyGetter(psiMethod)) {
|
||||
return psiMethod.getReturnType();
|
||||
}
|
||||
else if (isSimplePropertySetter(psiMethod)) {
|
||||
return psiMethod.getParameterList().getParameters()[0].getType();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiTypeElement getPropertyTypeElement(final PsiMember member) {
|
||||
if (member instanceof PsiField) {
|
||||
@@ -633,7 +648,7 @@ public class PropertyUtil {
|
||||
* returns the returned expression. Otherwise, returns null.
|
||||
*
|
||||
* @param method the method to check
|
||||
* @return the return value, or null if it doesn't match the condotions.
|
||||
* @return the return value, or null if it doesn't match the conditions.
|
||||
*/
|
||||
@Nullable
|
||||
public static PsiExpression getGetterReturnExpression(PsiMethod method) {
|
||||
@@ -655,201 +670,4 @@ public class PropertyUtil {
|
||||
return statement instanceof PsiReturnStatement ? ((PsiReturnStatement)statement).getReturnValue() : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiField getFieldOfGetter(PsiMethod method) {
|
||||
PsiField field = getSimplyReturnedField(method, getGetterReturnExpression(method));
|
||||
if (field != null) {
|
||||
final PsiType returnType = method.getReturnType();
|
||||
if (returnType != null && field.getType().equalsToText(returnType.getCanonicalText())) {
|
||||
return field;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiField getSimplyReturnedField(PsiMethod method, @Nullable PsiExpression value) {
|
||||
if (!(value instanceof PsiReferenceExpression)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final PsiReferenceExpression reference = (PsiReferenceExpression)value;
|
||||
if (hasSubstantialQualifier(reference)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final PsiElement referent = reference.resolve();
|
||||
if (!(referent instanceof PsiField)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final PsiField field = (PsiField)referent;
|
||||
return InheritanceUtil.isInheritorOrSelf(method.getContainingClass(), field.getContainingClass(), true) ? field : null;
|
||||
}
|
||||
|
||||
private static boolean hasSubstantialQualifier(PsiReferenceExpression reference) {
|
||||
final PsiExpression qualifier = reference.getQualifierExpression();
|
||||
if (qualifier == null) return false;
|
||||
|
||||
if (qualifier instanceof PsiThisExpression || qualifier instanceof PsiSuperExpression) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (qualifier instanceof PsiReferenceExpression) {
|
||||
return !(((PsiReferenceExpression)qualifier).resolve() instanceof PsiClass);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isSimpleGetter(PsiMethod method) {
|
||||
return getFieldOfGetter(method) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiField getFieldOfSetter(PsiMethod method) {
|
||||
if (method == null) {
|
||||
return null;
|
||||
}
|
||||
final PsiParameterList parameterList = method.getParameterList();
|
||||
if (parameterList.getParametersCount() != 1) {
|
||||
return null;
|
||||
}
|
||||
@NonNls final String name = method.getName();
|
||||
if (!name.startsWith("set")) {
|
||||
return null;
|
||||
}
|
||||
if (method.hasModifierProperty(PsiModifier.SYNCHRONIZED)) {
|
||||
return null;
|
||||
}
|
||||
final PsiCodeBlock body = method.getBody();
|
||||
if (body == null) {
|
||||
return null;
|
||||
}
|
||||
final PsiStatement[] statements = body.getStatements();
|
||||
if (statements.length != 1) {
|
||||
return null;
|
||||
}
|
||||
final PsiStatement statement = statements[0];
|
||||
if (!(statement instanceof PsiExpressionStatement)) {
|
||||
return null;
|
||||
}
|
||||
final PsiExpressionStatement possibleAssignmentStatement = (PsiExpressionStatement)statement;
|
||||
final PsiExpression possibleAssignment = possibleAssignmentStatement.getExpression();
|
||||
if (!(possibleAssignment instanceof PsiAssignmentExpression)) {
|
||||
return null;
|
||||
}
|
||||
final PsiAssignmentExpression assignment = (PsiAssignmentExpression)possibleAssignment;
|
||||
if (!JavaTokenType.EQ.equals(assignment.getOperationTokenType())) {
|
||||
return null;
|
||||
}
|
||||
final PsiExpression lhs = assignment.getLExpression();
|
||||
if (!(lhs instanceof PsiReferenceExpression)) {
|
||||
return null;
|
||||
}
|
||||
final PsiReferenceExpression reference = (PsiReferenceExpression)lhs;
|
||||
final PsiExpression qualifier = reference.getQualifierExpression();
|
||||
if (qualifier instanceof PsiReferenceExpression) {
|
||||
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)qualifier;
|
||||
final PsiElement target = referenceExpression.resolve();
|
||||
if (!(target instanceof PsiClass)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else if (qualifier != null && !(qualifier instanceof PsiThisExpression) && !(qualifier instanceof PsiSuperExpression)) {
|
||||
return null;
|
||||
}
|
||||
final PsiElement referent = reference.resolve();
|
||||
if (referent == null) {
|
||||
return null;
|
||||
}
|
||||
if (!(referent instanceof PsiField)) {
|
||||
return null;
|
||||
}
|
||||
final PsiField field = (PsiField)referent;
|
||||
final PsiClass fieldContainingClass = field.getContainingClass();
|
||||
final PsiClass methodContainingClass = method.getContainingClass();
|
||||
if (!InheritanceUtil.isInheritorOrSelf(methodContainingClass, fieldContainingClass, true)) {
|
||||
return null;
|
||||
}
|
||||
final PsiExpression rhs = assignment.getRExpression();
|
||||
if (!(rhs instanceof PsiReferenceExpression)) {
|
||||
return null;
|
||||
}
|
||||
final PsiReferenceExpression rReference = (PsiReferenceExpression)rhs;
|
||||
final PsiExpression rQualifier = rReference.getQualifierExpression();
|
||||
if (rQualifier != null) {
|
||||
return null;
|
||||
}
|
||||
final PsiElement rReferent = rReference.resolve();
|
||||
if (rReferent == null) {
|
||||
return null;
|
||||
}
|
||||
if (!(rReferent instanceof PsiParameter)) {
|
||||
return null;
|
||||
}
|
||||
final PsiType fieldType = field.getType();
|
||||
final PsiType parameterType = ((PsiVariable)rReferent).getType();
|
||||
if (fieldType.equalsToText(parameterType.getCanonicalText())) {
|
||||
return field;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isSimpleSetter(PsiMethod method) {
|
||||
return getFieldOfSetter(method) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiMethod getReversePropertyMethod(PsiMethod propertyMethod) {
|
||||
if (propertyMethod == null) {
|
||||
return null;
|
||||
}
|
||||
final PsiClass aClass = propertyMethod.getContainingClass();
|
||||
if (aClass == null) {
|
||||
return null;
|
||||
}
|
||||
final String methodName = propertyMethod.getName();
|
||||
final String prefix;
|
||||
if (methodName.startsWith("get")) {
|
||||
prefix = "get";
|
||||
}
|
||||
else if (methodName.startsWith(IS_PREFIX)) {
|
||||
prefix = IS_PREFIX;
|
||||
}
|
||||
else if (methodName.startsWith("set")) {
|
||||
prefix = "set";
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
final String name = methodName.substring(prefix.length());
|
||||
final PsiField field = prefix.equals("set") ? getFieldOfSetter(propertyMethod) : getFieldOfGetter(propertyMethod);
|
||||
if (field == null) {
|
||||
return null;
|
||||
}
|
||||
if (prefix.equals("set")) {
|
||||
final PsiMethod result = findPropertyMethod(aClass, "get", name, field);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
return findPropertyMethod(aClass, IS_PREFIX, name, field);
|
||||
}
|
||||
else {
|
||||
return findPropertyMethod(aClass, "set", name, field);
|
||||
}
|
||||
}
|
||||
|
||||
private static PsiMethod findPropertyMethod(@NotNull PsiClass aClass,
|
||||
@NotNull String prefix,
|
||||
@NotNull String propertyName,
|
||||
@NotNull PsiField field1) {
|
||||
final PsiMethod[] methods = aClass.findMethodsByName(prefix + propertyName, true);
|
||||
for (PsiMethod method : methods) {
|
||||
final PsiField field2 = prefix.equals("set") ? getFieldOfSetter(method) : getFieldOfGetter(method);
|
||||
if (field1.equals(field2)) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -39,10 +39,7 @@ import com.intellij.psi.impl.source.tree.JavaDocElementType;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -108,7 +105,7 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
|
||||
if (statements.length == 0) return false;
|
||||
|
||||
PsiStatement statement = statements[0];
|
||||
if (PropertyUtil.isSimplePropertyGetter(method)) {
|
||||
if (PropertyUtilBase.isSimplePropertyGetter(method)) {
|
||||
if (statement instanceof PsiReturnStatement) {
|
||||
return ((PsiReturnStatement)statement).getReturnValue() instanceof PsiReferenceExpression;
|
||||
}
|
||||
@@ -127,7 +124,7 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
|
||||
return lhs instanceof PsiReferenceExpression &&
|
||||
rhs instanceof PsiReferenceExpression &&
|
||||
!((PsiReferenceExpression)rhs).isQualified() &&
|
||||
PropertyUtil.isSimplePropertySetter(method); // last check because it can perform long return type resolve
|
||||
PropertyUtilBase.isSimplePropertySetter(method); // last check because it can perform long return type resolve
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,7 @@
|
||||
package com.intellij.codeInsight.highlighting;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import com.intellij.psi.util.PropertyUtilBase;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -61,7 +61,7 @@ public class JavaReadWriteAccessDetector extends ReadWriteAccessDetector {
|
||||
if (!writeAccess && expr instanceof PsiReferenceExpression) {
|
||||
//when searching usages of fields, should show all found setters as a "only write usage"
|
||||
PsiElement actualReferee = ((PsiReferenceExpression) expr).resolve();
|
||||
if (actualReferee instanceof PsiMethod && PropertyUtil.isSimplePropertySetter((PsiMethod)actualReferee)) {
|
||||
if (actualReferee instanceof PsiMethod && PropertyUtilBase.isSimplePropertySetter((PsiMethod)actualReferee)) {
|
||||
writeAccess = true;
|
||||
readAccess = false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed 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 com.intellij.psi.stub;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.impl.source.PsiFileImpl;
|
||||
import com.intellij.psi.impl.source.PsiMethodImpl;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.psi.stubs.StubTree;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
|
||||
public class JavaStubImplUtil {
|
||||
public static int getMethodStubIndex(PsiMethod method) {
|
||||
if (!(method instanceof PsiMethodImpl)) return -1;
|
||||
PsiFileImpl file = (PsiFileImpl)method.getContainingFile();
|
||||
if (file.getElementTypeForStubBuilder() == null) return -1;
|
||||
StubTree stubTree = file.getStubTree();
|
||||
if (stubTree == null) {
|
||||
stubTree = file.calcStubTree();
|
||||
}
|
||||
|
||||
PsiElement[] stubs = stubTree
|
||||
.getPlainList()
|
||||
.stream()
|
||||
.filter(e -> e.getStubType() == JavaElementType.METHOD)
|
||||
.map(StubElement::getPsi)
|
||||
.toArray(PsiElement[]::new);
|
||||
return ArrayUtil.indexOf(stubs, method);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,7 +28,7 @@ import com.intellij.openapi.project.IndexNotReadyException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import com.intellij.psi.util.PropertyUtilBase;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -65,7 +65,7 @@ public class PropertyGroup implements Group, ColoredItemPresentation, AccessLeve
|
||||
public static PropertyGroup createOn(PsiElement object, final TreeElement treeElement) {
|
||||
if (object instanceof PsiField) {
|
||||
PsiField field = (PsiField)object;
|
||||
PropertyGroup group = new PropertyGroup(PropertyUtil.suggestPropertyName(field), field.getType(),
|
||||
PropertyGroup group = new PropertyGroup(PropertyUtilBase.suggestPropertyName(field), field.getType(),
|
||||
field.hasModifierProperty(PsiModifier.STATIC), object.getProject());
|
||||
group.setField(field);
|
||||
group.myChildren.add(treeElement);
|
||||
@@ -73,16 +73,16 @@ public class PropertyGroup implements Group, ColoredItemPresentation, AccessLeve
|
||||
}
|
||||
else if (object instanceof PsiMethod) {
|
||||
PsiMethod method = (PsiMethod)object;
|
||||
if (PropertyUtil.isSimplePropertyGetter(method)) {
|
||||
PropertyGroup group = new PropertyGroup(PropertyUtil.getPropertyNameByGetter(method), method.getReturnType(),
|
||||
if (PropertyUtilBase.isSimplePropertyGetter(method)) {
|
||||
PropertyGroup group = new PropertyGroup(PropertyUtilBase.getPropertyNameByGetter(method), method.getReturnType(),
|
||||
method.hasModifierProperty(PsiModifier.STATIC), object.getProject());
|
||||
group.setGetter(method);
|
||||
group.myChildren.add(treeElement);
|
||||
return group;
|
||||
}
|
||||
else if (PropertyUtil.isSimplePropertySetter(method)) {
|
||||
else if (PropertyUtilBase.isSimplePropertySetter(method)) {
|
||||
PropertyGroup group =
|
||||
new PropertyGroup(PropertyUtil.getPropertyNameBySetter(method), method.getParameterList().getParameters()[0].getType(),
|
||||
new PropertyGroup(PropertyUtilBase.getPropertyNameBySetter(method), method.getParameterList().getParameters()[0].getType(),
|
||||
method.hasModifierProperty(PsiModifier.STATIC), object.getProject());
|
||||
group.setSetter(method);
|
||||
group.myChildren.add(treeElement);
|
||||
|
||||
@@ -13,8 +13,6 @@ class Editor {
|
||||
}
|
||||
|
||||
class Main {
|
||||
|
||||
|
||||
void stats() {
|
||||
Editor e = <caret>
|
||||
}
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed 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 com.intellij.util
|
||||
|
||||
import com.intellij.ide.highlighter.JavaFileType
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.psi.util.PropertyMemberType
|
||||
import com.intellij.psi.util.PropertyUtil
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
||||
import kotlin.test.assertNotEquals
|
||||
|
||||
class JavaPropertyDetectionTest : LightCodeInsightFixtureTestCase() {
|
||||
|
||||
// getter field test
|
||||
|
||||
fun testFieldRef() {
|
||||
assertPropertyMember("""class Some {private String name;public String getN<caret>ame() { return name; }}""", PropertyMemberType.GETTER)
|
||||
}
|
||||
|
||||
fun testUnresolvedRef() {
|
||||
assertNotPropertyMember("class Some { public String getN<caret>ame() { return name; }}", PropertyMemberType.GETTER)
|
||||
}
|
||||
|
||||
fun testUnresolvedRef2() {
|
||||
assertNotPropertyMember("""class Some {private String name;public static String getN<caret>ame() { return name; }}""", PropertyMemberType.GETTER)
|
||||
}
|
||||
|
||||
fun testSuperFieldRef() {
|
||||
doTest("""class Some extends SomeBase {public String getN<caret>ame() { return name; }}class SomeBase { private String name;}""", PropertyMemberType.GETTER,
|
||||
false)
|
||||
}
|
||||
|
||||
fun testSuperFieldRef2() {
|
||||
assertPropertyMember("""class Some extends SomeBase
|
||||
|{public String getN<caret>ame() { return name; }}class SomeBase { protected String name;}""".trimMargin(), PropertyMemberType.GETTER)
|
||||
}
|
||||
|
||||
fun testInconsistentType() {
|
||||
assertNotPropertyMember("""class Some
|
||||
|{String name;public long getNa<caret>me() { return name;}}""".trimMargin(), PropertyMemberType.GETTER)
|
||||
|
||||
}
|
||||
|
||||
fun testWithSuperKeyWord() {
|
||||
assertPropertyMember("""import java.util.List; class Some extends SomeBase
|
||||
|{ List<String> getL<caret>ist() { return Some.super.list;}} class SomeBase {List<String> list;} """.trimMargin(), PropertyMemberType.GETTER)
|
||||
}
|
||||
|
||||
fun testRedundantParenthesises() {
|
||||
assertNotPropertyMember("""import java.util.List;
|
||||
class Some {
|
||||
Some a;
|
||||
List<String> list;
|
||||
List<String> getL<caret>ist() {return (a).list;}
|
||||
}""", PropertyMemberType.GETTER)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// setter field test
|
||||
|
||||
fun testSimpleSetter() {
|
||||
assertPropertyMember("""class Some {
|
||||
|private String name; public void set<caret>Name(String name) { this.name = name; }}""".trimMargin(), PropertyMemberType.SETTER)
|
||||
}
|
||||
|
||||
fun testFieldNotResolved() {
|
||||
assertNotPropertyMember("""class Some {
|
||||
| public void set<caret>Name(String name) { this.name = name; }}""".trimMargin(), PropertyMemberType.SETTER)
|
||||
}
|
||||
|
||||
fun testInvalidExpression() {
|
||||
assertNotPropertyMember("""class Some {
|
||||
|public void set<caret>Name(String name) { = name; }}""".trimMargin(), PropertyMemberType.SETTER)
|
||||
}
|
||||
|
||||
fun testInvalidReference() {
|
||||
assertNotPropertyMember("""class Some {
|
||||
|public void set<caret>Name(String name) { name = name; }}""".trimMargin(), PropertyMemberType.SETTER)
|
||||
}
|
||||
|
||||
fun testSuperClassField() {
|
||||
assertPropertyMember( """class Some extends SomeBase {
|
||||
| public void set<caret>Name(String name) { this.name = name; }}
|
||||
| class SomeBase {protected String name;}""".trimMargin(), PropertyMemberType.SETTER)
|
||||
}
|
||||
|
||||
fun testRefWithSuperKeyword() {
|
||||
assertPropertyMember( """class Some extends SomeBase {
|
||||
|public void set<caret>Name(String name) { Some.super.name = name; }}
|
||||
| class SomeBase {protected String name;}""".trimMargin(), PropertyMemberType.SETTER)
|
||||
}
|
||||
|
||||
fun testOuterClassFieldSetter() {
|
||||
assertNotPropertyMember("""class Outer {String name; class Some {
|
||||
|public void set<caret>Name(String name) { this.name = name; }}}""".trimMargin(), PropertyMemberType.SETTER)
|
||||
}
|
||||
|
||||
private fun assertPropertyMember(text: String, memberType: PropertyMemberType) {
|
||||
doTest(text, memberType, true)
|
||||
}
|
||||
|
||||
private fun assertNotPropertyMember(text: String, memberType: PropertyMemberType) {
|
||||
doTest(text, memberType, false)
|
||||
}
|
||||
|
||||
private fun doTest(text: String, memberType: PropertyMemberType, expectedDecision: Boolean) {
|
||||
assertNotEquals(PropertyMemberType.FIELD, memberType)
|
||||
myFixture.configureByText(JavaFileType.INSTANCE, text)
|
||||
val method = PsiTreeUtil.getNonStrictParentOfType(myFixture.elementAtCaret, PsiMethod::class.java)
|
||||
assertNotNull(method)
|
||||
//use index
|
||||
assertEquals(expectedDecision, if (memberType == PropertyMemberType.GETTER) PropertyUtil.isSimpleGetter(method) else PropertyUtil.isSimpleSetter(method))
|
||||
//use ast
|
||||
assertEquals(expectedDecision, if (memberType == PropertyMemberType.GETTER) PropertyUtil.isSimpleGetter(method, false) else PropertyUtil.isSimpleSetter(method, false))
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,7 +24,7 @@ import com.intellij.ide.TypePresentationService;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.ProjectScope;
|
||||
import com.intellij.psi.util.PropertyMemberType;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import com.intellij.psi.util.PropertyUtilBase;
|
||||
import com.intellij.util.xml.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -67,11 +67,11 @@ public abstract class AbstractMemberResolveConverter extends ResolvingConverter<
|
||||
if (field != null) return field;
|
||||
break;
|
||||
case GETTER:
|
||||
final PsiMethod getter = PropertyUtil.findPropertyGetter(psiClass, getPropertyName(s, context), false, isLookDeep());
|
||||
final PsiMethod getter = PropertyUtilBase.findPropertyGetter(psiClass, getPropertyName(s, context), false, isLookDeep());
|
||||
if (getter != null) return getter;
|
||||
break;
|
||||
case SETTER:
|
||||
final PsiMethod setter = PropertyUtil.findPropertySetter(psiClass, getPropertyName(s, context), false, isLookDeep());
|
||||
final PsiMethod setter = PropertyUtilBase.findPropertySetter(psiClass, getPropertyName(s, context), false, isLookDeep());
|
||||
if (setter != null) return setter;
|
||||
break;
|
||||
}
|
||||
@@ -110,7 +110,7 @@ public abstract class AbstractMemberResolveConverter extends ResolvingConverter<
|
||||
}
|
||||
|
||||
protected boolean methodSuits(final PsiMethod psiMethod) {
|
||||
return !psiMethod.isConstructor() && !psiMethod.hasModifierProperty(PsiModifier.STATIC) && PropertyUtil.getPropertyName(psiMethod) != null;
|
||||
return !psiMethod.isConstructor() && !psiMethod.hasModifierProperty(PsiModifier.STATIC) && PropertyUtilBase.getPropertyName(psiMethod) != null;
|
||||
}
|
||||
|
||||
protected boolean fieldSuits(final PsiField psiField) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,7 @@ import com.intellij.codeInsight.completion.*;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import com.intellij.psi.util.PropertyUtilBase;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.jetbrains.python.psi.*;
|
||||
@@ -62,8 +62,8 @@ public class PyConstructorArgumentCompletionContributor extends CompletionContri
|
||||
// see PyJavaType.init() in Jython source code for matching logic
|
||||
for (PsiMethod method : containingClass.getAllMethods()) {
|
||||
final Project project = containingClass.getProject();
|
||||
if (PropertyUtil.isSimplePropertySetter(method)) {
|
||||
final String propName = PropertyUtil.getPropertyName(method);
|
||||
if (PropertyUtilBase.isSimplePropertySetter(method)) {
|
||||
final String propName = PropertyUtilBase.getPropertyName(method);
|
||||
result.addElement(PyUtil.createNamedParameterLookup(propName, project));
|
||||
}
|
||||
else if (method.getName().startsWith("add") && method.getName().endsWith("Listener") && PsiType.VOID.equals(method.getReturnType())) {
|
||||
|
||||
@@ -1769,6 +1769,8 @@
|
||||
<fileBasedIndex implementation="com.intellij.codeInspection.bytecodeAnalysis.BytecodeAnalysisIndex"/>
|
||||
<fileBasedIndex implementation="com.intellij.psi.RefQueueIndex"/>
|
||||
<fileBasedIndex implementation="com.intellij.psi.impl.java.stubs.index.JavaAutoModuleNameIndex"/>
|
||||
<fileBasedIndex implementation="com.intellij.psi.impl.search.JavaNullMethodArgumentIndex"/>
|
||||
<fileBasedIndex implementation="com.intellij.psi.impl.JavaSimplePropertyIndex"/>
|
||||
|
||||
<stubElementTypeHolder class="com.intellij.psi.impl.java.stubs.JavaStubElementTypes"/>
|
||||
|
||||
@@ -1993,8 +1995,6 @@
|
||||
<refactoring.pushDown language="JAVA" implementationClass="com.intellij.refactoring.memberPushDown.JavaPushDownDelegate" id="java"/>
|
||||
<library.javaSourceRootDetector implementation="com.intellij.openapi.roots.ui.configuration.LibraryJavaSourceRootDetector"/>
|
||||
|
||||
<fileBasedIndex implementation="com.intellij.psi.impl.search.JavaNullMethodArgumentIndex"/>
|
||||
|
||||
<codeUsageScopeOptimizer implementation="com.intellij.compiler.JavaCompilerReferencesCodeUsageScopeOptimizer"/>
|
||||
<importTestOutput implementation="com.intellij.execution.AntTestContentHandler$AntTestOutputExtension"/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user