[java] add default static imports

GitOrigin-RevId: 746402d1272aa0a410abbbfb18bd8571f545029c
This commit is contained in:
Aleksey Dobrynin
2023-12-13 11:31:37 +00:00
committed by intellij-monorepo-bot
parent 696c7f7465
commit 131bfc4609
11 changed files with 108 additions and 16 deletions
@@ -5,7 +5,10 @@ import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.modcommand.ActionContext;
import com.intellij.modcommand.ModPsiUpdater;
import com.intellij.modcommand.PsiUpdateModCommandAction;
import com.intellij.psi.CommonClassNames;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiTemplateExpression;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.siyeh.ig.psiutils.CommentTracker;
import org.jetbrains.annotations.NotNull;
@@ -22,7 +25,9 @@ public final class MissingStrProcessorFix extends PsiUpdateModCommandAction<PsiT
@Override
protected void invoke(@NotNull ActionContext context, @NotNull PsiTemplateExpression template, @NotNull ModPsiUpdater updater) {
if (template.getProcessor() == null && template.getTemplate() != null) {
new CommentTracker().replaceAndRestoreComments(template, "STR." + template.getText());
final PsiElement result = new CommentTracker()
.replaceAndRestoreComments(template, CommonClassNames.JAVA_LANG_STRING_TEMPLATE + ".STR." + template.getText());
JavaCodeStyleManager.getInstance(result.getProject()).shortenClassReferences(result);
}
}
}
@@ -8,6 +8,7 @@ import com.intellij.modcommand.PsiUpdateModCommandQuickFix;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.util.PsiLiteralUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
@@ -121,6 +122,7 @@ public class StringTemplateMigrationInspection extends AbstractBaseJavaLocalInsp
if (stringTemplate == null) return;
CommentTracker tracker = new CommentTracker();
PsiElement result = tracker.replaceAndRestoreComments(polyadicExpression, stringTemplate);
result = JavaCodeStyleManager.getInstance(project).shortenClassReferences(result);
if (result instanceof PsiTemplateExpression template) {
replaceRedundantEmbeddedExpression(template);
}
@@ -156,7 +158,7 @@ public class StringTemplateMigrationInspection extends AbstractBaseJavaLocalInsp
toTemplateExpression(content, isStringFound, operand);
}
}
return textBlock ? "STR.\"\"\"\n" + content + "\"\"\"" : "STR.\"" + content + "\"";
return textBlock ? CommonClassNames.JAVA_LANG_STRING_TEMPLATE + ".STR.\"\"\"\n" + content + "\"\"\"" : CommonClassNames.JAVA_LANG_STRING_TEMPLATE + ".STR.\"" + content + "\"";
}
private static boolean useTextBlockTemplate(PsiPolyadicExpression expression) {
@@ -6,6 +6,7 @@ import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.VariableLookupItem;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.psi.*;
import com.intellij.psi.util.ImportsUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ObjectUtils;
@@ -25,9 +26,11 @@ public class JavaStaticMemberProcessor extends StaticMemberProcessor {
final PsiImportList importList = ((PsiJavaFile)file).getImportList();
if (importList != null) {
for (PsiImportStaticStatement statement : importList.getImportStaticStatements()) {
PsiClass aClass = statement.resolveTargetClass();
if (aClass != null) {
importMembersOf(aClass);
if (!ImportsUtil.isImplicitImport(statement)) {
PsiClass aClass = statement.resolveTargetClass();
if (aClass != null) {
importMembersOf(aClass);
}
}
}
}
@@ -2,6 +2,7 @@
package com.intellij.psi.util;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Key;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -11,6 +12,8 @@ import java.util.List;
import java.util.Objects;
public final class ImportsUtil {
private static final Key<Boolean> IS_IMPLICIT = Key.create("IMPORT_IS_IMPLICIT");
private ImportsUtil() {
}
@@ -86,4 +89,12 @@ public final class ImportsUtil {
}
return false;
}
public static void markAsImplicitImport(@NotNull PsiImportStatementBase importStatement) {
importStatement.putUserData(IS_IMPLICIT, Boolean.TRUE);
}
public static boolean isImplicitImport(@NotNull PsiImportStatementBase importStatement) {
return importStatement.getUserData(IS_IMPLICIT) == Boolean.TRUE;
}
}
@@ -11,6 +11,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.filters.ElementFilter;
import com.intellij.psi.impl.light.LightClassReference;
@@ -221,7 +222,7 @@ public final class PsiImplUtil {
for (PsiResourceListElement resource : resourceList) {
if (resource == lastParent) break;
if (resource instanceof PsiResourceVariable &&
!((PsiResourceVariable)resource).isUnnamed() &&
!((PsiResourceVariable)resource).isUnnamed() &&
!processor.execute(resource, state)) return false;
}
@@ -868,4 +869,28 @@ public final class PsiImplUtil {
return file;
}
}
public static PsiImportStaticStatement[] getImplicitStaticImports(@NotNull PsiFile file) {
PsiImportStaticStatement[] staticImports = new PsiImportStaticStatement[1];
int counter = 0;
// java.lang.StringTemplate.STR
if (PsiUtil.getLanguageLevel(file).isAtLeast(LanguageLevel.JDK_21_PREVIEW)) {
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(file.getProject());
final PsiClass aClass = psiFacade.findClass(CommonClassNames.JAVA_LANG_STRING_TEMPLATE, file.getResolveScope());
if (aClass != null) {
final PsiImportStaticStatement stringTemplate = psiFacade.getElementFactory().createImportStaticStatement(aClass, "STR");
staticImports[counter++] = stringTemplate;
}
}
// preparation of results
if (counter < staticImports.length) {
staticImports = Arrays.copyOf(staticImports, counter);
}
for (PsiImportStaticStatement statement : staticImports) {
ImportsUtil.markAsImplicitImport(statement);
}
return staticImports;
}
}
@@ -3,15 +3,16 @@ package com.intellij.psi.impl.source;
import com.intellij.lang.ASTNode;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
import com.intellij.psi.impl.java.stubs.PsiImportListStub;
import com.intellij.psi.impl.source.tree.ElementType;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
public class PsiImportListImpl extends JavaStubPsiElement<PsiImportListStub> implements PsiImportList {
private volatile Map<String,PsiImportStatement> myClassNameToImportMap;
@@ -53,7 +54,11 @@ public class PsiImportListImpl extends JavaStubPsiElement<PsiImportListStub> imp
@Override
public PsiImportStaticStatement @NotNull [] getImportStaticStatements() {
return getStubOrPsiChildren(IMPORT_STATIC_STATEMENT_BIT_SET, PsiImportStaticStatementImpl.ARRAY_FACTORY);
final PsiImportStaticStatement[] explicitStaticImports =
getStubOrPsiChildren(IMPORT_STATIC_STATEMENT_BIT_SET, PsiImportStaticStatementImpl.ARRAY_FACTORY);
final PsiImportStaticStatement[] implicitStaticImports =
PsiImplUtil.getImplicitStaticImports(getContainingFile());
return ArrayUtil.mergeArrays(explicitStaticImports, implicitStaticImports);
}
@Override
@@ -326,13 +326,9 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava
staticImports.putValue(name, staticImport);
}
}
if (PsiUtil.getLanguageLevel(this).isAtLeast(LanguageLevel.JDK_21_PREVIEW)) {
JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(getProject());
PsiClass aClass = psiFacade.findClass(CommonClassNames.JAVA_LANG_STRING_TEMPLATE, getResolveScope());
if (aClass != null) {
PsiImportStaticStatement importStaticStatement = psiFacade.getElementFactory().createImportStaticStatement(aClass, "STR");
staticImports.putValue("STR", importStaticStatement);
}
for (PsiImportStaticStatement staticImport : PsiImplUtil.getImplicitStaticImports(this)) {
staticImports.putValue(staticImport.getReferenceName(), staticImport);
}
Map<String, Iterable<ResultWithContext>> result = new LinkedHashMap<>();
@@ -0,0 +1,9 @@
// "Add 'STR.' Processor" "true-preview"
class a {
public static final String STR = "surprise!";
void f() {
String name = "world";
String str = StringTemplate.STR."hello \{name}";
}
}
@@ -0,0 +1,9 @@
// "Add 'STR.' Processor" "true-preview"
class a {
public static final String STR = "surprise!";
void f() {
String name = "world";
String str = "<caret>hello \{name}";
}
}
@@ -2,7 +2,9 @@
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.testFramework.IdeaTestUtil;
public class MissingStrProcessorFixTest extends LightQuickFixParameterizedTestCase {
@Override
@@ -14,4 +16,9 @@ public class MissingStrProcessorFixTest extends LightQuickFixParameterizedTestCa
protected LanguageLevel getLanguageLevel() {
return LanguageLevel.JDK_21_PREVIEW;
}
@Override
protected Sdk getProjectJDK() {
return IdeaTestUtil.getMockJdk21();
}
}
@@ -27,6 +27,26 @@ public class StringTemplateMigrationInspectionTest extends LightJavaCodeInsightF
}""");
}
public void testOverrideStringProcessor() {
doTest("""
class StringTemplateMigration {
public static final String STR = "surprise!";
void test() {
String name = "World";
String test = "Hello " + na<caret>me + "!" + "!" + "!";
}
private static class StringTemplate {}
}""", """
class StringTemplateMigration {
public static final String STR = "surprise!";
void test() {
String name = "World";
String test = java.lang.StringTemplate.STR."Hello \\{name}!!!";
}
private static class StringTemplate {}
}""");
}
public void testNumberPlusString() {
doTest("""
class StringTemplateMigration {