mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-10 08:31:29 +00:00
Find Usages: Add support of naming conventions
#KT-1356 Fixed
This commit is contained in:
@@ -1,4 +1,29 @@
|
||||
<root>
|
||||
<item name='com.google.common.collect.ImmutableBiMap com.google.common.collect.ImmutableBiMap<V,K> inverse()'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item name='com.google.common.collect.ImmutableSet com.google.common.collect.ImmutableSet<E> of()'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item name='com.google.common.collect.ImmutableSet com.google.common.collect.ImmutableSet<E> of(E)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item name='com.google.common.collect.ImmutableSet com.google.common.collect.ImmutableSet<E> of(E, E)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item name='com.google.common.collect.ImmutableSet com.google.common.collect.ImmutableSet.Builder<E> builder()'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item name='com.google.common.collect.ImmutableSet.Builder com.google.common.collect.ImmutableSet<E> build()'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item name='com.google.common.collect.ImmutableSet.Builder com.google.common.collect.ImmutableSet.Builder<E> add(E)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item
|
||||
name='com.google.common.collect.ImmutableSet.Builder com.google.common.collect.ImmutableSet.Builder<E> addAll(java.lang.Iterable<? extends E>)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item name='com.google.common.collect.Lists java.util.ArrayList<E> newArrayList(E...)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
|
||||
10
annotations/com/intellij/lang/cacheBuilder/annotations.xml
Normal file
10
annotations/com/intellij/lang/cacheBuilder/annotations.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<root>
|
||||
<item
|
||||
name='com.intellij.lang.cacheBuilder.WordsScanner void processWords(java.lang.CharSequence, com.intellij.util.Processor<com.intellij.lang.cacheBuilder.WordOccurrence>) 0'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item
|
||||
name='com.intellij.lang.cacheBuilder.WordsScanner void processWords(java.lang.CharSequence, com.intellij.util.Processor<com.intellij.lang.cacheBuilder.WordOccurrence>) 1'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
6
annotations/com/intellij/openapi/roots/annotations.xml
Normal file
6
annotations/com/intellij/openapi/roots/annotations.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<root>
|
||||
<item
|
||||
name='com.intellij.openapi.roots.FileIndexFacade com.intellij.openapi.roots.FileIndexFacade getInstance(com.intellij.openapi.project.Project)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
5
annotations/com/intellij/util/indexing/annotations.xml
Normal file
5
annotations/com/intellij/util/indexing/annotations.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<root>
|
||||
<item name='com.intellij.util.indexing.FileBasedIndex com.intellij.util.indexing.FileBasedIndex getInstance()'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
@@ -17,11 +17,13 @@
|
||||
package org.jetbrains.jet.lang.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.JetNodeTypes;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -55,4 +57,14 @@ public class JetMultiDeclaration extends JetDeclarationImpl {
|
||||
public ASTNode getValOrVarNode() {
|
||||
return getNode().findChildByType(TokenSet.create(VAL_KEYWORD, VAR_KEYWORD));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement getRPar() {
|
||||
return findChildByType(JetTokens.RPAR);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement getLPar() {
|
||||
return findChildByType(JetTokens.LPAR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -898,7 +898,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
else if (OperatorConventions.EQUALS_OPERATIONS.contains(operationType)) {
|
||||
result = visitEquality(expression, context, operationSign, left, right);
|
||||
}
|
||||
else if (operationType == JetTokens.EQEQEQ || operationType == JetTokens.EXCLEQEQEQ) {
|
||||
else if (OperatorConventions.IDENTITY_EQUALS_OPERATIONS.contains(operationType)) {
|
||||
context.trace.record(REFERENCE_TARGET, operationSign, KotlinBuiltIns.getInstance().getIdentityEquals());
|
||||
ensureNonemptyIntersectionOfOperandTypes(expression, context);
|
||||
// TODO : Check comparison pointlessness
|
||||
result = JetTypeInfo.create(KotlinBuiltIns.getInstance().getBooleanType(), context.dataFlowInfo);
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.jet.lang.types.expressions;
|
||||
|
||||
import com.google.common.collect.ImmutableBiMap;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -28,6 +27,7 @@ import org.jetbrains.jet.lexer.JetTokens;
|
||||
public class OperatorConventions {
|
||||
|
||||
public static final Name EQUALS = Name.identifier("equals");
|
||||
public static final Name IDENTITY_EQUALS = Name.identifier("identityEquals");
|
||||
public static final Name COMPARE_TO = Name.identifier("compareTo");
|
||||
public static final Name CONTAINS = Name.identifier("contains");
|
||||
|
||||
@@ -77,6 +77,9 @@ public class OperatorConventions {
|
||||
public static final ImmutableSet<JetToken> EQUALS_OPERATIONS =
|
||||
ImmutableSet.<JetToken>of(JetTokens.EQEQ, JetTokens.EXCLEQ);
|
||||
|
||||
public static final ImmutableSet<JetToken> IDENTITY_EQUALS_OPERATIONS =
|
||||
ImmutableSet.<JetToken>of(JetTokens.EQEQEQ, JetTokens.EXCLEQEQEQ);
|
||||
|
||||
public static final ImmutableSet<JetToken> IN_OPERATIONS =
|
||||
ImmutableSet.<JetToken>of(JetTokens.IN_KEYWORD, JetTokens.NOT_IN);
|
||||
|
||||
@@ -88,7 +91,7 @@ public class OperatorConventions {
|
||||
.put(JetTokens.MINUSEQ, Name.identifier("minusAssign"))
|
||||
.build();
|
||||
|
||||
public static final ImmutableMap<JetToken, JetToken> ASSIGNMENT_OPERATION_COUNTERPARTS = ImmutableMap.<JetToken, JetToken>builder()
|
||||
public static final ImmutableBiMap<JetToken, JetToken> ASSIGNMENT_OPERATION_COUNTERPARTS = ImmutableBiMap.<JetToken, JetToken>builder()
|
||||
.put(JetTokens.MULTEQ, JetTokens.MUL)
|
||||
.put(JetTokens.DIVEQ, JetTokens.DIV)
|
||||
.put(JetTokens.PERCEQ, JetTokens.PERC)
|
||||
@@ -100,7 +103,7 @@ public class OperatorConventions {
|
||||
.put(JetTokens.ANDAND, Name.identifier("and"))
|
||||
.put(JetTokens.OROR, Name.identifier("or"))
|
||||
.build();
|
||||
|
||||
|
||||
@Nullable
|
||||
public static Name getNameForOperationSymbol(@NotNull JetToken token) {
|
||||
Name name = UNARY_OPERATION_NAMES.get(token);
|
||||
|
||||
@@ -105,7 +105,7 @@ public interface JetTokens {
|
||||
JetSingleValueToken EQEQEQ = new JetSingleValueToken("EQEQEQ", "===");
|
||||
JetSingleValueToken ARROW = new JetSingleValueToken("ARROW", "->");
|
||||
JetSingleValueToken DOUBLE_ARROW = new JetSingleValueToken("DOUBLE_ARROW", "=>");
|
||||
JetSingleValueToken EXCLEQEQEQ = new JetSingleValueToken("EXCLEQEQEQ", "!===");
|
||||
JetSingleValueToken EXCLEQEQEQ = new JetSingleValueToken("EXCLEQEQEQ", "!==");
|
||||
JetSingleValueToken EQEQ = new JetSingleValueToken("EQEQ", "==");
|
||||
JetSingleValueToken EXCLEQ = new JetSingleValueToken("EXCLEQ", "!=");
|
||||
JetSingleValueToken EXCLEXCL = new JetSingleValueToken("EXCLEXCL", "!!");
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.types.lang;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Lists;
|
||||
import kotlin.KotlinPackage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.PlatformToKotlinClassMap;
|
||||
@@ -881,4 +882,15 @@ public class KotlinBuiltIns {
|
||||
public JetType getDefaultBound() {
|
||||
return getNullableAnyType();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// GET FUNCTION
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@NotNull
|
||||
public FunctionDescriptor getIdentityEquals() {
|
||||
return KotlinPackage.first(getBuiltInsPackageFragment().getMemberScope().getFunctions(Name.identifier("identityEquals")));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,20 +21,13 @@ import com.intellij.lang.findUsages.FindUsagesProvider
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiNamedElement
|
||||
import org.jetbrains.jet.lang.psi.*
|
||||
import org.jetbrains.jet.lexer.JetLexer
|
||||
import com.intellij.lang.cacheBuilder.DefaultWordsScanner
|
||||
import org.jetbrains.jet.lexer.JetTokens
|
||||
import com.intellij.psi.tree.TokenSet
|
||||
import org.jetbrains.jet.plugin.refactoring.changeSignature.JetParameterInfo
|
||||
|
||||
public class JetFindUsagesProvider : FindUsagesProvider {
|
||||
class JetWordsScanner : DefaultWordsScanner(JetLexer(), TokenSet.create(JetTokens.IDENTIFIER), JetTokens.COMMENTS, JetTokens.STRINGS)
|
||||
|
||||
public override fun canFindUsagesFor(psiElement: PsiElement): Boolean =
|
||||
psiElement is JetNamedDeclaration
|
||||
|
||||
public override fun getWordsScanner(): WordsScanner =
|
||||
JetWordsScanner()
|
||||
KotlinWordsScanner()
|
||||
|
||||
public override fun getHelpId(psiElement: PsiElement): String? = null
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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 org.jetbrains.jet.plugin.findUsages
|
||||
|
||||
import org.jetbrains.jet.plugin.search.usagesSearch.*
|
||||
import com.intellij.lang.cacheBuilder.WordsScanner
|
||||
import com.intellij.util.Processor
|
||||
import org.jetbrains.jet.lexer.JetLexer
|
||||
import com.intellij.lang.cacheBuilder.WordOccurrence
|
||||
import org.jetbrains.jet.lexer.JetTokens
|
||||
import com.intellij.lang.cacheBuilder.SimpleWordsScanner
|
||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions
|
||||
|
||||
class KotlinWordsScanner() : WordsScanner {
|
||||
private val lexer = JetLexer()
|
||||
private val simpleWordsScanner = SimpleWordsScanner()
|
||||
|
||||
fun scanWords(kind: WordOccurrence.Kind, processor: Processor<WordOccurrence>) {
|
||||
val tokenStart = lexer.getTokenStart()
|
||||
simpleWordsScanner.processWords(lexer.getTokenSequence()) {
|
||||
it!!.init(lexer.getBufferSequence(), tokenStart + it.getStart(), tokenStart + it.getEnd(), kind)
|
||||
processor.process(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun processWords(fileText: CharSequence, processor: Processor<WordOccurrence>) {
|
||||
lexer.start(fileText)
|
||||
|
||||
val occurrence = WordOccurrence(null, 0, 0, null)
|
||||
|
||||
stream { lexer.getTokenType() }.forEach { elementType ->
|
||||
// todo: replace with when
|
||||
if (ALL_SEARCHABLE_OPERATIONS.contains(elementType)) {
|
||||
occurrence.init(lexer.getBufferSequence(), lexer.getTokenStart(), lexer.getTokenEnd(), WordOccurrence.Kind.CODE)
|
||||
processor.process(occurrence)
|
||||
}
|
||||
else if (JetTokens.COMMENTS.contains(elementType)) scanWords(WordOccurrence.Kind.COMMENTS, processor)
|
||||
else if (JetTokens.STRINGS.contains(elementType)) scanWords(WordOccurrence.Kind.LITERALS, processor)
|
||||
else scanWords(WordOccurrence.Kind.CODE, processor)
|
||||
|
||||
lexer.advance()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,10 @@ import org.jetbrains.jet.lang.psi.JetMultiDeclaration
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import java.util.Collections
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor
|
||||
import org.jetbrains.jet.lang.resolve.source.PsiSourceElement
|
||||
import org.jetbrains.jet.lang.resolve.source.getPsi
|
||||
|
||||
class JetMultiDeclarationReference(element: JetMultiDeclaration) : JetMultiReference<JetMultiDeclaration>(element) {
|
||||
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
|
||||
@@ -28,14 +32,10 @@ class JetMultiDeclarationReference(element: JetMultiDeclaration) : JetMultiRefer
|
||||
}.filterNotNull()
|
||||
}
|
||||
|
||||
|
||||
override fun getRangeInElement(): TextRange? {
|
||||
val entries = expression.getEntries()
|
||||
if (entries.isEmpty()) {
|
||||
return TextRange.EMPTY_RANGE
|
||||
}
|
||||
val start = entries.first!!.getStartOffsetInParent()
|
||||
val end = entries.last!!.getStartOffsetInParent() + entries.last!!.getTextLength()
|
||||
return TextRange(start, end)
|
||||
val start = expression.getLPar()
|
||||
val end = expression.getRPar()
|
||||
if (start == null || end == null) return TextRange.EMPTY_RANGE
|
||||
return TextRange(start.getStartOffsetInParent(), end.getStartOffsetInParent())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,17 +28,13 @@ import org.jetbrains.jet.lang.resolve.BindingContext
|
||||
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
|
||||
import java.util.Collections
|
||||
import java.util.HashSet
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils
|
||||
import org.jetbrains.jet.lang.descriptors.PackageViewDescriptor
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import org.jetbrains.jet.lang.psi.JetReferenceExpression
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.jet.plugin.codeInsight.DescriptorToDeclarationUtil
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import org.jetbrains.jet.asJava.*
|
||||
import org.jetbrains.jet.lang.psi.JetElement
|
||||
import org.jetbrains.jet.utils.keysToMap
|
||||
import com.intellij.psi.PsiMethod
|
||||
import org.jetbrains.jet.plugin.search.allScope
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils
|
||||
|
||||
@@ -65,20 +61,16 @@ abstract class AbstractJetReference<T : JetElement>(element: T)
|
||||
return null
|
||||
}
|
||||
|
||||
override fun isReferenceTo(element: PsiElement?): Boolean {
|
||||
return element != null && matchesTarget(element)
|
||||
}
|
||||
|
||||
override fun getCanonicalText(): String = "<TBD>"
|
||||
|
||||
override fun handleElementRename(newElementName: String?): PsiElement? = throw IncorrectOperationException()
|
||||
|
||||
override fun bindToElement(element: PsiElement): PsiElement = throw IncorrectOperationException()
|
||||
|
||||
protected fun checkElementMatch(referenceTarget: PsiElement, elementToMatch: PsiElement): Boolean {
|
||||
val unwrappedTarget = referenceTarget.namedUnwrappedElement
|
||||
val unwrappedElementToMatch = elementToMatch.namedUnwrappedElement
|
||||
|
||||
return (unwrappedTarget == unwrappedElementToMatch) ||
|
||||
(referenceTarget is PsiMethod && referenceTarget.isConstructor() && referenceTarget.getContainingClass() == elementToMatch)
|
||||
}
|
||||
|
||||
[suppress("CAST_NEVER_SUCCEEDS")]
|
||||
override fun getVariants(): Array<Any> = PsiReference.EMPTY_ARRAY as Array<Any>
|
||||
|
||||
@@ -152,21 +144,6 @@ public abstract class JetSimpleReference<T : JetReferenceExpression>(expression:
|
||||
}
|
||||
return context[BindingContext.AMBIGUOUS_REFERENCE_TARGET, expression].orEmpty()
|
||||
}
|
||||
|
||||
override fun isReferenceTo(element: PsiElement?): Boolean {
|
||||
val resolvedElement = resolve()
|
||||
if (resolvedElement == null || element == null) {
|
||||
return false
|
||||
}
|
||||
return checkElementMatch(resolvedElement, element)
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class JetMultiReference<T : JetElement>(expression: T) : AbstractJetReference<T>(expression) {
|
||||
override fun isReferenceTo(element: PsiElement?): Boolean {
|
||||
if (element == null) {
|
||||
return false
|
||||
}
|
||||
return multiResolve(false).map { it.getElement() }.filterNotNull().any { checkElementMatch(it, element) }
|
||||
}
|
||||
}
|
||||
public abstract class JetMultiReference<T : JetElement>(expression: T) : AbstractJetReference<T>(expression)
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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 org.jetbrains.jet.plugin.references
|
||||
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.jet.asJava.unwrapped
|
||||
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor
|
||||
import com.intellij.psi.PsiMethod
|
||||
import org.jetbrains.jet.lang.psi.JetPropertyAccessor
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.getParentByType
|
||||
import org.jetbrains.jet.lang.psi.JetProperty
|
||||
import java.util.HashSet
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import org.jetbrains.jet.lang.psi.JetNamedDeclaration
|
||||
|
||||
// Navigation element of the resolved reference
|
||||
// For property accessor return enclosing property
|
||||
val PsiReference.unwrappedTargets: Set<PsiElement>
|
||||
get() {
|
||||
fun PsiElement.adjust(): PsiElement? {
|
||||
val target = unwrapped
|
||||
return if (target is JetPropertyAccessor) target.getParentByType(javaClass<JetProperty>()) else target
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is JetMultiReference<*> -> multiResolve(false).map { it.getElement()?.adjust() }.filterNotNullTo(HashSet<PsiElement>())
|
||||
else -> ContainerUtil.createMaybeSingletonSet(resolve()?.adjust())
|
||||
}
|
||||
}
|
||||
|
||||
fun PsiReference.matchesTarget(target: PsiElement): Boolean {
|
||||
val unwrapped = target.unwrapped
|
||||
return when {
|
||||
unwrapped in unwrappedTargets ->
|
||||
true
|
||||
|
||||
this is JetReference
|
||||
&& unwrappedTargets.any { it is PsiMethod && it.isConstructor() && it.getContainingClass() == unwrapped } ->
|
||||
true
|
||||
|
||||
else ->
|
||||
false
|
||||
}
|
||||
}
|
||||
@@ -24,11 +24,13 @@ import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.asJava.AsJavaPackage;
|
||||
import org.jetbrains.jet.asJava.LightClassUtil;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.java.jetAsJava.KotlinLightMethod;
|
||||
import org.jetbrains.jet.plugin.JetPluginUtil;
|
||||
import org.jetbrains.jet.plugin.search.usagesSearch.*;
|
||||
|
||||
public class KotlinReferencesSearcher extends QueryExecutorBase<PsiReference, ReferencesSearch.SearchParameters> {
|
||||
public static void processJetClassOrObject(
|
||||
@@ -43,20 +45,48 @@ public class KotlinReferencesSearcher extends QueryExecutorBase<PsiReference, Re
|
||||
}
|
||||
});
|
||||
if (lightClass != null) {
|
||||
queryParameters.getOptimizer().searchWord(className, queryParameters.getEffectiveSearchScope(), true, lightClass);
|
||||
searchNamedElement(queryParameters, lightClass, className);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processQuery(@NotNull ReferencesSearch.SearchParameters queryParameters, @NotNull Processor<PsiReference> consumer) {
|
||||
public void processQuery(
|
||||
@NotNull final ReferencesSearch.SearchParameters queryParameters,
|
||||
@NotNull final Processor<PsiReference> consumer
|
||||
) {
|
||||
PsiElement element = queryParameters.getElementToSearch();
|
||||
|
||||
PsiElement unwrappedElement = AsJavaPackage.getUnwrapped(element);
|
||||
if (unwrappedElement == null
|
||||
|| !JetPluginUtil.isInSource(unwrappedElement)
|
||||
|| JetPluginUtil.isKtFileInGradleProjectInWrongFolder(unwrappedElement)) return;
|
||||
final PsiNamedElement unwrappedElement = AsJavaPackage.getNamedUnwrappedElement(element);
|
||||
if (unwrappedElement == null || JetPluginUtil.isKtFileInGradleProjectInWrongFolder(unwrappedElement)) return;
|
||||
|
||||
ApplicationManager.getApplication().runReadAction(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
KotlinPsiSearchHelper searchHelper = new KotlinPsiSearchHelper(queryParameters.getElementToSearch().getProject());
|
||||
UsagesSearchTarget<PsiNamedElement> searchTarget = new UsagesSearchTarget<PsiNamedElement>(
|
||||
unwrappedElement,
|
||||
queryParameters.getEffectiveSearchScope(),
|
||||
UsagesSearchLocation.EVERYWHERE,
|
||||
false
|
||||
);
|
||||
UsagesSearchRequestItem requestItem = new UsagesSearchRequestItem(
|
||||
searchTarget,
|
||||
UsagesSearchPackage.getSpecialNamesToSearch(unwrappedElement),
|
||||
UsagesSearchPackage.getIsTargetUsage()
|
||||
);
|
||||
searchHelper.processFilesWithText(requestItem, consumer);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (!JetPluginUtil.isInSource(unwrappedElement)) return;
|
||||
|
||||
searchLightElements(queryParameters, element);
|
||||
}
|
||||
|
||||
private static void searchLightElements(ReferencesSearch.SearchParameters queryParameters, PsiElement element) {
|
||||
if (element instanceof JetClassOrObject) {
|
||||
processJetClassOrObject((JetClassOrObject) element, queryParameters);
|
||||
}
|
||||
@@ -99,7 +129,10 @@ public class KotlinReferencesSearcher extends QueryExecutorBase<PsiReference, Re
|
||||
}
|
||||
|
||||
private static void searchNamedElement(ReferencesSearch.SearchParameters queryParameters, PsiNamedElement element) {
|
||||
String name = element != null ? element.getName() : null;
|
||||
searchNamedElement(queryParameters, element, element != null ? element.getName() : null);
|
||||
}
|
||||
|
||||
private static void searchNamedElement(ReferencesSearch.SearchParameters queryParameters, PsiNamedElement element, @Nullable String name) {
|
||||
if (name != null) {
|
||||
queryParameters.getOptimizer().searchWord(name, queryParameters.getEffectiveSearchScope(), true, element);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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 org.jetbrains.jet.plugin.search.usagesSearch
|
||||
|
||||
import org.jetbrains.jet.lang.resolve.name.Name
|
||||
import org.jetbrains.jet.lexer.JetToken
|
||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions.*
|
||||
import com.google.common.collect.ImmutableSet
|
||||
import org.jetbrains.jet.lexer.JetTokens
|
||||
import org.jetbrains.jet.lexer.JetSingleValueToken
|
||||
import java.util.regex.Pattern
|
||||
|
||||
public val ALL_SEARCHABLE_OPERATIONS: ImmutableSet<JetToken> = ImmutableSet
|
||||
.builder<JetToken>()
|
||||
.addAll(UNARY_OPERATION_NAMES.keySet())
|
||||
.addAll(BINARY_OPERATION_NAMES.keySet())
|
||||
.addAll(ASSIGNMENT_OPERATIONS.keySet())
|
||||
.addAll(COMPARISON_OPERATIONS)
|
||||
.addAll(EQUALS_OPERATIONS)
|
||||
.addAll(IDENTITY_EQUALS_OPERATIONS)
|
||||
.addAll(IN_OPERATIONS)
|
||||
.add(JetTokens.LBRACKET)
|
||||
.add(JetTokens.LPAR)
|
||||
.add(JetTokens.BY_KEYWORD)
|
||||
.build()
|
||||
|
||||
public val ALL_SEARCHABLE_OPERATION_PATTERNS: Set<String> =
|
||||
ALL_SEARCHABLE_OPERATIONS.map { (it as JetSingleValueToken).getValue() }.toSet()
|
||||
|
||||
public val INDEXING_OPERATION_NAMES: ImmutableSet<Name> =
|
||||
ImmutableSet.of(Name.identifier("get"), Name.identifier("set"))
|
||||
|
||||
public val INVOKE_OPERATION_NAME: Name = Name.identifier("invoke")
|
||||
|
||||
public val ITERATOR_OPERATION_NAME: Name = Name.identifier("iterator")
|
||||
|
||||
public val COMPONENT_OPERATION_PATTERN: Pattern = Pattern.compile("component\\d+")
|
||||
|
||||
public val IN_OPERATIONS_TO_SEARCH: ImmutableSet<JetToken> = ImmutableSet.of(JetTokens.IN_KEYWORD)
|
||||
|
||||
public val COMPARISON_OPERATIONS_TO_SEARCH: ImmutableSet<JetToken> = ImmutableSet.of<JetToken>(JetTokens.LT, JetTokens.GT)
|
||||
|
||||
public fun Name.getOperationSymbolsToSearch(): Set<JetToken> {
|
||||
when (this) {
|
||||
COMPARE_TO -> return COMPARISON_OPERATIONS_TO_SEARCH
|
||||
EQUALS -> return EQUALS_OPERATIONS
|
||||
IDENTITY_EQUALS -> return IDENTITY_EQUALS_OPERATIONS
|
||||
CONTAINS -> return IN_OPERATIONS_TO_SEARCH
|
||||
INVOKE_OPERATION_NAME -> return ImmutableSet.of<JetToken>(JetTokens.LPAR)
|
||||
ITERATOR_OPERATION_NAME -> return ImmutableSet.of<JetToken>(JetTokens.IN_KEYWORD)
|
||||
in INDEXING_OPERATION_NAMES -> return ImmutableSet.of<JetToken>(JetTokens.LBRACKET)
|
||||
}
|
||||
|
||||
if (COMPONENT_OPERATION_PATTERN.matcher(asString()).matches()) return ImmutableSet.of<JetToken>(JetTokens.LPAR)
|
||||
|
||||
val unaryOp = UNARY_OPERATION_NAMES.inverse()[this]
|
||||
if (unaryOp != null) return ImmutableSet.of(unaryOp)
|
||||
|
||||
val binaryOp = BINARY_OPERATION_NAMES.inverse()[this]
|
||||
if (binaryOp != null) {
|
||||
val assignmentOp = ASSIGNMENT_OPERATION_COUNTERPARTS.inverse()[binaryOp]
|
||||
return if (assignmentOp != null) ImmutableSet.of<JetToken>(binaryOp, assignmentOp) else ImmutableSet.of<JetToken>(binaryOp)
|
||||
}
|
||||
|
||||
val assignmentOp = ASSIGNMENT_OPERATIONS.inverse()[this]
|
||||
if (assignmentOp != null) return ImmutableSet.of<JetToken>(assignmentOp)
|
||||
|
||||
return ImmutableSet.of<JetToken>()
|
||||
}
|
||||
@@ -18,8 +18,6 @@ package org.jetbrains.jet.plugin.search.usagesSearch
|
||||
|
||||
import com.intellij.psi.PsiReference
|
||||
import org.jetbrains.jet.lang.psi.JetClassOrObject
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.getParentByType
|
||||
import org.jetbrains.jet.lang.psi.JetImportDirective
|
||||
import org.jetbrains.jet.plugin.search.usagesSearch.*
|
||||
import org.jetbrains.jet.plugin.search.usagesSearch.UsagesSearchFilter.*
|
||||
import org.jetbrains.jet.lang.psi.JetProperty
|
||||
@@ -28,34 +26,35 @@ import java.util.Collections
|
||||
import java.util.ArrayList
|
||||
import org.jetbrains.jet.lang.psi.JetNamedDeclaration
|
||||
import com.intellij.psi.PsiNamedElement
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import org.jetbrains.jet.asJava.LightClassUtil
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.util.Query
|
||||
import com.intellij.psi.search.SearchRequestCollector
|
||||
import org.jetbrains.jet.lang.psi.JetCallableDeclaration
|
||||
import org.jetbrains.jet.lang.psi.JetParameter
|
||||
import org.jetbrains.jet.lang.psi.JetPsiUtil
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.*
|
||||
import org.jetbrains.jet.asJava.LightClassUtil.PropertyAccessorsPsiMethods
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.*
|
||||
import org.jetbrains.jet.lang.resolve.name.Name
|
||||
import org.jetbrains.jet.lexer.JetSingleValueToken
|
||||
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.jet.lexer.JetTokens
|
||||
import org.jetbrains.jet.plugin.references.*
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
|
||||
val isTargetUsage = (PsiReference::isTargetUsage).searchFilter
|
||||
|
||||
fun JetNamedDeclaration.namesWithAccessors(readable: Boolean = true, writable: Boolean = true): List<String> {
|
||||
val name = getName()!!
|
||||
val isTargetUsage = (PsiReference::matchesTarget).searchFilter
|
||||
|
||||
fun PsiNamedElement.getAccessorNames(readable: Boolean = true, writable: Boolean = true): List<String> {
|
||||
fun PropertyAccessorsPsiMethods.toNameList(): List<String> {
|
||||
val getter = getGetter()
|
||||
val setter = getSetter()
|
||||
|
||||
val result = arrayListOf(name)
|
||||
val result = ArrayList<String>()
|
||||
if (readable && getter != null) result.add(getter.getName())
|
||||
if (writable && setter != null) result.add(setter.getName())
|
||||
return result
|
||||
}
|
||||
|
||||
if (JetPsiUtil.isLocal(this)) return Collections.singletonList(name)
|
||||
if (this !is JetDeclaration || JetPsiUtil.isLocal(this)) return Collections.emptyList()
|
||||
|
||||
when (this) {
|
||||
is JetProperty ->
|
||||
@@ -66,21 +65,32 @@ fun JetNamedDeclaration.namesWithAccessors(readable: Boolean = true, writable: B
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.singletonList(name)
|
||||
return Collections.emptyList()
|
||||
}
|
||||
|
||||
public fun PsiNamedElement.getSpecialNamesToSearch(): List<String> {
|
||||
val name = getName()
|
||||
return when {
|
||||
name == null || !Name.isValidIdentifier(name) -> Collections.emptyList<String>()
|
||||
this is JetParameter -> {
|
||||
if (!hasValOrVarNode()) return Collections.emptyList<String>()
|
||||
|
||||
val context = AnalyzerFacadeWithCache.getContextForElement(this)
|
||||
val paramDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, this] as? ValueParameterDescriptor
|
||||
context[BindingContext.DATA_CLASS_COMPONENT_FUNCTION, paramDescriptor]?.let {
|
||||
listOf(it.getName().asString(), JetTokens.LPAR.getValue())
|
||||
} ?: Collections.emptyList<String>()
|
||||
}
|
||||
else -> Name.identifier(name).getOperationSymbolsToSearch().map { (it as JetSingleValueToken).getValue() }
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class UsagesSearchHelper<T : PsiNamedElement> {
|
||||
protected open fun makeFilter(target: UsagesSearchTarget<T>): UsagesSearchFilter = isTargetUsage
|
||||
|
||||
protected open fun makeWordList(target: UsagesSearchTarget<T>): List<String> {
|
||||
return with(target) {
|
||||
val name = element.getName()
|
||||
|
||||
when {
|
||||
name == null -> Collections.emptyList<String>()
|
||||
element is JetProperty, element is JetParameter -> (element as JetNamedDeclaration).namesWithAccessors()
|
||||
else -> Collections.singletonList(name)
|
||||
}
|
||||
return with(target.element) {
|
||||
ContainerUtil.createMaybeSingletonList(getName()) + getAccessorNames() + getSpecialNamesToSearch()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,7 +195,11 @@ class PropertyUsagesSearchHelper(
|
||||
skipImports: Boolean = false
|
||||
) : DefaultSearchHelper<JetNamedDeclaration>(skipImports), OverrideSearchHelper {
|
||||
override fun makeWordList(target: UsagesSearchTarget<JetNamedDeclaration>): List<String> {
|
||||
return target.element.namesWithAccessors(readable = readUsages, writable = writeUsages)
|
||||
return with(target.element) {
|
||||
ContainerUtil.createMaybeSingletonList(getName()) +
|
||||
getAccessorNames(readable = readUsages, writable = writeUsages) +
|
||||
getSpecialNamesToSearch()
|
||||
}
|
||||
}
|
||||
|
||||
override fun makeFilter(target: UsagesSearchTarget<JetNamedDeclaration>): UsagesSearchFilter {
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.jetbrains.jet.plugin.search.usagesSearch
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.util.QueryFactory
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.search.SearchRequestCollector
|
||||
import com.intellij.psi.search.SearchSession
|
||||
import com.intellij.psi.search.PsiSearchHelper
|
||||
@@ -29,7 +28,6 @@ import com.intellij.psi.search.SearchRequestQuery
|
||||
import com.intellij.util.UniqueResultsQuery
|
||||
import com.intellij.psi.search.searches.ReferenceDescriptor
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.psi.search.UsageSearchContext
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.search.RequestResultProcessor
|
||||
@@ -38,15 +36,22 @@ import com.intellij.openapi.application.QueryExecutorBase
|
||||
import com.intellij.psi.PsiReferenceService
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.psi.ReferenceRange
|
||||
import java.util.Collections
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import java.util.ArrayList
|
||||
import com.intellij.util.EmptyQuery
|
||||
import com.intellij.openapi.project.Project
|
||||
import java.util.ArrayDeque
|
||||
import org.jetbrains.jet.plugin.search.usagesSearch.UsagesSearchFilter.*
|
||||
import org.jetbrains.jet.plugin.search.and
|
||||
import com.intellij.psi.impl.search.PsiSearchHelperImpl
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.impl.cache.impl.id.IdIndexEntry
|
||||
import java.util.Collections
|
||||
import com.intellij.openapi.roots.FileIndexFacade
|
||||
import com.intellij.util.indexing.FileBasedIndex
|
||||
import com.intellij.psi.impl.cache.impl.id.IdIndex
|
||||
import org.jetbrains.jet.plugin.refactoring.runReadAction
|
||||
import com.intellij.psi.search.TextOccurenceProcessor
|
||||
import org.jetbrains.jet.plugin.references.JetMultiDeclarationReference
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.impl.PsiManagerEx
|
||||
|
||||
public data class UsagesSearchLocation(
|
||||
val inCode: Boolean = true,
|
||||
@@ -103,39 +108,61 @@ public data class UsagesSearchRequest(val project: Project, val items: List<Usag
|
||||
val collector: SearchRequestCollector = SearchRequestCollector(SearchSession())
|
||||
}
|
||||
|
||||
public object UsagesSearch: QueryFactory<PsiReference, UsagesSearchRequest>() {
|
||||
{
|
||||
class ResultProcessorImpl(private val node: UsagesSearchRequestItem) : RequestResultProcessor() {
|
||||
private val referenceService = PsiReferenceService.getService()!!
|
||||
public class KotlinPsiSearchHelper(private val project: Project): PsiSearchHelperImpl(PsiManager.getInstance(project) as PsiManagerEx) {
|
||||
class ResultTextProcessorImpl(
|
||||
private val node: UsagesSearchRequestItem,
|
||||
private val consumer: Processor<PsiReference>
|
||||
): TextOccurenceProcessor {
|
||||
private val referenceService = PsiReferenceService.getService()!!
|
||||
|
||||
override fun processTextOccurrence(element: PsiElement, offsetInElement: Int, consumer: Processor<PsiReference>): Boolean {
|
||||
return referenceService.getReferences(element, PsiReferenceService.Hints.NO_HINTS).all { ref ->
|
||||
ProgressManager.checkCanceled()
|
||||
override fun execute(element: PsiElement, offsetInElement: Int): Boolean {
|
||||
return referenceService.getReferences(element, PsiReferenceService.Hints.NO_HINTS).all { ref ->
|
||||
ProgressManager.checkCanceled()
|
||||
|
||||
when {
|
||||
!ReferenceRange.containsOffsetInElement(ref, offsetInElement) -> true
|
||||
!node.filter.accepts(ref, node) -> true
|
||||
else -> consumer.process(ref)
|
||||
}
|
||||
when {
|
||||
!ReferenceRange.containsOffsetInElement(ref, offsetInElement) -> true
|
||||
!node.filter.accepts(ref, node) -> true
|
||||
else -> consumer.process(ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun processFilesWithText(
|
||||
scope: GlobalSearchScope,
|
||||
searchContext: Short,
|
||||
caseSensitively: Boolean,
|
||||
text: String,
|
||||
processor: Processor<VirtualFile>
|
||||
): Boolean {
|
||||
if (text !in ALL_SEARCHABLE_OPERATION_PATTERNS) {
|
||||
return super.processFilesWithText(scope, searchContext, caseSensitively, text, processor)
|
||||
}
|
||||
|
||||
val entries = Collections.singletonList(IdIndexEntry(text, caseSensitively))
|
||||
val index = FileIndexFacade.getInstance(project)
|
||||
val checker: (Int?) -> Boolean = { (it!! and searchContext.toInt()) != 0 }
|
||||
return runReadAction{
|
||||
FileBasedIndex.getInstance().processFilesContainingAllKeys(IdIndex.NAME, entries, scope, checker) { file ->
|
||||
!index.shouldBeFound(scope, file) || processor.process(file)
|
||||
}
|
||||
}!!
|
||||
}
|
||||
|
||||
public fun processFilesWithText(item: UsagesSearchRequestItem, consumer: Processor<PsiReference>): Boolean {
|
||||
return item.words.all { word ->
|
||||
val textProcessor = ResultTextProcessorImpl(item, consumer)
|
||||
processElementsWithWord(textProcessor, item.target.scope, word, UsageSearchContext.IN_CODE, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public object UsagesSearch: QueryFactory<PsiReference, UsagesSearchRequest>() {
|
||||
{
|
||||
object ExecutorImpl: QueryExecutorBase<PsiReference, UsagesSearchRequest>() {
|
||||
override fun processQuery(request: UsagesSearchRequest, consumer: Processor<PsiReference>) {
|
||||
for (item in request.items) {
|
||||
with (item) {
|
||||
if (filter != False) {
|
||||
ApplicationManager.getApplication()?.runReadAction {
|
||||
for (word in words) {
|
||||
request.collector.searchWord(
|
||||
word, target.scope, target.location.searchContext, true, ResultProcessorImpl(item)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val searchHelper = KotlinPsiSearchHelper(request.project)
|
||||
request.items.filter { it.filter != False }.all { searchHelper.processFilesWithText(it, consumer) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.jet.lang.psi.*
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.*
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils
|
||||
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
|
||||
import com.intellij.psi.PsiReference
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
|
||||
@@ -38,14 +37,13 @@ import org.jetbrains.jet.lang.resolve.java.jetAsJava.KotlinLightMethod
|
||||
import org.jetbrains.jet.asJava.unwrapped
|
||||
import org.jetbrains.jet.lang.resolve.OverrideResolver
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils
|
||||
|
||||
// Navigation element of the resolved reference
|
||||
// For property accessor return enclosing property
|
||||
val PsiReference.unwrappedTarget: PsiElement?
|
||||
get() {
|
||||
val target = resolve()?.unwrapped
|
||||
return if (target is JetPropertyAccessor) target.getParentByType(javaClass<JetProperty>()) else target
|
||||
}
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import org.jetbrains.jet.plugin.references.JetMultiReference
|
||||
import java.util.HashSet
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.jet.plugin.references.JetReference
|
||||
import com.intellij.psi.PsiMethod
|
||||
import org.jetbrains.jet.plugin.references.*
|
||||
|
||||
val JetDeclaration.descriptor: DeclarationDescriptor?
|
||||
get() = AnalyzerFacadeWithCache.getContextForElement(this).get(BindingContext.DECLARATION_TO_DESCRIPTOR, this)
|
||||
@@ -53,21 +51,19 @@ val JetDeclaration.descriptor: DeclarationDescriptor?
|
||||
val JetParameter.propertyDescriptor: PropertyDescriptor?
|
||||
get() = AnalyzerFacadeWithCache.getContextForElement(this).get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, this)
|
||||
|
||||
fun PsiReference.isTargetUsage(target: PsiElement): Boolean {
|
||||
return target.unwrapped == unwrappedTarget
|
||||
}
|
||||
|
||||
fun PsiReference.checkUsageVsOriginalDescriptor(
|
||||
target: JetDeclaration,
|
||||
declarationToDescriptor: (JetDeclaration) -> DeclarationDescriptor? = {it.descriptor},
|
||||
checker: (usageDescriptor: DeclarationDescriptor, targetDescriptor: DeclarationDescriptor) -> Boolean
|
||||
): Boolean {
|
||||
val refTarget = unwrappedTarget
|
||||
if (refTarget !is JetDeclaration) return false
|
||||
|
||||
val usageDescriptor = declarationToDescriptor(refTarget)
|
||||
val targetDescriptor = declarationToDescriptor(target)
|
||||
return usageDescriptor != null && targetDescriptor != null && checker(usageDescriptor, targetDescriptor)
|
||||
return unwrappedTargets.any {
|
||||
if (it is JetDeclaration) {
|
||||
val usageDescriptor = declarationToDescriptor(it)
|
||||
val targetDescriptor = declarationToDescriptor(target)
|
||||
usageDescriptor != null && targetDescriptor != null && checker(usageDescriptor, targetDescriptor)
|
||||
}
|
||||
else false
|
||||
}
|
||||
}
|
||||
|
||||
fun PsiReference.isImportUsage(): Boolean =
|
||||
|
||||
20
idea/testData/findUsages/kotlin/conventions/compareTo.0.kt
Normal file
20
idea/testData/findUsages/kotlin/conventions/compareTo.0.kt
Normal file
@@ -0,0 +1,20 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetNamedFunction
|
||||
// OPTIONS: usages
|
||||
|
||||
class A(val n: Int) {
|
||||
fun <caret>compareTo(other: A): Int = compareTo(other.n)
|
||||
fun compareTo(m: Int): Int = n.compareTo(m)
|
||||
}
|
||||
|
||||
fun test() {
|
||||
A(0) compareTo A(1)
|
||||
A(0) < A(1)
|
||||
A(0) <= A(1)
|
||||
A(0) > A(1)
|
||||
A(0) >= A(1)
|
||||
A(0) compareTo 1
|
||||
A(0) < 1
|
||||
A(0) <= 1
|
||||
A(0) > 1
|
||||
A(0) >= 1
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
Function call (10: 10) A(0) compareTo A(1)
|
||||
Function call (11: 10) A(0) < A(1)
|
||||
Function call (12: 10) A(0) <= A(1)
|
||||
Function call (13: 10) A(0) > A(1)
|
||||
Function call (14: 10) A(0) >= A(1)
|
||||
@@ -0,0 +1,11 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetParameter
|
||||
// OPTIONS: usages
|
||||
|
||||
data class A(val <caret>n: Int, val s: String, val o: Any)
|
||||
|
||||
fun test() {
|
||||
val a = A(1, "2", Any())
|
||||
a.n
|
||||
a.component1()
|
||||
val (x, y, z) = a
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
Function call (9: 7) a.component1()
|
||||
Value read (10: 9) val (x, y, z) = a
|
||||
Value read (8: 7) a.n
|
||||
@@ -0,0 +1,12 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetParameter
|
||||
// OPTIONS: usages
|
||||
// FIND_BY_REF
|
||||
|
||||
data class A(val n: Int, val s: String, val o: Any)
|
||||
|
||||
fun test() {
|
||||
val a = A(1, "2", Any())
|
||||
a.n
|
||||
a.<caret>component1()
|
||||
val (x, y, z) = a
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
Function call (10: 7) a.component1()
|
||||
Value read (11: 9) val (x, y, z) = a
|
||||
Value read (9: 7) a.n
|
||||
16
idea/testData/findUsages/kotlin/conventions/contains.0.kt
Normal file
16
idea/testData/findUsages/kotlin/conventions/contains.0.kt
Normal file
@@ -0,0 +1,16 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetNamedFunction
|
||||
// OPTIONS: usages
|
||||
|
||||
class A(val n: Int) {
|
||||
fun <caret>contains(k: Int): Boolean = k <= n
|
||||
}
|
||||
|
||||
fun test() {
|
||||
A(2) contains 1
|
||||
1 in A(2)
|
||||
1 !in A(2)
|
||||
when (1) {
|
||||
in A(2) -> {}
|
||||
!in A(2) -> {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
Function call (10: 7) 1 in A(2)
|
||||
Function call (11: 7) 1 !in A(2)
|
||||
Function call (13: 9) in A(2) -> {}
|
||||
Function call (14: 9) !in A(2) -> {}
|
||||
Function call (9: 10) A(2) contains 1
|
||||
14
idea/testData/findUsages/kotlin/conventions/equals.0.kt
Normal file
14
idea/testData/findUsages/kotlin/conventions/equals.0.kt
Normal file
@@ -0,0 +1,14 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetNamedFunction
|
||||
// OPTIONS: usages
|
||||
|
||||
class A(val n: Int) {
|
||||
override fun <caret>equals(other: Any?): Boolean = other is A && other.n == n
|
||||
}
|
||||
|
||||
fun test() {
|
||||
A(0) == A(1)
|
||||
A(0) != A(1)
|
||||
A(0) equals A(1)
|
||||
A(0) === A(1)
|
||||
A(0) !== A(1)
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
Function call (10: 10) A(0) != A(1)
|
||||
Function call (11: 10) A(0) equals A(1)
|
||||
Function call (5: 71) override fun equals(other: Any?): Boolean = other is A && other.n == n
|
||||
Function call (9: 10) A(0) == A(1)
|
||||
@@ -0,0 +1,17 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetNamedFunction
|
||||
// OPTIONS: usages
|
||||
|
||||
class A<T: Any> {
|
||||
public fun <caret>iterator(): Iterator<T> = throw IllegalStateException("")
|
||||
}
|
||||
|
||||
class B<T: Any> {
|
||||
public fun iterator(): Iterator<T> = throw IllegalStateException("")
|
||||
}
|
||||
|
||||
fun test() {
|
||||
for (a in A<String>()) {}
|
||||
for (b in B<String>()) {}
|
||||
for (a in A<Int>()) {}
|
||||
for (b in B<Int>()) {}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
Implicit iteration (13: 12) for (a in A<String>()) {}
|
||||
Implicit iteration (15: 12) for (a in A<Int>()) {}
|
||||
11
idea/testData/findUsages/kotlin/conventions/get.0.kt
Normal file
11
idea/testData/findUsages/kotlin/conventions/get.0.kt
Normal file
@@ -0,0 +1,11 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetNamedFunction
|
||||
// OPTIONS: usages
|
||||
|
||||
class B(val n: Int) {
|
||||
fun <caret>get(i: Int): B = B(i)
|
||||
}
|
||||
|
||||
fun test() {
|
||||
B(1).get(2)
|
||||
B(1)[2]
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
Function call (9: 10) B(1).get(2)
|
||||
Implicit 'get' (10: 5) B(1)[2]
|
||||
@@ -0,0 +1,16 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetNamedFunction
|
||||
// OPTIONS: usages
|
||||
// FIND_BY_REF
|
||||
|
||||
class A(val n: Int) {
|
||||
override fun equals(other: Any?): Boolean = other is A && other.n == n
|
||||
}
|
||||
|
||||
fun test() {
|
||||
A(0) == A(1)
|
||||
A(0) != A(1)
|
||||
A(0) equals A(1)
|
||||
A(0) <caret>identityEquals A(1)
|
||||
A(0) === A(1)
|
||||
A(0) !== A(1)
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
Function call (13: 10) A(0) identityEquals A(1)
|
||||
Function call (14: 10) A(0) === A(1)
|
||||
Function call (15: 10) A(0) !== A(1)
|
||||
13
idea/testData/findUsages/kotlin/conventions/inc.0.kt
Normal file
13
idea/testData/findUsages/kotlin/conventions/inc.0.kt
Normal file
@@ -0,0 +1,13 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetNamedFunction
|
||||
// OPTIONS: usages
|
||||
|
||||
class A(val n: Int) {
|
||||
fun <caret>inc(): A = A(n + 1)
|
||||
}
|
||||
|
||||
fun test() {
|
||||
var a = A(1)
|
||||
a.inc()
|
||||
++a
|
||||
a++
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
Function call (10: 7) a.inc()
|
||||
Function call (11: 5) ++a
|
||||
Function call (12: 6) a++
|
||||
11
idea/testData/findUsages/kotlin/conventions/invoke.0.kt
Normal file
11
idea/testData/findUsages/kotlin/conventions/invoke.0.kt
Normal file
@@ -0,0 +1,11 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetNamedFunction
|
||||
// OPTIONS: usages
|
||||
|
||||
class B(val n: Int) {
|
||||
fun <caret>invoke(i: Int): B = B(i)
|
||||
}
|
||||
|
||||
fun test() {
|
||||
B(1).invoke(2)
|
||||
B(1)(2)
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
Function call (9: 10) B(1).invoke(2)
|
||||
Implicit 'invoke' (10: 5) B(1)(2)
|
||||
19
idea/testData/findUsages/kotlin/conventions/plus.0.kt
Normal file
19
idea/testData/findUsages/kotlin/conventions/plus.0.kt
Normal file
@@ -0,0 +1,19 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetNamedFunction
|
||||
// OPTIONS: usages
|
||||
|
||||
class A(val n: Int) {
|
||||
fun <caret>plus(m: Int): A = A(n + m)
|
||||
fun plus(a: A): A = this + a.n
|
||||
}
|
||||
|
||||
fun test() {
|
||||
A(0) + A(1) + 2
|
||||
A(0) plus A(1) plus 2
|
||||
A(0).plus(A(1).plus(2))
|
||||
|
||||
var a = A(0)
|
||||
a += 1
|
||||
a += A(1)
|
||||
|
||||
+A(0)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
Function call (12: 20) A(0).plus(A(1).plus(2))
|
||||
Function call (10: 17) A(0) + A(1) + 2
|
||||
Function call (11: 20) A(0) plus A(1) plus 2
|
||||
Function call (15: 7) a += 1
|
||||
Function call (6: 30) fun plus(a: A): A = this + a.n
|
||||
19
idea/testData/findUsages/kotlin/conventions/plusAssign.0.kt
Normal file
19
idea/testData/findUsages/kotlin/conventions/plusAssign.0.kt
Normal file
@@ -0,0 +1,19 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetNamedFunction
|
||||
// OPTIONS: usages
|
||||
|
||||
class A(var n: Int) {
|
||||
fun <caret>plusAssign(m: Int) {
|
||||
n += m
|
||||
}
|
||||
|
||||
fun plusAssign(a: A) {
|
||||
this += a.n
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
val a = A(0)
|
||||
a.plusAssign(1)
|
||||
a += 1
|
||||
a += A(1)
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
Function call (16: 7) a.plusAssign(1)
|
||||
Function call (10: 14) this += a.n
|
||||
Function call (17: 7) a += 1
|
||||
13
idea/testData/findUsages/kotlin/conventions/set.0.kt
Normal file
13
idea/testData/findUsages/kotlin/conventions/set.0.kt
Normal file
@@ -0,0 +1,13 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetNamedFunction
|
||||
// OPTIONS: usages
|
||||
|
||||
class B(val n: Int) {
|
||||
fun <caret>set(i: Int, a: B) {}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
var a = B(1)
|
||||
a.set(2, B(2))
|
||||
a[2] = B(2)
|
||||
a[2]
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
Function call (10: 7) a.set(2, B(2))
|
||||
Implicit 'set' (11: 5) a[2] = B(2)
|
||||
11
idea/testData/findUsages/kotlin/conventions/unaryMinus.0.kt
Normal file
11
idea/testData/findUsages/kotlin/conventions/unaryMinus.0.kt
Normal file
@@ -0,0 +1,11 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetNamedFunction
|
||||
// OPTIONS: usages
|
||||
|
||||
class A(val n: Int) {
|
||||
fun <caret>minus(): A = this
|
||||
}
|
||||
|
||||
fun test() {
|
||||
A(1).minus()
|
||||
-A(1)
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
Function call (9: 10) A(1).minus()
|
||||
Function call (10: 5) -A(1)
|
||||
@@ -33,12 +33,90 @@ import org.jetbrains.jet.findUsages.AbstractJetFindUsagesTest;
|
||||
@InnerTestClasses({JetFindUsagesTestGenerated.Kotlin.class, JetFindUsagesTestGenerated.Java.class})
|
||||
public class JetFindUsagesTestGenerated extends AbstractJetFindUsagesTest {
|
||||
@TestMetadata("idea/testData/findUsages/kotlin")
|
||||
@InnerTestClasses({Kotlin.FindClassUsages.class, Kotlin.FindFunctionUsages.class, Kotlin.FindObjectUsages.class, Kotlin.FindPackageUsages.class, Kotlin.FindParameterUsages.class, Kotlin.FindPropertyUsages.class, Kotlin.FindTypeParameterUsages.class, Kotlin.FindWithFilteringImports.class, Kotlin.FindWithStructuralGrouping.class, Kotlin.UnresolvedAnnotation.class})
|
||||
@InnerTestClasses({Kotlin.Conventions.class, Kotlin.FindClassUsages.class, Kotlin.FindFunctionUsages.class, Kotlin.FindObjectUsages.class, Kotlin.FindPackageUsages.class, Kotlin.FindParameterUsages.class, Kotlin.FindPropertyUsages.class, Kotlin.FindTypeParameterUsages.class, Kotlin.FindWithFilteringImports.class, Kotlin.FindWithStructuralGrouping.class, Kotlin.UnresolvedAnnotation.class})
|
||||
public static class Kotlin extends AbstractJetFindUsagesTest {
|
||||
public void testAllFilesPresentInKotlin() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/findUsages/kotlin"), Pattern.compile("^(.+)\\.0\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/findUsages/kotlin/conventions")
|
||||
public static class Conventions extends AbstractJetFindUsagesTest {
|
||||
public void testAllFilesPresentInConventions() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/findUsages/kotlin/conventions"), Pattern.compile("^(.+)\\.0\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("compareTo.0.kt")
|
||||
public void testCompareTo() throws Exception {
|
||||
doTest("idea/testData/findUsages/kotlin/conventions/compareTo.0.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("componentFunctions.0.kt")
|
||||
public void testComponentFunctions() throws Exception {
|
||||
doTest("idea/testData/findUsages/kotlin/conventions/componentFunctions.0.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("componentFunctionsByRef.0.kt")
|
||||
public void testComponentFunctionsByRef() throws Exception {
|
||||
doTest("idea/testData/findUsages/kotlin/conventions/componentFunctionsByRef.0.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("contains.0.kt")
|
||||
public void testContains() throws Exception {
|
||||
doTest("idea/testData/findUsages/kotlin/conventions/contains.0.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("equals.0.kt")
|
||||
public void testEquals() throws Exception {
|
||||
doTest("idea/testData/findUsages/kotlin/conventions/equals.0.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("forIteration.0.kt")
|
||||
public void testForIteration() throws Exception {
|
||||
doTest("idea/testData/findUsages/kotlin/conventions/forIteration.0.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("get.0.kt")
|
||||
public void testGet() throws Exception {
|
||||
doTest("idea/testData/findUsages/kotlin/conventions/get.0.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("identityEquals.0.kt")
|
||||
public void testIdentityEquals() throws Exception {
|
||||
doTest("idea/testData/findUsages/kotlin/conventions/identityEquals.0.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inc.0.kt")
|
||||
public void testInc() throws Exception {
|
||||
doTest("idea/testData/findUsages/kotlin/conventions/inc.0.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("invoke.0.kt")
|
||||
public void testInvoke() throws Exception {
|
||||
doTest("idea/testData/findUsages/kotlin/conventions/invoke.0.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("plus.0.kt")
|
||||
public void testPlus() throws Exception {
|
||||
doTest("idea/testData/findUsages/kotlin/conventions/plus.0.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("plusAssign.0.kt")
|
||||
public void testPlusAssign() throws Exception {
|
||||
doTest("idea/testData/findUsages/kotlin/conventions/plusAssign.0.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("set.0.kt")
|
||||
public void testSet() throws Exception {
|
||||
doTest("idea/testData/findUsages/kotlin/conventions/set.0.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unaryMinus.0.kt")
|
||||
public void testUnaryMinus() throws Exception {
|
||||
doTest("idea/testData/findUsages/kotlin/conventions/unaryMinus.0.kt");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/findUsages/kotlin/findClassUsages")
|
||||
public static class FindClassUsages extends AbstractJetFindUsagesTest {
|
||||
public void testAllFilesPresentInFindClassUsages() throws Exception {
|
||||
@@ -597,6 +675,7 @@ public class JetFindUsagesTestGenerated extends AbstractJetFindUsagesTest {
|
||||
public static Test innerSuite() {
|
||||
TestSuite suite = new TestSuite("Kotlin");
|
||||
suite.addTestSuite(Kotlin.class);
|
||||
suite.addTestSuite(Conventions.class);
|
||||
suite.addTestSuite(FindClassUsages.class);
|
||||
suite.addTestSuite(FindFunctionUsages.class);
|
||||
suite.addTestSuite(FindObjectUsages.class);
|
||||
|
||||
Reference in New Issue
Block a user