mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
+4
-1
@@ -45,6 +45,7 @@ public class SuperClassHasFrequentlyUsedInheritorsInspection extends BaseJavaBat
|
||||
@NotNull final InspectionManager manager,
|
||||
final boolean isOnTheFly) {
|
||||
if (aClass.isInterface() ||
|
||||
aClass.isEnum() ||
|
||||
aClass instanceof PsiTypeParameter ||
|
||||
aClass.getMethods().length != 0 ||
|
||||
aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||
@@ -86,7 +87,9 @@ public class SuperClassHasFrequentlyUsedInheritorsInspection extends BaseJavaBat
|
||||
@Nullable
|
||||
private static PsiClass getSuperIfUnique(@NotNull final PsiClass aClass) {
|
||||
if (aClass instanceof PsiAnonymousClass) {
|
||||
return (PsiClass)((PsiAnonymousClass)aClass).getBaseClassReference().resolve();
|
||||
final PsiClass returnClass = (PsiClass)((PsiAnonymousClass)aClass).getBaseClassReference().resolve();
|
||||
if (returnClass != null && CommonClassNames.JAVA_LANG_OBJECT.equals(returnClass.getQualifiedName())) return null;
|
||||
return returnClass;
|
||||
}
|
||||
final PsiReferenceList extendsList = aClass.getExtendsList();
|
||||
if (extendsList != null) {
|
||||
|
||||
@@ -19,8 +19,6 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.ClassFileViewProvider;
|
||||
import com.intellij.psi.impl.source.JavaFileElementType;
|
||||
import com.intellij.psi.stubs.BinaryFileStubBuilder;
|
||||
import com.intellij.psi.stubs.PsiFileStub;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
@@ -36,7 +34,7 @@ import java.util.Comparator;
|
||||
public class ClassFileStubBuilder implements BinaryFileStubBuilder {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.compiled.ClassFileStubBuilder");
|
||||
|
||||
public static final int STUB_VERSION = 7;
|
||||
public static final int STUB_VERSION = 8;
|
||||
|
||||
@Override
|
||||
public boolean acceptsFile(final VirtualFile file) {
|
||||
|
||||
@@ -283,9 +283,9 @@ public class ClsMethodImpl extends ClsMemberImpl<PsiMethodStub> implements PsiAn
|
||||
@Nullable
|
||||
@Override
|
||||
public Result<PsiMethod> compute() {
|
||||
return Result.create(calcSourceMirrorMethod(),
|
||||
getContainingFile(),
|
||||
getContainingFile().getNavigationElement(),
|
||||
return Result.create(calcSourceMirrorMethod(),
|
||||
getContainingFile(),
|
||||
getContainingFile().getNavigationElement(),
|
||||
FileIndexFacade.getInstance(getProject()).getRootModificationTracker());
|
||||
}
|
||||
});
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 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.
|
||||
@@ -41,7 +41,7 @@ public class ClsTypeParametersListImpl extends ClsRepositoryPsiElement<PsiTypePa
|
||||
if (i > 0) buffer.append(", ");
|
||||
appendText(params[i], indentLevel, buffer);
|
||||
}
|
||||
buffer.append("> ");
|
||||
buffer.append(">");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 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.
|
||||
@@ -29,12 +29,13 @@ import com.intellij.psi.impl.java.stubs.impl.PsiTypeParameterStubImpl;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.cls.ClsFormatException;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.io.StringRef;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.text.CharacterIterator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings({"HardCodedStringLiteral"})
|
||||
public class SignatureParsing {
|
||||
@@ -55,30 +56,33 @@ public class SignatureParsing {
|
||||
return list;
|
||||
}
|
||||
|
||||
private static PsiTypeParameterStub parseTypeParameter(CharacterIterator signatureIterator, PsiTypeParameterListStub parent)
|
||||
throws ClsFormatException {
|
||||
private static PsiTypeParameterStub parseTypeParameter(CharacterIterator iterator, PsiTypeParameterListStub parent) throws ClsFormatException {
|
||||
StringBuilder name = new StringBuilder();
|
||||
while (signatureIterator.current() != ':' && signatureIterator.current() != CharacterIterator.DONE) {
|
||||
name.append(signatureIterator.current());
|
||||
signatureIterator.next();
|
||||
while (iterator.current() != ':' && iterator.current() != CharacterIterator.DONE) {
|
||||
name.append(iterator.current());
|
||||
iterator.next();
|
||||
}
|
||||
if (signatureIterator.current() == CharacterIterator.DONE) {
|
||||
if (iterator.current() == CharacterIterator.DONE) {
|
||||
throw new ClsFormatException();
|
||||
}
|
||||
|
||||
//todo parse annotations on type param
|
||||
PsiTypeParameterStub parameterStub = new PsiTypeParameterStubImpl(parent, StringRef.fromString(name.toString()));
|
||||
|
||||
ArrayList<String> bounds = null;
|
||||
while (signatureIterator.current() == ':') {
|
||||
signatureIterator.next();
|
||||
String bound = parseTopLevelClassRefSignature(signatureIterator);
|
||||
if (bound != null && !bound.equals(CommonClassNames.JAVA_LANG_OBJECT)) {
|
||||
if (bounds == null) bounds = new ArrayList<String>();
|
||||
List<String> bounds = ContainerUtil.newSmartList();
|
||||
while (iterator.current() == ':') {
|
||||
iterator.next();
|
||||
String bound = parseTopLevelClassRefSignature(iterator);
|
||||
if (bound != null) {
|
||||
bounds.add(bound);
|
||||
}
|
||||
}
|
||||
|
||||
int size = bounds.size();
|
||||
if (size > 0 && CommonClassNames.JAVA_LANG_OBJECT.equals(bounds.get(size - 1))) {
|
||||
bounds.remove(size - 1);
|
||||
}
|
||||
|
||||
StubBuildingVisitor.newReferenceList(JavaStubElementTypes.EXTENDS_BOUND_LIST, parameterStub, ArrayUtil.toStringArray(bounds));
|
||||
|
||||
return parameterStub;
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
// IntelliJ API Decompiler stub source generated from a class file
|
||||
// Implementation of methods is not available
|
||||
|
||||
package pkg;
|
||||
|
||||
class Bounds {
|
||||
Bounds() { /* compiled code */ }
|
||||
|
||||
public static <T extends java.lang.Object & java.lang.Comparable<? super T>> T max(java.util.Collection<? extends T> ts) { /* compiled code */ }
|
||||
|
||||
public static <T> T max(java.util.Collection<? extends T> ts, java.util.Comparator<? super T> comparator) { /* compiled code */ }
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
package pkg;
|
||||
|
||||
public abstract class KotlinFunList <T> {
|
||||
public abstract class KotlinFunList <T> {
|
||||
public static pkg.KotlinFunList.ClassObject$ $classobj;
|
||||
|
||||
public KotlinFunList() { /* compiled code */ }
|
||||
@@ -12,13 +12,13 @@ public abstract class KotlinFunList <T> {
|
||||
public static final class ClassObject$ {
|
||||
public ClassObject$() { /* compiled code */ }
|
||||
|
||||
public final class Standard <T> {
|
||||
public final class Standard <T> {
|
||||
final pkg.KotlinFunList.ClassObject$ this$0;
|
||||
|
||||
public Standard() { /* compiled code */ }
|
||||
}
|
||||
|
||||
public final class Empty <T> {
|
||||
public final class Empty <T> {
|
||||
final pkg.KotlinFunList.ClassObject$ this$0;
|
||||
|
||||
public Empty() { /* compiled code */ }
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,14 @@
|
||||
package pkg;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
|
||||
class Bounds {
|
||||
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1693,7 +1693,7 @@ PsiJavaFileStub [java.util]
|
||||
PsiModifierListStub[mask=9]
|
||||
PsiTypeParameterListStub
|
||||
PsiTypeParameter[T]
|
||||
PsiRefListStub[EXTENDS_BOUNDS_LIST:java.lang.Comparable<? super T>]
|
||||
PsiRefListStub[EXTENDS_BOUNDS_LIST:java.lang.Object, java.lang.Comparable<? super T>]
|
||||
PsiParameterListStub
|
||||
PsiParameterStub[p1:java.util.List<? extends T>]
|
||||
PsiModifierListStub[mask=0]
|
||||
@@ -1704,7 +1704,7 @@ PsiJavaFileStub [java.util]
|
||||
PsiModifierListStub[mask=10]
|
||||
PsiTypeParameterListStub
|
||||
PsiTypeParameter[T]
|
||||
PsiRefListStub[EXTENDS_BOUNDS_LIST:java.lang.Comparable<? super T>]
|
||||
PsiRefListStub[EXTENDS_BOUNDS_LIST:java.lang.Object, java.lang.Comparable<? super T>]
|
||||
PsiParameterListStub
|
||||
PsiParameterStub[p1:java.util.List<? extends T>]
|
||||
PsiModifierListStub[mask=0]
|
||||
@@ -1715,7 +1715,7 @@ PsiJavaFileStub [java.util]
|
||||
PsiModifierListStub[mask=10]
|
||||
PsiTypeParameterListStub
|
||||
PsiTypeParameter[T]
|
||||
PsiRefListStub[EXTENDS_BOUNDS_LIST:java.lang.Comparable<? super T>]
|
||||
PsiRefListStub[EXTENDS_BOUNDS_LIST:java.lang.Object, java.lang.Comparable<? super T>]
|
||||
PsiParameterListStub
|
||||
PsiParameterStub[p1:java.util.List<? extends T>]
|
||||
PsiModifierListStub[mask=0]
|
||||
@@ -1843,7 +1843,7 @@ PsiJavaFileStub [java.util]
|
||||
PsiModifierListStub[mask=9]
|
||||
PsiTypeParameterListStub
|
||||
PsiTypeParameter[T]
|
||||
PsiRefListStub[EXTENDS_BOUNDS_LIST:java.lang.Comparable<? super T>]
|
||||
PsiRefListStub[EXTENDS_BOUNDS_LIST:java.lang.Object, java.lang.Comparable<? super T>]
|
||||
PsiParameterListStub
|
||||
PsiParameterStub[p1:java.util.Collection<? extends T>]
|
||||
PsiModifierListStub[mask=0]
|
||||
@@ -1863,7 +1863,7 @@ PsiJavaFileStub [java.util]
|
||||
PsiModifierListStub[mask=9]
|
||||
PsiTypeParameterListStub
|
||||
PsiTypeParameter[T]
|
||||
PsiRefListStub[EXTENDS_BOUNDS_LIST:java.lang.Comparable<? super T>]
|
||||
PsiRefListStub[EXTENDS_BOUNDS_LIST:java.lang.Object, java.lang.Comparable<? super T>]
|
||||
PsiParameterListStub
|
||||
PsiParameterStub[p1:java.util.Collection<? extends T>]
|
||||
PsiModifierListStub[mask=0]
|
||||
|
||||
@@ -27,6 +27,28 @@ import gnu.trove.TObjectHashingStrategy;
|
||||
import java.util.Set;
|
||||
|
||||
public class ClsDuplicatesTest extends PsiTestCase {
|
||||
private Set<PsiNamedElement> myUnique = new THashSet<PsiNamedElement>(new TObjectHashingStrategy<PsiNamedElement>() {
|
||||
@Override
|
||||
public int computeHashCode(PsiNamedElement object) {
|
||||
String name = object.getName();
|
||||
return name == null ? 0 : name.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(PsiNamedElement o1, PsiNamedElement o2) {
|
||||
return o1.getParent() == o2.getParent() &&
|
||||
o1.getClass() == o2.getClass() &&
|
||||
StringUtil.equals(o1.getName(), o2.getName()) &&
|
||||
StringUtil.equals(o1.getText(), o2.getText());
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
myUnique = null;
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sdk getTestProjectJdk() {
|
||||
return JavaTestUtil.getTestJdk();
|
||||
@@ -35,12 +57,11 @@ public class ClsDuplicatesTest extends PsiTestCase {
|
||||
public void testDuplicates() throws Exception {
|
||||
final PsiPackage rootPackage = JavaPsiFacade.getInstance(getProject()).findPackage("");
|
||||
assert rootPackage != null;
|
||||
|
||||
final GlobalSearchScope scope = GlobalSearchScope.allScope(getProject());
|
||||
JavaRecursiveElementVisitor visitor = new JavaRecursiveElementVisitor() {
|
||||
@Override
|
||||
public void visitPackage(PsiPackage aPackage) {
|
||||
// System.out.println(aPackage.getQualifiedName());
|
||||
|
||||
visit(aPackage);
|
||||
for (PsiPackage subPackage : aPackage.getSubPackages(scope)) {
|
||||
visitPackage(subPackage);
|
||||
@@ -60,46 +81,21 @@ public class ClsDuplicatesTest extends PsiTestCase {
|
||||
|
||||
@Override
|
||||
public void visitClass(PsiClass aClass) {
|
||||
if ("com.sun.xml.internal.bind.v2.runtime.unmarshaller.DomLoader.State".equals(aClass.getQualifiedName())) {
|
||||
int i =0;
|
||||
}
|
||||
super.visitClass(aClass);
|
||||
PsiElement parent = aClass.getParent();
|
||||
if (parent instanceof PsiFile){
|
||||
uniques.clear();
|
||||
if (parent instanceof PsiFile) {
|
||||
myUnique.clear();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
rootPackage.accept(visitor);
|
||||
}
|
||||
|
||||
private final Set<PsiNamedElement> uniques = new THashSet<PsiNamedElement>(new TObjectHashingStrategy<PsiNamedElement>() {
|
||||
@Override
|
||||
public int computeHashCode(PsiNamedElement object) {
|
||||
String name = object.getName();
|
||||
return name == null ? 0 : name.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(PsiNamedElement o1, PsiNamedElement o2) {
|
||||
boolean eq = o1.getParent() == o2.getParent() && StringUtil.equals(o1.getName(), o2.getName()) && o1.getClass() == o2.getClass()
|
||||
&& StringUtil.equals(o1.getText(), o2.getText());
|
||||
|
||||
if (eq) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
private void visit(PsiNamedElement element) {
|
||||
if (!uniques.add(element)) {
|
||||
fail("Duplicate Element: " +
|
||||
ElementDescriptionUtil.getElementDescription(element, UsageViewLongNameLocation.INSTANCE) +
|
||||
": " +
|
||||
element.getText());
|
||||
if (!myUnique.add(element)) {
|
||||
String description = ElementDescriptionUtil.getElementDescription(element, UsageViewLongNameLocation.INSTANCE);
|
||||
fail("Duplicate Element: " + description + ": " + element.getText());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ public class ClsMirrorBuildingTest extends LightIdeaTestCase {
|
||||
public void testMiddle$Buck() { doTest(); }
|
||||
public void testDefaultPackage() { doTest(); }
|
||||
public void testLocalClass() { doTest(); }
|
||||
public void testBounds() { doTest(); }
|
||||
|
||||
private void doTest() {
|
||||
doTest(getTestName(false));
|
||||
|
||||
+15
-19
@@ -37,7 +37,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper;
|
||||
@@ -57,7 +56,7 @@ public class GrReassignedLocalVarsChecker {
|
||||
private static final Key<CachedValue<Boolean>> REASSIGNED_VAR = Key.create("least upper bound type");
|
||||
|
||||
@Nullable
|
||||
public static Boolean isReassignedVar(final GrReferenceExpression refExpr) {
|
||||
public static Boolean isReassignedVar(@NotNull final GrReferenceExpression refExpr) {
|
||||
if (!PsiUtil.isCompileStatic(refExpr)) {
|
||||
return false;
|
||||
}
|
||||
@@ -86,7 +85,7 @@ public class GrReassignedLocalVarsChecker {
|
||||
return data.getValue();
|
||||
}
|
||||
|
||||
private static boolean isReassignedVarImpl(final GrVariable resolved) {
|
||||
private static boolean isReassignedVarImpl(@NotNull final GrVariable resolved) {
|
||||
final GrControlFlowOwner variableScope = PsiTreeUtil.getParentOfType(resolved, GrCodeBlock.class, GroovyFile.class);
|
||||
if (variableScope == null) return false;
|
||||
|
||||
@@ -97,7 +96,7 @@ public class GrReassignedLocalVarsChecker {
|
||||
((GroovyPsiElement)scope).accept(new GroovyRecursiveElementVisitor() {
|
||||
@Override
|
||||
public void visitClosure(GrClosableBlock closure) {
|
||||
if (getAssignedVarsInsideBlock(closure).contains(name)) {
|
||||
if (getUsedVarsInsideBlock(closure).contains(name)) {
|
||||
isReassigned.set(true);
|
||||
}
|
||||
}
|
||||
@@ -133,7 +132,7 @@ public class GrReassignedLocalVarsChecker {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiType getLeastUpperBoundByVar(final GrVariable resolved) {
|
||||
private static PsiType getLeastUpperBoundByVar(@NotNull final GrVariable resolved) {
|
||||
CachedValue<PsiType> data = resolved.getUserData(LEAST_UPPER_BOUND_TYPE);
|
||||
if (data == null) {
|
||||
data = CachedValuesManager.getManager(resolved.getProject()).createCachedValue(new CachedValueProvider<PsiType>() {
|
||||
@@ -148,7 +147,7 @@ public class GrReassignedLocalVarsChecker {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiType getLeastUpperBoundByVarImpl(final GrVariable resolved) {
|
||||
private static PsiType getLeastUpperBoundByVarImpl(@NotNull final GrVariable resolved) {
|
||||
return RecursionManager.doPreventingRecursion(resolved, false, new NullableComputable<PsiType>() {
|
||||
@Override
|
||||
public PsiType compute() {
|
||||
@@ -170,7 +169,7 @@ public class GrReassignedLocalVarsChecker {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Set<String> getAssignedVarsInsideBlock(@NotNull final GrCodeBlock block) {
|
||||
private static Set<String> getUsedVarsInsideBlock(@NotNull final GrCodeBlock block) {
|
||||
CachedValue<Set<String>> data = block.getUserData(ASSIGNED_VARS);
|
||||
|
||||
if (data == null) {
|
||||
@@ -181,27 +180,24 @@ public class GrReassignedLocalVarsChecker {
|
||||
final Set<String> result = ContainerUtil.newHashSet();
|
||||
|
||||
block.acceptChildren(new GroovyRecursiveElementVisitor() {
|
||||
@Override
|
||||
public void visitAssignmentExpression(GrAssignmentExpression expression) {
|
||||
super.visitAssignmentExpression(expression);
|
||||
|
||||
GrExpression lValue = expression.getLValue();
|
||||
if (lValue instanceof GrReferenceExpression && !((GrReferenceExpression)lValue).isQualified()) {
|
||||
result.add(((GrReferenceExpression)lValue).getReferenceName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOpenBlock(GrOpenBlock openBlock) {
|
||||
result.addAll(getAssignedVarsInsideBlock(openBlock));
|
||||
result.addAll(getUsedVarsInsideBlock(openBlock));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClosure(GrClosableBlock closure) {
|
||||
result.addAll(getAssignedVarsInsideBlock(closure));
|
||||
result.addAll(getUsedVarsInsideBlock(closure));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitReferenceExpression(GrReferenceExpression referenceExpression) {
|
||||
if (referenceExpression.getQualifier() == null && referenceExpression.getReferenceName() != null) {
|
||||
result.add(referenceExpression.getReferenceName());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return Result.create(result, block);
|
||||
}
|
||||
}, false);
|
||||
|
||||
+1
-1
@@ -85,7 +85,7 @@ replace.postfix.0.with.prefix.0=Replace postfix {0} with prefix {0}
|
||||
replace.0.with.1=Replace {0} with binary {1}
|
||||
gr.deprecated.api.usage=Deprecated API inspection
|
||||
category.method.0.cannot.be.applied.to.1=Category method ''{0}'' cannot be applied to ''{1}''
|
||||
local.var.0.is.reassigned.in.closure=Local variable {0} is reassigned in {1} with other type
|
||||
local.var.0.is.reassigned=Local variable ''{0}'' is reassigned
|
||||
anonymous.class=anonymous class
|
||||
closure=closure
|
||||
other.scope=Other scope
|
||||
|
||||
+7
-31
@@ -21,16 +21,12 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiType;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.codeInsight.GrReassignedLocalVarsChecker;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.BaseInspection;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrNamedElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
|
||||
|
||||
@@ -70,38 +66,18 @@ public class GrReassignedInClosureLocalVarInspection extends BaseInspection {
|
||||
final PsiElement resolved = referenceExpression.resolve();
|
||||
if (!GroovyRefactoringUtil.isLocalVariable(resolved)) return;
|
||||
|
||||
final PsiType checked = GrReassignedLocalVarsChecker.getReassignedVarType(referenceExpression, false);
|
||||
if (checked == null) return;
|
||||
|
||||
final GrControlFlowOwner varFlowOwner = ControlFlowUtils.findControlFlowOwner(resolved);
|
||||
final GrControlFlowOwner refFlorOwner = ControlFlowUtils.findControlFlowOwner(referenceExpression);
|
||||
if (isOtherScopeAndType(referenceExpression, checked, varFlowOwner, refFlorOwner)) {
|
||||
String flowDescription = getFlowDescription(refFlorOwner);
|
||||
final String message = message("local.var.0.is.reassigned.in.closure", ((GrNamedElement)resolved).getName(), flowDescription);
|
||||
if (isOtherTypeOrDifferent(referenceExpression, (GrVariable)resolved) ) {
|
||||
final String message = message("local.var.0.is.reassigned", ((GrNamedElement)resolved).getName());
|
||||
registerError(referenceExpression, message, LocalQuickFix.EMPTY_ARRAY, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static boolean isOtherScopeAndType(GrReferenceExpression referenceExpression,
|
||||
PsiType checked,
|
||||
GrControlFlowOwner varFlowOwner,
|
||||
GrControlFlowOwner refFlorOwner) {
|
||||
return varFlowOwner != refFlorOwner && !TypesUtil.isAssignable(referenceExpression.getType(), checked, referenceExpression);
|
||||
}
|
||||
private static boolean isOtherTypeOrDifferent(@NotNull GrReferenceExpression referenceExpression, GrVariable resolved) {
|
||||
if (ControlFlowUtils.findControlFlowOwner(referenceExpression) != ControlFlowUtils.findControlFlowOwner(resolved)) return true;
|
||||
|
||||
private static String getFlowDescription(GrControlFlowOwner refFlorOwner) {
|
||||
String flowDescription;
|
||||
if (refFlorOwner instanceof GrClosableBlock) {
|
||||
flowDescription = message("closure");
|
||||
}
|
||||
else if (refFlorOwner instanceof GrAnonymousClassDefinition) {
|
||||
flowDescription = message("anonymous.class");
|
||||
}
|
||||
else {
|
||||
flowDescription = message("other.scope");
|
||||
}
|
||||
return flowDescription;
|
||||
final PsiType currentType = referenceExpression.getType();
|
||||
return currentType != null && currentType != PsiType.NULL && !ControlFlowUtils.findAccess(resolved, referenceExpression, false, true).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
+1
-6
@@ -709,15 +709,10 @@ public class ControlFlowUtils {
|
||||
* @param ahead if true search for next write. if false searches for previous write
|
||||
* @return all write instructions leading to (or preceding) the place
|
||||
*/
|
||||
public static ReadWriteVariableInstruction[] findWriteAccess(GrVariable local, final PsiElement place, boolean ahead) {
|
||||
List<ReadWriteVariableInstruction> res = findAccess(local, place, ahead, true);
|
||||
return res.toArray(new ReadWriteVariableInstruction[res.size()]);
|
||||
}
|
||||
|
||||
public static List<ReadWriteVariableInstruction> findAccess(GrVariable local, final PsiElement place, boolean ahead, boolean writeAccessOnly) {
|
||||
LOG.assertTrue(!(local instanceof GrField), local.getClass());
|
||||
|
||||
final GrControlFlowOwner owner = findControlFlowOwner(local);
|
||||
final GrControlFlowOwner owner = findControlFlowOwner(place);
|
||||
assert owner != null;
|
||||
|
||||
final Instruction cur = findInstruction(place, owner.getControlFlow());
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ public class GrLiteralImpl extends GrAbstractLiteral implements GrLiteral, PsiLa
|
||||
|
||||
public PsiType getType() {
|
||||
IElementType elemType = getLiteralType(this);
|
||||
return elemType == kNULL ? PsiType.NULL : TypesUtil.getPsiType(this, elemType);
|
||||
return TypesUtil.getPsiType(this, elemType);
|
||||
}
|
||||
|
||||
public void accept(GroovyElementVisitor visitor) {
|
||||
|
||||
+2
-2
@@ -149,7 +149,7 @@ boolean bar(def list) {
|
||||
test() {
|
||||
def var = "abc"
|
||||
def cl = {
|
||||
<warning descr="Local variable var is reassigned in closure with other type">var</warning> = new Date()
|
||||
<warning descr="Local variable 'var' is reassigned">var</warning> = new Date()
|
||||
}
|
||||
cl()
|
||||
var.toUpperCase()
|
||||
@@ -158,7 +158,7 @@ test() {
|
||||
test2() {
|
||||
def var = "abc"
|
||||
def cl = {
|
||||
var = 'cde'
|
||||
<warning descr="Local variable 'var' is reassigned">var</warning> = 'cde'
|
||||
}
|
||||
cl()
|
||||
var.toUpperCase()
|
||||
|
||||
Reference in New Issue
Block a user