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 @@
-
-
-
-
-
-
-
-
@@ -23,42 +15,18 @@
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
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);
}