mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -19,6 +19,7 @@ package com.intellij.codeInsight.folding;
|
||||
import com.intellij.codeInsight.folding.impl.CodeFoldingManagerImpl
|
||||
import com.intellij.codeInsight.folding.impl.JavaCodeFoldingSettingsImpl
|
||||
import com.intellij.find.FindManager
|
||||
import com.intellij.openapi.actionSystem.IdeActions
|
||||
import com.intellij.openapi.application.ex.PathManagerEx
|
||||
import com.intellij.openapi.editor.FoldRegion
|
||||
import com.intellij.openapi.editor.ex.FoldingModelEx
|
||||
@@ -35,10 +36,10 @@ import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
||||
* @since 1/17/11 1:00 PM
|
||||
*/
|
||||
public class JavaFoldingTest extends LightCodeInsightFixtureTestCase {
|
||||
|
||||
|
||||
def JavaCodeFoldingSettingsImpl myFoldingSettings
|
||||
def JavaCodeFoldingSettingsImpl myFoldingStateToRestore
|
||||
|
||||
|
||||
@Override
|
||||
public void setUp() {
|
||||
super.setUp()
|
||||
@@ -65,7 +66,7 @@ import java.util.Map;
|
||||
|
||||
class Foo { List a; Map b; }
|
||||
"""
|
||||
|
||||
|
||||
assert myFixture.editor.foldingModel.getCollapsedRegionAtOffset(10)
|
||||
|
||||
myFixture.type 'import '
|
||||
@@ -118,25 +119,25 @@ class Test {
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
configure text
|
||||
def foldingModel = myFixture.editor.foldingModel as FoldingModelImpl
|
||||
def closureStartFold = foldingModel.getCollapsedRegionAtOffset(text.indexOf("Runnable"))
|
||||
assertNotNull closureStartFold
|
||||
assertFalse closureStartFold.expanded
|
||||
|
||||
|
||||
assertNotNull closureStartFold.group
|
||||
def closureFolds = foldingModel.getGroupedRegions(closureStartFold.group)
|
||||
assertNotNull closureFolds
|
||||
assertEquals(2, closureFolds.size())
|
||||
|
||||
|
||||
def closureEndFold = closureFolds.get(1)
|
||||
assertFalse closureEndFold.expanded
|
||||
|
||||
|
||||
myFixture.editor.caretModel.moveToOffset(closureEndFold.startOffset + 1)
|
||||
assertTrue closureStartFold.expanded
|
||||
assertTrue closureEndFold.expanded
|
||||
|
||||
|
||||
changeFoldRegions { closureStartFold.expanded = false }
|
||||
assertTrue closureStartFold.expanded
|
||||
assertTrue closureEndFold.expanded
|
||||
@@ -172,7 +173,7 @@ class Test {
|
||||
assertNotNull closureFolds
|
||||
assertEquals(2, closureFolds.size())
|
||||
}
|
||||
|
||||
|
||||
public void "test builder style setter"() {
|
||||
myFoldingSettings.COLLAPSE_ACCESSORS = true
|
||||
def text = """\
|
||||
@@ -379,22 +380,22 @@ class Test {
|
||||
FindManager.getInstance(project).findNextUsageInEditor(TextEditorProvider.getInstance().getTextEditor(myFixture.editor))
|
||||
assertEquals('test1', myFixture.editor.selectionModel.selectedText)
|
||||
}
|
||||
|
||||
|
||||
public void testCustomFolding() {
|
||||
myFixture.testFolding("$PathManagerEx.testDataPath/codeInsight/folding/${getTestName(false)}.java");
|
||||
}
|
||||
|
||||
|
||||
public void "test move methods"() {
|
||||
def initialText = '''\
|
||||
class Test {
|
||||
void test1() {
|
||||
}
|
||||
|
||||
|
||||
void test2() {
|
||||
}
|
||||
}
|
||||
'''
|
||||
|
||||
|
||||
Closure<FoldRegion> fold = { String methodName ->
|
||||
def text = myFixture.editor.document.text
|
||||
def nameIndex = text.indexOf(methodName)
|
||||
@@ -444,7 +445,7 @@ class Test {
|
||||
assertEquals(2, folds[0].startOffset)
|
||||
assertEquals(6, folds[0].endOffset)
|
||||
}
|
||||
|
||||
|
||||
private def configure(String text) {
|
||||
myFixture.configureByText("a.java", text)
|
||||
CodeFoldingManagerImpl.getInstance(getProject()).buildInitialFoldings(myFixture.editor);
|
||||
@@ -458,21 +459,21 @@ class Test {
|
||||
int field;
|
||||
int field2;
|
||||
int field3;
|
||||
|
||||
|
||||
int getField()
|
||||
{
|
||||
return field;
|
||||
}
|
||||
|
||||
|
||||
void setField(int f) {
|
||||
field = f;
|
||||
}
|
||||
|
||||
|
||||
void setField2(int f){field2=f;} // normal method folding here
|
||||
|
||||
// normal method folding here
|
||||
void setField3(int f){
|
||||
|
||||
|
||||
field2=f;
|
||||
}
|
||||
|
||||
@@ -480,10 +481,10 @@ class Test {
|
||||
PsiClass fooClass = JavaPsiFacade.getInstance(project).findClass('Foo', GlobalSearchScope.allScope(project))
|
||||
def regions = myFixture.editor.foldingModel.allFoldRegions.sort { it.startOffset }
|
||||
assert regions.size() == 6
|
||||
|
||||
|
||||
checkAccessorFolding(regions[0], regions[1], fooClass.methods[0])
|
||||
checkAccessorFolding(regions[2], regions[3], fooClass.methods[1])
|
||||
|
||||
|
||||
assert regions[4].placeholderText == '{...}'
|
||||
assert regions[5].placeholderText == '{...}'
|
||||
}
|
||||
@@ -504,7 +505,7 @@ class Test {
|
||||
int someMethod() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}"""
|
||||
PsiClass fooClass = JavaPsiFacade.getInstance(project).findClass('Foo', GlobalSearchScope.allScope(project))
|
||||
def regions = myFixture.editor.foldingModel.allFoldRegions.sort { it.startOffset }
|
||||
@@ -516,7 +517,7 @@ class Test {
|
||||
configure """class Foo {
|
||||
int someVeryVeryLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongVariable;
|
||||
|
||||
// don't create folding that would exceed the right margin
|
||||
// don't create folding that would exceed the right margin
|
||||
int getSomeVeryVeryLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongVariable() {
|
||||
return someVeryVeryLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongVariable;
|
||||
}
|
||||
@@ -529,4 +530,18 @@ class Test {
|
||||
private def changeFoldRegions(Closure op) {
|
||||
myFixture.editor.foldingModel.runBatchFoldingOperationDoNotCollapseCaret(op)
|
||||
}
|
||||
|
||||
public void "test unselect word should go inside folding group"() {
|
||||
configure """class Foo {
|
||||
int field;
|
||||
|
||||
<selection>int getField() {
|
||||
<caret>return field;
|
||||
}</selection>
|
||||
|
||||
}"""
|
||||
assertSize 2, myFixture.editor.foldingModel.allFoldRegions
|
||||
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_UNSELECT_WORD_AT_CARET)
|
||||
assert 'return field;' == myFixture.editor.selectionModel.selectedText
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,40 +66,43 @@ public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx
|
||||
@Override
|
||||
@NotNull
|
||||
public RangeHighlighter addLineHighlighter(int lineNumber, int layer, TextAttributes textAttributes) {
|
||||
if (lineNumber >= getDocument().getLineCount() || lineNumber < 0) {
|
||||
if (isNotValidLine(lineNumber)) {
|
||||
throw new IndexOutOfBoundsException("lineNumber:" + lineNumber + ". Must be in [0, " + (getDocument().getLineCount() - 1) + "]");
|
||||
}
|
||||
|
||||
// The rationale why we don't bind to the line start offset here is that following: suppose particular breakpoint is hit
|
||||
// during debugging. We may want to type <enter> at the active line indent and highlighted string will be moved one line
|
||||
// down as well then.
|
||||
int offset = getFirstNonspaceCharOffset(getDocument(), lineNumber);
|
||||
|
||||
int offset = getFirstNonSpaceCharOffset(getDocument(), lineNumber);
|
||||
return addRangeHighlighter(offset, offset, layer, textAttributes, HighlighterTargetArea.LINES_IN_RANGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public RangeHighlighter addPersistentLineHighlighter(int lineNumber, int layer, TextAttributes textAttributes) {
|
||||
if (lineNumber >= getDocument().getLineCount() || lineNumber < 0) return null;
|
||||
|
||||
int offset = getFirstNonspaceCharOffset(getDocument(), lineNumber);
|
||||
if (isNotValidLine(lineNumber)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int offset = getFirstNonSpaceCharOffset(getDocument(), lineNumber);
|
||||
return addRangeHighlighterAndChangeAttributes(offset, offset, layer, textAttributes, HighlighterTargetArea.LINES_IN_RANGE, true, null);
|
||||
}
|
||||
|
||||
private static int getFirstNonspaceCharOffset(@NotNull Document doc, int lineNumber) {
|
||||
int lineStart = doc.getLineStartOffset(lineNumber);
|
||||
int lineEnd = doc.getLineEndOffset(lineNumber);
|
||||
CharSequence text = doc.getCharsSequence();
|
||||
int offset = lineStart;
|
||||
private boolean isNotValidLine(int lineNumber) {
|
||||
return lineNumber >= getDocument().getLineCount() || lineNumber < 0;
|
||||
}
|
||||
|
||||
private static int getFirstNonSpaceCharOffset(@NotNull Document document, int lineNumber) {
|
||||
int lineStart = document.getLineStartOffset(lineNumber);
|
||||
int lineEnd = document.getLineEndOffset(lineNumber);
|
||||
CharSequence text = document.getImmutableCharSequence();
|
||||
for (int i = lineStart; i < lineEnd; i++) {
|
||||
char c = text.charAt(i);
|
||||
if (c != ' ' && c != '\t') {
|
||||
offset = i;
|
||||
break;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
return lineStart;
|
||||
}
|
||||
|
||||
// NB: Can return invalid highlighters
|
||||
|
||||
+1
-1
@@ -75,6 +75,6 @@ public class ProcessBackedConsoleExecuteActionHandler extends BaseConsoleExecute
|
||||
|
||||
@Override
|
||||
public boolean value(LanguageConsoleImpl console) {
|
||||
return isProcessTerminated();
|
||||
return !isProcessTerminated();
|
||||
}
|
||||
}
|
||||
@@ -131,7 +131,7 @@ public class PluginsTableRenderer extends DefaultTableCellRenderer {
|
||||
if (!isSelected) {
|
||||
myName.setForeground(JBColor.RED);
|
||||
}
|
||||
myName.setIcon(AllIcons.Nodes.Pluginobsolete);
|
||||
myStatus.setIcon(AllIcons.Nodes.Pluginobsolete);
|
||||
}
|
||||
//todo[kb] set proper icon
|
||||
//myStatus.setText("v." + pluginNode.getInstalledVersion() + (hasNewerVersion ? (" -> " + pluginNode.getVersion()) : ""));
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.intellij.openapi.diff.impl;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.actions.EditSourceAction;
|
||||
import com.intellij.idea.ActionsBundle;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.application.Application;
|
||||
@@ -126,6 +127,9 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
|
||||
private AnAction getEditSourceAction() {
|
||||
AnAction editSourceAction = new EditSourceAction();
|
||||
editSourceAction.getTemplatePresentation().setIcon(AllIcons.Actions.EditSource);
|
||||
editSourceAction.getTemplatePresentation().setText(ActionsBundle.actionText("EditSource"));
|
||||
editSourceAction.getTemplatePresentation().setDescription(ActionsBundle.actionText("EditSource"));
|
||||
editSourceAction.registerCustomShortcutSet(CommonShortcuts.getEditSource(), myPanel, DiffPanelImpl.this);
|
||||
return editSourceAction;
|
||||
}
|
||||
};
|
||||
@@ -202,9 +206,6 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
|
||||
}
|
||||
|
||||
private void registerActions() {
|
||||
// EditSourceAction is not enabled in modal context, so we need to register it here explicitly
|
||||
new EditSourceAction().registerCustomShortcutSet(CommonShortcuts.getEditSource(), myPanel, this);
|
||||
|
||||
//control+tab switches editors
|
||||
new AnAction(){
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -230,7 +230,8 @@ public class MacMainFrameDecorator extends IdeFrameDecorator implements UISettin
|
||||
@Override
|
||||
public void windowEnteredFullScreen(AppEvent.FullScreenEvent event) {
|
||||
// We can get the notification when the frame has been disposed
|
||||
if (myFrame == null/*|| ORACLE_BUG_ID_8003173*/) return;
|
||||
JRootPane rootPane = frame.getRootPane();
|
||||
if (rootPane != null) rootPane.putClientProperty(FULL_SCREEN, Boolean.TRUE);
|
||||
enterFullscreen();
|
||||
myFrame.validate();
|
||||
}
|
||||
|
||||
@@ -15,8 +15,10 @@
|
||||
*/
|
||||
package com.intellij.ui.messages;
|
||||
|
||||
import com.apple.eawt.FullScreenUtilities;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.mac.MacMainFrameDecorator;
|
||||
import com.intellij.util.ui.Animator;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
|
||||
@@ -37,6 +39,7 @@ public class SheetMessage {
|
||||
|
||||
private Image staticImage;
|
||||
private int imageHeight;
|
||||
private boolean restoreFullscreenButton;
|
||||
|
||||
public SheetMessage(final Window owner,
|
||||
final String title,
|
||||
@@ -68,10 +71,22 @@ public class SheetMessage {
|
||||
|
||||
startAnimation(true);
|
||||
myWindow.setSize(myController.SHEET_WIDTH, myController.SHEET_HEIGHT);
|
||||
restoreFullscreenButton = couldBeInFullScreen();
|
||||
if (restoreFullscreenButton) {
|
||||
FullScreenUtilities.setWindowCanFullScreen(myParent, false);
|
||||
}
|
||||
myWindow.setVisible(true);
|
||||
setPositionRelativeToParent();
|
||||
}
|
||||
|
||||
private boolean couldBeInFullScreen() {
|
||||
if (myParent instanceof JFrame) {
|
||||
JRootPane rootPane = ((JFrame)myParent).getRootPane();
|
||||
return rootPane.getClientProperty(MacMainFrameDecorator.FULL_SCREEN) == null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean toBeShown() {
|
||||
return !myController.getDoNotAskResult();
|
||||
}
|
||||
@@ -123,6 +138,9 @@ public class SheetMessage {
|
||||
myWindow.setContentPane(myController.getPanel(myWindow));
|
||||
myController.requestFocus();
|
||||
} else {
|
||||
if (restoreFullscreenButton) {
|
||||
FullScreenUtilities.setWindowCanFullScreen(myParent, true);
|
||||
}
|
||||
myWindow.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
+23
-1
@@ -31,7 +31,10 @@ import com.intellij.util.xmlb.XmlSerializer;
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
import com.intellij.xdebugger.XDebuggerBundle;
|
||||
import com.intellij.xdebugger.XSourcePosition;
|
||||
import com.intellij.xdebugger.breakpoints.*;
|
||||
import com.intellij.xdebugger.breakpoints.SuspendPolicy;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpoint;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpointProperties;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpointType;
|
||||
import com.intellij.xdebugger.impl.DebuggerSupport;
|
||||
import com.intellij.xdebugger.impl.XDebugSessionImpl;
|
||||
import com.intellij.xdebugger.impl.XDebuggerSupport;
|
||||
@@ -88,10 +91,12 @@ public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointP
|
||||
myBreakpointManager.fireBreakpointChanged(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XSourcePosition getSourcePosition() {
|
||||
return getType().getSourcePosition(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Navigatable getNavigatable() {
|
||||
XSourcePosition position = getSourcePosition();
|
||||
if (position == null) {
|
||||
@@ -100,10 +105,12 @@ public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointP
|
||||
return position.createNavigatable(getProject());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return myState.isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(final boolean enabled) {
|
||||
if (enabled != isEnabled()) {
|
||||
myState.setEnabled(enabled);
|
||||
@@ -111,11 +118,13 @@ public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointP
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public SuspendPolicy getSuspendPolicy() {
|
||||
return myState.getSuspendPolicy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSuspendPolicy(@NotNull SuspendPolicy policy) {
|
||||
if (myState.getSuspendPolicy() != policy) {
|
||||
myState.setSuspendPolicy(policy);
|
||||
@@ -123,10 +132,12 @@ public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointP
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLogMessage() {
|
||||
return myState.isLogMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLogMessage(final boolean logMessage) {
|
||||
if (logMessage != isLogMessage()) {
|
||||
myState.setLogMessage(logMessage);
|
||||
@@ -134,10 +145,12 @@ public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointP
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLogExpression() {
|
||||
return myState.getLogExpression();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLogExpression(@Nullable final String expression) {
|
||||
if (!Comparing.equal(getLogExpression(), expression)) {
|
||||
myState.setLogExpression(expression);
|
||||
@@ -145,10 +158,12 @@ public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointP
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCondition() {
|
||||
return myState.getCondition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCondition(@Nullable final String condition) {
|
||||
if (!Comparing.equal(condition, getCondition())) {
|
||||
myState.setCondition(condition);
|
||||
@@ -165,11 +180,13 @@ public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointP
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public P getProperties() {
|
||||
return myProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public XBreakpointType<Self,P> getType() {
|
||||
return myType;
|
||||
@@ -350,16 +367,19 @@ public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointP
|
||||
}
|
||||
|
||||
protected class BreakpointGutterIconRenderer extends GutterIconRenderer {
|
||||
@Override
|
||||
@NotNull
|
||||
public Icon getIcon() {
|
||||
return XBreakpointBase.this.getIcon();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public AnAction getClickAction() {
|
||||
return new RemoveBreakpointGutterIconAction(XBreakpointBase.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public AnAction getMiddleButtonClickAction() {
|
||||
return new ToggleBreakpointGutterIconAction(XBreakpointBase.this);
|
||||
@@ -376,11 +396,13 @@ public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointP
|
||||
return Alignment.RIGHT;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ActionGroup getPopupMenuActions() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getTooltipText() {
|
||||
return getDescription();
|
||||
|
||||
+1
@@ -459,6 +459,7 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta
|
||||
myBreakpoints = breakpoints;
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public void setDefaultBreakpoints(List<BreakpointState> defaultBreakpoints) {
|
||||
myDefaultBreakpoints = defaultBreakpoints;
|
||||
}
|
||||
|
||||
+2
-3
@@ -149,7 +149,7 @@ public class XLineBreakpointImpl<P extends XBreakpointProperties> extends XBreak
|
||||
if (mySourcePosition == null) {
|
||||
new ReadAction() {
|
||||
@Override
|
||||
protected void run(final Result result) {
|
||||
protected void run(@NotNull Result result) {
|
||||
mySourcePosition = XDebuggerUtil.getInstance().createPosition(getFile(), getLine());
|
||||
}
|
||||
}.execute();
|
||||
@@ -201,8 +201,7 @@ public class XLineBreakpointImpl<P extends XBreakpointProperties> extends XBreak
|
||||
|
||||
public void updatePosition() {
|
||||
if (myHighlighter != null && myHighlighter.isValid()) {
|
||||
Document document = myHighlighter.getDocument();
|
||||
setLine(document.getLineNumber(myHighlighter.getStartOffset()));
|
||||
setLine(myHighlighter.getDocument().getLineNumber(myHighlighter.getStartOffset()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+16
-12
@@ -18,8 +18,6 @@ package com.intellij.xdebugger.impl.breakpoints;
|
||||
import com.intellij.ide.startup.StartupManagerEx;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.EditorFactory;
|
||||
@@ -43,6 +41,7 @@ import com.intellij.openapi.vfs.VirtualFileEvent;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.openapi.vfs.VirtualFileUrlChangeAdapter;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.BidirectionalMap;
|
||||
import com.intellij.util.ui.update.MergingUpdateQueue;
|
||||
import com.intellij.util.ui.update.Update;
|
||||
@@ -53,7 +52,6 @@ import gnu.trove.TIntHashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@@ -101,7 +99,7 @@ public class XLineBreakpointManager {
|
||||
|
||||
@Override
|
||||
public void fileDeleted(@NotNull VirtualFileEvent event) {
|
||||
List<XBreakpoint<?>> toRemove = new ArrayList<XBreakpoint<?>>();
|
||||
List<XBreakpoint<?>> toRemove = new SmartList<XBreakpoint<?>>();
|
||||
for (XLineBreakpointImpl breakpoint : myBreakpoints.keySet()) {
|
||||
if (breakpoint.getFileUrl().equals(event.getFile().getUrl())) {
|
||||
toRemove.add(breakpoint);
|
||||
@@ -164,12 +162,14 @@ public class XLineBreakpointManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateBreakpoints(final Document document) {
|
||||
private void updateBreakpoints(@NotNull Document document) {
|
||||
Collection<XLineBreakpointImpl> breakpoints = myBreakpoints.getKeysByValue(document);
|
||||
if (breakpoints == null) return;
|
||||
if (breakpoints == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
TIntHashSet lines = new TIntHashSet();
|
||||
final List<XBreakpoint<?>> toRemove = new ArrayList<XBreakpoint<?>>();
|
||||
List<XBreakpoint<?>> toRemove = new SmartList<XBreakpoint<?>>();
|
||||
for (XLineBreakpointImpl breakpoint : breakpoints) {
|
||||
breakpoint.updatePosition();
|
||||
if (!breakpoint.isValid() || !lines.add(breakpoint.getLine())) {
|
||||
@@ -181,20 +181,25 @@ public class XLineBreakpointManager {
|
||||
}
|
||||
|
||||
private void removeBreakpoints(final List<? extends XBreakpoint<?>> toRemove) {
|
||||
new WriteAction() {
|
||||
if (toRemove.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
protected void run(@NotNull final Result result) {
|
||||
public void run() {
|
||||
for (XBreakpoint<?> breakpoint : toRemove) {
|
||||
XDebuggerManager.getInstance(myProject).getBreakpointManager().removeBreakpoint(breakpoint);
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
});
|
||||
}
|
||||
|
||||
public void breakpointChanged(final XLineBreakpointImpl breakpoint) {
|
||||
if (ApplicationManager.getApplication().isDispatchThread()) {
|
||||
breakpoint.updateUI();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
queueBreakpointUpdate(breakpoint);
|
||||
}
|
||||
}
|
||||
@@ -266,7 +271,6 @@ public class XLineBreakpointManager {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!myProject.isDisposed() && myProject.isInitialized() && file.isValid()) {
|
||||
|
||||
XDebuggerUtil.getInstance().toggleLineBreakpoint(myProject, file, line, mouseEvent.isAltDown());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -836,7 +836,7 @@ public class GroovyAssignabilityCheckInspection extends BaseInspection {
|
||||
return LocalQuickFix.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
final List<GrClosureSignature> signatures = GrClosureSignatureUtil.generateSimpleSignature(signature);
|
||||
final List<GrClosureSignature> signatures = GrClosureSignatureUtil.generateSimpleSignatures(signature);
|
||||
|
||||
List<Pair<Integer, PsiType>> allErrors = new ArrayList<Pair<Integer, PsiType>>();
|
||||
for (GrClosureSignature closureSignature : signatures) {
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,9 +15,9 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.lang.psi.api.signatures;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
@@ -37,7 +37,7 @@ public interface GrMultiSignature extends GrSignature {
|
||||
}
|
||||
|
||||
@Override
|
||||
public GrSignature curry(@NotNull PsiType[] args, int position, @NotNull GroovyPsiElement context) {
|
||||
public GrSignature curry(@NotNull PsiType[] args, int position, @NotNull PsiElement context) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,10 +15,10 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.lang.psi.api.signatures;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
@@ -27,7 +27,7 @@ public interface GrSignature {
|
||||
boolean isValid();
|
||||
|
||||
@Nullable
|
||||
GrSignature curry(@NotNull PsiType[] args, int position, @NotNull GroovyPsiElement context);
|
||||
GrSignature curry(@NotNull PsiType[] args, int position, @NotNull PsiElement context);
|
||||
|
||||
void accept(GrSignatureVisitor visitor);
|
||||
}
|
||||
|
||||
+2
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -43,18 +43,7 @@ public class GrClassReferenceType extends PsiClassType {
|
||||
@Override
|
||||
@Nullable
|
||||
public PsiClass resolve() {
|
||||
ResolveResult[] results = multiResolve();
|
||||
if (results.length == 1) {
|
||||
PsiElement only = results[0].getElement();
|
||||
return only instanceof PsiClass ? (PsiClass) only : null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
//reference resolve is cached
|
||||
private GroovyResolveResult[] multiResolve() {
|
||||
return myReferenceElement.multiResolve(false);
|
||||
return resolveGenerics().getElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -42,7 +42,7 @@ public class GrClosureType extends GrLiteralClassType {
|
||||
private final GrSignature mySignature;
|
||||
private volatile PsiType[] myTypeArgs = null;
|
||||
|
||||
private GrClosureType(@NotNull LanguageLevel languageLevel,
|
||||
private GrClosureType(LanguageLevel languageLevel,
|
||||
@NotNull GlobalSearchScope scope,
|
||||
@NotNull JavaPsiFacade facade,
|
||||
@NotNull GrSignature closureSignature,
|
||||
@@ -52,7 +52,7 @@ public class GrClosureType extends GrLiteralClassType {
|
||||
if (!shouldInferTypeParameters) myTypeArgs = PsiType.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
private GrClosureType(@NotNull LanguageLevel level,
|
||||
private GrClosureType(LanguageLevel level,
|
||||
@NotNull GlobalSearchScope scope,
|
||||
@NotNull JavaPsiFacade facade,
|
||||
@NotNull GrSignature signature,
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -33,7 +33,7 @@ public abstract class GrLiteralClassType extends PsiClassType {
|
||||
protected final JavaPsiFacade myFacade;
|
||||
private final GroovyPsiManager myGroovyPsiManager;
|
||||
|
||||
public GrLiteralClassType(@NotNull LanguageLevel languageLevel, @NotNull GlobalSearchScope scope, @NotNull JavaPsiFacade facade) {
|
||||
public GrLiteralClassType(LanguageLevel languageLevel, @NotNull GlobalSearchScope scope, @NotNull JavaPsiFacade facade) {
|
||||
super(languageLevel);
|
||||
myScope = scope;
|
||||
myFacade = facade;
|
||||
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.lang.psi.impl.signatures;
|
||||
|
||||
import com.intellij.psi.PsiArrayType;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiSubstitutor;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
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.signatures.GrSignatureVisitor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureParameter;
|
||||
|
||||
/**
|
||||
* Created by Max Medvedev on 26/02/14
|
||||
*/
|
||||
class GrClosableSignatureImpl implements GrClosureSignature {
|
||||
private final GrClosableBlock myBlock;
|
||||
|
||||
public GrClosableSignatureImpl(GrClosableBlock block) {
|
||||
myBlock = block;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiSubstitutor getSubstitutor() {
|
||||
return PsiSubstitutor.EMPTY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public GrClosureParameter[] getParameters() {
|
||||
GrParameter[] parameters = myBlock.getAllParameters();
|
||||
|
||||
return ContainerUtil.map(parameters, new Function<GrParameter, GrClosureParameter>() {
|
||||
@Override
|
||||
public GrClosureParameter fun(final GrParameter parameter) {
|
||||
return new GrClosureParameterImpl(parameter);
|
||||
}
|
||||
}, new GrClosureParameter[parameters.length]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getParameterCount() {
|
||||
return myBlock.getAllParameters().length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVarargs() {
|
||||
GrParameter last = ArrayUtil.getLastElement(myBlock.getAllParameters());
|
||||
return last != null && last.getType() instanceof PsiArrayType;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiType getReturnType() {
|
||||
return myBlock.getReturnType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCurried() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return myBlock.isValid();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public GrSignature curry(@NotNull PsiType[] args, int position, @NotNull PsiElement context) {
|
||||
return GrClosureSignatureUtil.curryImpl(this, args, position, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(GrSignatureVisitor visitor) {
|
||||
visitor.visitClosureSignature(this);
|
||||
}
|
||||
|
||||
private static class GrClosureParameterImpl implements GrClosureParameter {
|
||||
private final GrParameter myParameter;
|
||||
|
||||
public GrClosureParameterImpl(GrParameter parameter) {
|
||||
myParameter = parameter;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiType getType() {
|
||||
return myParameter.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptional() {
|
||||
return myParameter.isOptional();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public GrExpression getDefaultInitializer() {
|
||||
return myParameter.getInitializerGroovy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return myParameter.isValid();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return myParameter.getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
+70
-39
@@ -50,7 +50,6 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GrMapType;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureParameterImpl;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
|
||||
import java.util.*;
|
||||
@@ -98,30 +97,20 @@ public class GrClosureSignatureUtil {
|
||||
ContainerUtil.map(types, new Function<PsiType, GrClosureParameter>() {
|
||||
@Override
|
||||
public GrClosureParameter fun(PsiType type) {
|
||||
return new GrClosureParameterImpl(type, null, false, null);
|
||||
return new GrImmediateClosureParameterImpl(type, null, false, null);
|
||||
}
|
||||
}, parameters);
|
||||
return new GrClosureSignatureImpl(parameters, null, false, false);
|
||||
return new GrImmediateClosureSignatureImpl(parameters, null, false, false);
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
public static GrClosureSignature createSignature(final GrClosableBlock block) {
|
||||
return new GrClosureSignatureImpl(block.getAllParameters(), null) {
|
||||
@Override
|
||||
public PsiType getReturnType() {
|
||||
return block.getReturnType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return block.isValid();
|
||||
}
|
||||
};
|
||||
return new GrClosableSignatureImpl(block);
|
||||
}
|
||||
|
||||
public static GrClosureSignature createSignature(final PsiMethod method, PsiSubstitutor substitutor) {
|
||||
return new GrClosureSignatureImpl(method.getParameterList().getParameters(), null, substitutor) {
|
||||
return new GrImmediateClosureSignatureImpl(method.getParameterList().getParameters(), null, substitutor) {
|
||||
@Override
|
||||
public PsiType getReturnType() {
|
||||
return getSubstitutor().substitute(PsiUtil.getSmartReturnType(method));
|
||||
@@ -136,7 +125,7 @@ public class GrClosureSignatureUtil {
|
||||
|
||||
public static GrClosureSignature removeParam(final GrClosureSignature signature, int i) {
|
||||
final GrClosureParameter[] newParams = ArrayUtil.remove(signature.getParameters(), i);
|
||||
return new GrClosureSignatureImpl(newParams, null, newParams.length > 0 && signature.isVarargs(), false) {
|
||||
return new GrImmediateClosureSignatureImpl(newParams, null, newParams.length > 0 && signature.isVarargs(), false) {
|
||||
@Override
|
||||
public PsiType getReturnType() {
|
||||
return signature.getReturnType();
|
||||
@@ -151,15 +140,14 @@ public class GrClosureSignatureUtil {
|
||||
|
||||
public static GrClosureSignature createSignatureWithErasedParameterTypes(final PsiMethod method) {
|
||||
final PsiParameter[] params = method.getParameterList().getParameters();
|
||||
final GrClosureParameter[] closureParams = new GrClosureParameter[params.length];
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
PsiParameter param = params[i];
|
||||
PsiType type = TypeConversionUtil.erasure(param.getType());
|
||||
closureParams[i] =
|
||||
new GrClosureParameterImpl(type, GrClosureParameterImpl.getParameterName(param), GrClosureParameterImpl.isParameterOptional(param),
|
||||
GrClosureParameterImpl.getDefaultInitializer(param));
|
||||
}
|
||||
return new GrClosureSignatureImpl(closureParams, null, GrClosureParameterImpl.isVararg(closureParams), false) {
|
||||
final GrClosureParameter[] closureParams = ContainerUtil.map(params, new Function<PsiParameter, GrClosureParameter>() {
|
||||
@Override
|
||||
public GrClosureParameter fun(PsiParameter parameter) {
|
||||
return GrImmediateClosureParameterImpl.createErasedParameter(parameter);
|
||||
}
|
||||
}, new GrClosureParameter[params.length]);
|
||||
|
||||
return new GrImmediateClosureSignatureImpl(closureParams, null, GrImmediateClosureParameterImpl.isVararg(closureParams), false) {
|
||||
@Override
|
||||
public PsiType getReturnType() {
|
||||
return PsiUtil.getSmartReturnType(method);
|
||||
@@ -181,13 +169,16 @@ public class GrClosureSignatureUtil {
|
||||
@NotNull
|
||||
public static GrClosureSignature rawSignature(@NotNull final GrClosureSignature signature) {
|
||||
final GrClosureParameter[] params = signature.getParameters();
|
||||
final GrClosureParameter[] closureParams = new GrClosureParameter[params.length];
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
GrClosureParameter param = params[i];
|
||||
PsiType type = TypeConversionUtil.erasure(param.getType());
|
||||
closureParams[i] = new GrClosureParameterImpl(type, param.getName(), param.isOptional(), param.getDefaultInitializer());
|
||||
}
|
||||
return new GrClosureSignatureImpl(closureParams, null, GrClosureParameterImpl.isVararg(closureParams), false) {
|
||||
|
||||
final GrClosureParameter[] closureParams = ContainerUtil.map(params, new Function<GrClosureParameter, GrClosureParameter>() {
|
||||
@Override
|
||||
public GrClosureParameter fun(GrClosureParameter parameter) {
|
||||
PsiType type = TypeConversionUtil.erasure(parameter.getType());
|
||||
return new GrImmediateClosureParameterImpl(type, parameter.getName(), parameter.isOptional(), parameter.getDefaultInitializer());
|
||||
}
|
||||
}, new GrClosureParameter[params.length]);
|
||||
|
||||
return new GrImmediateClosureSignatureImpl(closureParams, null, GrImmediateClosureParameterImpl.isVararg(closureParams), false) {
|
||||
@Override
|
||||
public PsiType getReturnType() {
|
||||
return signature.getReturnType();
|
||||
@@ -202,7 +193,7 @@ public class GrClosureSignatureUtil {
|
||||
|
||||
|
||||
public static GrClosureSignature createSignature(PsiParameter[] parameters, @Nullable PsiType returnType) {
|
||||
return new GrClosureSignatureImpl(parameters, returnType);
|
||||
return new GrImmediateClosureSignatureImpl(parameters, returnType);
|
||||
}
|
||||
|
||||
|
||||
@@ -349,6 +340,46 @@ public class GrClosureSignatureUtil {
|
||||
return ApplicabilityResult.applicable;
|
||||
}
|
||||
|
||||
static GrSignature curryImpl(GrClosureSignature original, PsiType[] args, int position, PsiElement context) {
|
||||
GrClosureParameter[] params = original.getParameters();
|
||||
|
||||
List<GrClosureParameter> newParams = new ArrayList<GrClosureParameter>(params.length);
|
||||
List<GrClosureParameter> opts = new ArrayList<GrClosureParameter>(params.length);
|
||||
List<Integer> optInds = new ArrayList<Integer>(params.length);
|
||||
|
||||
if (position == -1) {
|
||||
position = params.length - args.length;
|
||||
}
|
||||
|
||||
if (position < 0 || position >= params.length) return GrMultiSignature.EMPTY_SIGNATURE;
|
||||
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
if (params[i].isOptional()) {
|
||||
opts.add(params[i]);
|
||||
optInds.add(i);
|
||||
}
|
||||
else {
|
||||
newParams.add(params[i]);
|
||||
}
|
||||
}
|
||||
|
||||
final PsiType rtype = original.getReturnType();
|
||||
final ArrayList<GrClosureSignature> result = new ArrayList<GrClosureSignature>();
|
||||
checkAndAddSignature(result, args, position, newParams, rtype, context);
|
||||
|
||||
for (int i = 0; i < opts.size(); i++) {
|
||||
newParams.add(optInds.get(i), opts.get(i));
|
||||
checkAndAddSignature(result, args, position, newParams, rtype, context);
|
||||
}
|
||||
|
||||
if (result.size() == 1) {
|
||||
return result.get(0);
|
||||
}
|
||||
else {
|
||||
return new GrMultiSignatureImpl(result.toArray(new GrClosureSignature[result.size()]));
|
||||
}
|
||||
}
|
||||
|
||||
public enum ApplicabilityResult {
|
||||
applicable, inapplicable, canBeApplicable, ambiguous;
|
||||
|
||||
@@ -470,7 +501,7 @@ public class GrClosureSignatureUtil {
|
||||
int position,
|
||||
List<GrClosureParameter> params,
|
||||
PsiType returnType,
|
||||
@NotNull GroovyPsiElement context) {
|
||||
@NotNull PsiElement context) {
|
||||
final int last = position + args.length;
|
||||
if (last > params.size()) return;
|
||||
|
||||
@@ -488,7 +519,7 @@ public class GrClosureSignatureUtil {
|
||||
_p[j++] = params.get(i);
|
||||
}
|
||||
|
||||
list.add(new GrClosureSignatureImpl(_p, returnType, _p.length > 0 && _p[_p.length - 1].getType() instanceof PsiArrayType, true));
|
||||
list.add(new GrImmediateClosureSignatureImpl(_p, returnType, _p.length > 0 && _p[_p.length - 1].getType() instanceof PsiArrayType, true));
|
||||
}
|
||||
|
||||
|
||||
@@ -999,7 +1030,7 @@ public class GrClosureSignatureUtil {
|
||||
return new MapResultWithError<Arg>(map, errors);
|
||||
}
|
||||
|
||||
public static List<GrClosureSignature> generateSimpleSignature(@NotNull GrSignature signature) {
|
||||
public static List<GrClosureSignature> generateSimpleSignatures(@NotNull GrSignature signature) {
|
||||
final List<GrClosureSignature> result = new ArrayList<GrClosureSignature>();
|
||||
signature.accept(new GrRecursiveSignatureVisitor() {
|
||||
@Override
|
||||
@@ -1008,17 +1039,17 @@ public class GrClosureSignatureUtil {
|
||||
final ArrayList<GrClosureParameter> parameters = new ArrayList<GrClosureParameter>(original.length);
|
||||
|
||||
for (GrClosureParameter parameter : original) {
|
||||
parameters.add(new GrClosureParameterImpl(parameter.getType(), parameter.getName(), false, null));
|
||||
parameters.add(new GrImmediateClosureParameterImpl(parameter.getType(), parameter.getName(), false, null));
|
||||
}
|
||||
|
||||
final int pcount = signature.isVarargs() ? signature.getParameterCount() - 2 : signature.getParameterCount() - 1;
|
||||
for (int i = pcount; i >= 0; i--) {
|
||||
if (original[i].isOptional()) {
|
||||
result.add(new GrClosureSignatureImpl(parameters.toArray(new GrClosureParameter[parameters.size()]), signature.getReturnType(), signature.isVarargs(), false));
|
||||
result.add(new GrImmediateClosureSignatureImpl(parameters.toArray(new GrClosureParameter[parameters.size()]), signature.getReturnType(), signature.isVarargs(), false));
|
||||
parameters.remove(i);
|
||||
}
|
||||
}
|
||||
result.add(new GrClosureSignatureImpl(parameters.toArray(new GrClosureParameter[parameters.size()]), signature.getReturnType(), signature.isVarargs(), false));
|
||||
result.add(new GrImmediateClosureSignatureImpl(parameters.toArray(new GrClosureParameter[parameters.size()]), signature.getReturnType(), signature.isVarargs(), false));
|
||||
}
|
||||
});
|
||||
return result;
|
||||
|
||||
+13
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,10 +13,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.lang.psi.impl.types;
|
||||
package org.jetbrains.plugins.groovy.lang.psi.impl.signatures;
|
||||
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
@@ -26,23 +27,30 @@ import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureParameter;
|
||||
/**
|
||||
* @author Maxim.Medvedev
|
||||
*/
|
||||
public class GrClosureParameterImpl implements GrClosureParameter {
|
||||
public class GrImmediateClosureParameterImpl implements GrClosureParameter {
|
||||
@Nullable final PsiType myType;
|
||||
@Nullable private final String myName;
|
||||
final boolean myOptional;
|
||||
@Nullable final GrExpression myDefaultInitializer;
|
||||
|
||||
public GrClosureParameterImpl(@Nullable PsiType type, @Nullable String name, boolean optional, GrExpression defaultInitializer) {
|
||||
public GrImmediateClosureParameterImpl(@Nullable PsiType type, @Nullable String name, boolean optional, GrExpression defaultInitializer) {
|
||||
myType = type;
|
||||
myName = name;
|
||||
myOptional = optional;
|
||||
myDefaultInitializer = optional ? defaultInitializer : null;
|
||||
}
|
||||
|
||||
public GrClosureParameterImpl(@NotNull PsiParameter parameter, @NotNull PsiSubstitutor substitutor) {
|
||||
public GrImmediateClosureParameterImpl(@NotNull PsiParameter parameter, @NotNull PsiSubstitutor substitutor) {
|
||||
this(substitutor.substitute(getParameterType(parameter)), getParameterName(parameter), isParameterOptional(parameter), getDefaultInitializer(parameter));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static GrImmediateClosureParameterImpl createErasedParameter(@NotNull PsiParameter param) {
|
||||
PsiType type = TypeConversionUtil.erasure(param.getType());
|
||||
return new GrImmediateClosureParameterImpl(type, getParameterName(param), isParameterOptional(param), getDefaultInitializer(param));
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private static PsiType getParameterType(@NotNull PsiParameter parameter) {
|
||||
return parameter instanceof GrParameter ? ((GrParameter)parameter).getDeclaredType() : parameter.getType();
|
||||
@@ -71,7 +79,6 @@ public class GrClosureParameterImpl implements GrClosureParameter {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
public PsiType getType() {
|
||||
return myType;
|
||||
+12
-52
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,34 +20,30 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrMultiSignature;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignature;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignatureVisitor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureParameter;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureParameterImpl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Maxim.Medvedev
|
||||
*/
|
||||
public class GrClosureSignatureImpl implements GrClosureSignature {
|
||||
public class GrImmediateClosureSignatureImpl implements GrClosureSignature {
|
||||
private final boolean myIsVarargs;
|
||||
private final boolean myCurried;
|
||||
@Nullable private final PsiType myReturnType;
|
||||
@NotNull private final GrClosureParameter[] myParameters;
|
||||
@NotNull private final PsiSubstitutor mySubstitutor;
|
||||
|
||||
public GrClosureSignatureImpl(@NotNull PsiParameter[] parameters, @Nullable PsiType returnType, @NotNull PsiSubstitutor substitutor) {
|
||||
public GrImmediateClosureSignatureImpl(@NotNull PsiParameter[] parameters,
|
||||
@Nullable PsiType returnType,
|
||||
@NotNull PsiSubstitutor substitutor) {
|
||||
myReturnType = substitutor.substitute(returnType);
|
||||
final int length = parameters.length;
|
||||
myParameters = new GrClosureParameter[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
myParameters[i] = new GrClosureParameterImpl(parameters[i], substitutor);
|
||||
myParameters[i] = new GrImmediateClosureParameterImpl(parameters[i], substitutor);
|
||||
}
|
||||
if (length > 0) {
|
||||
myIsVarargs = myParameters[length - 1].getType() instanceof PsiArrayType;
|
||||
@@ -59,11 +55,11 @@ public class GrClosureSignatureImpl implements GrClosureSignature {
|
||||
myCurried = false;
|
||||
}
|
||||
|
||||
public GrClosureSignatureImpl(PsiParameter[] parameters, @Nullable PsiType returnType) {
|
||||
public GrImmediateClosureSignatureImpl(PsiParameter[] parameters, @Nullable PsiType returnType) {
|
||||
this(parameters, returnType, PsiSubstitutor.EMPTY);
|
||||
}
|
||||
|
||||
GrClosureSignatureImpl(@NotNull GrClosureParameter[] params, @Nullable PsiType returnType, boolean isVarArgs, boolean isCurried) {
|
||||
GrImmediateClosureSignatureImpl(@NotNull GrClosureParameter[] params, @Nullable PsiType returnType, boolean isVarArgs, boolean isCurried) {
|
||||
myParameters = params;
|
||||
myReturnType = returnType;
|
||||
myIsVarargs = isVarArgs;
|
||||
@@ -99,44 +95,8 @@ public class GrClosureSignatureImpl implements GrClosureSignature {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GrSignature curry(@NotNull PsiType[] args, int position, @NotNull GroovyPsiElement context) {
|
||||
GrClosureParameter[] params = myParameters;
|
||||
|
||||
List<GrClosureParameter> newParams = new ArrayList<GrClosureParameter>(params.length);
|
||||
List<GrClosureParameter> opts = new ArrayList<GrClosureParameter>(params.length);
|
||||
List<Integer> optInds = new ArrayList<Integer>(params.length);
|
||||
|
||||
if (position == -1) {
|
||||
position = params.length - args.length;
|
||||
}
|
||||
|
||||
if (position < 0 || position >= params.length) return GrMultiSignature.EMPTY_SIGNATURE;
|
||||
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
if (params[i].isOptional()) {
|
||||
opts.add(params[i]);
|
||||
optInds.add(i);
|
||||
}
|
||||
else {
|
||||
newParams.add(params[i]);
|
||||
}
|
||||
}
|
||||
|
||||
final PsiType rtype = getReturnType();
|
||||
final ArrayList<GrClosureSignature> result = new ArrayList<GrClosureSignature>();
|
||||
GrClosureSignatureUtil.checkAndAddSignature(result, args, position, newParams, rtype, context);
|
||||
|
||||
for (int i = 0; i < opts.size(); i++) {
|
||||
newParams.add(optInds.get(i), opts.get(i));
|
||||
GrClosureSignatureUtil.checkAndAddSignature(result, args, position, newParams, rtype, context);
|
||||
}
|
||||
|
||||
if (result.size() == 1) {
|
||||
return result.get(0);
|
||||
}
|
||||
else {
|
||||
return new GrMultiSignatureImpl(result.toArray(new GrClosureSignature[result.size()]));
|
||||
}
|
||||
public GrSignature curry(@NotNull PsiType[] args, int position, @NotNull PsiElement context) {
|
||||
return GrClosureSignatureUtil.curryImpl(this, args, position, context);
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
@@ -173,7 +133,7 @@ public class GrClosureSignatureImpl implements GrClosureSignature {
|
||||
final PsiType type = GenericsUtil.getGreatestLowerBound(parameters1[i].getType(), parameters2[i].getType());
|
||||
boolean opt = parameters1[i].isOptional() && parameters2[i].isOptional();
|
||||
String name = StringUtil.equals(parameters1[i].getName(), parameters2[i].getName()) ? parameters1[i].getName() : null;
|
||||
params[i] = new GrClosureParameterImpl(type, name, opt, null);
|
||||
params[i] = new GrImmediateClosureParameterImpl(type, name, opt, null);
|
||||
}
|
||||
final PsiType s1type = signature1.getReturnType();
|
||||
final PsiType s2type = signature2.getReturnType();
|
||||
@@ -182,7 +142,7 @@ public class GrClosureSignatureImpl implements GrClosureSignature {
|
||||
returnType = TypesUtil.getLeastUpperBound(s1type, s2type, manager);
|
||||
}
|
||||
boolean isVarArgs = signature1.isVarargs() && signature2.isVarargs();
|
||||
return new GrClosureSignatureImpl(params, returnType, isVarArgs, false);
|
||||
return new GrImmediateClosureSignatureImpl(params, returnType, isVarArgs, false);
|
||||
}
|
||||
return null; //todo
|
||||
}
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,9 +15,9 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.lang.psi.impl.signatures;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrMultiSignature;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignature;
|
||||
@@ -51,7 +51,7 @@ public class GrMultiSignatureImpl implements GrMultiSignature {
|
||||
}
|
||||
|
||||
@Override
|
||||
public GrSignature curry(@NotNull PsiType[] args, int position, @NotNull GroovyPsiElement context) {
|
||||
public GrSignature curry(@NotNull PsiType[] args, int position, @NotNull PsiElement context) {
|
||||
List<GrClosureSignature> newClosures = new ArrayList<GrClosureSignature>();
|
||||
|
||||
for (GrClosureSignature old : mySignatures) {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -118,7 +118,7 @@ public class GrClosableBlockImpl extends GrBlockImpl implements GrClosableBlock
|
||||
@NotNull PsiScopeProcessor nonCodeProcessor,
|
||||
@NotNull ResolveState state,
|
||||
@NotNull PsiElement place) {
|
||||
GrDelegatesToUtil.DelegatesToInfo info = GrDelegatesToUtil.getDelegateToInfo(place, this);
|
||||
GrDelegatesToUtil.DelegatesToInfo info = GrDelegatesToUtil.getDelegatesToInfo(place, this);
|
||||
if (info == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -44,7 +44,7 @@ import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
|
||||
*/
|
||||
public class GrDelegatesToUtil {
|
||||
@Nullable
|
||||
static DelegatesToInfo getDelegateToInfo(@NotNull PsiElement place, @NotNull final GrClosableBlock closableBlock) {
|
||||
static DelegatesToInfo getDelegatesToInfo(@NotNull PsiElement place, @NotNull final GrClosableBlock closableBlock) {
|
||||
GrCall call = getContainingCall(closableBlock);
|
||||
if (call == null) return null;
|
||||
|
||||
|
||||
+3
-3
@@ -47,7 +47,7 @@ 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.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.*;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureImpl;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrImmediateClosureSignatureImpl;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.GrTypeConverter;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
||||
@@ -545,8 +545,8 @@ public class TypesUtil {
|
||||
|
||||
if (signature1 instanceof GrClosureSignature && signature2 instanceof GrClosureSignature) {
|
||||
if (((GrClosureSignature)signature1).getParameterCount() == ((GrClosureSignature)signature2).getParameterCount()) {
|
||||
final GrClosureSignature signature = GrClosureSignatureImpl.getLeastUpperBound(((GrClosureSignature)signature1),
|
||||
((GrClosureSignature)signature2), manager);
|
||||
final GrClosureSignature signature = GrImmediateClosureSignatureImpl.getLeastUpperBound(((GrClosureSignature)signature1),
|
||||
((GrClosureSignature)signature2), manager);
|
||||
if (signature != null) {
|
||||
GlobalSearchScope scope = clType1.getResolveScope().intersectWith(clType2.getResolveScope());
|
||||
final LanguageLevel languageLevel = ComparatorUtil.max(clType1.getLanguageLevel(), clType2.getLanguageLevel());
|
||||
|
||||
+1
-8
@@ -16,8 +16,6 @@
|
||||
package org.jetbrains.plugins.groovy.lang.psi.impl.synthetic;
|
||||
|
||||
import com.intellij.navigation.NavigationItem;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.RecursionManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiIntersectionType;
|
||||
import com.intellij.psi.PsiType;
|
||||
@@ -69,12 +67,7 @@ public class ClosureSyntheticParameter extends GrLightParameter implements Navig
|
||||
public PsiType getTypeGroovy() {
|
||||
assert isValid();
|
||||
|
||||
return RecursionManager.doPreventingRecursion(this, false, new Computable<PsiType>() {
|
||||
@Override
|
||||
public PsiType compute() {
|
||||
return TypeInferenceHelper.getCurrentContext().getExpressionType(ClosureSyntheticParameter.this, TYPES_CALCULATOR);
|
||||
}
|
||||
});
|
||||
return TypeInferenceHelper.getCurrentContext().getExpressionType(this, TYPES_CALCULATOR);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+20
-6
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.lang.psi.typeEnhancers;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
@@ -25,12 +40,8 @@ public class GrGenericTypeConverter extends GrTypeConverter {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
PsiClassType.ClassResolveResult lresult = ((PsiClassType)ltype).resolveGenerics();
|
||||
PsiClassType.ClassResolveResult rresult = ((PsiClassType)rtype).resolveGenerics();
|
||||
|
||||
PsiClass lclass = lresult.getElement();
|
||||
PsiClass rclass = rresult.getElement();
|
||||
PsiClass lclass = ((PsiClassType)ltype).resolve();
|
||||
PsiClass rclass = ((PsiClassType)rtype).resolve();
|
||||
|
||||
if (lclass == null || rclass == null) return null;
|
||||
|
||||
@@ -38,6 +49,9 @@ public class GrGenericTypeConverter extends GrTypeConverter {
|
||||
|
||||
if (!InheritanceUtil.isInheritorOrSelf(rclass, lclass, true)) return null;
|
||||
|
||||
PsiClassType.ClassResolveResult lresult = ((PsiClassType)ltype).resolveGenerics();
|
||||
PsiClassType.ClassResolveResult rresult = ((PsiClassType)rtype).resolveGenerics();
|
||||
|
||||
if (typeParametersAgree(lclass, rclass, lresult.getSubstitutor(), rresult.getSubstitutor(), context)) return Boolean.TRUE;
|
||||
|
||||
return null;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,6 +22,8 @@ import com.intellij.testFramework.LightProjectDescriptor
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
||||
import org.jetbrains.annotations.NonNls
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import org.jetbrains.annotations.Nullable
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
@@ -247,7 +249,7 @@ public abstract class TestCase extends junit.framework.Assert implements junit.f
|
||||
''')
|
||||
}
|
||||
|
||||
public static void assertType(String expected, PsiType actual) {
|
||||
public static void assertType(@Nullable String expected, @Nullable PsiType actual) {
|
||||
if (expected == null) {
|
||||
assertNull(actual)
|
||||
return
|
||||
|
||||
+52
-1
@@ -137,7 +137,6 @@ class Thing {
|
||||
''', 'java.lang.Integer')
|
||||
}
|
||||
|
||||
|
||||
void testSamInference4() {
|
||||
doTest('''
|
||||
interface Action<T> {
|
||||
@@ -154,4 +153,56 @@ def foo() {
|
||||
|
||||
''', 'java.lang.String')
|
||||
}
|
||||
|
||||
void testSamInference5() {
|
||||
doTest('''
|
||||
interface Action<T> {
|
||||
void execute(T t)
|
||||
}
|
||||
|
||||
public <T> void exec(T t, Action<T> f) {
|
||||
}
|
||||
|
||||
|
||||
def foo() {
|
||||
exec('foo') {i<caret>t.toUpperCase() }
|
||||
}
|
||||
|
||||
''', 'java.lang.String')
|
||||
}
|
||||
|
||||
void testSamInference6() {
|
||||
doTest('''
|
||||
interface Action<T> {
|
||||
void execute(T t)
|
||||
}
|
||||
|
||||
public <T> void exec(T t, Action<T> f) {
|
||||
}
|
||||
|
||||
|
||||
def foo() {
|
||||
exec('foo') {print i<caret>t.toUpperCase() }
|
||||
}
|
||||
|
||||
''', 'java.lang.String')
|
||||
}
|
||||
|
||||
void testSamInference7() {
|
||||
doTest('''
|
||||
interface CustomCallable<T> {
|
||||
T call()
|
||||
}
|
||||
|
||||
class Thing {
|
||||
static <T> T customType(CustomCallable<T> callable) {
|
||||
}
|
||||
|
||||
static void run() {
|
||||
customType { i<caret>t }
|
||||
}
|
||||
}''', null)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+3
-2
@@ -16,6 +16,7 @@
|
||||
package org.jetbrains.plugins.groovy.lang.resolve
|
||||
|
||||
import org.intellij.lang.annotations.Language
|
||||
import org.jetbrains.annotations.Nullable
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression
|
||||
@@ -35,14 +36,14 @@ abstract class TypeInferenceTestBase extends GroovyResolveTestCase {
|
||||
myFixture.addClass("package java.math; public class BigDecimal extends Number implements Comparable<BigDecimal> {}");
|
||||
}
|
||||
|
||||
protected void doTest(@Language("Groovy") String text, String type) {
|
||||
protected void doTest(@Language("Groovy") String text, @Nullable String type) {
|
||||
def file = myFixture.configureByText('_.groovy', text)
|
||||
def ref = file.findReferenceAt(myFixture.editor.caretModel.offset) as GrReferenceExpression
|
||||
def actual = ref.type
|
||||
assertType(type, actual)
|
||||
}
|
||||
|
||||
protected void doExprTest(@Language("Groovy") String text, String expectedType) {
|
||||
protected void doExprTest(@Language("Groovy") String text, @Nullable String expectedType) {
|
||||
GroovyFile file = myFixture.configureByText('_.groovy', text) as GroovyFile
|
||||
GrStatement lastStatement = file.statements.last()
|
||||
assertInstanceOf lastStatement, GrExpression
|
||||
|
||||
@@ -563,6 +563,7 @@ refactoring.extract.method.error.cannot.perform.refactoring.with.local=Cannot pe
|
||||
|
||||
# extract superclass
|
||||
refactoring.extract.super.target.path.outside.roots=Target directory is outside the project. Must be within content roots
|
||||
refactoring.extract.super.target.class.already.exists=Class ''{0}'' already exists in this module
|
||||
refactoring.extract.super.name.0.must.be.ident=Name ''{0}'' is invalid. Must be a valid Python identifier
|
||||
refactoring.extract.super.class.no.members.allowed=None of members could be extracted
|
||||
|
||||
|
||||
+21
-3
@@ -6,13 +6,17 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.classMembers.MemberInfoModel;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.PythonLanguage;
|
||||
import com.jetbrains.python.psi.PyClass;
|
||||
import com.jetbrains.python.psi.PyElement;
|
||||
import com.jetbrains.python.psi.PyFile;
|
||||
import com.jetbrains.python.psi.PyUtil;
|
||||
import com.jetbrains.python.refactoring.classes.PyMemberInfoStorage;
|
||||
import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
|
||||
@@ -47,8 +51,9 @@ class PyExtractSuperclassPresenterImpl extends MembersBasedPresenterNoPreviewImp
|
||||
throw new BadDataException(PyBundle.message("refactoring.extract.super.name.0.must.be.ident", myView.getSuperClassName()));
|
||||
}
|
||||
boolean rootFound = false;
|
||||
final File moduleFile = new File(myView.getModuleFile());
|
||||
try {
|
||||
final String targetDir = FileUtil.toSystemIndependentName(new File(myView.getModuleFile()).getCanonicalPath());
|
||||
final String targetDir = FileUtil.toSystemIndependentName(moduleFile.getCanonicalPath());
|
||||
for (final VirtualFile file : ProjectRootManager.getInstance(project).getContentRoots()) {
|
||||
if (StringUtil.startsWithIgnoreCase(targetDir, file.getPath())) {
|
||||
rootFound = true;
|
||||
@@ -61,6 +66,19 @@ class PyExtractSuperclassPresenterImpl extends MembersBasedPresenterNoPreviewImp
|
||||
if (!rootFound) {
|
||||
throw new BadDataException(PyBundle.message("refactoring.extract.super.target.path.outside.roots"));
|
||||
}
|
||||
|
||||
// TODO: Cover with test. It can't be done for now, because testFixture reports root path incorrectly
|
||||
// PY-12173
|
||||
myView.getModuleFile();
|
||||
final VirtualFile moduleVirtualFile = LocalFileSystem.getInstance().findFileByIoFile(moduleFile);
|
||||
if (moduleVirtualFile != null) {
|
||||
final PsiFile psiFile = PsiManager.getInstance(project).findFile(moduleVirtualFile);
|
||||
if (psiFile instanceof PyFile) {
|
||||
if (((PyFile)psiFile).findTopLevelClass(myView.getSuperClassName()) != null) {
|
||||
throw new BadDataException(PyBundle.message("refactoring.extract.super.target.class.already.exists", myView.getSuperClassName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -71,9 +89,9 @@ class PyExtractSuperclassPresenterImpl extends MembersBasedPresenterNoPreviewImp
|
||||
PyUtil.filterOutObject(myStorage.getClassMemberInfos(myClassUnderRefactoring));
|
||||
myView.configure(
|
||||
new PyExtractSuperclassInitializationInfo(myModel, pyMemberInfos, defaultFilePath,
|
||||
roots));
|
||||
roots)
|
||||
);
|
||||
myView.initAndShow();
|
||||
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -17,8 +17,6 @@ package com.jetbrains.python.refactoring.classes.pullUp;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.psi.PyClass;
|
||||
import com.jetbrains.python.refactoring.classes.PyClassRefactoringHandler;
|
||||
@@ -39,14 +37,10 @@ public class PyPullUpHandler extends PyClassRefactoringHandler {
|
||||
@NotNull final PyMemberInfoStorage infoStorage,
|
||||
@NotNull final Editor editor) {
|
||||
//TODO: Move to vp (presenter) as well
|
||||
final PyPullUpNothingToRefactorMessage nothingToRefactor = new PyPullUpNothingToRefactorMessage(project, editor, classUnderRefactoring);
|
||||
|
||||
if (PyAncestorsUtils.getAncestorsUnderUserControl(classUnderRefactoring).isEmpty() ||
|
||||
infoStorage.getClassMemberInfos(classUnderRefactoring).isEmpty()) {
|
||||
CommonRefactoringUtil.showErrorHint(project, editor, PyBundle
|
||||
.message("refactoring.pull.up.error.cannot.perform.refactoring.no.base.classes",
|
||||
classUnderRefactoring.getName()), RefactoringBundle.message("pull.members.up.title"),
|
||||
"members.pull.up"
|
||||
);
|
||||
if (PyAncestorsUtils.getAncestorsUnderUserControl(classUnderRefactoring).isEmpty()) {
|
||||
nothingToRefactor.showNothingToRefactor();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -62,13 +56,13 @@ public class PyPullUpHandler extends PyClassRefactoringHandler {
|
||||
@NotNull
|
||||
@Override
|
||||
public PyPullUpView createView(@NotNull final PyPullUpPresenter presenter) {
|
||||
return new PyPullUpViewSwingImpl(project, presenter, classUnderRefactoring);
|
||||
return new PyPullUpViewSwingImpl(project, presenter, classUnderRefactoring, nothingToRefactor);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
return REFACTORING_NAME;
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package com.jetbrains.python.refactoring.classes.pullUp;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.psi.PyClass;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Displays "nothing to refactor" message
|
||||
* @author Ilya.Kazakevich
|
||||
*/
|
||||
class PyPullUpNothingToRefactorMessage {
|
||||
|
||||
@NotNull
|
||||
private final Project myProject;
|
||||
@NotNull
|
||||
private final Editor myEditor;
|
||||
@NotNull
|
||||
private final PyClass myClassUnderRefactoring;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param project project to be used
|
||||
* @param editor editor to be used
|
||||
* @param classUnderRefactoring class user refactors
|
||||
*/
|
||||
PyPullUpNothingToRefactorMessage(@NotNull final Project project,
|
||||
@NotNull final Editor editor,
|
||||
@NotNull final PyClass classUnderRefactoring) {
|
||||
myProject = project;
|
||||
myEditor = editor;
|
||||
myClassUnderRefactoring = classUnderRefactoring;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display message
|
||||
*/
|
||||
void showNothingToRefactor() {
|
||||
CommonRefactoringUtil.showErrorHint(myProject, myEditor, PyBundle
|
||||
.message("refactoring.pull.up.error.cannot.perform.refactoring.no.base.classes",
|
||||
myClassUnderRefactoring.getName()), RefactoringBundle.message("pull.members.up.title"),
|
||||
"members.pull.up"
|
||||
);
|
||||
}
|
||||
}
|
||||
+16
-1
@@ -55,7 +55,22 @@ class PyPullUpPresenterImpl extends MembersBasedPresenterWithPreviewImpl<PyPullU
|
||||
public void launch() {
|
||||
myView.configure(
|
||||
new PyPullUpViewInitializationInfo(myModel, myStorage.getClassMemberInfos(myClassUnderRefactoring), myParents));
|
||||
myView.initAndShow();
|
||||
|
||||
// If there is no enabled member then only error should be displayed
|
||||
|
||||
boolean atLeastOneEnabled = false;
|
||||
for (final PyMemberInfo<PyElement> info : myStorage.getClassMemberInfos(myClassUnderRefactoring)) {
|
||||
if (myModel.isMemberEnabled(info)) {
|
||||
atLeastOneEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (atLeastOneEnabled) {
|
||||
myView.initAndShow();
|
||||
} else {
|
||||
myView.showNothingToRefactor();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -31,4 +31,9 @@ public interface PyPullUpView extends MembersBasedView<PyPullUpViewInitializatio
|
||||
*/
|
||||
@NotNull
|
||||
PyClass getSelectedParent();
|
||||
|
||||
/**
|
||||
* Display "nothing to refactor" message.
|
||||
*/
|
||||
void showNothingToRefactor();
|
||||
}
|
||||
|
||||
+13
-2
@@ -39,15 +39,23 @@ class PyPullUpViewSwingImpl extends MembersBasedViewSwingImpl<PyPullUpPresenter,
|
||||
private final ComboBox myParentsCombo;
|
||||
@NotNull
|
||||
private final DefaultComboBoxModel myParentsComboBoxModel;
|
||||
@NotNull
|
||||
private final PyPullUpNothingToRefactorMessage myNothingToRefactorMessage;
|
||||
|
||||
/**
|
||||
* @param project project where refactoring takes place
|
||||
* @param presenter presenter for this view
|
||||
* @param clazz class to refactor
|
||||
* @param nothingToRefactorMessage class that displays message "nothing to refactor" when presenter calls {@link #showNothingToRefactor()}
|
||||
*/
|
||||
PyPullUpViewSwingImpl(@NotNull final Project project, @NotNull final PyPullUpPresenter presenter, @NotNull final PyClass clazz) {
|
||||
PyPullUpViewSwingImpl(
|
||||
@NotNull final Project project,
|
||||
@NotNull final PyPullUpPresenter presenter,
|
||||
@NotNull final PyClass clazz,
|
||||
@NotNull final PyPullUpNothingToRefactorMessage nothingToRefactorMessage) {
|
||||
super(project, presenter, RefactoringBundle.message("members.to.be.pulled.up"), true);
|
||||
setTitle(PyPullUpHandler.REFACTORING_NAME);
|
||||
myNothingToRefactorMessage = nothingToRefactorMessage;
|
||||
|
||||
myParentsComboBoxModel = new DefaultComboBoxModel();
|
||||
|
||||
@@ -91,7 +99,10 @@ class PyPullUpViewSwingImpl extends MembersBasedViewSwingImpl<PyPullUpPresenter,
|
||||
return (PyClass)myParentsComboBoxModel.getSelectedItem();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void showNothingToRefactor() {
|
||||
myNothingToRefactorMessage.showNothingToRefactor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(@NotNull final PyPullUpViewInitializationInfo configInfo) {
|
||||
|
||||
+10
-2
@@ -37,7 +37,7 @@ public class PyPullUpPresenterTest extends PyRefactoringPresenterTestCase<PyPull
|
||||
*/
|
||||
public void testParentsOrder() throws Exception {
|
||||
final PyPullUpPresenter sut = configureByClass("Child");
|
||||
|
||||
configureParent();
|
||||
myMocksControl.replay();
|
||||
|
||||
sut.launch();
|
||||
@@ -59,6 +59,7 @@ public class PyPullUpPresenterTest extends PyRefactoringPresenterTestCase<PyPull
|
||||
*/
|
||||
public void testConflicts() throws Exception {
|
||||
final PyPullUpPresenterImpl sut = configureByClass("ChildWithConflicts");
|
||||
configureParent();
|
||||
final Collection<PyMemberInfo<PyElement>> infos = getMemberInfos(sut);
|
||||
|
||||
final Capture<MultiMap<PyClass, PyMemberInfo<?>>> conflictCapture = new Capture<MultiMap<PyClass, PyMemberInfo<?>>>();
|
||||
@@ -123,7 +124,6 @@ public class PyPullUpPresenterTest extends PyRefactoringPresenterTestCase<PyPull
|
||||
ensureCorrectMembersForHugeChild(true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks members for class HugeChild
|
||||
*
|
||||
@@ -148,6 +148,7 @@ public class PyPullUpPresenterTest extends PyRefactoringPresenterTestCase<PyPull
|
||||
compareMembers(memberNamesAndStatus, matcher);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Launches presenter and returns members it displayed to user
|
||||
*
|
||||
@@ -196,4 +197,11 @@ public class PyPullUpPresenterTest extends PyRefactoringPresenterTestCase<PyPull
|
||||
final PyMemberInfoStorage storage = new PyMemberInfoStorage(childClass);
|
||||
return new PyPullUpPresenterImpl(myView, storage, childClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes view to return class "Parent" as selected parent
|
||||
*/
|
||||
private void configureParent() {
|
||||
EasyMock.expect(myView.getSelectedParent()).andReturn(getClassByName("Parent")).anyTimes();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user