From 216f420f724f65558495154be6edb8c66b488c8c Mon Sep 17 00:00:00 2001 From: Danila Ponomarenko Date: Wed, 30 May 2012 14:51:48 +0400 Subject: [PATCH 01/11] IDEA-85987 inner anonymous classes cannot implement interfaces fixed --- .../quickfix/ChangeParameterClassFix.java | 30 +++++++++++-------- .../beforeAnonymousClassArgument.java | 14 +++++++++ .../beforeAnonymousClassValue.java | 19 ++++++++++++ 3 files changed, 50 insertions(+), 13 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/beforeAnonymousClassArgument.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/beforeAnonymousClassValue.java diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeParameterClassFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeParameterClassFix.java index 75f1fad5c7a0..7182aaf6d974 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeParameterClassFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeParameterClassFix.java @@ -61,11 +61,11 @@ public class ChangeParameterClassFix extends ExtendsListFix { @NotNull PsiElement startElement, @NotNull PsiElement endElement) { return - super.isAvailable(project, file, startElement, endElement) - && myClassToExtendFrom != null - && myClassToExtendFrom.isValid() - && myClassToExtendFrom.getQualifiedName() != null - ; + super.isAvailable(project, file, startElement, endElement) + && myClassToExtendFrom != null + && myClassToExtendFrom.isValid() + && myClassToExtendFrom.getQualifiedName() != null + ; } @Override @@ -115,17 +115,20 @@ public class ChangeParameterClassFix extends ExtendsListFix { } public static void registerQuickFixAction(PsiVariable variable, PsiType returnType, HighlightInfo info) { - final PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(returnType); + final PsiClass returnClass = PsiUtil.resolveClassInClassTypeOnly(returnType); final PsiType variableType = variable.getType(); final PsiClass variableClass = PsiUtil.resolveClassInClassTypeOnly(variableType); - if (psiClass != null && variableClass != null && !psiClass.isInheritor(variableClass, true)) { - QuickFixAction.registerQuickFixAction(info, new ChangeParameterClassFix(psiClass, (PsiClassType)variableType)); - } + + if (returnClass == null || variableClass == null) return; + if (returnClass instanceof PsiAnonymousClass) return; + if (returnClass.isInheritor(variableClass, true)) return; + + QuickFixAction.registerQuickFixAction(info, new ChangeParameterClassFix(returnClass, (PsiClassType)variableType)); } - + public static void registerQuickFixActions(PsiCall methodCall, PsiExpressionList list, HighlightInfo highlightInfo) { final JavaResolveResult result = methodCall.resolveMethodGenerics(); - PsiMethod method = (PsiMethod) result.getElement(); + PsiMethod method = (PsiMethod)result.getElement(); final PsiSubstitutor substitutor = result.getSubstitutor(); PsiExpression[] expressions = list.getExpressions(); if (method == null || method.getParameterList().getParametersCount() != expressions.length) return; @@ -134,12 +137,13 @@ public class ChangeParameterClassFix extends ExtendsListFix { PsiParameter parameter = method.getParameterList().getParameters()[i]; PsiType expressionType = expression.getType(); PsiType parameterType = substitutor.substitute(parameter.getType()); - if (expressionType == null || expressionType instanceof PsiPrimitiveType || TypeConversionUtil.isNullType(expressionType) || expressionType instanceof PsiArrayType ) continue; - if (parameterType instanceof PsiPrimitiveType || TypeConversionUtil.isNullType(parameterType) || parameterType instanceof PsiArrayType ) continue; + if (expressionType == null || expressionType instanceof PsiPrimitiveType || TypeConversionUtil.isNullType(expressionType) || expressionType instanceof PsiArrayType) continue; + if (parameterType instanceof PsiPrimitiveType || TypeConversionUtil.isNullType(parameterType) || parameterType instanceof PsiArrayType) continue; if (parameterType.isAssignableFrom(expressionType)) continue; PsiClass parameterClass = PsiUtil.resolveClassInType(parameterType); PsiClass expressionClass = PsiUtil.resolveClassInType(expressionType); if (parameterClass == null || expressionClass == null) continue; + if (expressionClass instanceof PsiAnonymousClass) continue; if (parameterClass.isInheritor(expressionClass, true)) continue; QuickFixAction.registerQuickFixAction(highlightInfo, new ChangeParameterClassFix(expressionClass, (PsiClassType)parameterType)); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/beforeAnonymousClassArgument.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/beforeAnonymousClassArgument.java new file mode 100644 index 000000000000..92a5cf480d85 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/beforeAnonymousClassArgument.java @@ -0,0 +1,14 @@ +// "Make 'null' implement 'Foo.IBar'" "false" + +public abstract class Foo { + static Foo anonymous = new Foo() { + @Override + void fooMethod() { + foo2Method(this); + } + }; + + protected Foo() { + IBar bar = anonymous; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/beforeAnonymousClassValue.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/beforeAnonymousClassValue.java new file mode 100644 index 000000000000..4937d111245e --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/beforeAnonymousClassValue.java @@ -0,0 +1,19 @@ +// "Make 'null' implement 'Foo.IBar'" "false" + +public abstract class Foo { + public static interface IBar { + void barMethod(); + } + + abstract void fooMethod(); + + void foo2Method(IBar b) { + } + + static Foo anonymous = new Foo() { + @Override + void fooMethod() { + foo2Method(this); + } + }; +} \ No newline at end of file From d836edf6c52f4b01985cfa8cdfa079bff952e59e Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 30 May 2012 15:36:46 +0400 Subject: [PATCH 02/11] push down: search for method in inheritor by super method signature (IDEA-86806) --- .../memberPushDown/PushDownProcessor.java | 4 +++- .../pushDown/OverridingMethodWithSubst.java | 13 +++++++++++++ .../pushDown/OverridingMethodWithSubst.java.after | 12 ++++++++++++ .../com/intellij/refactoring/PushDownTest.java | 4 ++++ 4 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/refactoring/pushDown/OverridingMethodWithSubst.java create mode 100644 java/java-tests/testData/refactoring/pushDown/OverridingMethodWithSubst.java.after diff --git a/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java b/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java index 3daa17d0ea5b..543137d65e60 100644 --- a/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java @@ -30,6 +30,7 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.search.searches.ClassInheritorsSearch; import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.psi.util.MethodSignatureUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; @@ -356,7 +357,8 @@ public class PushDownProcessor extends BaseRefactoringProcessor { } else if (member instanceof PsiMethod) { PsiMethod method = (PsiMethod)member; - final PsiMethod methodBySignature = targetClass.findMethodBySignature(method, false); + final PsiMethod methodBySignature = + MethodSignatureUtil.findMethodBySuperSignature(targetClass, method.getSignature(substitutor), false); if (methodBySignature == null) { final boolean wasInterface = myClass.isInterface(); newMember = (PsiMethod)targetClass.add(method); diff --git a/java/java-tests/testData/refactoring/pushDown/OverridingMethodWithSubst.java b/java/java-tests/testData/refactoring/pushDown/OverridingMethodWithSubst.java new file mode 100644 index 000000000000..7292155e0ecd --- /dev/null +++ b/java/java-tests/testData/refactoring/pushDown/OverridingMethodWithSubst.java @@ -0,0 +1,13 @@ +abstract class BaseTask> { + public abstract S makeTask(int depth, ParallelStream coll); +} + + +class ForEachTask extends BaseTask> { + public ForEachTask makeTask(int depth, ParallelStream coll) { + return new ForEachTask(); + } +} + +class ParallelStream { +} diff --git a/java/java-tests/testData/refactoring/pushDown/OverridingMethodWithSubst.java.after b/java/java-tests/testData/refactoring/pushDown/OverridingMethodWithSubst.java.after new file mode 100644 index 000000000000..4a34fba36632 --- /dev/null +++ b/java/java-tests/testData/refactoring/pushDown/OverridingMethodWithSubst.java.after @@ -0,0 +1,12 @@ +abstract class BaseTask> { +} + + +class ForEachTask extends BaseTask> { + public ForEachTask makeTask(int depth, ParallelStream coll) { + return new ForEachTask(); + } +} + +class ParallelStream { +} diff --git a/java/java-tests/testSrc/com/intellij/refactoring/PushDownTest.java b/java/java-tests/testSrc/com/intellij/refactoring/PushDownTest.java index 54fb2b7b3535..455b87b19e89 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/PushDownTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/PushDownTest.java @@ -115,6 +115,10 @@ public class PushDownTest extends LightRefactoringTestCase { doTest(); } + public void testOverridingMethodWithSubst() throws Exception { + doTest(); + } + public void testSameClassInterface() throws Exception { final String filePath = "/refactoring/pushDown/" + getTestName(false) + ".java"; configureByFile(filePath); From f33811b72d94e1aa570d4eb698eab2625011440a Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 30 May 2012 15:39:09 +0400 Subject: [PATCH 03/11] inline superclass: do not call for refactoring which would be invoked later: call method instead (IDEA-86806) --- .../com/intellij/refactoring/inline/InlineMethodProcessor.java | 2 +- .../inlineSuperClass/usageInfo/InlineSuperCallUsageInfo.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java index 983a510f4a68..d008ebdce664 100644 --- a/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java @@ -412,7 +412,7 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor { } } - private void inlineMethodCall(PsiReferenceExpression ref) throws IncorrectOperationException { + public void inlineMethodCall(PsiReferenceExpression ref) throws IncorrectOperationException { InlineUtil.TailCallType tailCall = InlineUtil.getTailCallType(ref); ChangeContextUtil.encodeContextInfo(myMethod, false); myMethodCopy = (PsiMethod)myMethod.copy(); diff --git a/java/java-impl/src/com/intellij/refactoring/inlineSuperClass/usageInfo/InlineSuperCallUsageInfo.java b/java/java-impl/src/com/intellij/refactoring/inlineSuperClass/usageInfo/InlineSuperCallUsageInfo.java index 1115aefe8cb6..d2b5ba2b1837 100644 --- a/java/java-impl/src/com/intellij/refactoring/inlineSuperClass/usageInfo/InlineSuperCallUsageInfo.java +++ b/java/java-impl/src/com/intellij/refactoring/inlineSuperClass/usageInfo/InlineSuperCallUsageInfo.java @@ -72,7 +72,7 @@ public class InlineSuperCallUsageInfo extends FixableUsageInfo { assert inliningClass != null; methodCopy = (PsiMethod)inliningClass.add(methodCopy); final InlineMethodProcessor inlineMethodProcessor = new InlineMethodProcessor(getProject(), methodCopy, methodExpression, null, true); - inlineMethodProcessor.run(); + inlineMethodProcessor.inlineMethodCall(methodExpression); methodCopy.delete(); } } From 8b33af3c57edad744c9dd1bfedad434d77116a4c Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 29 May 2012 12:02:36 +0400 Subject: [PATCH 04/11] RUBY-4982: "run irb console" implemented as run configuration with custom console TODO: - console command history saving doesn't work well - console shows help for run window, not a specific help topic --- .../runners/ConsoleExecuteActionHandler.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java b/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java index 8945622d5b56..d16ccb5d5e4a 100644 --- a/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java +++ b/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java @@ -23,6 +23,8 @@ import com.intellij.openapi.command.undo.DocumentReferenceManager; import com.intellij.openapi.command.undo.UndoManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.util.TextRange; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.io.OutputStream; @@ -31,7 +33,7 @@ import java.io.OutputStream; * @author traff */ public class ConsoleExecuteActionHandler { - private final ProcessHandler myProcessHandler; + private ProcessHandler myProcessHandler; private final boolean myPreserveMarkup; private boolean myAddCurrentToHistory = true; private ConsoleHistoryModel myConsoleHistoryModel; @@ -42,6 +44,15 @@ public class ConsoleExecuteActionHandler { myPreserveMarkup = preserveMarkup; } + @Nullable + private synchronized ProcessHandler getProcessHandler() { + return myProcessHandler; + } + + public synchronized void setProcessHandler(@NotNull final ProcessHandler processHandler) { + myProcessHandler = processHandler; + } + public void setConsoleHistoryModel(ConsoleHistoryModel consoleHistoryModel) { myConsoleHistoryModel = consoleHistoryModel; } @@ -81,7 +92,10 @@ public class ConsoleExecuteActionHandler { public void sendText(String line) { //final Charset charset = myProcessHandler.getCharset(); - final OutputStream outputStream = myProcessHandler.getProcessInput(); + final ProcessHandler handler = getProcessHandler(); + assert handler != null : "process handler is null"; + final OutputStream outputStream = handler.getProcessInput(); + assert outputStream != null : "output stream is null"; try { //byte[] bytes = (line + "\n").getBytes(charset.name()); byte[] bytes = line.getBytes(); From 19a4621b04f9c5dfa897533c41d47204cfd6dfb7 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 30 May 2012 14:26:17 +0400 Subject: [PATCH 05/11] RUBY-4982: Reload action added to Rails Console isRailsConsole property added to IrbRunConfiguration. IRBConsoleRunner and IRBToolbarAction removed --- .../execution/runners/ConsoleExecuteActionHandler.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java b/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java index d16ccb5d5e4a..13cf5a7c67b6 100644 --- a/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java +++ b/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java @@ -114,6 +114,11 @@ public class ConsoleExecuteActionHandler { public void finishExecution() { } + public final boolean isProcessTerminated() { + final ProcessHandler handler = getProcessHandler(); + return handler == null || handler.isProcessTerminated(); + } + public String getEmptyExecuteAction() { return "Console.Execute"; } From c88fa60c790c282ac3c8c178effb9e8efb4d1a63 Mon Sep 17 00:00:00 2001 From: Dmitry Boulytchev Date: Wed, 30 May 2012 15:46:17 +0400 Subject: [PATCH 06/11] Fixed bug in integrate (classToSubClasses) (compile-server) --- .../ether/dependencyView/Mappings.java | 64 +++++++++++++------ 1 file changed, 46 insertions(+), 18 deletions(-) diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java index 0ff6160c71d4..bd739573dcfd 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java @@ -846,7 +846,7 @@ public class Mappings { } private class Differential { - static final int DESPERATE_MASK = Opcodes.ACC_STATIC | Opcodes.ACC_FINAL; + final int DESPERATE_MASK = Opcodes.ACC_STATIC | Opcodes.ACC_FINAL; final Mappings myDelta; final Collection myRemoved; @@ -994,7 +994,7 @@ public class Mappings { } } - private void processAddedMethods (final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) { + private void processAddedMethods(final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) { debug("Processing added methods: "); for (final MethodRepr m : diff.methods().added()) { debug("Method: ", m.name); @@ -1120,7 +1120,7 @@ public class Mappings { debug("End of added methods processing"); } - private void processRemovedMethods (final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) { + private void processRemovedMethods(final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) { debug("Processing removed methods:"); for (final MethodRepr m : diff.methods().removed()) { debug("Method ", m.name); @@ -1216,7 +1216,7 @@ public class Mappings { debug("End of removed methods processing"); } - private void processChangedMethods (final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) { + private void processChangedMethods(final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) { debug("Processing changed methods:"); for (final Pair mr : diff.methods().changed()) { final MethodRepr m = mr.first; @@ -1305,7 +1305,7 @@ public class Mappings { debug("End of changed methods processing"); } - private boolean processAddedFields (final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) { + private boolean processAddedFields(final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) { debug("Processing added fields"); for (final FieldRepr f : diff.fields().added()) { @@ -1407,7 +1407,7 @@ public class Mappings { return true; } - private boolean processRemovedFields (final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) { + private boolean processRemovedFields(final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) { debug("Processing removed fields:"); for (final FieldRepr f : diff.fields().removed()) { @@ -1434,7 +1434,7 @@ public class Mappings { return true; } - private boolean processChangedFields (final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) { + private boolean processChangedFields(final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) { debug("Processing changed fields:"); for (final Pair f : diff.fields().changed()) { @@ -1623,19 +1623,19 @@ public class Mappings { debug("End of annotation-specific analysis"); } - processAddedMethods (state, diff, it); - processRemovedMethods (state, diff, it); - processChangedMethods (state, diff, it); + processAddedMethods(state, diff, it); + processRemovedMethods(state, diff, it); + processChangedMethods(state, diff, it); - if (!processAddedFields (state, diff, it)) { + if (!processAddedFields(state, diff, it)) { return false; } - if (!processRemovedFields (state, diff, it)) { + if (!processRemovedFields(state, diff, it)) { return false; } - if (!processChangedFields (state, diff, it)) { + if (!processChangedFields(state, diff, it)) { return false; } } @@ -1880,6 +1880,16 @@ public class Mappings { } if (delta.myIsDifferentiated) { + final TIntHashSet compiledClasses = new TIntHashSet(); + + delta.myClassToSourceFile.forEachEntry(new TIntIntProcedure() { + @Override + public boolean execute(final int a, final int b) { + compiledClasses.add(a); + return true; + } + }); + for (ClassRepr repr : delta.getDeletedClasses()) { cleanupRemovedClass(repr, null, subclassesTrashBin, dependenciesTrashBin); } @@ -1895,13 +1905,31 @@ public class Mappings { delta.getChangedClasses().forEach(new TIntProcedure() { @Override - public boolean execute(int className) { - final TIntHashSet subClasses = delta.myClassToSubclasses.get(className); - if (subClasses != null) { - myClassToSubclasses.replace(className, subClasses); + public boolean execute(final int className) { + TIntHashSet s = delta.myClassToSubclasses.get(className); + + final TIntHashSet newSubClasses = s == null ? new TIntHashSet() : s; + final TIntHashSet oldSubClasses = myClassToSubclasses.get(className); + + if (oldSubClasses != null) { + oldSubClasses.forEach(new TIntProcedure() { + @Override + public boolean execute(final int value) { + if (!compiledClasses.contains(value)) { + newSubClasses.add(value); + } + + return true; + } + } + ); + } + + if (newSubClasses.size() == 0) { + myClassToSubclasses.remove(className); } else { - myClassToSubclasses.remove(className); + myClassToSubclasses.replace(className, newSubClasses); } final int sourceFile = delta.myClassToSourceFile.get(className); From d6ab8d12c4f14ac8cee550702daf869a3d6d8c87 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 30 May 2012 16:00:40 +0400 Subject: [PATCH 07/11] UmlEditorProvider is DumbAware --- .../src/com/intellij/openapi/vfs/VfsUtilCore.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java b/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java index b8d501cd705b..ad4d1e5454a0 100644 --- a/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java +++ b/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java @@ -204,6 +204,17 @@ public class VfsUtilCore { } } + @NotNull + public static String loadText(@NotNull VirtualFile file, int length) throws IOException{ + InputStreamReader reader = new InputStreamReader(file.getInputStream(), file.getCharset()); + try { + return new String(FileUtil.loadText(reader, length)); + } + finally { + reader.close(); + } + } + @NotNull public static VirtualFile[] toVirtualFileArray(@NotNull Collection files) { int size = files.size(); From 27fca99c771e10f28eb897e5be0b60756c317089 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Tue, 29 May 2012 16:47:47 +0400 Subject: [PATCH 08/11] \n in enforced braces --- .../plugins/groovy/formatter/GroovyBraceEnforcer.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBraceEnforcer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBraceEnforcer.java index 371c27c025c6..d166f44a64d6 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBraceEnforcer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBraceEnforcer.java @@ -77,15 +77,9 @@ public class GroovyBraceEnforcer extends GroovyRecursiveElementVisitor { // if (true) i = 1; // Cool assignment // We can't just surround target block of code with curly braces because the closing one will be treated as comment as well. // Hence, we perform a check if we have such situation at the moment and insert new line before the closing brace. - int lastLineFeedIndex = oldText.lastIndexOf("\n"); - lastLineFeedIndex = Math.max(0, lastLineFeedIndex); - int lastLineCommentIndex = oldText.indexOf("//", lastLineFeedIndex); StringBuilder buf = new StringBuilder(oldText.length() + 5); - buf.append("{ ").append(oldText); - if (lastLineCommentIndex >= 0) { - buf.append("\n"); - } - buf.append(" }"); + buf.append("{\n").append(oldText); + buf.append("\n}"); final int oldTextLength = statement.getTextLength(); try { CodeEditUtil.replaceChild(SourceTreeToPsiMap.psiElementToTree(statement), From eb52dde764c30ecfd043e182d45ce56147d73338 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Wed, 30 May 2012 15:08:38 +0400 Subject: [PATCH 09/11] IDEA-86459 Report Groovy 2.0 typing errors --- .../groovy/annotator/GroovyAnnotator.java | 48 ++++++++++++++----- .../annotator/intentions/QuickfixUtil.java | 28 ++++------- .../lang/psi/impl/GroovyPsiManager.java | 21 ++++++++ .../lang/psi/util/GroovyCommonClassNames.java | 3 +- .../groovy/lang/GroovyHighlightingTest.groovy | 24 ++++++++++ 5 files changed, 91 insertions(+), 33 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java index 25588db24afb..8d15fc37c8a8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java @@ -62,6 +62,7 @@ import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.DynamicMethodFi import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.DynamicPropertyFix; import org.jetbrains.plugins.groovy.config.GroovyConfigUtils; import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment; +import org.jetbrains.plugins.groovy.dsl.toplevel.AnnotatedContextFilter; import org.jetbrains.plugins.groovy.extensions.GroovyUnresolvedHighlightFilter; import org.jetbrains.plugins.groovy.highlighter.DefaultHighlighter; import org.jetbrains.plugins.groovy.lang.documentation.GroovyPresentationUtil; @@ -101,12 +102,14 @@ import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatem import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.packaging.GrPackageDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.types.*; import org.jetbrains.plugins.groovy.lang.psi.api.util.GrVariableDeclarationOwner; +import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager; import org.jetbrains.plugins.groovy.lang.psi.impl.TypeInferenceHelper; import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.annotation.GrAnnotationImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightParameter; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass; import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil; +import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; @@ -324,6 +327,7 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { PsiElement resolved = resolveResult.getElement(); final PsiElement parent = referenceExpression.getParent(); + if (resolved != null) { if (resolved instanceof PsiMember) { highlightMemberResolved(myHolder, referenceExpression, ((PsiMember)resolved)); @@ -337,7 +341,7 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { Annotation annotation = myHolder.createInfoAnnotation(referenceExpression, GroovyBundle.message("cannot.reference.nonstatic", referenceExpression.getReferenceName())); - annotation.setTextAttributes(DefaultHighlighter.UNRESOLVED_ACCESS); + annotation.setTextAttributes(isStaticallyCompiled(referenceExpression)?DefaultHighlighter.BAD_CHARACTER:DefaultHighlighter.UNRESOLVED_ACCESS); } } } @@ -377,8 +381,22 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { PsiElement refNameElement = referenceExpression.getReferenceNameElement(); PsiElement elt = refNameElement == null ? referenceExpression : refNameElement; - Annotation annotation = myHolder.createInfoAnnotation(elt, null); final GrExpression qualifier = referenceExpression.getQualifierExpression(); + + Annotation annotation; + + boolean compileStatic = isCompileStatic(referenceExpression); + if (compileStatic) { + annotation = myHolder.createInfoAnnotation(elt, GroovyBundle.message("cannot.resolve", referenceExpression.getReferenceName())); + annotation.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL); + } + else { + if (qualifier != null && qualifier.getType() == null) return; + + annotation = myHolder.createInfoAnnotation(elt, null); + annotation.setTextAttributes(DefaultHighlighter.UNRESOLVED_ACCESS); + } + if (qualifier == null) { if (parent instanceof GrMethodCall) { registerStaticImportFix(referenceExpression, annotation); @@ -388,20 +406,22 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { registerAddImportFixes(referenceExpression, annotation); } } - else { - if (qualifier.getType() == null) { - return; - } - } - registerReferenceFixes(referenceExpression, annotation); + registerReferenceFixes(referenceExpression, annotation, compileStatic); UnresolvedReferenceQuickFixProvider.registerReferenceFixes(referenceExpression, new QuickFixActionRegistrarAdapter(annotation)); OrderEntryFix.registerFixes(new QuickFixActionRegistrarAdapter(annotation), referenceExpression); - - annotation.setTextAttributes(DefaultHighlighter.UNRESOLVED_ACCESS); } } + private static boolean isCompileStatic(GrReferenceExpression referenceExpression) { + PsiMember containingMember = PsiTreeUtil.getParentOfType(referenceExpression, PsiMember.class); + return containingMember != null && GroovyPsiManager.getInstance(containingMember.getProject()).isCompileStatic(containingMember); + } + + private static boolean isStaticallyCompiled(GrReferenceExpression referenceExpression) { + return AnnotatedContextFilter.findContextAnnotation(referenceExpression, GroovyCommonClassNames.GROOVY_TRANSFORM_COMPILE_STATIC)!=null; + } + private void highlightVariable(GrVariable variable, PsiElement toHighlight) { Annotation annotation = myHolder.createInfoAnnotation(toHighlight, null); boolean reassigned = isReassigned(variable); @@ -1772,11 +1792,13 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { } - private static void registerReferenceFixes(GrReferenceExpression refExpr, Annotation annotation) { - PsiClass targetClass = QuickfixUtil.findTargetClass(refExpr); + private static void registerReferenceFixes(GrReferenceExpression refExpr, Annotation annotation, boolean compileStatic) { + PsiClass targetClass = QuickfixUtil.findTargetClass(refExpr, compileStatic); if (targetClass == null) return; - addDynamicAnnotation(annotation, refExpr); + if (!compileStatic) { + addDynamicAnnotation(annotation, refExpr); + } if (targetClass.isWritable()) { if (!(targetClass instanceof GroovyScriptClass)) { if (targetClass instanceof GrMemberOwner) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/QuickfixUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/QuickfixUtil.java index 0bdf81f41459..e64cd56068b1 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/QuickfixUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/QuickfixUtil.java @@ -26,7 +26,6 @@ import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.codeStyle.SuggestedNameInfo; import com.intellij.psi.codeStyle.VariableKind; -import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTypesUtil; import com.intellij.util.ArrayUtil; import gnu.trove.THashSet; @@ -34,13 +33,13 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.ParamInfo; import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.ui.DynamicElementSettings; -import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentLabel; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall; 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.api.statements.typedef.GrTypeDefinition; +import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrReferenceResolveUtil; 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.lang.resolve.ResolveUtil; @@ -53,22 +52,13 @@ import java.util.*; */ public class QuickfixUtil { @Nullable - public static PsiClass findTargetClass(GrReferenceExpression refExpr) { - final PsiClass psiClass; - if (refExpr.isQualified()) { - GrExpression qualifier = refExpr.getQualifierExpression(); - PsiType type = qualifier.getType(); - if (!(type instanceof PsiClassType)) return null; - - psiClass = ((PsiClassType)type).resolve(); - } else { - GroovyPsiElement context = PsiTreeUtil.getParentOfType(refExpr, GrTypeDefinition.class, GroovyFileBase.class); - if (context instanceof GrTypeDefinition) { - return (PsiClass)context; - } else if (context instanceof GroovyFileBase) return ((GroovyFileBase)context).getScriptClass(); - return null; + public static PsiClass findTargetClass(GrReferenceExpression refExpr, boolean compileStatic) { + PsiType type = GrReferenceResolveUtil.getQualifierType(refExpr); + if (type == null && compileStatic) { + return GroovyPsiManager.getInstance(refExpr.getProject()).findClassWithCache(CommonClassNames.JAVA_LANG_OBJECT, refExpr.getResolveScope()); } - return psiClass; + if (!(type instanceof PsiClassType)) return null; + return ((PsiClassType)type).resolve(); } public static boolean isStaticCall(GrReferenceExpression refExpr) { @@ -184,7 +174,7 @@ public class QuickfixUtil { public static DynamicElementSettings createSettings(GrReferenceExpression referenceExpression) { DynamicElementSettings settings = new DynamicElementSettings(); - final PsiClass containingClass = findTargetClass(referenceExpression); + final PsiClass containingClass = findTargetClass(referenceExpression, false); assert containingClass != null; String className = containingClass.getQualifiedName(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiManager.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiManager.java index c6e9c8cfe03e..f14ad91f7f9c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiManager.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiManager.java @@ -65,6 +65,7 @@ public class GroovyPsiManager { private final ConcurrentMap myCalculatedTypes = new ConcurrentWeakHashMap(); private final ConcurrentMap>> myClassCache = new ConcurrentHashMap>>(); + private final ConcurrentMap myCompileStatic = new ConcurrentHashMap(); private static final RecursionGuard ourGuard = RecursionManager.createGuard("groovyPsiManager"); @@ -92,6 +93,7 @@ public class GroovyPsiManager { public void dropTypesCache() { myCalculatedTypes.clear(); + myCompileStatic.clear(); } public static boolean isInheritorCached(@Nullable PsiClass aClass, @NotNull String baseClassName) { @@ -122,6 +124,25 @@ public class GroovyPsiManager { return JavaPsiFacade.getElementFactory(myProject).createTypeByFQClassName(fqName, resolveScope); } + public boolean isCompileStatic(PsiMember member) { + Boolean aBoolean = myCompileStatic.get(member); + if (aBoolean == null) { + aBoolean = ConcurrencyUtil.cacheOrGet(myCompileStatic, member, isCompileStaticInner(member)); + } + return aBoolean; + } + + private boolean isCompileStaticInner(PsiMember member) { + PsiModifierList list = member.getModifierList(); + if (list != null) { + PsiAnnotation annotation = list.findAnnotation(GroovyCommonClassNames.GROOVY_TRANSFORM_COMPILE_STATIC); + if (annotation != null) return true; + } + PsiClass aClass = member.getContainingClass(); + if (aClass != null) return isCompileStatic(aClass); + return false; + } + @Nullable public PsiClass findClassWithCache(String fqName, GlobalSearchScope resolveScope) { SoftReference> reference = myClassCache.get(fqName); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyCommonClassNames.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyCommonClassNames.java index 3af8dccbb9b1..f6e040e36eff 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyCommonClassNames.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyCommonClassNames.java @@ -50,7 +50,8 @@ public final class GroovyCommonClassNames { @NonNls public static final String GROOVY_LANG_USE = "groovy.lang.Use"; @NonNls public static final String GROOVY_LANG_MIXIN = "groovy.lang.Mixin"; @NonNls public static final String GROOVY_UTIL_TEST_CASE = "groovy.util.GroovyTestCase"; - public static final String GROOVY_LANG_SINGLETON = "groovy.lang.Singleton"; + @NonNls public static final String GROOVY_LANG_SINGLETON = "groovy.lang.Singleton"; + @NonNls public static final String GROOVY_TRANSFORM_COMPILE_STATIC = "groovy.transform.CompileStatic"; private GroovyCommonClassNames() { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy index 704262585a0d..2a0f9a818d25 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy @@ -1009,4 +1009,28 @@ use(Ca) { ''', GroovyAssignabilityCheckInspection) } + void testCompileStatic() { + myFixture.addClass('''\ +package groovy.transform; +public @interface CompileStatic { +}''') + + myFixture.configureByText('_.groovy', '''\ +import groovy.transform.CompileStatic + +class A { + +def foo() { +print abc +} + +@CompileStatic +def bar() { +print abc +} +} +''') + myFixture.testHighlighting(true, true, true) + } + } \ No newline at end of file From 713683550ba413d176fc742c34dec02786d3c623 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Wed, 30 May 2012 16:09:11 +0400 Subject: [PATCH 10/11] Assignability checks in groovy annotator for statically compiled code --- .../groovy/annotator/GroovyAnnotator.java | 8 +- .../GroovyAssignabilityCheckInspection.java | 102 ++++++++++++++++-- .../groovy/lang/GroovyHighlightingTest.groovy | 25 +++++ 3 files changed, 127 insertions(+), 8 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java index 8d15fc37c8a8..0cadee6aa3c9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java @@ -60,6 +60,7 @@ import org.jetbrains.plugins.groovy.GroovyBundle; import org.jetbrains.plugins.groovy.annotator.intentions.*; import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.DynamicMethodFix; import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.DynamicPropertyFix; +import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection; import org.jetbrains.plugins.groovy.config.GroovyConfigUtils; import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment; import org.jetbrains.plugins.groovy.dsl.toplevel.AnnotatedContextFilter; @@ -131,6 +132,9 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { if (element instanceof GroovyPsiElement) { myHolder = holder; ((GroovyPsiElement)element).accept(this); + if (isCompileStatic(element)) { + GroovyAssignabilityCheckInspection.checkElement((GroovyPsiElement)element, holder); + } myHolder = null; } else { @@ -413,8 +417,8 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { } } - private static boolean isCompileStatic(GrReferenceExpression referenceExpression) { - PsiMember containingMember = PsiTreeUtil.getParentOfType(referenceExpression, PsiMember.class); + private static boolean isCompileStatic(PsiElement e) { + PsiMember containingMember = PsiTreeUtil.getParentOfType(e, PsiMember.class); return containingMember != null && GroovyPsiManager.getInstance(containingMember.getProject()).isCompileStatic(containingMember); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java index f93e5f8511bd..5e0b1ef850ac 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java @@ -16,14 +16,22 @@ package org.jetbrains.plugins.groovy.codeInspection.assignment; +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInspection.InspectionManager; import com.intellij.codeInspection.LocalQuickFix; +import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.lang.annotation.Annotation; +import com.intellij.lang.annotation.AnnotationHolder; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.Function; +import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,7 +39,6 @@ import org.jetbrains.plugins.groovy.GroovyBundle; import org.jetbrains.plugins.groovy.annotator.GroovyAnnotator; import org.jetbrains.plugins.groovy.codeInspection.BaseInspection; import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor; -import org.jetbrains.plugins.groovy.codeInspection.GroovyFix; import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle; import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils; import org.jetbrains.plugins.groovy.config.GroovyConfigUtils; @@ -45,6 +52,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap; import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature; import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignature; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument; @@ -56,10 +64,12 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrString; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrIndexProperty; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.*; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction; import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType; +import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager; import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrReferenceResolveUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; @@ -80,11 +90,6 @@ import java.util.Map; public class GroovyAssignabilityCheckInspection extends BaseInspection { private static final Logger LOG = Logger.getInstance(GroovyAssignabilityCheckInspection.class); - @Override - protected GroovyFix buildFix(PsiElement location) { - return super.buildFix(location); //To change body of overridden methods use File | Settings | File Templates. - } - @Nls @NotNull @Override @@ -159,6 +164,8 @@ public class GroovyAssignabilityCheckInspection extends BaseInspection { @Override public void visitMethod(GrMethod method) { + if (GroovyPsiManager.getInstance(method.getProject()).isCompileStatic(method)) return; + super.visitMethod(method); final GrOpenBlock block = method.getBlock(); if (block == null) return; @@ -178,6 +185,18 @@ public class GroovyAssignabilityCheckInspection extends BaseInspection { }); } + @Override + public void visitField(GrField field) { + if (GroovyPsiManager.getInstance(field.getProject()).isCompileStatic(field)) return; + super.visitField(field); + } + + @Override + public void visitTypeDefinition(GrTypeDefinition typeDefinition) { + if (GroovyPsiManager.getInstance(typeDefinition.getProject()).isCompileStatic(typeDefinition)) return; + super.visitTypeDefinition(typeDefinition); + } + @Override public void visitReturnStatement(GrReturnStatement returnStatement) { super.visitReturnStatement(returnStatement); @@ -761,4 +780,75 @@ public class GroovyAssignabilityCheckInspection extends BaseInspection { } return GrReferenceResolveUtil.getQualifierType(place); } + + + private static class AnnotatingVisitor extends MyVisitor { + private AnnotationHolder myHolder; + + + @Override + protected void registerError(@NotNull final PsiElement location, + final String description, + final LocalQuickFix[] fixes, + final ProblemHighlightType highlightType) { + Annotation annotation = myHolder.createErrorAnnotation(location, description); + for (final LocalQuickFix fix : fixes) { + annotation.registerFix(new IntentionAction() { + @NotNull + @Override + public String getText() { + return fix.getName(); + } + + @NotNull + @Override + public String getFamilyName() { + return fix.getFamilyName(); + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + return true; + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + InspectionManager manager = InspectionManager.getInstance(project); + ProblemDescriptor descriptor = manager.createProblemDescriptor(location, description, fixes, highlightType, fixes.length == 1, false); + fix.applyFix(project, descriptor); + } + + @Override + public boolean startInWriteAction() { + return true; + } + }); + } + } + + @Override + public void visitElement(GroovyPsiElement element) { + //do nothing + } + } + + private static final ThreadLocal visitor = new ThreadLocal() { + @Override + protected AnnotatingVisitor initialValue() { + return new AnnotatingVisitor(); + } + }; + + public static void checkElement(GroovyPsiElement e, AnnotationHolder holder) { + AnnotatingVisitor annotatingVisitor = visitor.get(); + + AnnotationHolder oldHolder = annotatingVisitor.myHolder; + try { + annotatingVisitor.myHolder = holder; + e.accept(annotatingVisitor); + } + finally { + annotatingVisitor.myHolder = oldHolder; + } + } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy index 2a0f9a818d25..9022f9362348 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy @@ -1033,4 +1033,29 @@ public @interface CompileStatic { myFixture.testHighlighting(true, true, true) } + + void testCompileStaticWithAssignabilityCheck() { + myFixture.addClass('''\ +package groovy.transform; +public @interface CompileStatic { +}''') + + myFixture.configureByText('_.groovy', '''\ +import groovy.transform.CompileStatic + +class A { + + def foo(String s) { + int x = new Date() + } + + @CompileStatic + def bar() { + int x = new Date() + } +} +''') + myFixture.enableInspections(GroovyAssignabilityCheckInspection) + myFixture.checkHighlighting(true, false, true) + } } \ No newline at end of file From 360643e7ff2dac4add5a2bc5f32cc912204be85f Mon Sep 17 00:00:00 2001 From: nik Date: Wed, 30 May 2012 16:16:59 +0400 Subject: [PATCH 11/11] creating new library: NPE fixed --- .../configuration/libraryEditor/CreateNewLibraryAction.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/CreateNewLibraryAction.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/CreateNewLibraryAction.java index 4594d4e33674..ff1b722772a1 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/CreateNewLibraryAction.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/CreateNewLibraryAction.java @@ -80,9 +80,11 @@ public class CreateNewLibraryAction extends DumbAwareAction { @NotNull final Project project, @NotNull final LibrariesModifiableModel modifiableModel) { final NewLibraryConfiguration configuration = createNewLibraryConfiguration(type, parentComponent, project); if (configuration == null) return null; - final Library library = modifiableModel.createLibrary(LibraryEditingUtil.suggestNewLibraryName(modifiableModel, configuration.getDefaultLibraryName()), configuration.getLibraryType().getKind()); + final LibraryType libraryType = configuration.getLibraryType(); + final Library library = modifiableModel.createLibrary( + LibraryEditingUtil.suggestNewLibraryName(modifiableModel, configuration.getDefaultLibraryName()), libraryType != null ? libraryType.getKind() : null); - final NewLibraryEditor editor = new NewLibraryEditor(configuration.getLibraryType(), configuration.getProperties()); + final NewLibraryEditor editor = new NewLibraryEditor(libraryType, configuration.getProperties()); configuration.addRoots(editor); final Library.ModifiableModel model = library.getModifiableModel(); editor.applyTo((LibraryEx.ModifiableModelEx)model);