From d8175c6e01882a0aae0920a8ee72833f436ae438 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Tue, 12 Dec 2023 11:24:50 +0100 Subject: [PATCH] [java-inspections] ReplaceConstructorWithFactoryAction: turn off in implicit classes GitOrigin-RevId: 2d2e3691b2127ab193226009f4dc5c5d86e40843 --- .../ReplaceConstructorWithFactoryAction.java | 10 +- .../StringTemplatesJava22.java | 123 ++++++++++++++++++ 2 files changed, 126 insertions(+), 7 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingStringTemplates/StringTemplatesJava22.java diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/ReplaceConstructorWithFactoryAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/ReplaceConstructorWithFactoryAction.java index 40a204e6c92f..22a804507088 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/ReplaceConstructorWithFactoryAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/ReplaceConstructorWithFactoryAction.java @@ -238,18 +238,14 @@ public class ReplaceConstructorWithFactoryAction implements ModCommandAction { PsiClass containingClass = ClassUtils.getContainingClass(element); if (!isSuitableClass(containingClass)) return null; PsiElement lBrace = containingClass.getLBrace(); - if (lBrace != null && element.getTextRange().getStartOffset() >= lBrace.getTextRange().getStartOffset()) return null; + if (lBrace == null || element.getTextRange().getStartOffset() >= lBrace.getTextRange().getStartOffset()) return null; if (containingClass.getConstructors().length > 0) return null; return containingClass; } private static boolean isSuitableClass(PsiClass containingClass) { - return containingClass != null && - PsiTreeUtil.getParentOfType(containingClass, PsiImplicitClass.class, false) == null && - !containingClass.isInterface() && - !containingClass.isEnum() && - !containingClass.isRecord() && - !containingClass.hasModifierProperty(PsiModifier.ABSTRACT) && + return containingClass != null && !containingClass.isInterface() && !containingClass.isEnum() && !containingClass.isRecord() && + !(containingClass instanceof PsiImplicitClass) && !containingClass.hasModifierProperty(PsiModifier.ABSTRACT) && containingClass.getQualifiedName() != null; } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingStringTemplates/StringTemplatesJava22.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingStringTemplates/StringTemplatesJava22.java new file mode 100644 index 000000000000..682b1ff1dd2e --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingStringTemplates/StringTemplatesJava22.java @@ -0,0 +1,123 @@ +class X { + + void processorMissing() { + System.out.println(""" + \{1} + """); + "\{}"; + System.out.println(NOPE."\{false}"); + System.out.println(RAW."\{false}"); + } + + void correct(int i) { + System.out.println(STR."the value is \{i}"); + String s = STR.""; + StringTemplate st = StringTemplate.RAW.""" + """; + } + + void wrongType(String foo) { + String s = StringTemplate.RAW.""" + this: \{foo} + """; + + var x = (java.io.Serializable & StringTemplate.Processor)null; + java.util.ArrayList v = x."asdf"; + String t = x."reticulation"; + } + + String unresolvedValues() { + return STR."\{logic} \{proportion}"; + } + + interface MyProcessor extends StringTemplate.Processor {} + + String raw(StringTemplate.Processor processor, MyProcessor myProcessor) { + System.out.println(myProcessor.""); + return processor."\{}\{}\{}\{}\{}\{}"; + var z = (java.io.Serializable & StringTemplate.Processor)myProcessor; + System.out.println(z.""); + } + + void nested() { + System.out.println(STR."\{STR."\{STR."\{STR."\{STR."\{STR."\{STR.""}"}"}"}"}"}"); + } + + String badEscape() { + System.out.println(STR."b\ad \{} esc\ape 1"); + System.out.println(STR. """ + b\ad \{} esc\ape 2 + """); + System.out.println(STR."\{}unclosed); + return STR."\{} \uX"; + } + + static class Covariant implements StringTemplate.Processor { + @Override + public Integer process(StringTemplate stringTemplate) { + return 123; + } + } + + public static void testCovariant() { + Covariant proc = new Covariant(); + // As of Java 21, covariant processors are not supported + Integer i = proc."hello"; + } + + static class CovariantException implements StringTemplate.Processor { + @Override + public Integer process(StringTemplate stringTemplate) throws Ex { + return 123; + } + } + + class Ex extends Exception {} + class Ex2 extends Exception {} + + public static void testHandle(StringTemplate.Processor proc) { + try { + Object x = proc."hello"; + } + catch (Ex ex) {} + } + + public static void testExceptionInFragments(StringTemplate.Processor proc, + StringTemplate.Processor proc2) { + try { + proc."hell\{proc2."xyz"}o"; + } + catch (Ex ex) {} + } + + public static void testCovariantException() { + CovariantException proc = new CovariantException(); + // As of Java 21, covariant processors are not supported + Integer i = proc."hello"; + + try { + Integer i2 = proc."hello"; + } + catch (Ex ex) {} + } + + public static void testCapturedWilcard(StringTemplate.Processor str) { + Object s = str.""; + } + + void testCapturedWildcard2() { + StringTemplate.Processor, RuntimeException> processor = null; + Object o = processor.""" + """.""" + """; + } + + public static void noNewlineAfterTextBlockOpeningQuotes() { + System.out.println(STR."""\{}"""); + } + + public static void voidExpression() { + String a = STR."\{voidExpression()}"; + System.out.println(a); + } +} \ No newline at end of file