Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Trofimov
2014-02-26 15:14:15 +01:00
38 changed files with 577 additions and 228 deletions
@@ -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
@@ -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();
}
}
@@ -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();
@@ -459,6 +459,7 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta
myBreakpoints = breakpoints;
}
@SuppressWarnings("UnusedDeclaration")
public void setDefaultBreakpoints(List<BreakpointState> defaultBreakpoints) {
myDefaultBreakpoints = defaultBreakpoints;
}
@@ -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()));
}
}
@@ -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());
}
}
@@ -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) {
@@ -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;
}
@@ -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);
}
@@ -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,
@@ -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;
@@ -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();
}
}
}
@@ -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;
@@ -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;
@@ -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
}
@@ -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) {
@@ -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;
}
@@ -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;
@@ -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());
@@ -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
@@ -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
@@ -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)
}
}
@@ -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
@@ -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;
@@ -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"
);
}
}
@@ -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();
}
@@ -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) {
@@ -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();
}
}