mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-05 01:50:56 +07:00
ensure inserted single-static-import when conflicting on-demand imports are presented (IDEA-155031)
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 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.
|
||||
@@ -25,21 +25,18 @@ import com.intellij.codeInsight.intention.BaseElementAtCaretIntentionAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.codeStyle.ImportHelper;
|
||||
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.MethodSignatureUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class AddSingleMemberStaticImportAction extends BaseElementAtCaretIntentionAction {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.intention.impl.AddSingleMemberStaticImportAction");
|
||||
private static final Key<PsiElement> TEMP_REFERENT_USER_DATA = new Key<>("TEMP_REFERENT_USER_DATA");
|
||||
@@ -100,8 +97,7 @@ public class AddSingleMemberStaticImportAction extends BaseElementAtCaretIntenti
|
||||
final PsiElement currentFileResolveScope = resolveResult.getCurrentFileResolveScope();
|
||||
if (currentFileResolveScope instanceof PsiImportStaticStatement) {
|
||||
//don't hide another on-demand import and don't create ambiguity
|
||||
if (((PsiImportStaticStatement)currentFileResolveScope).isOnDemand() ||
|
||||
MethodSignatureUtil.areSignaturesEqual((PsiMethod)method, (PsiMethod)resolved)) {
|
||||
if (MethodSignatureUtil.areSignaturesEqual((PsiMethod)method, (PsiMethod)resolved)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -216,12 +212,12 @@ public class AddSingleMemberStaticImportAction extends BaseElementAtCaretIntenti
|
||||
}
|
||||
});
|
||||
|
||||
if (findExistingImport(file, resolvedClass, referenceName) == null) {
|
||||
if (resolved instanceof PsiClass) {
|
||||
((PsiImportHolder) file).importClass((PsiClass) resolved);
|
||||
} else {
|
||||
PsiReferenceExpressionImpl.bindToElementViaStaticImport(resolvedClass, referenceName, ((PsiJavaFile)file).getImportList());
|
||||
}
|
||||
PsiImportStatementBase existingImport = findExistingImport(file, resolvedClass, referenceName);
|
||||
if (existingImport == null && resolved instanceof PsiClass) {
|
||||
((PsiImportHolder) file).importClass((PsiClass) resolved);
|
||||
}
|
||||
else if (existingImport == null || existingImport.isOnDemand() && resolvedClass != null && ImportHelper.hasConflictingOnDemandImport((PsiJavaFile)file, resolvedClass, referenceName)) {
|
||||
PsiReferenceExpressionImpl.bindToElementViaStaticImport(resolvedClass, referenceName, ((PsiJavaFile)file).getImportList());
|
||||
}
|
||||
|
||||
file.accept(new JavaRecursiveElementVisitor() {
|
||||
|
||||
@@ -759,6 +759,19 @@ public class ImportHelper{
|
||||
return findEntryIndex(packageName, statement instanceof PsiImportStaticStatement, mySettings.IMPORT_LAYOUT_TABLE.getEntries());
|
||||
}
|
||||
|
||||
public static boolean hasConflictingOnDemandImport(@NotNull PsiJavaFile file, @NotNull PsiClass psiClass, @NotNull String referenceName) {
|
||||
Collection<Pair<String, Boolean>> resultList = collectNamesToImport(file, new ArrayList<>());
|
||||
for (Pair<String, Boolean> pair : resultList) {
|
||||
if (pair.second &&
|
||||
referenceName.equals(StringUtil.getShortName(pair.first)) &&
|
||||
!StringUtil.getPackageName(pair.first).equals(psiClass.getQualifiedName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
// returns list of (name, isImportStatic) pairs
|
||||
private static Collection<Pair<String,Boolean>> collectNamesToImport(@NotNull PsiJavaFile file, List<PsiElement> comments){
|
||||
|
||||
@@ -32,7 +32,6 @@ import com.intellij.psi.util.*;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.BitUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -127,6 +126,11 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
|
||||
return new ImportHelper(getSettings()).prepareOptimizeImportsResult(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasConflictingOnDemandImport(@NotNull PsiJavaFile file, @NotNull PsiClass psiClass, @NotNull String referenceName) {
|
||||
return ImportHelper.hasConflictingOnDemandImport(file, psiClass, referenceName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addImport(@NotNull PsiJavaFile file, @NotNull PsiClass refClass) {
|
||||
return new ImportHelper(getSettings()).addImport(file, refClass);
|
||||
|
||||
@@ -91,6 +91,19 @@ public abstract class JavaCodeStyleManager {
|
||||
*/
|
||||
public abstract PsiImportList prepareOptimizeImportsResult(@NotNull PsiJavaFile file);
|
||||
|
||||
/**
|
||||
* Single-static-import <code>import static classFQN.referenceName;</code> shadows on-demand static imports, like described
|
||||
* JLS 6.4.1
|
||||
* A single-static-import declaration d in a compilation unit c of package p that imports a {member} named n
|
||||
* shadows the declaration of any static {member} named n imported by a static-import-on-demand declaration in c, throughout c.
|
||||
*
|
||||
* @return true if file contains import which would be shadowed
|
||||
* false otherwise
|
||||
*/
|
||||
public boolean hasConflictingOnDemandImport(@NotNull PsiJavaFile file, @NotNull PsiClass psiClass, @NotNull String referenceName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the kind of the specified variable (local, parameter, field, static field or static final field).
|
||||
*
|
||||
|
||||
@@ -121,9 +121,9 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple
|
||||
assert importList != null;
|
||||
final String qualifiedName = qualifierClass.getQualifiedName();
|
||||
final List<PsiJavaCodeReferenceElement> refs = getImportsFromClass(importList, qualifiedName);
|
||||
if (refs.size() < JavaCodeStyleSettingsFacade.getInstance(qualifierClass.getProject()).getNamesCountToUseImportOnDemand()) {
|
||||
importList.add(JavaPsiFacade.getInstance(qualifierClass.getProject()).getElementFactory().createImportStaticStatement(qualifierClass,
|
||||
staticName));
|
||||
if (refs.size() < JavaCodeStyleSettingsFacade.getInstance(qualifierClass.getProject()).getNamesCountToUseImportOnDemand() ||
|
||||
JavaCodeStyleManager.getInstance(qualifierClass.getProject()).hasConflictingOnDemandImport((PsiJavaFile)importList.getContainingFile(), qualifierClass, staticName)) {
|
||||
importList.add(JavaPsiFacade.getInstance(qualifierClass.getProject()).getElementFactory().createImportStaticStatement(qualifierClass, staticName));
|
||||
} else {
|
||||
for (PsiJavaCodeReferenceElement ref : refs) {
|
||||
final PsiImportStaticStatement importStatement = PsiTreeUtil.getParentOfType(ref, PsiImportStaticStatement.class);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package use;
|
||||
|
||||
import foo.Bar;
|
||||
|
||||
import static foo.Foo.*;
|
||||
|
||||
public class Test {
|
||||
void test() {
|
||||
foo(1);
|
||||
Bar.<caret>foo("1");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package use;
|
||||
|
||||
import foo.Bar;
|
||||
import foo.Foo;
|
||||
|
||||
import static foo.Bar.foo;
|
||||
import static foo.Foo.*;
|
||||
|
||||
public class Test {
|
||||
void test() {
|
||||
Foo.foo(1);
|
||||
foo("1");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package use;
|
||||
|
||||
import foo.Bar;
|
||||
|
||||
import static foo.Foo.foo;
|
||||
|
||||
public class Test {
|
||||
void test() {
|
||||
foo(1);
|
||||
Bar.<caret>foo("1");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
import foo.Foo;
|
||||
|
||||
import static foo.Bar.foo;
|
||||
import static foo.Foo.*;
|
||||
class Test {
|
||||
void test() {
|
||||
Foo.f<caret>oo(1);
|
||||
foo("1");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
import foo.Foo;
|
||||
|
||||
import static foo.Bar.foo;
|
||||
import static foo.Foo.*;
|
||||
import static foo.Foo.foo;
|
||||
|
||||
class Test {
|
||||
void test() {
|
||||
foo(1);
|
||||
foo("1");
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 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,6 +16,8 @@
|
||||
package com.intellij.codeInsight.intention;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
|
||||
|
||||
public class AddSingleStaticImportActionTest extends JavaCodeInsightFixtureTestCase {
|
||||
@@ -85,7 +87,6 @@ public class AddSingleStaticImportActionTest extends JavaCodeInsightFixtureTestC
|
||||
}
|
||||
|
||||
public void testSkipSameNamedNonStaticReferences() throws Exception {
|
||||
|
||||
myFixture.addClass("package foo;" +
|
||||
"public class Clazz {" +
|
||||
" public void print(String s) {}" +
|
||||
@@ -99,6 +100,45 @@ public class AddSingleStaticImportActionTest extends JavaCodeInsightFixtureTestC
|
||||
myFixture.checkResultByFile(getTestName(false) + "_after.java");
|
||||
}
|
||||
|
||||
public void testAllowSingleStaticImportWhenOnDemandImportOverloadedMethod() throws Exception {
|
||||
myFixture.addClass("package foo; class Foo {public static void foo(int i){}}");
|
||||
myFixture.addClass("package foo; class Bar {public static void foo(String s){}}");
|
||||
myFixture.configureByFile(getTestName(false) + ".java");
|
||||
|
||||
IntentionAction intention = myFixture.findSingleIntention("Add static import for 'foo.Bar.foo'");
|
||||
assertNotNull(intention);
|
||||
myFixture.launchAction(intention);
|
||||
myFixture.checkResultByFile(getTestName(false) + "_after.java");
|
||||
}
|
||||
|
||||
public void testSingleImportWhenConflictingWithOnDemand() throws Exception {
|
||||
myFixture.addClass("package foo; class Foo {public static void foo(int i){}}");
|
||||
myFixture.addClass("package foo; class Bar {public static void foo(String s){}}");
|
||||
myFixture.configureByFile(getTestName(false) + ".java");
|
||||
|
||||
CodeStyleSettings settings = CodeStyleSettingsManager.getInstance(getProject()).getCurrentSettings();
|
||||
int old = settings.NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND;
|
||||
settings.NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND = 1;
|
||||
try {
|
||||
IntentionAction intention = myFixture.findSingleIntention("Add static import for 'foo.Foo.foo'");
|
||||
assertNotNull(intention);
|
||||
myFixture.launchAction(intention);
|
||||
myFixture.checkResultByFile(getTestName(false) + "_after.java");
|
||||
}
|
||||
finally {
|
||||
settings.NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND = old;
|
||||
}
|
||||
}
|
||||
|
||||
public void testProhibitWhenMethodWithIdenticalSignatureAlreadyImportedFromAnotherClass() throws Exception {
|
||||
myFixture.addClass("package foo; class Foo {public static void foo(int i){}}");
|
||||
myFixture.addClass("package foo; class Bar {public static void foo(int i){}}");
|
||||
myFixture.configureByFile(getTestName(false) + ".java");
|
||||
|
||||
IntentionAction intention = myFixture.getAvailableIntention("Add static import for 'foo.Bar.foo'");
|
||||
assertNull(intention);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return JavaTestUtil.getJavaTestDataPath() + "/codeInsight/daemonCodeAnalyzer/quickFix/addSingleStaticImport";
|
||||
|
||||
Reference in New Issue
Block a user