diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 78153889a308..80aea01d1661 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -3,16 +3,8 @@ - - - - - - - - - diff --git a/java/execution/openapi/src/com/intellij/execution/filters/AuxiliaryCallsFolding.java b/java/execution/openapi/src/com/intellij/execution/filters/AuxiliaryCallsFolding.java index 5240ad7b7add..83df6698588d 100644 --- a/java/execution/openapi/src/com/intellij/execution/filters/AuxiliaryCallsFolding.java +++ b/java/execution/openapi/src/com/intellij/execution/filters/AuxiliaryCallsFolding.java @@ -13,12 +13,12 @@ public class AuxiliaryCallsFolding extends ConsoleFolding { @Override public boolean shouldFoldLine(String line) { final Trinity pair = ExceptionFilter.parseExceptionLine(line); - return pair != null && shouldFold(pair.first); + return pair != null && shouldFold(pair.first, pair.second); } - private static boolean shouldFold(String className) { + private static boolean shouldFold(String className, String methodName) { for (StackFrameFilter provider : StackFrameFilter.EP_NAME.getExtensions()) { - if (provider.isAuxiliaryFrame(className, "")) { + if (provider.isAuxiliaryFrame(className, methodName)) { return true; } } diff --git a/java/execution/openapi/src/com/intellij/execution/filters/ExceptionFilter.java b/java/execution/openapi/src/com/intellij/execution/filters/ExceptionFilter.java index 6b05b21f3fa6..bce070511d3d 100644 --- a/java/execution/openapi/src/com/intellij/execution/filters/ExceptionFilter.java +++ b/java/execution/openapi/src/com/intellij/execution/filters/ExceptionFilter.java @@ -74,13 +74,12 @@ public class ExceptionFilter implements Filter, DumbAware { if (lastDotIndex < 0 || lastDotIndex < atIndex) return null; String className = line.substring(atIndex + AT.length() + 1, lastDotIndex).trim(); - //String methodName = text.substring(lastDotIndex + 1, lparenthIndex).trim(); + String methodName = line.substring(lastDotIndex + 1, lparenthIndex).trim(); final int rparenthIndex = line.indexOf(')', lparenthIndex); if (rparenthIndex < 0) return null; - final String fileAndLine = line.substring(lparenthIndex + 1, rparenthIndex).trim(); - return Trinity.create(className, fileAndLine, new TextRange(lparenthIndex, rparenthIndex)); + return Trinity.create(className, methodName, new TextRange(lparenthIndex, rparenthIndex)); } public Result applyFilter(final String line, final int textEndOffset) { @@ -95,7 +94,9 @@ public class ExceptionFilter implements Filter, DumbAware { className = className.substring(0, dollarIndex); } - final String fileAndLine = info.second; + final int lparenthIndex = info.third.getStartOffset(); + final int rparenthIndex = info.third.getEndOffset(); + final String fileAndLine = line.substring(lparenthIndex + 1, rparenthIndex).trim(); final int colonIndex = fileAndLine.lastIndexOf(':'); if (colonIndex < 0) return null; @@ -118,8 +119,9 @@ public class ExceptionFilter implements Filter, DumbAware { */ final int textStartOffset = textEndOffset - line.length(); - final int highlightStartOffset = textStartOffset + info.third.getStartOffset() + 1; - final int highlightEndOffset = textStartOffset + info.third.getEndOffset(); + + final int highlightStartOffset = textStartOffset + lparenthIndex + 1; + final int highlightEndOffset = textStartOffset + rparenthIndex; VirtualFile virtualFile = file.getVirtualFile(); final OpenFileHyperlinkInfo linkInfo = new OpenFileHyperlinkInfo(myProject, virtualFile, lineNumber - 1); TextAttributes attributes = HYPERLINK_ATTRIBUTES.clone(); diff --git a/java/execution/openapi/src/com/intellij/execution/filters/ReflectionStackFrameFilter.java b/java/execution/openapi/src/com/intellij/execution/filters/ReflectionStackFrameFilter.java index ed60d87c0b4d..3cd61a5d95f8 100644 --- a/java/execution/openapi/src/com/intellij/execution/filters/ReflectionStackFrameFilter.java +++ b/java/execution/openapi/src/com/intellij/execution/filters/ReflectionStackFrameFilter.java @@ -5,6 +5,13 @@ package com.intellij.execution.filters; */ public class ReflectionStackFrameFilter extends StackFrameFilter { public boolean isAuxiliaryFrame(String className, String methodName) { + if (className.equals("java.lang.reflect.Method") && methodName.equals("invoke")) { + return true; + } + if (className.equals("java.lang.reflect.Constructor") && methodName.equals("newInstance")) { + return true; + } + return className.startsWith("sun.reflect."); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/simple/PsiMethodInsertHandler.java b/java/java-impl/src/com/intellij/codeInsight/completion/simple/PsiMethodInsertHandler.java index 0f9f5f2bdf39..928ddc97fe21 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/simple/PsiMethodInsertHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/simple/PsiMethodInsertHandler.java @@ -53,24 +53,26 @@ public class PsiMethodInsertHandler implements InsertHandler 1 || item.getUserData(LookupItem.FORCE_SHOW_SIGNATURE_ATTR) != null; + final boolean overloadsMatter = allItems.length == 1 && item.getUserData(LookupItem.FORCE_SHOW_SIGNATURE_ATTR) == null; - int offset = editor.getCaretModel().getOffset(); + final boolean hasParams = MethodParenthesesHandler.hasParams(item, allItems, overloadsMatter, myMethod); final boolean needLeftParenth = isToInsertParenth(file.findElementAt(context.getStartOffset())); - final boolean hasParams = MethodParenthesesHandler.hasParams(item, allItems, !signatureSelected, myMethod); + final boolean needRightParenth = shouldInsertRParenth(completionChar, tailType, hasParams); + if (needLeftParenth) { final CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(context.getProject()); - new MethodParenthesesHandler(myMethod, !signatureSelected, + new MethodParenthesesHandler(myMethod, overloadsMatter, styleSettings.SPACE_BEFORE_METHOD_CALL_PARENTHESES, styleSettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES && hasParams, - shouldInsertRightParenthesis(tailType) + needRightParenth ).handleInsert(context, item); } - + insertExplicitTypeParams(item, document, offset, file); final PsiType type = myMethod.getReturnType(); @@ -86,14 +88,25 @@ public class PsiMethodInsertHandler implements InsertHandler 1) return; PsiDirectory dir = element.getContainingDirectory(); if (dir == null) return; diff --git a/java/java-tests/testData/codeInsight/completion/normal/MethodWithLeftParTailTypeNoPairBrace.java b/java/java-tests/testData/codeInsight/completion/normal/MethodWithLeftParTailTypeNoPairBrace.java new file mode 100644 index 000000000000..0403bf2a8dab --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/MethodWithLeftParTailTypeNoPairBrace.java @@ -0,0 +1,8 @@ +class MyClass { + +void foo() {} + +{ + fo +} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/MethodWithLeftParTailTypeNoPairBrace_after.java b/java/java-tests/testData/codeInsight/completion/normal/MethodWithLeftParTailTypeNoPairBrace_after.java new file mode 100644 index 000000000000..c976d92117e9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/MethodWithLeftParTailTypeNoPairBrace_after.java @@ -0,0 +1,8 @@ +class MyClass { + +void foo() {} + +{ + foo( +} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/MethodWithLeftParTailTypeNoPairBrace_after2.java b/java/java-tests/testData/codeInsight/completion/normal/MethodWithLeftParTailTypeNoPairBrace_after2.java new file mode 100644 index 000000000000..b7841df3ff15 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/MethodWithLeftParTailTypeNoPairBrace_after2.java @@ -0,0 +1,8 @@ +class MyClass { + +void foo() {} + +{ + foo(); +} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/MethodWithLeftParTailType_after.java b/java/java-tests/testData/codeInsight/completion/normal/MethodWithLeftParTailType_after.java index b7841df3ff15..7680812e2f7c 100644 --- a/java/java-tests/testData/codeInsight/completion/normal/MethodWithLeftParTailType_after.java +++ b/java/java-tests/testData/codeInsight/completion/normal/MethodWithLeftParTailType_after.java @@ -3,6 +3,6 @@ class MyClass { void foo() {} { - foo(); + foo(); } } \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.java index c0103a0adde7..f6a2431c26d6 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.java @@ -308,6 +308,25 @@ public class NormalCompletionTest extends LightCompletionTestCase { checkResultByFile("/codeInsight/completion/normal/MethodWithLeftParTailType2_after.java"); } + public void testMethodWithLeftParTailTypeNoPairBrace() throws Exception { + final boolean old = CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET; + CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET = false; + + try { + configureByFile("/codeInsight/completion/normal/" + getTestName(false) + ".java"); + selectItem(myItems[0], '('); + checkResultByFile("/codeInsight/completion/normal/" + getTestName(false) + "_after.java"); + + //no tail type should work the normal way + configureByFile("/codeInsight/completion/normal/" + getTestName(false) + ".java"); + selectItem(myItems[0]); + checkResultByFile("/codeInsight/completion/normal/" + getTestName(false) + "_after2.java"); + } + finally { + CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET = old; + } + } + public void testExcessSpaceInTypeCast() throws Throwable { configureByFile("/codeInsight/completion/normal/" + getTestName(false) + ".java"); selectItem(myItems[0]); diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/util/ParenthesesInsertHandler.java b/platform/lang-api/src/com/intellij/codeInsight/completion/util/ParenthesesInsertHandler.java index 939c63455152..c958c6e5b525 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/completion/util/ParenthesesInsertHandler.java +++ b/platform/lang-api/src/com/intellij/codeInsight/completion/util/ParenthesesInsertHandler.java @@ -72,9 +72,9 @@ public abstract class ParenthesesInsertHandler implemen final Document document = editor.getDocument(); PsiElement element = findNextToken(context); - final boolean hasParams = placeCaretInsideParentheses(context, item); - final char completionChar = context.getCompletionChar(); + final boolean putCaretInside = completionChar == '(' || placeCaretInsideParentheses(context, item); + if (completionChar == '(') { context.setAddCompletionChar(false); } @@ -99,7 +99,7 @@ public abstract class ParenthesesInsertHandler implemen if (isToken(last, ")")) { int rparenthOffset = last.getTextRange().getStartOffset(); context.setTailOffset(rparenthOffset + 1); - if (!hasParams) { + if (!putCaretInside) { for (int i = lparenthOffset + 1; i < rparenthOffset; i++) { if (!Character.isWhitespace(document.getCharsSequence().charAt(i))) { return; @@ -132,7 +132,7 @@ public abstract class ParenthesesInsertHandler implemen tailOffset = TailType.insertChar(editor, tailOffset, ' '); } document.insertString(tailOffset, ")"); - editor.getCaretModel().moveToOffset(hasParams ? caret : context.getTailOffset()); + editor.getCaretModel().moveToOffset(putCaretInside ? caret : context.getTailOffset()); } @Nullable diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyPasteFoldingProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyPasteFoldingProcessor.java index 9636cfc40ea8..350f8550566b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyPasteFoldingProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyPasteFoldingProcessor.java @@ -24,6 +24,7 @@ import com.intellij.psi.PsiFile; import com.intellij.codeInsight.folding.CodeFoldingManager; import org.jetbrains.annotations.Nullable; +import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.util.ArrayList; @@ -59,8 +60,10 @@ public class CopyPasteFoldingProcessor implements CopyPastePostProcessor { public TextBlockTransferableData extractTransferableData(final Transferable content) { FoldingTransferableData foldingData = null; try { - foldingData = - (FoldingTransferableData)content.getTransferData(FoldingTransferableData.FoldingData.FLAVOR); + final DataFlavor flavor = FoldingTransferableData.FoldingData.getDataFlavor(); + if (flavor != null) { + foldingData = (FoldingTransferableData)content.getTransferData(flavor); + } } catch (UnsupportedFlavorException e) { } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/FoldingTransferableData.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/FoldingTransferableData.java index 20791b4c4ffc..6225bae2f458 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/FoldingTransferableData.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/FoldingTransferableData.java @@ -16,7 +16,6 @@ package com.intellij.codeInsight.editorActions; -import com.intellij.codeInsight.CodeInsightBundle; import org.jetbrains.annotations.NonNls; import java.awt.datatransfer.DataFlavor; @@ -30,7 +29,7 @@ public class FoldingTransferableData implements TextBlockTransferableData, Seria } public DataFlavor getFlavor() { - return FoldingData.FLAVOR; + return FoldingData.getDataFlavor(); } public int getOffsetCount() { @@ -66,8 +65,7 @@ public class FoldingTransferableData implements TextBlockTransferableData, Seria } public static class FoldingData implements Cloneable, Serializable { - public static final @NonNls DataFlavor FLAVOR = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";class=" + FoldingData.class.getName(), - CodeInsightBundle.message("paste.data.flavor.folding")); + private static @NonNls DataFlavor ourFlavor; public int startOffset; public int endOffset; @@ -87,5 +85,18 @@ public class FoldingTransferableData implements TextBlockTransferableData, Seria throw new RuntimeException(); } } + + public static DataFlavor getDataFlavor() { + if (ourFlavor != null) { + return ourFlavor; + } + try { + ourFlavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";class=" + FoldingData.class.getName(), "FoldingData"); + } + catch (NoClassDefFoundError e) { + return null; + } + return ourFlavor; + } } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java index 1d06ad27857a..6e056a425b7c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java @@ -45,8 +45,6 @@ import com.intellij.util.text.CharArrayUtil; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; -import java.awt.datatransfer.UnsupportedFlavorException; -import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Map; @@ -153,14 +151,7 @@ public class PasteHandler extends EditorActionHandler { ); } - RawText rawText = null; - try { - rawText = (RawText)content.getTransferData(RawText.FLAVOR); - } - catch (UnsupportedFlavorException e) { - } - catch (IOException e) { - } + RawText rawText = RawText.fromTransferable(content); String newText = text; for(CopyPastePreProcessor preProcessor: Extensions.getExtensions(CopyPastePreProcessor.EP_NAME)) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TextBlockTransferable.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TextBlockTransferable.java index 4fc8a411f461..3b8f1904dcd1 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TextBlockTransferable.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TextBlockTransferable.java @@ -17,6 +17,7 @@ package com.intellij.codeInsight.editorActions; import com.intellij.openapi.editor.RawText; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.text.StringUtil; import java.awt.datatransfer.DataFlavor; @@ -41,9 +42,16 @@ class TextBlockTransferable implements Transferable { myRawText = rawText; List dataFlavors = new ArrayList(); - Collections.addAll(dataFlavors, DataFlavor.stringFlavor, DataFlavor.plainTextFlavor, RawText.FLAVOR); + Collections.addAll(dataFlavors, DataFlavor.stringFlavor, DataFlavor.plainTextFlavor); + final DataFlavor flavor = RawText.getDataFlavor(); + if (flavor != null) { + dataFlavors.add(flavor); + } for(TextBlockTransferableData data: extraData) { - dataFlavors.add(data.getFlavor()); + final DataFlavor blockFlavor = data.getFlavor(); + if (blockFlavor != null) { + dataFlavors.add(blockFlavor); + } } myTransferDataFlavors = dataFlavors.toArray(new DataFlavor[dataFlavors.size()]); } @@ -65,11 +73,11 @@ class TextBlockTransferable implements Transferable { public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { try { for(TextBlockTransferableData data: myExtraData) { - if (data.getFlavor().equals(flavor)) { + if (Comparing.equal(data.getFlavor(), flavor)) { return data; } } - if (RawText.FLAVOR.equals(flavor)) { + if (Comparing.equal(RawText.getDataFlavor(), flavor)) { return myRawText; } else if (DataFlavor.stringFlavor.equals(flavor)) { diff --git a/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java b/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java index f3f2231e5dbd..db72cbb5091e 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java @@ -141,17 +141,7 @@ public class EditorModificationUtil { } private static String getStringContent(final Transferable content) throws UnsupportedFlavorException, IOException { - RawText raw = null; - try { - raw = (RawText)content.getTransferData(RawText.FLAVOR); - } - catch (UnsupportedFlavorException e) { - // OK. raw will be null and we'll get plain string - } - catch (IOException e) { - // OK. raw will be null and we'll get plain string - } - + RawText raw = RawText.fromTransferable(content); String s; if (raw != null) { s = raw.rawText; diff --git a/platform/platform-api/src/com/intellij/openapi/editor/RawText.java b/platform/platform-api/src/com/intellij/openapi/editor/RawText.java index f94ade31ef31..4c070ff737e9 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/RawText.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/RawText.java @@ -23,13 +23,16 @@ package com.intellij.openapi.editor; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.Nullable; import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.IOException; import java.io.Serializable; public class RawText implements Cloneable, Serializable { - public static final @NonNls DataFlavor FLAVOR = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";class=" + RawText.class.getName(), - "Raw Text"); + public static @NonNls DataFlavor ourFlavor; public String rawText; public RawText(final String rawText) { @@ -44,4 +47,35 @@ public class RawText implements Cloneable, Serializable { throw new RuntimeException(); } } + + public static DataFlavor getDataFlavor() { + if (ourFlavor != null) { + return ourFlavor; + } + try { + ourFlavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";class=" + RawText.class.getName(), "Raw Text"); + } + catch (NoClassDefFoundError e) { + return null; + } + return ourFlavor; + } + + @Nullable + public static RawText fromTransferable(Transferable content) { + RawText raw = null; + final DataFlavor flavor = getDataFlavor(); + if (flavor != null) { + try { + raw = (RawText)content.getTransferData(flavor); + } + catch (UnsupportedFlavorException e) { + // OK. raw will be null and we'll get plain string + } + catch (IOException e) { + // OK. raw will be null and we'll get plain string + } + } + return raw; + } } \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java index 3eff8f0b667b..0702fc30acdb 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java @@ -15,8 +15,10 @@ */ package org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiConstantEvaluationHelper; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiType; import com.intellij.psi.tree.IElementType; @@ -51,6 +53,12 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { private List myInstructions; private Stack myProcessingStack; + private PsiConstantEvaluationHelper myConstantEvaluator; + + public ControlFlowBuilder(Project project) { + myConstantEvaluator = JavaPsiFacade.getInstance(project).getConstantEvaluationHelper(); + + } private class ExceptionInfo { GrCatchClause myClause; @@ -485,7 +493,10 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { if (condition != null) { condition.accept(this); } - addPendingEdge(whileStatement, myHead); //break + final boolean endless = Boolean.TRUE.equals(myConstantEvaluator.computeConstantExpression(condition)); + if (!endless) { + addPendingEdge(whileStatement, myHead); //break + } final GrCondition body = whileStatement.getBody(); if (body != null) { body.accept(this); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java index 2e2246893e74..1577d8611e01 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java @@ -177,7 +177,7 @@ public abstract class GroovyFileBaseImpl extends PsiFileBase implements GroovyFi public Instruction[] getControlFlow() { if (myControlFlow == null) { - myControlFlow = new ControlFlowBuilder().buildControlFlow(this, null, null); + myControlFlow = new ControlFlowBuilder(getProject()).buildControlFlow(this, null, null); } return myControlFlow; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java index 921542e897b0..e35d332bdab7 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java @@ -49,7 +49,7 @@ public abstract class GrBlockImpl extends GroovyPsiElementImpl implements GrCode public Instruction[] getControlFlow() { if (myControlFlow == null) { - myControlFlow = new ControlFlowBuilder().buildControlFlow(this, null, null); + myControlFlow = new ControlFlowBuilder(getProject()).buildControlFlow(this, null, null); } return myControlFlow; diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.java index 62e41e0863e9..6d0696852f6b 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.java @@ -33,6 +33,7 @@ public class MissingReturnTest extends LightCodeInsightFixtureTestCase { public void testMissingReturnOvertReturnType() throws Throwable {doTest();} public void testMissingReturnFromClosure() throws Throwable {doTest();} public void testReturnsWithoutValue() throws Throwable {doTest();} + public void testEndlessLoop() throws Throwable {doTest();} private void doTest() throws Exception { myFixture.enableInspections(new MissingReturnInspection()); diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.java index f4f314a4884d..0454648a1d18 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.java @@ -44,6 +44,7 @@ public class ControlFlowTest extends LightCodeInsightFixtureTestCase { public void testTry7() throws Throwable { doTest(); } public void testWhile1() throws Throwable { doTest(); } public void testWhile2() throws Throwable { doTest(); } + public void testWhileNonConstant() throws Throwable { doTest(); } public void testIfInstanceofElse() throws Throwable { doTest(); } private static String dumpControlFlow(Instruction[] instructions) { @@ -66,7 +67,7 @@ public class ControlFlowTest extends LightCodeInsightFixtureTestCase { final PsiElement start = file.findElementAt(model.hasSelection() ? model.getSelectionStart() : 0); final PsiElement end = file.findElementAt(model.hasSelection() ? model.getSelectionEnd() - 1 : file.getTextLength() - 1); final GrControlFlowOwner owner = PsiTreeUtil.getParentOfType(PsiTreeUtil.findCommonParent(start, end), GrControlFlowOwner.class, false); - final Instruction[] instructions = new ControlFlowBuilder().buildControlFlow(owner, null, null); + final Instruction[] instructions = new ControlFlowBuilder(getProject()).buildControlFlow(owner, null, null); final String cf = dumpControlFlow(instructions); assertEquals(input.get(1).trim(), cf.trim()); } diff --git a/plugins/groovy/testdata/groovy/completion/FinishMethodWithLParen_after.groovy b/plugins/groovy/testdata/groovy/completion/FinishMethodWithLParen_after.groovy index 0ace8f68f796..529a0ccf047b 100644 --- a/plugins/groovy/testdata/groovy/completion/FinishMethodWithLParen_after.groovy +++ b/plugins/groovy/testdata/groovy/completion/FinishMethodWithLParen_after.groovy @@ -3,4 +3,4 @@ class Foo { def bar } -new Foo().getBar() +new Foo().getBar() diff --git a/plugins/groovy/testdata/groovy/controlFlow/while1.test b/plugins/groovy/testdata/groovy/controlFlow/while1.test index 323c64ef13eb..f0cd07908070 100644 --- a/plugins/groovy/testdata/groovy/controlFlow/while1.test +++ b/plugins/groovy/testdata/groovy/controlFlow/while1.test @@ -6,7 +6,7 @@ while (true) { ----- 0(1) element: null 1(2) WRITE i -2(3,7) element: WHILE statement +2(3) element: WHILE statement 3(4,5) element: IF statement 4(7) READ i 5(6) READ i diff --git a/plugins/groovy/testdata/groovy/controlFlow/while2.test b/plugins/groovy/testdata/groovy/controlFlow/while2.test index 4464fd5ef1b7..e3542ab03ed1 100644 --- a/plugins/groovy/testdata/groovy/controlFlow/while2.test +++ b/plugins/groovy/testdata/groovy/controlFlow/while2.test @@ -6,7 +6,7 @@ while (true) { ----- 0(1) element: null 1(2) WRITE i -2(3,7) element: WHILE statement +2(3) element: WHILE statement 3(4,5) element: IF statement 4(2) READ i 5(6) READ i diff --git a/plugins/groovy/testdata/groovy/controlFlow/whileNonConstant.test b/plugins/groovy/testdata/groovy/controlFlow/whileNonConstant.test new file mode 100644 index 000000000000..3f126683e0eb --- /dev/null +++ b/plugins/groovy/testdata/groovy/controlFlow/whileNonConstant.test @@ -0,0 +1,15 @@ +i = 0 +while (condition()) { + if (i > 10) break + i++ +} +----- +0(1) element: null +1(2) WRITE i +2(3) element: WHILE statement +3(4,8) READ condition +4(5,6) element: IF statement +5(8) READ i +6(7) READ i +7(2) WRITE i +8() element: null \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/inter1.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/inter1.test index 2732a393f9d1..e079d4bdc59d 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/inter1.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/inter1.test @@ -12,9 +12,10 @@ def i = 6 println i ----- def i = 6 -i = testMethod(i) +i = testMethod() -private int testMethod(int i) { +private int testMethod() { + int i while (true) { println "preved" i = 42 diff --git a/plugins/groovy/testdata/highlighting/missingReturn/EndlessLoop.groovy b/plugins/groovy/testdata/highlighting/missingReturn/EndlessLoop.groovy new file mode 100644 index 000000000000..7e19ff80273f --- /dev/null +++ b/plugins/groovy/testdata/highlighting/missingReturn/EndlessLoop.groovy @@ -0,0 +1,5 @@ +def foo() { + while (true) { + return 239 + } +} \ No newline at end of file diff --git a/xml/dom-openapi/src/com/intellij/util/xml/model/impl/DomModelFactory.java b/xml/dom-openapi/src/com/intellij/util/xml/model/impl/DomModelFactory.java index bda38ed13487..5f5f4dd6690f 100644 --- a/xml/dom-openapi/src/com/intellij/util/xml/model/impl/DomModelFactory.java +++ b/xml/dom-openapi/src/com/intellij/util/xml/model/impl/DomModelFactory.java @@ -41,9 +41,8 @@ public abstract class DomModelFactory { protected final DomFileElement myMergedModel; protected final Set myConfigFiles; + private Class myClass; + private Project myProject; /** * Using this method may result in a large memory usage, since it will keep all the DOM and PSI for all the config files * @return */ @Deprecated - public DomModelImpl(@NotNull T mergedModel, @NotNull Set configFiles) { + public DomModelImpl(T mergedModel, @NotNull Set configFiles) { myMergedModel = DomUtil.getFileElement(mergedModel); myConfigFiles = configFiles; } - public DomModelImpl(@NotNull DomFileElement mergedModel, @NotNull Set configFiles) { + public DomModelImpl(DomFileElement mergedModel, @NotNull Set configFiles) { myMergedModel = DomUtil.getFileElement(mergedModel); myConfigFiles = configFiles; } + public DomModelImpl(@NotNull Set configFiles, Class clazz, Project project) { + myProject = project; + myMergedModel = null; + myConfigFiles = configFiles; + myClass = clazz; + } + @NotNull public T getMergedModel() { + if (myMergedModel == null) { + final DomManager domManager = DomManager.getDomManager(myProject); + return domManager.createModelMerger().mergeModels(myClass, ContainerUtil.mapNotNull(myConfigFiles, new NullableFunction() { + public T fun(XmlFile xmlFile) { + DomFileElement fileElement = domManager.getFileElement(xmlFile, myClass); + return fileElement == null ? null : fileElement.getRootElement(); + } + })); + } return myMergedModel.getRootElement(); } @@ -62,6 +80,13 @@ public class DomModelImpl { @NotNull public List> getRoots() { + if (myMergedModel == null) { + return ContainerUtil.mapNotNull(myConfigFiles, new NullableFunction>() { + public DomFileElement fun(XmlFile xmlFile) { + return DomManager.getDomManager(xmlFile.getProject()).getFileElement(xmlFile, myClass); + } + }); + } return myMergedModel instanceof MergedObject ? ((MergedObject) myMergedModel).getImplementations() : Collections.singletonList(myMergedModel); }