From 6fcd436862d85487e28d1d3e8f0d42b4bb284f93 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 18 Feb 2011 14:23:51 +0100 Subject: [PATCH 001/169] catch more general exception from Velocity (EA-25752 - PE: Parser.parse) --- .../intellij/ide/actions/CreateFileFromTemplateAction.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/actions/CreateFileFromTemplateAction.java b/platform/lang-impl/src/com/intellij/ide/actions/CreateFileFromTemplateAction.java index a1469634bc87..e450ed8f792a 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/CreateFileFromTemplateAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/CreateFileFromTemplateAction.java @@ -27,7 +27,7 @@ import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.util.IncorrectOperationException; -import org.apache.velocity.runtime.parser.TemplateParseException; +import org.apache.velocity.runtime.parser.ParseException; import javax.swing.*; @@ -58,7 +58,7 @@ public abstract class CreateFileFromTemplateAction extends CreateFromTemplateAct return psiFile; } } - catch (TemplateParseException e) { + catch (ParseException e) { Messages.showErrorDialog(dir.getProject(), "Error parsing Velocity template: " + e.getMessage(), "Create File from Template"); return null; } From 361d7d0b9abdfa1f997e04fe10bfe58a206937e7 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Fri, 18 Feb 2011 16:26:36 +0300 Subject: [PATCH 002/169] EA-25165 - PIEAE: ASTDelegatePsiElement.getManager --- .../org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java index 14caa5c9b638..1e2ae47a3710 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java @@ -521,6 +521,7 @@ public class ResolveUtil { } public static boolean isInUseScope(PsiElement context) { + if (!context.isValid()) return false; if (context instanceof GrMethodCall) { final GrExpression expression = ((GrMethodCall)context).getInvokedExpression(); if (expression instanceof GrReferenceExpression) { From 5255b336659a3983f14aa1b3279fab9323ce89ea Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Sun, 20 Feb 2011 15:15:40 +0300 Subject: [PATCH 003/169] IDEA-59733 scroll from/to source async problems fix take 1 --- .../impl/AbstractProjectViewPane.java | 7 +++- .../ide/projectView/impl/ProjectViewImpl.java | 9 +++- .../com/intellij/openapi/wm/ToolWindow.java | 3 +- .../ui/AutoScrollToSourceHandler.java | 42 ++++++++++++------- .../src/com/intellij/ui/content/Content.java | 7 +++- .../intellij/ui/content/ContentManager.java | 3 +- .../impl/ToolWindowHeadlessManagerImpl.java | 12 +++++- .../openapi/wm/impl/ToolWindowImpl.java | 19 +++++++-- .../intellij/ui/content/impl/ContentImpl.java | 16 +++++-- .../ui/content/impl/ContentManagerImpl.java | 12 ++++-- 10 files changed, 98 insertions(+), 32 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java index b5eba4485b24..c581147a1eaf 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java @@ -74,7 +74,7 @@ import java.util.List; import java.util.Map; -public abstract class AbstractProjectViewPane implements DataProvider, Disposable { +public abstract class AbstractProjectViewPane implements DataProvider, Disposable, BusyObject { public static ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.projectViewPane"); protected final Project myProject; @@ -635,4 +635,9 @@ public abstract class AbstractProjectViewPane implements DataProvider, Disposabl } return false; } + + @Override + public ActionCallback getReady(Object requestor) { + return myTreeBuilder.getUi().getReady(requestor); + } } diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java index 61d5dc90cf70..b72c14c6b5bd 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java @@ -116,7 +116,7 @@ import java.util.List; file = "$WORKSPACE_FILE$" )} ) -public final class ProjectViewImpl extends ProjectView implements PersistentStateComponent, Disposable, QuickActionProvider { +public final class ProjectViewImpl extends ProjectView implements PersistentStateComponent, Disposable, QuickActionProvider, BusyObject { private static final Logger LOG = Logger.getInstance("#com.intellij.ide.projectView.impl.ProjectViewImpl"); private final CopyPasteDelegator myCopyPasteDelegator; private boolean isInitialized; @@ -577,6 +577,7 @@ public final class ProjectViewImpl extends ProjectView implements PersistentStat if (toolWindow != null) { final ContentManager contentManager = toolWindow.getContentManager(); final Content content = contentManager.getFactory().createContent(getComponent(), ToolWindowId.PROJECT_VIEW, false); + content.setBusyObject(this); contentManager.addContent(content); content.setPreferredFocusedComponent(new Computable() { @@ -1836,4 +1837,10 @@ public final class ProjectViewImpl extends ProjectView implements PersistentStat ensurePanesLoaded(); return mySelectInTargets.values(); } + + @Override + public ActionCallback getReady(Object requestor) { + AbstractProjectViewPane pane = myId2Pane.get(myCurrentViewSubId); + return pane != null ? pane.getReady(requestor) : new ActionCallback.Done(); + } } diff --git a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindow.java b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindow.java index 12aca9181a42..93870283c6ce 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindow.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindow.java @@ -16,6 +16,7 @@ package com.intellij.openapi.wm; import com.intellij.openapi.util.ActionCallback; +import com.intellij.openapi.util.BusyObject; import com.intellij.openapi.util.Key; import com.intellij.ui.content.ContentManager; import org.jetbrains.annotations.NotNull; @@ -26,7 +27,7 @@ import javax.swing.border.EmptyBorder; import java.awt.*; import java.awt.event.InputEvent; -public interface ToolWindow { +public interface ToolWindow extends BusyObject { Key SHOW_CONTENT_ICON = new Key("ContentIcon"); diff --git a/platform/platform-api/src/com/intellij/ui/AutoScrollToSourceHandler.java b/platform/platform-api/src/com/intellij/ui/AutoScrollToSourceHandler.java index fa9496738462..d42881301d22 100644 --- a/platform/platform-api/src/com/intellij/ui/AutoScrollToSourceHandler.java +++ b/platform/platform-api/src/com/intellij/ui/AutoScrollToSourceHandler.java @@ -25,8 +25,11 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.util.ActionCallback; +import com.intellij.openapi.util.BusyObject; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.ToolWindow; import com.intellij.pom.Navigatable; import com.intellij.util.Alarm; import com.intellij.util.OpenSourceUtil; @@ -140,22 +143,28 @@ public abstract class AutoScrollToSourceHandler { protected abstract boolean isAutoScrollMode(); protected abstract void setAutoScrollMode(boolean state); - protected void scrollToSource(Component tree) { + protected void scrollToSource(final Component tree) { DataContext dataContext=DataManager.getInstance().getDataContext(tree); - final VirtualFile vFile = PlatformDataKeys.VIRTUAL_FILE.getData(dataContext); - if (vFile != null) { - // Attempt to navigate to the virtual file with unknown file type will show a modal dialog - // asking to register some file type for this file. This behaviour is undesirable when autoscrolling. - if (FileTypeManager.getInstance().getFileTypeByFile(vFile) == FileTypes.UNKNOWN) return; - } - Navigatable[] navigatables = PlatformDataKeys.NAVIGATABLE_ARRAY.getData(dataContext); - if (navigatables != null) { - for (Navigatable navigatable : navigatables) { - // we are not going to open modal dialog during autoscrolling - if (!navigatable.canNavigateToSource()) return; + getReady(dataContext).doWhenDone(new Runnable() { + @Override + public void run() { + DataContext context = DataManager.getInstance().getDataContext(tree); + final VirtualFile vFile = PlatformDataKeys.VIRTUAL_FILE.getData(context); + if (vFile != null) { + // Attempt to navigate to the virtual file with unknown file type will show a modal dialog + // asking to register some file type for this file. This behaviour is undesirable when autoscrolling. + if (FileTypeManager.getInstance().getFileTypeByFile(vFile) == FileTypes.UNKNOWN) return; + } + Navigatable[] navigatables = PlatformDataKeys.NAVIGATABLE_ARRAY.getData(context); + if (navigatables != null) { + for (Navigatable navigatable : navigatables) { + // we are not going to open modal dialog during autoscrolling + if (!navigatable.canNavigateToSource()) return; + } + } + OpenSourceUtil.openSourcesFrom(context, false); } - } - OpenSourceUtil.openSourcesFrom(dataContext, false); + }); } public ToggleAction createToggleAction() { @@ -175,5 +184,10 @@ public abstract class AutoScrollToSourceHandler { setAutoScrollMode(flag); } } + + private ActionCallback getReady(DataContext context) { + ToolWindow toolWindow = PlatformDataKeys.TOOL_WINDOW.getData(context); + return toolWindow != null ? toolWindow.getReady(this) : new ActionCallback.Done(); + } } diff --git a/platform/platform-api/src/com/intellij/ui/content/Content.java b/platform/platform-api/src/com/intellij/ui/content/Content.java index e0b134bcccd6..68c6d96ace9c 100644 --- a/platform/platform-api/src/com/intellij/ui/content/Content.java +++ b/platform/platform-api/src/com/intellij/ui/content/Content.java @@ -18,6 +18,7 @@ package com.intellij.ui.content; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.ActionGroup; import com.intellij.openapi.ui.ComponentContainer; +import com.intellij.openapi.util.BusyObject; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.UserDataHolder; import org.jetbrains.annotations.NonNls; @@ -102,5 +103,9 @@ public interface Content extends UserDataHolder, ComponentContainer { @Nullable AlertIcon getAlertIcon(); void fireAlert(); - + + @Nullable + BusyObject getBusyObject(); + void setBusyObject(BusyObject object); + } diff --git a/platform/platform-api/src/com/intellij/ui/content/ContentManager.java b/platform/platform-api/src/com/intellij/ui/content/ContentManager.java index 75dbc3a17ac6..f3668b2da457 100644 --- a/platform/platform-api/src/com/intellij/ui/content/ContentManager.java +++ b/platform/platform-api/src/com/intellij/ui/content/ContentManager.java @@ -19,13 +19,14 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.DataProvider; import com.intellij.openapi.util.ActionCallback; +import com.intellij.openapi.util.BusyObject; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.List; -public interface ContentManager extends Disposable { +public interface ContentManager extends Disposable, BusyObject { boolean canCloseContents(); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java index 6d976bc72805..0f37f3b72fbd 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java @@ -71,7 +71,11 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { public boolean isVisible() { return false; } - + + @Override + public ActionCallback getReady(Object requestor) { + return new ActionCallback.Done(); + } public void show(@Nullable Runnable runnable) { } @@ -175,6 +179,12 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { }; @NonNls private static final ContentManager MOCK_CONTENT_MANAGER = new ContentManager() { + + @Override + public ActionCallback getReady(Object requestor) { + return new ActionCallback.Done(); + } + public void addContent(@NotNull final Content content) { } public void addContent(@NotNull Content content, int order) { } public void addContent(@NotNull final Content content, final Object constraints) { } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java index f84197091b98..12cf1e0e189f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java @@ -20,10 +20,7 @@ import com.intellij.openapi.actionSystem.ActionGroup; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.util.ActionCallback; -import com.intellij.openapi.wm.ToolWindowAnchor; -import com.intellij.openapi.wm.ToolWindowContentUiType; -import com.intellij.openapi.wm.ToolWindowFactory; -import com.intellij.openapi.wm.ToolWindowType; +import com.intellij.openapi.wm.*; import com.intellij.openapi.wm.ex.ToolWindowEx; import com.intellij.openapi.wm.impl.content.ToolWindowContentUi; import com.intellij.ui.content.Content; @@ -117,6 +114,20 @@ public final class ToolWindowImpl implements ToolWindowEx { return myToolWindowManager.isToolWindowActive(myId) || (myDecorator != null && myDecorator.isFocused()); } + @Override + public ActionCallback getReady(Object requestor) { + final ActionCallback result = new ActionCallback(3); + myContentManager.getReady(requestor).notify(result); + getActivation().notify(result); + IdeFocusManager.getInstance(myToolWindowManager.getProject()).doWhenFocusSettlesDown(new Runnable() { + @Override + public void run() { + result.setDone(); + } + }); + return result; + } + public final void show(final Runnable runnable) { ApplicationManager.getApplication().assertIsDispatchThread(); myToolWindowManager.showToolWindow(myId); diff --git a/platform/platform-impl/src/com/intellij/ui/content/impl/ContentImpl.java b/platform/platform-impl/src/com/intellij/ui/content/impl/ContentImpl.java index 4487d294804a..d345f257b02c 100644 --- a/platform/platform-impl/src/com/intellij/ui/content/impl/ContentImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/content/impl/ContentImpl.java @@ -18,10 +18,7 @@ package com.intellij.ui.content.impl; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.ActionGroup; -import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.IconLoader; -import com.intellij.openapi.util.UserDataHolderBase; +import com.intellij.openapi.util.*; import com.intellij.ui.LayeredIcon; import com.intellij.ui.content.AlertIcon; import com.intellij.ui.content.Content; @@ -57,6 +54,7 @@ public class ContentImpl extends UserDataHolderBase implements Content { private JComponent mySearchComponent; private Computable myFocusRequest; + private BusyObject myBusyObject; public ContentImpl(JComponent component, String displayName, boolean isPinnable) { myComponent = component; @@ -264,6 +262,16 @@ public class ContentImpl extends UserDataHolderBase implements Content { myChangeSupport.firePropertyChange(PROP_ALERT, null, true); } + @Override + public void setBusyObject(BusyObject object) { + myBusyObject = object; + } + + @Override + public BusyObject getBusyObject() { + return myBusyObject; + } + public void setSearchComponent(@Nullable final JComponent comp) { mySearchComponent = comp; } diff --git a/platform/platform-impl/src/com/intellij/ui/content/impl/ContentManagerImpl.java b/platform/platform-impl/src/com/intellij/ui/content/impl/ContentManagerImpl.java index 2e3707e37bb0..f47c0df6739f 100644 --- a/platform/platform-impl/src/com/intellij/ui/content/impl/ContentManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/content/impl/ContentManagerImpl.java @@ -23,10 +23,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.ActionCallback; -import com.intellij.openapi.util.ActiveRunnable; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.*; import com.intellij.openapi.wm.FocusCommand; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy; @@ -109,6 +106,13 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene return myComponent; } + @Override + public ActionCallback getReady(Object requestor) { + Content selected = getSelectedContent(); + BusyObject busyObject = selected.getBusyObject(); + return busyObject != null ? busyObject.getReady(requestor) : new ActionCallback.Done(); + } + private class MyContentComponent extends NonOpaquePanel implements DataProvider, SwitchProvider { private final List myProviders = new ArrayList(); From 30c9e3defb7c98a07f6603dd5ad6c092f8ad48ef Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Sun, 20 Feb 2011 18:11:44 +0300 Subject: [PATCH 004/169] IDEA-59733 scroll from/to source async problems fix take 2 --- .../openapi/wm/impl/ToolWindowImpl.java | 42 ++++++++++++++++--- .../wm/impl/ToolWindowManagerImpl.java | 2 +- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java index 12cf1e0e189f..a5ecf97f5c77 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java @@ -20,13 +20,18 @@ import com.intellij.openapi.actionSystem.ActionGroup; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.util.ActionCallback; +import com.intellij.openapi.util.BusyObject; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.wm.*; import com.intellij.openapi.wm.ex.ToolWindowEx; +import com.intellij.openapi.wm.impl.commands.FinalizableCommand; import com.intellij.openapi.wm.impl.content.ToolWindowContentUi; import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentFactory; import com.intellij.ui.content.ContentManager; import com.intellij.ui.content.impl.ContentImpl; +import com.intellij.util.ui.update.Activatable; +import com.intellij.util.ui.update.UiNotifyConnector; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -35,6 +40,7 @@ import java.awt.*; import java.awt.event.InputEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; +import java.util.ArrayList; /** * @author Anton Katilin @@ -59,6 +65,12 @@ public final class ToolWindowImpl implements ToolWindowEx { private ToolWindowFactory myContentFactory; private ActionCallback myActivation = new ActionCallback.Done(); + private BusyObject.Impl myShowing = new BusyObject.Impl() { + @Override + protected boolean isReady() { + return myComponent != null && myComponent.isShowing(); + } + }; ToolWindowImpl(final ToolWindowManagerImpl toolWindowManager, final String id, boolean canCloseContent, @Nullable final JComponent component) { myToolWindowManager = toolWindowManager; @@ -78,6 +90,14 @@ public final class ToolWindowImpl implements ToolWindowEx { } myComponent = myContentManager.getComponent(); + + UiNotifyConnector notifyConnector = new UiNotifyConnector(myComponent, new Activatable.Adapter() { + @Override + public void showNotify() { + myShowing.onReady(); + } + }); + Disposer.register(myContentManager, notifyConnector); } public final void addPropertyChangeListener(final PropertyChangeListener l) { @@ -115,14 +135,24 @@ public final class ToolWindowImpl implements ToolWindowEx { } @Override - public ActionCallback getReady(Object requestor) { - final ActionCallback result = new ActionCallback(3); - myContentManager.getReady(requestor).notify(result); - getActivation().notify(result); - IdeFocusManager.getInstance(myToolWindowManager.getProject()).doWhenFocusSettlesDown(new Runnable() { + public ActionCallback getReady(final Object requestor) { + final ActionCallback result = new ActionCallback(); + myShowing.getReady(this).doWhenDone(new Runnable() { @Override public void run() { - result.setDone(); + ArrayList cmd = new ArrayList(); + cmd.add(new FinalizableCommand(null) { + @Override + public void run() { + IdeFocusManager.getInstance(myToolWindowManager.getProject()).doWhenFocusSettlesDown(new Runnable() { + @Override + public void run() { + myContentManager.getReady(requestor).notify(result); + } + }); + } + }); + myToolWindowManager.execute(cmd); } }); return result; diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java index e02c51fc3a5c..a9528c3256c9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java @@ -558,7 +558,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements * This is helper method. It delegated its fuctionality to the WindowManager. * Before delegating it fires state changed. */ - private void execute(final ArrayList commandList) { + public void execute(final ArrayList commandList) { for (FinalizableCommand each : commandList) { if (each.willChangeState()) { fireStateChanged(); From 872d8ddef2659171b0cb583aec365db480077738 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Mon, 21 Feb 2011 11:55:05 +0300 Subject: [PATCH 005/169] IDEA-65601 Scroll after zoom bug Vertical scrollbar of editor scroll pane recalculates its bounds on font size change now --- .../src/com/intellij/openapi/editor/impl/EditorImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index e003cb69d206..e2e5963c3d03 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -765,6 +765,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi int oldFontSize = myScheme.getEditorFontSize(); myScheme.setEditorFontSize(fontSize); myPropertyChangeSupport.firePropertyChange(PROP_FONT_SIZE, oldFontSize, fontSize); + // Update vertical scroll bar bounds if necessary (we had a problem that use increased editor font size and it was not possible + // to scroll to the bottom of the document). + myScrollPane.getViewport().invalidate(); } public ActionCallback type(final String text) { From 5a5e84f3ef8c4dceb8c1b1ca452dc7b31b66a413 Mon Sep 17 00:00:00 2001 From: anna Date: Sat, 19 Feb 2011 15:11:06 +0100 Subject: [PATCH 006/169] complex inference algorithm for diamond --- .../impl/analysis/GenericsHighlightUtil.java | 18 +- .../ExplicitTypeCanBeDiamondInspection.java | 31 +- .../com/intellij/psi/impl/PsiImplUtil.java | 2 +- .../source/resolve/PsiResolveHelperImpl.java | 14 +- .../advHighlighting7/DiamondMisc.java | 2 +- .../advHighlighting7/DiamondNeg1.java | 16 +- .../advHighlighting7/DiamondNeg10.java | 7 + .../advHighlighting7/DiamondNeg11.java | 8 + .../advHighlighting7/DiamondNeg2.java | 32 +- .../advHighlighting7/DiamondNeg3.java | 48 +-- .../advHighlighting7/DiamondNeg4.java | 16 +- .../advHighlighting7/DiamondNeg6.java | 11 + .../advHighlighting7/DiamondNeg7.java | 9 + .../advHighlighting7/DiamondNeg8.java | 20 ++ .../advHighlighting7/DiamondNeg9.java | 12 + .../advHighlighting7/DiamondPos5.java | 12 + .../quickFix/explicit2diamond/after2.java | 7 - .../quickFix/explicit2diamond/after3.java | 11 - .../quickFix/explicit2diamond/after5.java | 16 + .../quickFix/explicit2diamond/after6.java | 16 + .../quickFix/explicit2diamond/after8.java | 16 + .../quickFix/explicit2diamond/after9.java | 16 + .../quickFix/explicit2diamond/before2.java | 2 +- .../quickFix/explicit2diamond/before3.java | 2 +- .../quickFix/explicit2diamond/before4.java | 16 + .../quickFix/explicit2diamond/before5.java | 16 + .../quickFix/explicit2diamond/before6.java | 16 + .../quickFix/explicit2diamond/before7.java | 16 + .../quickFix/explicit2diamond/before8.java | 16 + .../quickFix/explicit2diamond/before9.java | 16 + .../daemon/LightAdvHighlightingJdk7Test.java | 30 ++ .../src/com/intellij/psi/PsiDiamondType.java | 334 +++++++++++------- 32 files changed, 580 insertions(+), 224 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg10.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg11.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg6.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg7.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg8.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg9.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondPos5.java delete mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after2.java delete mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after3.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after5.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after6.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after8.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after9.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before4.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before5.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before6.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before7.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before8.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before9.java diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index d915d14f4bc3..519151b2189f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -107,6 +107,19 @@ public class GenericsHighlightUtil { } } + PsiDiamondType.DiamondInferenceResult inferenceResult = null; + PsiTypeElement[] referenceElements = null; + if (referenceParameterList != null) { + referenceElements = referenceParameterList.getTypeParameterElements(); + if (referenceElements.length == 1 && referenceElements[0].getType() instanceof PsiDiamondType) { + inferenceResult = ((PsiDiamondType)referenceElements[0].getType()).resolveInferredTypes(); + final String errorMessage = inferenceResult.getErrorMessage(); + if (errorMessage != null) { + return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, referenceElements[0], errorMessage); + } + } + } + final PsiTypeParameter[] typeParameters = typeParameterListOwner.getTypeParameters(); final int targetParametersNum = typeParameters.length; final int refParametersNum = referenceParameterList == null ? 0 : referenceParameterList.getTypeArguments().length; @@ -140,9 +153,8 @@ public class GenericsHighlightUtil { // bounds check if (targetParametersNum > 0 && refParametersNum != 0) { - final PsiTypeElement[] referenceElements = referenceParameterList.getTypeParameterElements(); - if (referenceElements.length == 1 && referenceElements[0].getType() instanceof PsiDiamondType) { - final PsiType[] types = ((PsiDiamondType)referenceElements[0].getType()).getInferredTypes(); + if (inferenceResult != null) { + final PsiType[] types = inferenceResult.getTypes(); for (int i = 0; i < typeParameters.length; i++) { final PsiType type = types[i]; final HighlightInfo highlightInfo = checkTypeParameterWithinItsBound(typeParameters[i], substitutor, type, referenceElements[0]); diff --git a/java/java-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java b/java/java-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java index afd8c91f32b5..57c3d2a43852 100644 --- a/java/java-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java @@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.util.PsiUtil; +import com.intellij.psi.util.TypeConversionUtil; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; @@ -65,15 +66,39 @@ public class ExplicitTypeCanBeDiamondInspection extends BaseJavaLocalInspectionT @Override public void visitNewExpression(PsiNewExpression expression) { if (PsiUtil.getLanguageLevel(expression).isAtLeast(LanguageLevel.JDK_1_7)) { - final PsiJavaCodeReferenceElement classReference = expression.getClassReference(); + final PsiJavaCodeReferenceElement classReference = expression.getClassOrAnonymousClassReference(); if (classReference != null) { final PsiReferenceParameterList parameterList = classReference.getParameterList(); if (parameterList != null) { final PsiTypeElement[] typeElements = parameterList.getTypeParameterElements(); if (typeElements.length > 0) { if (typeElements.length == 1 && typeElements[0].getType() instanceof PsiDiamondType) return; - holder.registerProblem(parameterList, "Redundant type argument #ref #loc", - ProblemHighlightType.LIKE_UNUSED_SYMBOL, new ReplaceWithDiamondFix()); + final PsiDiamondType.DiamondInferenceResult inferenceResult = PsiDiamondType.resolveInferredTypes(expression); + if (inferenceResult.getErrorMessage() == null) { + final PsiType[] types = inferenceResult.getTypes(); + final PsiType[] typeArguments = parameterList.getTypeArguments(); + if (types.length == typeArguments.length) { + for (int i = 0, typeArgumentsLength = typeArguments.length; i < typeArgumentsLength; i++) { + PsiType typeArgument = typeArguments[i]; + if (types[i] instanceof PsiWildcardType) { + final PsiWildcardType wildcardType = (PsiWildcardType)types[i]; + final PsiType bound = wildcardType.getBound(); + if (bound != null) { + if (wildcardType.isExtends()) { + if (bound.isAssignableFrom(typeArgument)) continue; + } else { + if (typeArgument.isAssignableFrom(bound)) continue; + } + } + } + if (!typeArgument.equals(types[i])) { + return; + } + } + } + holder.registerProblem(parameterList, "Redundant type argument #ref #loc", + ProblemHighlightType.LIKE_UNUSED_SYMBOL, new ReplaceWithDiamondFix()); + } } } } diff --git a/java/java-impl/src/com/intellij/psi/impl/PsiImplUtil.java b/java/java-impl/src/com/intellij/psi/impl/PsiImplUtil.java index c2a7fa637c26..aaa1450e159d 100644 --- a/java/java-impl/src/com/intellij/psi/impl/PsiImplUtil.java +++ b/java/java-impl/src/com/intellij/psi/impl/PsiImplUtil.java @@ -233,7 +233,7 @@ public class PsiImplUtil { types[i] = typeElements[i].getType(); } if (types.length == 1 && types[0] instanceof PsiDiamondType) { - return ((PsiDiamondType)types[0]).getInferredTypes(); + return ((PsiDiamondType)types[0]).resolveInferredTypes().getTypes(); } return types; } diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java index fdcdc3a5ceb9..551b95ac8ba4 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java @@ -403,8 +403,8 @@ public class PsiResolveHelperImpl implements PsiResolveHelper { final boolean forCompletion) { PsiTypeParameterListOwner owner = typeParameter.getOwner(); Pair substitution = null; - if (owner instanceof PsiMethod && parent instanceof PsiMethodCallExpression) { - PsiMethodCallExpression methodCall = (PsiMethodCallExpression)parent; + if (owner instanceof PsiMethod && parent instanceof PsiCallExpression) { + PsiCallExpression methodCall = (PsiCallExpression)parent; substitution = inferMethodTypeParameterFromParent(methodCall.getParent(), methodCall, typeParameter, substitutor, forCompletion); } return substitution; @@ -604,7 +604,7 @@ public class PsiResolveHelperImpl implements PsiResolveHelper { } private static Pair inferMethodTypeParameterFromParent(PsiElement parent, - PsiMethodCallExpression methodCall, + PsiCallExpression methodCall, final PsiTypeParameter typeParameter, PsiSubstitutor substitutor, final boolean forCompletion) { @@ -701,13 +701,13 @@ public class PsiResolveHelperImpl implements PsiResolveHelper { return result; } - private static final ThreadLocal> myBlockedForInferenceMethodCalls = new ThreadLocal>() { - protected List initialValue() { - return new ArrayList(2); + private static final ThreadLocal> myBlockedForInferenceMethodCalls = new ThreadLocal>() { + protected List initialValue() { + return new ArrayList(2); } }; - private static Pair inferTypeForCompletionFromCallContext(final PsiMethodCallExpression innerMethodCall, + private static Pair inferTypeForCompletionFromCallContext(final PsiCallExpression innerMethodCall, final PsiExpressionList expressionList, final PsiCallExpression contextCall, final PsiTypeParameter typeParameter) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java index a3c496807427..30b750e35c9f 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java @@ -35,7 +35,7 @@ class P { class Test1 { void bar() { - foo(new FF<>()); + foo(new FF<>()); } void foo(F> p) {} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg1.java index ddf456df1746..220e99fd850a 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg1.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg1.java @@ -8,29 +8,29 @@ class Neg01 { void test() { Neg01<String> n1 = new Neg01<>("" ); //new Foo created - Neg01<? extends String> n2 = new Neg01<>(""); //new Foo created - Neg01 n3 = new Neg01<>(""); //new Foo created + Neg01<? extends String> n2 = new Neg01<>(""); //new Foo created + Neg01 n3 = new Neg01<>(""); //new Foo created Neg01<? super String> n4 = new Neg01<>(""); //new Foo created Neg01<String> n5 = new Neg01<>("") { }; //new Foo created - Neg01<? extends String> n6 = new Neg01<>("") { + Neg01<? extends String> n6 = new Neg01<>("") { }; //new Foo created - Neg01 n7 = new Neg01<>("") { + Neg01 n7 = new Neg01<>("") { }; //new Foo created Neg01<? super String> n8 = new Neg01<>("") { }; //new Foo created Neg01<String> n9 = new Neg01<>("", ""); //new Foo created - Neg01<? extends String> n10 = new Neg01<>("", ""); //new Foo created - Neg01 n11 = new Neg01<>("", ""); //new Foo created + Neg01<? extends String> n10 = new Neg01<>("", ""); //new Foo created + Neg01 n11 = new Neg01<>("", ""); //new Foo created Foo n12 = new Neg01<>("", ""); //new Foo created Neg01<String> n13 = new Neg01<>("", "") { }; //new Foo created - Neg01<? extends String> n14 = new Neg01<>("", "") { + Neg01<? extends String> n14 = new Neg01<>("", "") { }; //new Foo created - Neg01 n15 = new Neg01<>("", "") { + Neg01 n15 = new Neg01<>("", "") { }; //new Foo created Neg01<? super String> n16 = new Neg01<>("", "") { }; //new Foo created diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg10.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg10.java new file mode 100644 index 000000000000..e5efd0968f05 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg10.java @@ -0,0 +1,7 @@ +class Neg10 { + static class Foo { + Foo(X x) {} + } + + Foo fw = new Foo<>(1); +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg11.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg11.java new file mode 100644 index 000000000000..3e32e1a49071 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg11.java @@ -0,0 +1,8 @@ +class Neg11 { + + void test() { + class Foo { } + Foo f1 = new UndeclaredName<>(); //this is deliberate: aim is to test erroneous path + Foo f2 = new UndeclaredName<>() {}; //this is deliberate: aim is to test erroneous path + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg2.java index 635dc5bd9798..9a218866a1ce 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg2.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg2.java @@ -10,29 +10,29 @@ class Neg02 { void testSimple() { Foo<String> f1 = new Foo<>(""); //new Foo created - Foo<? extends String> f2 = new Foo<>(""); //new Foo created - Foo f3 = new Foo<>(""); //new Foo created + Foo<? extends String> f2 = new Foo<>(""); //new Foo created + Foo f3 = new Foo<>(""); //new Foo created Foo<? super String> f4 = new Foo<>(""); //new Foo created Foo<String> f5 = new Foo<>("") { }; //new Foo created - Foo<? extends String> f6 = new Foo<>("") { + Foo<? extends String> f6 = new Foo<>("") { }; //new Foo created - Foo f7 = new Foo< >("") { + Foo f7 = new Foo< >("") { }; //new Foo created Foo<? super String> f8 = new Foo<>("") { }; //new Foo created Foo<String> f9 = new Foo<>("", ""); //new Foo created - Foo<? extends String> f10 = new Foo<>("", ""); //new Foo created - Foo f11 = new Foo< >("", ""); //new Foo created + Foo<? extends String> f10 = new Foo<>("", ""); //new Foo created + Foo f11 = new Foo< >("", ""); //new Foo created Foo<? super String> f12 = new Foo<>("", ""); //new Foo created Foo<String> f13 = new Foo<>("", "") { }; //new Foo created - Foo<? extends String> f14 = new Foo<>("", "") { + Foo<? extends String> f14 = new Foo<>("", "") { }; //new Foo created - Foo f15 = new Foo< >("", "") { + Foo f15 = new Foo< >("", "") { }; //new Foo created Foo<? super String> f16 = new Foo<>("", "") { }; //new Foo created @@ -40,29 +40,29 @@ class Neg02 { void testQualified() { Foo<String> f1 = new Neg02.Foo<>(""); //new Foo created - Foo<? extends String> f2 = new Neg02.Foo<>(""); //new Foo created - Foo f3 = new Neg02.Foo< >(""); //new Foo created + Foo<? extends String> f2 = new Neg02.Foo<>(""); //new Foo created + Foo f3 = new Neg02.Foo< >(""); //new Foo created Foo<? super String> f4 = new Neg02.Foo<>(""); //new Foo created Foo<String> f5 = new Neg02.Foo<>("") { }; //new Foo created - Foo<? extends String> f6 = new Neg02.Foo<>("") { + Foo<? extends String> f6 = new Neg02.Foo<>("") { }; //new Foo created - Foo f7 = new Neg02.Foo< >("") { + Foo f7 = new Neg02.Foo< >("") { }; //new Foo created Foo<? super String> f8 = new Neg02.Foo<>("") { }; //new Foo created Foo<String> f9 = new Neg02.Foo<>("", ""); //new Foo created - Foo<? extends String> f10 = new Neg02.Foo<>("", ""); //new Foo created - Foo f11 = new Neg02.Foo< >("", ""); //new Foo created + Foo<? extends String> f10 = new Neg02.Foo<>("", ""); //new Foo created + Foo f11 = new Neg02.Foo< >("", ""); //new Foo created Foo<? super String> f12 = new Neg02.Foo<>("", ""); //new Foo created Foo<String> f13 = new Neg02.Foo<>("", "") { }; //new Foo created - Foo<? extends String> f14 = new Neg02.Foo<>("", "") { + Foo<? extends String> f14 = new Neg02.Foo<>("", "") { }; //new Foo created - Foo f15 = new Neg02.Foo< >("", "") { + Foo f15 = new Neg02.Foo< >("", "") { }; //new Foo created Foo<? super String> f16 = new Neg02.Foo<>("", "") { }; //new Foo created diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg3.java index 8d770ab57870..6b2a82b9227d 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg3.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg3.java @@ -7,67 +7,67 @@ class Neg03 { void testSimple() { Foo<String> f1 = new Foo<>(""); //new Foo created - Foo<? extends String> f2 = new Foo<>(""); //new Foo created - Foo f3 = new Foo<>(""); //new Foo created + Foo<? extends String> f2 = new Foo<>(""); //new Foo created + Foo f3 = new Foo<>(""); //new Foo created Foo<? super String> f4 = new Foo<>(""); //new Foo created Foo<String> f5 = new Foo<>(""){}; //new Foo created - Foo<? extends String> f6 = new Foo<>(""){}; //new Foo created - Foo f7 = new Foo<>(""){}; //new Foo created + Foo<? extends String> f6 = new Foo<>(""){}; //new Foo created + Foo f7 = new Foo<>(""){}; //new Foo created Foo<? super String> f8 = new Foo<>(""){}; //new Foo created Foo<String> f9 = new Foo<>("", ""); //new Foo created - Foo<? extends String> f10 = new Foo<>("", ""); //new Foo created - Foo f11 = new Foo<>("", ""); //new Foo created + Foo<? extends String> f10 = new Foo<>("", ""); //new Foo created + Foo f11 = new Foo<>("", ""); //new Foo created Foo<? super String> f12 = new Foo<>("", ""); //new Foo created Foo<String> f13 = new Foo<>("", ""){}; //new Foo created - Foo<? extends String> f14 = new Foo<>("", ""){}; //new Foo created - Foo f15 = new Foo<>("", ""){}; //new Foo created + Foo<? extends String> f14 = new Foo<>("", ""){}; //new Foo created + Foo f15 = new Foo<>("", ""){}; //new Foo created Foo<? super String> f16 = new Foo<>("", ""){}; //new Foo created } void testQualified_1() { Foo<String> f1 = new Neg03.Foo<>(""); //new Foo created - Foo<? extends String> f2 = new Neg03.Foo<>(""); //new Foo created - Foo f3 = new Neg03.Foo<>(""); //new Foo created + Foo<? extends String> f2 = new Neg03.Foo<>(""); //new Foo created + Foo f3 = new Neg03.Foo<>(""); //new Foo created Foo<? super String> f4 = new Neg03.Foo<>(""); //new Foo created Foo<String> f5 = new Neg03.Foo<>(""){}; //new Foo created - Foo<? extends String> f6 = new Neg03.Foo<>(""){}; //new Foo created - Foo f7 = new Neg03.Foo<>(""){}; //new Foo created + Foo<? extends String> f6 = new Neg03.Foo<>(""){}; //new Foo created + Foo f7 = new Neg03.Foo<>(""){}; //new Foo created Foo<? super String> f8 = new Neg03.Foo<>(""){}; //new Foo created Foo<String> f9 = new Neg03.Foo<>("", ""); //new Foo created - Foo<? extends String> f10 = new Neg03.Foo<>("", ""); //new Foo created - Foo f11 = new Neg03.Foo<>("", ""); //new Foo created + Foo<? extends String> f10 = new Neg03.Foo<>("", ""); //new Foo created + Foo f11 = new Neg03.Foo<>("", ""); //new Foo created Foo<? super String> f12 = new Neg03.Foo<>("", ""); //new Foo created Foo<String> f13 = new Neg03.Foo<>("", ""){}; //new Foo created - Foo<? extends String> f14 = new Neg03.Foo<>("", ""){}; //new Foo created - Foo f15 = new Neg03.Foo<>("", ""){}; //new Foo created + Foo<? extends String> f14 = new Neg03.Foo<>("", ""){}; //new Foo created + Foo f15 = new Neg03.Foo<>("", ""){}; //new Foo created Foo<? super String> f16 = new Neg03.Foo<>("", ""){}; //new Foo created } void testQualified_2(Neg03 n) { Foo<String> f1 = n.new Foo<>(""); //new Foo created - Foo<? extends String> f2 = n.new Foo<>(""); //new Foo created - Foo f3 = n.new Foo<>(""); //new Foo created + Foo<? extends String> f2 = n.new Foo<>(""); //new Foo created + Foo f3 = n.new Foo<>(""); //new Foo created Foo<? super String> f4 = n.new Foo<>(""); //new Foo created Foo<String> f5 = n.new Foo<>(""){}; //new Foo created - Foo<? extends String> f6 = n.new Foo<>(""){}; //new Foo created - Foo f7 = n.new Foo<>(""){}; //new Foo created + Foo<? extends String> f6 = n.new Foo<>(""){}; //new Foo created + Foo f7 = n.new Foo<>(""){}; //new Foo created Foo<? super String> f8 = n.new Foo<>(""){}; //new Foo created Foo<String> f9 = n.new Foo<>("", ""); //new Foo created - Foo<? extends String> f10 = n.new Foo<>("", ""); //new Foo created - Foo f11 = n.new Foo<>("", ""); //new Foo created + Foo<? extends String> f10 = n.new Foo<>("", ""); //new Foo created + Foo f11 = n.new Foo<>("", ""); //new Foo created Foo<? super String> f12 = n.new Foo<>("", ""); //new Foo created Foo<String> f13 = n.new Foo<>("", ""){}; //new Foo created - Foo<? extends String> f14 = n.new Foo<>("", ""){}; //new Foo created - Foo f15 = n.new Foo<>("", ""){}; //new Foo created + Foo<? extends String> f14 = n.new Foo<>("", ""){}; //new Foo created + Foo f15 = n.new Foo<>("", ""){}; //new Foo created Foo<? super String> f16 = n.new Foo<>("", ""){}; //new Foo created } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg4.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg4.java index 30b124f56668..204dd9fcc155 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg4.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg4.java @@ -6,23 +6,23 @@ class Neg04 { Foo(V x, Z z) {} } Foo<String> n1 = new Foo<>(""); //new Foo created - Foo<? extends String> n2 = new Foo<>(""); //new Foo created - Foo n3 = new Foo<>(""); //new Foo created + Foo<? extends String> n2 = new Foo<>(""); //new Foo created + Foo n3 = new Foo<>(""); //new Foo created Foo<? super String> n4 = new Foo<>(""); //new Foo created Foo<String> n5 = new Foo<>(""){}; //new Foo created - Foo<? extends String> n6 = new Foo<>(""){}; //new Foo created - Foo n7 = new Foo<>(""){}; //new Foo created + Foo<? extends String> n6 = new Foo<>(""){}; //new Foo created + Foo n7 = new Foo<>(""){}; //new Foo created Foo<? super String> n8 = new Foo<>(""){}; //new Foo created Foo<String> n9 = new Foo<>("", ""); //new Foo created - Foo<? extends String> n10 = new Foo<>("", ""); //new Foo created - Foo n11 = new Foo<>("", ""); //new Foo created + Foo<? extends String> n10 = new Foo<>("", ""); //new Foo created + Foo n11 = new Foo<>("", ""); //new Foo created Foo<? super String> n12 = new Foo<>("", ""); //new Foo created Foo<String> n13 = new Foo<>("", ""){}; //new Foo created - Foo<? extends String> n14 = new Foo<>("", ""){}; //new Foo created - Foo n15 = new Foo<>("", ""){}; //new Foo created + Foo<? extends String> n14 = new Foo<>("", ""){}; //new Foo created + Foo n15 = new Foo<>("", ""){}; //new Foo created Foo<? super String> n16 = new Foo<>("", ""){}; //new Foo created } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg6.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg6.java new file mode 100644 index 000000000000..585761fb8216 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg6.java @@ -0,0 +1,11 @@ +class Neg06 { + interface ISuperFoo {} + interface IFoo extends ISuperFoo {} + + static class CSuperFoo {} + static class CFoo extends CSuperFoo {} + + ISuperFoo isf = new IFoo<>() {}; + CSuperFoo csf1 = new CFoo<>(); + CSuperFoo csf2 = new CFoo<>() {}; +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg7.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg7.java new file mode 100644 index 000000000000..5bdbff54f378 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg7.java @@ -0,0 +1,9 @@ +class Neg07 { + static class SuperFoo {} + static class Foo extends SuperFoo { + Foo(X x) {} + } + + SuperFoo sf1 = new Foo<>(""); + SuperFoo sf2 = new Foo<>("") {}; +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg8.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg8.java new file mode 100644 index 000000000000..060efa6ebe7b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg8.java @@ -0,0 +1,20 @@ +class Neg08 { + static class Foo { + Foo(X x) { } + } + + static class DoubleFoo { + DoubleFoo(X x,Y y) { } + } + + static class TripleFoo { + TripleFoo(X x,Y y,Z z) { } + } + + Foo fi = new Foo<>(1); + Foo fw = new Foo<>(fi); + Foo fd = new Foo<>(3.0); + DoubleFoo dw = new DoubleFoo<>(fi,fd); + Foo fs = new Foo<>("one"); + TripleFoo tw = new TripleFoo<>(fi,fd,fs); +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg9.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg9.java new file mode 100644 index 000000000000..5bca169e0f2d --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondNeg9.java @@ -0,0 +1,12 @@ +class Neg09 { + static class Foo> {} + static class DoubleFoo, + Y extends Number & Comparable> {} + static class TripleFoo, + Y extends Number & Comparable, + Z> {} + + Foo fw = new Foo<>(); + DoubleFoo dw = new DoubleFoo<>(); + TripleFoo tw = new TripleFoo<>(); +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondPos5.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondPos5.java new file mode 100644 index 000000000000..1f60451ae16d --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondPos5.java @@ -0,0 +1,12 @@ +public class Pos05 { + + static class Foo { + Foo(X x) {} + } + + void m(Foo fi) {} + + void test() { + m(new Foo<>(1)); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after2.java deleted file mode 100644 index 0a5023e89f44..000000000000 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after2.java +++ /dev/null @@ -1,7 +0,0 @@ -// "Replace with <>" "true" -public class Test { - F> f = new FF<>(); -} - -class FF extends F{} -class F {} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after3.java deleted file mode 100644 index 2e9b69d52d2e..000000000000 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after3.java +++ /dev/null @@ -1,11 +0,0 @@ -// "Replace with <>" "true" -public class Test { - void bar() { - foo(new FF<>()); - } - - void foo(F> p) {} -} - -class FF extends F{} -class F {} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after5.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after5.java new file mode 100644 index 000000000000..dcc744c23ae5 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after5.java @@ -0,0 +1,16 @@ +// "Replace with <>" "true" +class Test { + + void test() { + class Foo { + Foo() {} + Foo(X x) {} + } + Foo f1 = new Foo(1); + Foo f2 = new Foo<>(); + Foo f3 = new Foo(); + Foo f4 = new Foo(1) {}; + Foo f5 = new Foo() {}; + Foo f6 = new Foo() {}; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after6.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after6.java new file mode 100644 index 000000000000..3f9bf24dbb06 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after6.java @@ -0,0 +1,16 @@ +// "Replace with <>" "true" +class Test { + + void test() { + class Foo { + Foo() {} + Foo(X x) {} + } + Foo f1 = new Foo(1); + Foo f2 = new Foo(); + Foo f3 = new Foo<>(); + Foo f4 = new Foo(1) {}; + Foo f5 = new Foo() {}; + Foo f6 = new Foo() {}; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after8.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after8.java new file mode 100644 index 000000000000..06cc7b7973bb --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after8.java @@ -0,0 +1,16 @@ +// "Replace with <>" "true" +class Test { + + void test() { + class Foo { + Foo() {} + Foo(X x) {} + } + Foo f1 = new Foo(1); + Foo f2 = new Foo(); + Foo f3 = new Foo(); + Foo f4 = new Foo(1) {}; + Foo f5 = new Foo<>() {}; + Foo f6 = new Foo() {}; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after9.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after9.java new file mode 100644 index 000000000000..550518376f67 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/after9.java @@ -0,0 +1,16 @@ +// "Replace with <>" "true" +class Test { + + void test() { + class Foo { + Foo() {} + Foo(X x) {} + } + Foo f1 = new Foo(1); + Foo f2 = new Foo(); + Foo f3 = new Foo(); + Foo f4 = new Foo(1) {}; + Foo f5 = new Foo() {}; + Foo f6 = new Foo<>() {}; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before2.java index 79e9cbcaad8e..eb4a2cf0e6e5 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before2.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before2.java @@ -1,4 +1,4 @@ -// "Replace with <>" "true" +// "Replace with <>" "false" public class Test { F> f = new FFing>(); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before3.java index d6d74cdc0908..8a08536a3ef5 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before3.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before3.java @@ -1,4 +1,4 @@ -// "Replace with <>" "true" +// "Replace with <>" "false" public class Test { void bar() { foo(new FFing>()); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before4.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before4.java new file mode 100644 index 000000000000..35cf27363787 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before4.java @@ -0,0 +1,16 @@ +// "Replace with <>" "false" +class Test { + + void test() { + class Foo { + Foo() {} + Foo(X x) {} + } + Foo f1 = new Foomber>(1); + Foo f2 = new Foo(); + Foo f3 = new Foo(); + Foo f4 = new Foo(1) {}; + Foo f5 = new Foo() {}; + Foo f6 = new Foo() {}; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before5.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before5.java new file mode 100644 index 000000000000..6f8c5068e0e0 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before5.java @@ -0,0 +1,16 @@ +// "Replace with <>" "true" +class Test { + + void test() { + class Foo { + Foo() {} + Foo(X x) {} + } + Foo f1 = new Foo(1); + Foo f2 = new Foober>(); + Foo f3 = new Foo(); + Foo f4 = new Foo(1) {}; + Foo f5 = new Foo() {}; + Foo f6 = new Foo() {}; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before6.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before6.java new file mode 100644 index 000000000000..48666f4d3c4a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before6.java @@ -0,0 +1,16 @@ +// "Replace with <>" "true" +class Test { + + void test() { + class Foo { + Foo() {} + Foo(X x) {} + } + Foo f1 = new Foo(1); + Foo f2 = new Foo(); + Foo f3 = new Fooger>(); + Foo f4 = new Foo(1) {}; + Foo f5 = new Foo() {}; + Foo f6 = new Foo() {}; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before7.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before7.java new file mode 100644 index 000000000000..1a0c0d45f200 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before7.java @@ -0,0 +1,16 @@ +// "Replace with <>" "false" +class Test { + + void test() { + class Foo { + Foo() {} + Foo(X x) {} + } + Foo f1 = new Foo(1); + Foo f2 = new Foo(); + Foo f3 = new Foo(); + Foo f4 = new Foomber>(1) {}; + Foo f5 = new Foo() {}; + Foo f6 = new Foo() {}; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before8.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before8.java new file mode 100644 index 000000000000..0ce27b5983a4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before8.java @@ -0,0 +1,16 @@ +// "Replace with <>" "true" +class Test { + + void test() { + class Foo { + Foo() {} + Foo(X x) {} + } + Foo f1 = new Foo(1); + Foo f2 = new Foo(); + Foo f3 = new Foo(); + Foo f4 = new Foo(1) {}; + Foo f5 = new Fooer>() {}; + Foo f6 = new Foo() {}; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before9.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before9.java new file mode 100644 index 000000000000..cd3b71989f5c --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/before9.java @@ -0,0 +1,16 @@ +// "Replace with <>" "true" +class Test { + + void test() { + class Foo { + Foo() {} + Foo(X x) {} + } + Foo f1 = new Foo(1); + Foo f2 = new Foo(); + Foo f3 = new Foo(); + Foo f4 = new Foo(1) {}; + Foo f5 = new Foo() {}; + Foo f6 = new Footeger>() {}; + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java index 6b64c70d82de..beba5cc637db 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java @@ -58,6 +58,10 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase { doTest(false, false); } + public void testDiamondPos5() throws Exception { + doTest(false, false); + } + public void testDiamondNeg1() throws Exception { doTest(false, false); } @@ -78,6 +82,32 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase { doTest(false, false); } + public void testDiamondNeg6() throws Exception { + doTest(false, false); + } + + public void testDiamondNeg7() throws Exception { + doTest(false, false); + } + + public void testDiamondNeg8() throws Exception { + doTest(false, false); + } + + public void testDiamondNeg9() throws Exception { + doTest(false, false); + } + + public void testDiamondNeg10() throws Exception { + doTest(false, false); + } + + public void testDiamondNeg11() throws Exception { + doTest(false, false); + } + + + public void testDiamondMisc() throws Exception { doTest(false, false); } diff --git a/java/openapi/src/com/intellij/psi/PsiDiamondType.java b/java/openapi/src/com/intellij/psi/PsiDiamondType.java index 926fbd99ef6b..96e6ed80cbe4 100644 --- a/java/openapi/src/com/intellij/psi/PsiDiamondType.java +++ b/java/openapi/src/com/intellij/psi/PsiDiamondType.java @@ -16,15 +16,19 @@ package com.intellij.psi; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.PsiUtil; -import com.intellij.psi.util.TypeConversionUtil; -import com.intellij.util.ArrayUtil; +import com.intellij.util.Function; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.*; + /** * User: anna * Date: Jul 30, 2010 @@ -82,152 +86,216 @@ public class PsiDiamondType extends PsiType { return new PsiType[]{getJavaLangObject(myManager, getResolveScope())}; } - public PsiType[] getInferredTypes() { - final PsiDeclarationStatement declarationStatement = PsiTreeUtil.getParentOfType(myTypeElement, PsiDeclarationStatement.class); - if (declarationStatement != null) { - final PsiElement[] declaredElements = declarationStatement.getDeclaredElements(); - if (declaredElements.length > 0 && declaredElements[0] instanceof PsiVariable) { - return getComponentTypes((PsiVariable)declaredElements[0]); - } + public DiamondInferenceResult resolveInferredTypes() { + final PsiNewExpression newExpression = PsiTreeUtil.getParentOfType(myTypeElement, PsiNewExpression.class); + if (newExpression == null) { + return PsiDiamondType.DiamondInferenceResult.NULL_RESULT; } - final PsiAssignmentExpression assignmentExpression = PsiTreeUtil.getParentOfType(myTypeElement, PsiAssignmentExpression.class); - if (assignmentExpression != null) { - final PsiExpression lExpression = assignmentExpression.getLExpression(); - if (lExpression instanceof PsiReferenceExpression) { - final PsiElement resolved = ((PsiReferenceExpression)lExpression).resolve(); - if (resolved instanceof PsiVariable) { - return getComponentTypes(((PsiVariable)resolved)); - } - } - } - - PsiExpression psiExpression = PsiTreeUtil.getParentOfType(myTypeElement, PsiExpression.class); - while (psiExpression != null) { - final PsiElement parent = psiExpression.getParent(); - if (parent instanceof PsiExpression) { - psiExpression = (PsiExpression)parent; - continue; - } - break; - } - if (psiExpression != null) { - final PsiElement parent = psiExpression.getParent(); - if (parent instanceof PsiExpressionList) { - final PsiElement parentParent = parent.getParent(); - if (parentParent instanceof PsiCallExpression) { - final JavaResolveResult resolveResult = ((PsiCallExpression)parentParent).resolveMethodGenerics(); - final PsiSubstitutor substitutor = resolveResult.getSubstitutor(); - final PsiElement element = resolveResult.getElement(); - if (element instanceof PsiMethod) { - final int paramIdx = ArrayUtil.find(((PsiExpressionList)parent).getExpressions(), psiExpression); - if (paramIdx > -1) { - final PsiParameter parameter = - ((PsiMethod)element).getParameterList().getParameters()[paramIdx]; - return getComponentTypes(substitutor.substitute(parameter.getType())); - } - } - } - } else if (parent instanceof PsiVariable) { - return getComponentTypes((PsiVariable)parent); - } else if (parent instanceof PsiReturnStatement) { - final PsiMethod containingMethod = PsiTreeUtil.getParentOfType(parent, PsiMethod.class); - if (containingMethod != null) { - final PsiType returnType = containingMethod.getReturnType(); - if (returnType != null) { - final PsiExpression returnValue = ((PsiReturnStatement)parent).getReturnValue(); - if (returnValue instanceof PsiNewExpression) { - return getComponentTypes(returnType, returnValue); - } - return getComponentTypes(returnType); - } - } - } - } - return NULL_TYPES; + return resolveInferredTypes(newExpression); } - private static PsiType[] getComponentTypes(PsiVariable declaredElement) { - final PsiType lType = declaredElement.getType(); - final PsiExpression initializer = declaredElement.getInitializer(); - return getComponentTypes(lType, initializer); - } - - private static PsiType[] getComponentTypes(PsiType lType, PsiExpression initializer) { - if (initializer instanceof PsiNewExpression) { - final PsiNewExpression newExpression = (PsiNewExpression)initializer; - final PsiJavaCodeReferenceElement classReference = newExpression.getClassOrAnonymousClassReference(); - if (classReference != null) { - final String text = classReference.getReferenceName(); - if (text != null) { - final PsiClass psiClass = - JavaPsiFacade.getInstance(initializer.getProject()).getResolveHelper().resolveReferencedClass(text, initializer); - final PsiType substitute = substitute(psiClass, lType); - if (substitute != null) { - lType = substitute; - } + public static DiamondInferenceResult resolveInferredTypes(PsiNewExpression newExpression) { + final PsiClass psiClass = findClass(newExpression); + if (psiClass == null) return DiamondInferenceResult.NULL_RESULT; + final PsiMethod constructor = findConstructor(psiClass, newExpression); + PsiTypeParameter[] params = getAllTypeParams(constructor, psiClass); + PsiMethod staticFactory = generateStaticFactory(constructor, psiClass, params); + if (staticFactory == null) { + return DiamondInferenceResult.NULL_RESULT; + } + final PsiSubstitutor inferredSubstitutor = inferTypeParametersForStaticFactory(staticFactory, newExpression); + final PsiTypeParameter[] parameters = staticFactory.getTypeParameters(); + final PsiTypeParameter[] classParameters = psiClass.getTypeParameters(); + final PsiJavaCodeReferenceElement classOrAnonymousClassReference = newExpression.getClassOrAnonymousClassReference(); + LOG.assertTrue(classOrAnonymousClassReference != null); + final DiamondInferenceResult result = new DiamondInferenceResult(classOrAnonymousClassReference.getReferenceName() + "<>"); + for (PsiTypeParameter parameter : parameters) { + for (PsiTypeParameter classParameter : classParameters) { + if (Comparing.strEqual(classParameter.getName(), parameter.getName())) { + result.addInferredType(inferredSubstitutor.substitute(parameter)); + break; } } } - return getComponentTypes(lType); + return result; + } + + + @Nullable + private static PsiMethod findConstructor(PsiClass containingClass, PsiNewExpression newExpression) { + final PsiExpressionList argumentList = newExpression.getArgumentList(); + if (argumentList == null) return null; + final Project project = newExpression.getProject(); + final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); + final PsiResolveHelper resolveHelper = facade.getResolveHelper(); + final JavaResolveResult result = + resolveHelper.resolveConstructor(facade.getElementFactory().createType(containingClass), argumentList, argumentList); + return (PsiMethod)result.getElement(); } @Nullable - private static PsiType substitute(PsiClass inheritor, PsiType baseType) { - if (inheritor == null) return null; - final JavaPsiFacade facade = JavaPsiFacade.getInstance(inheritor.getProject()); - final PsiResolveHelper resolveHelper = facade.getResolveHelper(); - final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(baseType); - final PsiClass baseClass = resolveResult.getElement(); - if (baseClass == null) return null; - - PsiSubstitutor superSubstitutor = TypeConversionUtil.getClassSubstitutor(baseClass, inheritor, PsiSubstitutor.EMPTY); - if (superSubstitutor == null) return null; - - final PsiSubstitutor baseSubstitutor = resolveResult.getSubstitutor(); - - PsiSubstitutor inheritorSubstitutor = PsiSubstitutor.EMPTY; - for (PsiTypeParameter inheritorParameter : PsiUtil.typeParametersIterable(inheritor)) { - for (PsiTypeParameter baseParameter : PsiUtil.typeParametersIterable(baseClass)) { - final PsiType substituted = superSubstitutor.substitute(baseParameter); - PsiType arg = baseSubstitutor.substitute(baseParameter); - if (arg instanceof PsiWildcardType) arg = ((PsiWildcardType)arg).getExtendsBound(); - PsiType substitution = resolveHelper.getSubstitutionForTypeParameter(inheritorParameter, - substituted, - arg, - true, - PsiUtil.getLanguageLevel(inheritor)); - if (PsiType.NULL.equals(substitution) || substitution instanceof PsiWildcardType) continue; - if (substitution == null) { - continue; - } - inheritorSubstitutor = inheritorSubstitutor.put(inheritorParameter, substitution); - break; + private static PsiClass findClass(PsiNewExpression newExpression) { + final PsiJavaCodeReferenceElement classReference = newExpression.getClassOrAnonymousClassReference(); + if (classReference != null) { + final String text = classReference.getReferenceName(); + if (text != null) { + final Project project = newExpression.getProject(); + final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); + final PsiResolveHelper resolveHelper = facade.getResolveHelper(); + return resolveHelper.resolveReferencedClass(text, newExpression); + } else { + return null; } } - - PsiType toAdd = facade.getElementFactory().createType(inheritor, inheritorSubstitutor); - if (baseType.isAssignableFrom(toAdd)) { - return toAdd; - } - return null; } - private static PsiType[] getComponentTypes(PsiType type) { - if (type instanceof PsiClassType) { - final PsiType[] types = ((PsiClassType)type).getParameters(); - for (int i = 0; i < types.length; i++) { - PsiType currentType = types[i]; - if (currentType instanceof PsiWildcardType) { - final PsiType bound = ((PsiWildcardType)currentType).getBound(); - if (bound != null) { - types[i] = bound; - } - } + @Nullable + private static PsiMethod generateStaticFactory(@Nullable PsiMethod constructor, PsiClass containingClass, PsiTypeParameter[] params) { + final StringBuilder buf = new StringBuilder(); + buf.append("public static "); + buf.append("<"); + buf.append(StringUtil.join(params, new Function() { + @Override + public String fun(PsiTypeParameter psiTypeParameter) { + return psiTypeParameter.getName(); } - return types; + }, ", ")); + buf.append(">"); + + final String qualifiedName = containingClass.getQualifiedName(); + buf.append(qualifiedName != null ? qualifiedName : containingClass.getName()); + final PsiTypeParameter[] parameters = containingClass.getTypeParameters(); + buf.append("<"); + buf.append(StringUtil.join(parameters, new Function() { + @Override + public String fun(PsiTypeParameter psiTypeParameter) { + return psiTypeParameter.getName(); + } + }, ", ")); + buf.append("> "); + + String staticFactoryName = "staticFactory"; + final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(containingClass.getProject()); + staticFactoryName = styleManager.suggestUniqueVariableName(staticFactoryName, containingClass, false); + buf.append(staticFactoryName); + if (constructor == null) { + buf.append("()"); + } + else { + buf.append("(").append(StringUtil.join(constructor.getParameterList().getParameters(), new Function() { + @Override + public String fun(PsiParameter psiParameter) { + return psiParameter.getType().getCanonicalText() + " " + psiParameter.getName(); + } + }, ",")).append(")"); + } + buf.append("{}"); + + return JavaPsiFacade.getElementFactory(containingClass.getProject()).createMethodFromText(buf.toString(), constructor != null ? constructor : containingClass); + } + + private static PsiTypeParameter[] getAllTypeParams(PsiTypeParameterListOwner listOwner, PsiClass containingClass) { + Set params = new LinkedHashSet(); + if (listOwner != null) { + Collections.addAll(params, listOwner.getTypeParameters()); + } + Collections.addAll(params, containingClass.getTypeParameters()); + return params.toArray(new PsiTypeParameter[params.size()]); + } + + + private static PsiSubstitutor inferTypeParametersForStaticFactory(@NotNull PsiMethod staticFactoryMethod, + PsiNewExpression expression) { + final JavaPsiFacade facade = JavaPsiFacade.getInstance(staticFactoryMethod.getProject()); + final PsiResolveHelper resolveHelper = facade.getResolveHelper(); + final PsiParameter[] parameters = staticFactoryMethod.getParameterList().getParameters(); + final PsiExpression[] expressions = expression.getArgumentList().getExpressions(); + return resolveHelper + .inferTypeArguments(staticFactoryMethod.getTypeParameters(), parameters, expressions, PsiSubstitutor.EMPTY, expression, false); + } + + public static class DiamondInferenceResult { + public static final DiamondInferenceResult NULL_RESULT = new DiamondInferenceResult() { + @Override + public PsiType[] getTypes() { + return NULL_TYPES; + } + + @Override + public String getErrorMessage() { + return "Cannot infer arguments"; + } + }; + + private List myInferredTypes = new ArrayList(); + private String myErrorMessage; + + private String myNewExpressionPresentableText; + + public DiamondInferenceResult() { + } + + public DiamondInferenceResult(String expressionPresentableText) { + myNewExpressionPresentableText = expressionPresentableText; + } + + public PsiType[] getTypes() { + if (myErrorMessage != null) { + return NULL_TYPES; + } + return myInferredTypes.toArray(new PsiType[myInferredTypes.size()]); + } + + public String getErrorMessage() { + return myErrorMessage; + } + + public void addInferredType(PsiType psiType) { + if (myErrorMessage != null) return; + if (psiType == null) { + myErrorMessage = "Cannot infer type arguments for " + myNewExpressionPresentableText; + } else if (!isValid(psiType)) { + myErrorMessage = "Cannot infer type arguments for " + + myNewExpressionPresentableText + " because type " + psiType.getPresentableText() + " inferred is not allowed in current context"; + } else { + myInferredTypes.add(psiType); + } + } + + private static Boolean isValid(PsiType type) { + return type.accept(new PsiTypeVisitor() { + @Override + public Boolean visitType(PsiType type) { + return !(type instanceof PsiIntersectionType); + } + + @Override + public Boolean visitCapturedWildcardType(PsiCapturedWildcardType capturedWildcardType) { + return false; + } + + @Override + public Boolean visitWildcardType(PsiWildcardType wildcardType) { + final PsiType bound = wildcardType.getBound(); + if (bound != null) { + if (bound instanceof PsiIntersectionType) return false; + return bound.accept(this); + } + return true; + } + + @Override + public Boolean visitClassType(PsiClassType classType) { + for (PsiType psiType : classType.getParameters()) { + if (!psiType.accept(this)) { + return false; + } + } + return true; + } + }); } - return NULL_TYPES; } } From 0e8d8869475791810e9892c6a711edcb09f5f857 Mon Sep 17 00:00:00 2001 From: anna Date: Sat, 19 Feb 2011 15:34:39 +0100 Subject: [PATCH 007/169] NPE (cannot infer without argument list) --- java/openapi/src/com/intellij/psi/PsiDiamondType.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/java/openapi/src/com/intellij/psi/PsiDiamondType.java b/java/openapi/src/com/intellij/psi/PsiDiamondType.java index 96e6ed80cbe4..084e408129e0 100644 --- a/java/openapi/src/com/intellij/psi/PsiDiamondType.java +++ b/java/openapi/src/com/intellij/psi/PsiDiamondType.java @@ -98,6 +98,8 @@ public class PsiDiamondType extends PsiType { public static DiamondInferenceResult resolveInferredTypes(PsiNewExpression newExpression) { final PsiClass psiClass = findClass(newExpression); if (psiClass == null) return DiamondInferenceResult.NULL_RESULT; + final PsiExpressionList argumentList = newExpression.getArgumentList(); + if (argumentList == null) return DiamondInferenceResult.NULL_RESULT; final PsiMethod constructor = findConstructor(psiClass, newExpression); PsiTypeParameter[] params = getAllTypeParams(constructor, psiClass); PsiMethod staticFactory = generateStaticFactory(constructor, psiClass, params); @@ -125,7 +127,6 @@ public class PsiDiamondType extends PsiType { @Nullable private static PsiMethod findConstructor(PsiClass containingClass, PsiNewExpression newExpression) { final PsiExpressionList argumentList = newExpression.getArgumentList(); - if (argumentList == null) return null; final Project project = newExpression.getProject(); final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); final PsiResolveHelper resolveHelper = facade.getResolveHelper(); @@ -211,7 +212,8 @@ public class PsiDiamondType extends PsiType { final JavaPsiFacade facade = JavaPsiFacade.getInstance(staticFactoryMethod.getProject()); final PsiResolveHelper resolveHelper = facade.getResolveHelper(); final PsiParameter[] parameters = staticFactoryMethod.getParameterList().getParameters(); - final PsiExpression[] expressions = expression.getArgumentList().getExpressions(); + final PsiExpressionList argumentList = expression.getArgumentList(); + final PsiExpression[] expressions = argumentList.getExpressions(); return resolveHelper .inferTypeArguments(staticFactoryMethod.getTypeParameters(), parameters, expressions, PsiSubstitutor.EMPTY, expression, false); } From 1901ac53269af7f81f1ac8e30bfdd139d0de74cb Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Mon, 21 Feb 2011 12:17:00 +0300 Subject: [PATCH 008/169] fix test --- .../actions/generate/constructors/GroovyGenerationInfo.java | 2 +- .../jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/constructors/GroovyGenerationInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/constructors/GroovyGenerationInfo.java index 87929cbb6865..6e36d660ffe5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/constructors/GroovyGenerationInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/constructors/GroovyGenerationInfo.java @@ -61,7 +61,7 @@ public class GroovyGenerationInfo extends PsiGenerationInfo } final IElementType type = element.getNode().getElementType(); - if (GroovyTokenTypes.WHITE_SPACES_SET.contains(type)) { + if (type == GroovyTokenTypes.mNLS || type == GroovyTokenTypes.mWS) { return element.getNextSibling(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java index 1e2ae47a3710..ae581d9070f4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java @@ -520,9 +520,8 @@ public class ResolveUtil { return resolveResult != null && isInUseScope(resolveResult.getCurrentFileResolveContext()); } - public static boolean isInUseScope(PsiElement context) { - if (!context.isValid()) return false; - if (context instanceof GrMethodCall) { + public static boolean isInUseScope(@Nullable PsiElement context) { + if (context instanceof GrMethodCall && context.isValid()) { final GrExpression expression = ((GrMethodCall)context).getInvokedExpression(); if (expression instanceof GrReferenceExpression) { final PsiElement resolved = ((GrReferenceExpression)expression).resolve(); From 6da30b8e533f51f61b93a4e44ee3a8e2cda27576 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Mon, 21 Feb 2011 12:46:56 +0300 Subject: [PATCH 009/169] IDEA-65686 Rectangular selection contracts width incorrectly Allow caret to be located after the end of line when block selection is present --- .../src/com/intellij/openapi/editor/impl/CaretModelImpl.java | 2 +- .../src/com/intellij/openapi/editor/impl/EditorImpl.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java index c8a218c3a956..91d6c9fb3ab1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java @@ -365,7 +365,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, EditorSettings editorSettings = myEditor.getSettings(); - if (!editorSettings.isVirtualSpace() && line < lineCount) { + if (!editorSettings.isVirtualSpace() && line < lineCount && !myEditor.getSelectionModel().hasBlockSelection()) { int lineEndOffset = doc.getLineEndOffset(line); int lineEndColumnNumber = myEditor.offsetToLogicalPosition(lineEndOffset).column; if (column > lineEndColumnNumber) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index e2e5963c3d03..917e8d449be9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -3258,7 +3258,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi return; } - if (!mySettings.isVirtualSpace()) { + if (!mySettings.isVirtualSpace() && !mySelectionModel.hasBlockSelection()) { int lineEndOffset = myDocument.getLineEndOffset(lineNumber); int lineEndColumnNumber = calcColumnNumber(lineEndOffset, lineNumber); if (columnNumber > lineEndColumnNumber) { From a26fab124cdfef9ade921f6898370a7ae0911af9 Mon Sep 17 00:00:00 2001 From: Oleg Shpynov Date: Mon, 21 Feb 2011 13:57:20 +0300 Subject: [PATCH 010/169] More consistent API RUBY-7865 feature request: ability to collapse commented out code --- .../impl/actions/SuppressWarningsFoldingBuilder.java | 3 ++- .../codeInsight/folding/impl/JavaFoldingBuilder.java | 2 +- .../intellij/lang/folding/CompositeFoldingBuilder.java | 7 ++++--- .../src/com/intellij/lang/folding/FoldingBuilder.java | 5 ++++- .../src/com/intellij/lang/folding/FoldingBuilderEx.java | 5 ++++- .../src/com/intellij/lang/folding/FoldingDescriptor.java | 8 ++++---- .../intellij/indentation/IndentationFoldingBuilder.java | 3 ++- .../plugins/groovy/lang/folding/GroovyFoldingBuilder.java | 2 +- .../i18n/folding/PropertyFoldingBuilder.java | 3 ++- .../relaxNG/compact/folding/RncFoldingBuilder.java | 2 +- .../uiDesigner/binding/GeneratedCodeFoldingBuilder.java | 2 +- xml/impl/src/com/intellij/lang/xml/XmlFoldingBuilder.java | 2 +- 12 files changed, 27 insertions(+), 17 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressWarningsFoldingBuilder.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressWarningsFoldingBuilder.java index 0c90b896ece3..608b66e3186e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressWarningsFoldingBuilder.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressWarningsFoldingBuilder.java @@ -26,6 +26,7 @@ import com.intellij.lang.folding.FoldingBuilderEx; import com.intellij.lang.folding.FoldingDescriptor; import com.intellij.openapi.editor.Document; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.util.PsiUtil; @@ -59,7 +60,7 @@ public class SuppressWarningsFoldingBuilder extends FoldingBuilderEx { } @Override - public String getPlaceholderText(@NotNull ASTNode node) { + public String getPlaceholderText(@NotNull ASTNode node, TextRange range) { final PsiElement element = node.getPsi(); if (element instanceof PsiAnnotation) { return "/" + StringUtil.join(((PsiAnnotation)element).getParameterList().getAttributes(), new Function() { diff --git a/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java b/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java index 975ac746d471..43d759fa8430 100644 --- a/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java +++ b/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java @@ -166,7 +166,7 @@ public class JavaFoldingBuilder extends FoldingBuilderEx implements DumbAware { } @NotNull - public String getPlaceholderText(@NotNull final ASTNode node) { + public String getPlaceholderText(@NotNull final ASTNode node, TextRange range) { return getPlaceholderText(SourceTreeToPsiMap.treeElementToPsi(node)); } diff --git a/platform/lang-api/src/com/intellij/lang/folding/CompositeFoldingBuilder.java b/platform/lang-api/src/com/intellij/lang/folding/CompositeFoldingBuilder.java index 92f563b0cceb..2c973ff89161 100644 --- a/platform/lang-api/src/com/intellij/lang/folding/CompositeFoldingBuilder.java +++ b/platform/lang-api/src/com/intellij/lang/folding/CompositeFoldingBuilder.java @@ -18,8 +18,9 @@ package com.intellij.lang.folding; import com.intellij.lang.ASTNode; import com.intellij.openapi.editor.Document; -import com.intellij.openapi.util.Key; import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; @@ -56,9 +57,9 @@ public class CompositeFoldingBuilder extends FoldingBuilderEx implements DumbAwa return descriptors.toArray(new FoldingDescriptor[descriptors.size()]); } - public String getPlaceholderText(@NotNull ASTNode node) { + public String getPlaceholderText(@NotNull ASTNode node, TextRange range) { final FoldingBuilder builder = node.getUserData(FOLDING_BUILDER); - return builder == null ? node.getText() : builder.getPlaceholderText(node); + return builder == null ? node.getText() : builder.getPlaceholderText(node, range); } public boolean isCollapsedByDefault(@NotNull ASTNode node) { diff --git a/platform/lang-api/src/com/intellij/lang/folding/FoldingBuilder.java b/platform/lang-api/src/com/intellij/lang/folding/FoldingBuilder.java index 2e527cb7cbc0..3225f1c8d43d 100644 --- a/platform/lang-api/src/com/intellij/lang/folding/FoldingBuilder.java +++ b/platform/lang-api/src/com/intellij/lang/folding/FoldingBuilder.java @@ -18,6 +18,7 @@ package com.intellij.lang.folding; import com.intellij.lang.ASTNode; import com.intellij.lang.Language; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.util.TextRange; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -45,11 +46,13 @@ public interface FoldingBuilder { * Returns the text which is displayed in the editor for the folding region related to the * specified node when the folding region is collapsed. * + * * @param node the node for which the placeholder text is requested. + * @param range folded range * @return the placeholder text. */ @Nullable - String getPlaceholderText(@NotNull ASTNode node); + String getPlaceholderText(@NotNull ASTNode node, TextRange range); /** * Returns the default collapsed state for the folding region related to the specified node. diff --git a/platform/lang-api/src/com/intellij/lang/folding/FoldingBuilderEx.java b/platform/lang-api/src/com/intellij/lang/folding/FoldingBuilderEx.java index 9c874f70b6b1..603b1cd9f4d1 100644 --- a/platform/lang-api/src/com/intellij/lang/folding/FoldingBuilderEx.java +++ b/platform/lang-api/src/com/intellij/lang/folding/FoldingBuilderEx.java @@ -18,6 +18,7 @@ package com.intellij.lang.folding; import com.intellij.lang.ASTNode; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -54,11 +55,13 @@ public abstract class FoldingBuilderEx implements FoldingBuilder { * Returns the text which is displayed in the editor for the folding region related to the * specified node when the folding region is collapsed. * + * * @param node the node for which the placeholder text is requested. + * @param range * @return the placeholder text. */ @Nullable - public abstract String getPlaceholderText(@NotNull ASTNode node); + public abstract String getPlaceholderText(@NotNull ASTNode node, TextRange range); /** * Returns the default collapsed state for the folding region related to the specified node. diff --git a/platform/lang-api/src/com/intellij/lang/folding/FoldingDescriptor.java b/platform/lang-api/src/com/intellij/lang/folding/FoldingDescriptor.java index 5833f4621267..d1c9dbb1f564 100644 --- a/platform/lang-api/src/com/intellij/lang/folding/FoldingDescriptor.java +++ b/platform/lang-api/src/com/intellij/lang/folding/FoldingDescriptor.java @@ -47,7 +47,7 @@ public class FoldingDescriptor { * Creates a folding region related to the specified AST node and covering the specified * text range. * @param node The node to which the folding region is related. The node is then passed to - * {@link FoldingBuilder#getPlaceholderText(com.intellij.lang.ASTNode)} and + * {@link FoldingBuilder#getPlaceholderText(com.intellij.lang.ASTNode, com.intellij.openapi.util.TextRange)} and * {@link FoldingBuilder#isCollapsedByDefault(com.intellij.lang.ASTNode)}. * @param range The folded text range. */ @@ -67,7 +67,7 @@ public class FoldingDescriptor { * Creates a folding region related to the specified AST node and covering the specified * text range. * @param node The node to which the folding region is related. The node is then passed to - * {@link com.intellij.lang.folding.FoldingBuilder#getPlaceholderText(com.intellij.lang.ASTNode)} and + * {@link FoldingBuilder#getPlaceholderText(com.intellij.lang.ASTNode, com.intellij.openapi.util.TextRange)} and * {@link com.intellij.lang.folding.FoldingBuilder#isCollapsedByDefault(com.intellij.lang.ASTNode)}. * @param range The folded text range. * @param group Regions with the same group instance expand and collapse together. @@ -82,7 +82,7 @@ public class FoldingDescriptor { * Creates a folding region related to the specified AST node and covering the specified * text range. * @param node The node to which the folding region is related. The node is then passed to - * {@link com.intellij.lang.folding.FoldingBuilder#getPlaceholderText(com.intellij.lang.ASTNode)} and + * {@link FoldingBuilder#getPlaceholderText(com.intellij.lang.ASTNode, com.intellij.openapi.util.TextRange)} and * {@link com.intellij.lang.folding.FoldingBuilder#isCollapsedByDefault(com.intellij.lang.ASTNode)}. * @param range The folded text range. * @param group Regions with the same group instance expand and collapse together. @@ -134,7 +134,7 @@ public class FoldingDescriptor { final Language lang = psiElement.getLanguage(); final FoldingBuilder foldingBuilder = LanguageFolding.INSTANCE.forLanguage(lang); if (foldingBuilder != null) { - return foldingBuilder.getPlaceholderText(myElement); + return foldingBuilder.getPlaceholderText(myElement, myRange); } return null; } diff --git a/platform/lang-impl/src/com/intellij/indentation/IndentationFoldingBuilder.java b/platform/lang-impl/src/com/intellij/indentation/IndentationFoldingBuilder.java index 5322803129ac..e2024bd96078 100644 --- a/platform/lang-impl/src/com/intellij/indentation/IndentationFoldingBuilder.java +++ b/platform/lang-impl/src/com/intellij/indentation/IndentationFoldingBuilder.java @@ -5,6 +5,7 @@ import com.intellij.lang.folding.FoldingBuilder; import com.intellij.lang.folding.FoldingDescriptor; import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.tree.TokenSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -42,7 +43,7 @@ public abstract class IndentationFoldingBuilder implements FoldingBuilder, DumbA } @Nullable - public String getPlaceholderText(@NotNull final ASTNode node) { + public String getPlaceholderText(@NotNull final ASTNode node, TextRange range) { final StringBuilder builder = new StringBuilder(); ASTNode child = node.getFirstChildNode(); String text; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java index 7551466bd588..1b2ee13fbeff 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java @@ -223,7 +223,7 @@ public class GroovyFoldingBuilder implements FoldingBuilder, GroovyElementTypes, return text.contains("\n") || text.contains("\r") || text.contains("\r\n"); } - public String getPlaceholderText(@NotNull ASTNode node) { + public String getPlaceholderText(@NotNull ASTNode node, TextRange range) { final IElementType elemType = node.getElementType(); if (BLOCK_SET.contains(elemType) || elemType == CLOSABLE_BLOCK) { return "{...}"; diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/folding/PropertyFoldingBuilder.java b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/folding/PropertyFoldingBuilder.java index 97ad87b3771c..65b1119d5fee 100644 --- a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/folding/PropertyFoldingBuilder.java +++ b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/folding/PropertyFoldingBuilder.java @@ -28,6 +28,7 @@ import com.intellij.lang.properties.psi.impl.PropertyImpl; import com.intellij.lang.properties.psi.impl.PropertyStubImpl; import com.intellij.openapi.editor.Document; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.impl.JavaConstantExpressionEvaluator; @@ -112,7 +113,7 @@ public class PropertyFoldingBuilder extends FoldingBuilderEx { } - public String getPlaceholderText(@NotNull ASTNode node) { + public String getPlaceholderText(@NotNull ASTNode node, TextRange range) { final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(node); if (element instanceof PsiLiteralExpression) { return getI18nMessage((PsiLiteralExpression)element); diff --git a/plugins/relaxng/src/org/intellij/plugins/relaxNG/compact/folding/RncFoldingBuilder.java b/plugins/relaxng/src/org/intellij/plugins/relaxNG/compact/folding/RncFoldingBuilder.java index 94ddafe1aa76..928b8783fb05 100644 --- a/plugins/relaxng/src/org/intellij/plugins/relaxNG/compact/folding/RncFoldingBuilder.java +++ b/plugins/relaxng/src/org/intellij/plugins/relaxNG/compact/folding/RncFoldingBuilder.java @@ -52,7 +52,7 @@ public class RncFoldingBuilder implements FoldingBuilder { : FoldingDescriptor.EMPTY; } - public String getPlaceholderText(@NotNull ASTNode node) { + public String getPlaceholderText(@NotNull ASTNode node, TextRange range) { final IElementType type = node.getElementType(); if (type == RncTokenTypes.LBRACE) { return "{ ... }"; diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/binding/GeneratedCodeFoldingBuilder.java b/plugins/ui-designer/src/com/intellij/uiDesigner/binding/GeneratedCodeFoldingBuilder.java index cc8a8836180a..be21555ff911 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/binding/GeneratedCodeFoldingBuilder.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/binding/GeneratedCodeFoldingBuilder.java @@ -40,7 +40,7 @@ public class GeneratedCodeFoldingBuilder extends FoldingBuilderEx { return visitor.myFoldingData.toArray(new FoldingDescriptor[visitor.myFoldingData.size()]); } - public String getPlaceholderText(@NotNull ASTNode node) { + public String getPlaceholderText(@NotNull ASTNode node, TextRange range) { return UIDesignerBundle.message("uidesigner.generated.code.folding.placeholder.text"); } diff --git a/xml/impl/src/com/intellij/lang/xml/XmlFoldingBuilder.java b/xml/impl/src/com/intellij/lang/xml/XmlFoldingBuilder.java index 32d44782ca7f..fca7eb082d1f 100644 --- a/xml/impl/src/com/intellij/lang/xml/XmlFoldingBuilder.java +++ b/xml/impl/src/com/intellij/lang/xml/XmlFoldingBuilder.java @@ -206,7 +206,7 @@ public class XmlFoldingBuilder implements FoldingBuilder, DumbAware { return false; } - public String getPlaceholderText(@NotNull ASTNode node) { + public String getPlaceholderText(@NotNull ASTNode node, TextRange range) { final PsiElement psi = node.getPsi(); if (psi instanceof XmlTag || psi instanceof XmlComment || From 53bdabd7105ac1814e7ae2248083f2c09202fae1 Mon Sep 17 00:00:00 2001 From: Oleg Shpynov Date: Mon, 21 Feb 2011 14:10:55 +0300 Subject: [PATCH 011/169] Revert "More consistent API" Prevent language API changes This reverts commit a26fab124cdfef9ade921f6898370a7ae0911af9. --- .../impl/actions/SuppressWarningsFoldingBuilder.java | 3 +-- .../codeInsight/folding/impl/JavaFoldingBuilder.java | 2 +- .../intellij/lang/folding/CompositeFoldingBuilder.java | 7 +++---- .../src/com/intellij/lang/folding/FoldingBuilder.java | 5 +---- .../src/com/intellij/lang/folding/FoldingBuilderEx.java | 5 +---- .../src/com/intellij/lang/folding/FoldingDescriptor.java | 8 ++++---- .../intellij/indentation/IndentationFoldingBuilder.java | 3 +-- .../plugins/groovy/lang/folding/GroovyFoldingBuilder.java | 2 +- .../i18n/folding/PropertyFoldingBuilder.java | 3 +-- .../relaxNG/compact/folding/RncFoldingBuilder.java | 2 +- .../uiDesigner/binding/GeneratedCodeFoldingBuilder.java | 2 +- xml/impl/src/com/intellij/lang/xml/XmlFoldingBuilder.java | 2 +- 12 files changed, 17 insertions(+), 27 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressWarningsFoldingBuilder.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressWarningsFoldingBuilder.java index 608b66e3186e..0c90b896ece3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressWarningsFoldingBuilder.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressWarningsFoldingBuilder.java @@ -26,7 +26,6 @@ import com.intellij.lang.folding.FoldingBuilderEx; import com.intellij.lang.folding.FoldingDescriptor; import com.intellij.openapi.editor.Document; import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.util.PsiUtil; @@ -60,7 +59,7 @@ public class SuppressWarningsFoldingBuilder extends FoldingBuilderEx { } @Override - public String getPlaceholderText(@NotNull ASTNode node, TextRange range) { + public String getPlaceholderText(@NotNull ASTNode node) { final PsiElement element = node.getPsi(); if (element instanceof PsiAnnotation) { return "/" + StringUtil.join(((PsiAnnotation)element).getParameterList().getAttributes(), new Function() { diff --git a/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java b/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java index 43d759fa8430..975ac746d471 100644 --- a/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java +++ b/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java @@ -166,7 +166,7 @@ public class JavaFoldingBuilder extends FoldingBuilderEx implements DumbAware { } @NotNull - public String getPlaceholderText(@NotNull final ASTNode node, TextRange range) { + public String getPlaceholderText(@NotNull final ASTNode node) { return getPlaceholderText(SourceTreeToPsiMap.treeElementToPsi(node)); } diff --git a/platform/lang-api/src/com/intellij/lang/folding/CompositeFoldingBuilder.java b/platform/lang-api/src/com/intellij/lang/folding/CompositeFoldingBuilder.java index 2c973ff89161..92f563b0cceb 100644 --- a/platform/lang-api/src/com/intellij/lang/folding/CompositeFoldingBuilder.java +++ b/platform/lang-api/src/com/intellij/lang/folding/CompositeFoldingBuilder.java @@ -18,9 +18,8 @@ package com.intellij.lang.folding; import com.intellij.lang.ASTNode; import com.intellij.openapi.editor.Document; -import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.util.Key; -import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.project.DumbAware; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; @@ -57,9 +56,9 @@ public class CompositeFoldingBuilder extends FoldingBuilderEx implements DumbAwa return descriptors.toArray(new FoldingDescriptor[descriptors.size()]); } - public String getPlaceholderText(@NotNull ASTNode node, TextRange range) { + public String getPlaceholderText(@NotNull ASTNode node) { final FoldingBuilder builder = node.getUserData(FOLDING_BUILDER); - return builder == null ? node.getText() : builder.getPlaceholderText(node, range); + return builder == null ? node.getText() : builder.getPlaceholderText(node); } public boolean isCollapsedByDefault(@NotNull ASTNode node) { diff --git a/platform/lang-api/src/com/intellij/lang/folding/FoldingBuilder.java b/platform/lang-api/src/com/intellij/lang/folding/FoldingBuilder.java index 3225f1c8d43d..2e527cb7cbc0 100644 --- a/platform/lang-api/src/com/intellij/lang/folding/FoldingBuilder.java +++ b/platform/lang-api/src/com/intellij/lang/folding/FoldingBuilder.java @@ -18,7 +18,6 @@ package com.intellij.lang.folding; import com.intellij.lang.ASTNode; import com.intellij.lang.Language; import com.intellij.openapi.editor.Document; -import com.intellij.openapi.util.TextRange; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -46,13 +45,11 @@ public interface FoldingBuilder { * Returns the text which is displayed in the editor for the folding region related to the * specified node when the folding region is collapsed. * - * * @param node the node for which the placeholder text is requested. - * @param range folded range * @return the placeholder text. */ @Nullable - String getPlaceholderText(@NotNull ASTNode node, TextRange range); + String getPlaceholderText(@NotNull ASTNode node); /** * Returns the default collapsed state for the folding region related to the specified node. diff --git a/platform/lang-api/src/com/intellij/lang/folding/FoldingBuilderEx.java b/platform/lang-api/src/com/intellij/lang/folding/FoldingBuilderEx.java index 603b1cd9f4d1..9c874f70b6b1 100644 --- a/platform/lang-api/src/com/intellij/lang/folding/FoldingBuilderEx.java +++ b/platform/lang-api/src/com/intellij/lang/folding/FoldingBuilderEx.java @@ -18,7 +18,6 @@ package com.intellij.lang.folding; import com.intellij.lang.ASTNode; import com.intellij.openapi.editor.Document; -import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -55,13 +54,11 @@ public abstract class FoldingBuilderEx implements FoldingBuilder { * Returns the text which is displayed in the editor for the folding region related to the * specified node when the folding region is collapsed. * - * * @param node the node for which the placeholder text is requested. - * @param range * @return the placeholder text. */ @Nullable - public abstract String getPlaceholderText(@NotNull ASTNode node, TextRange range); + public abstract String getPlaceholderText(@NotNull ASTNode node); /** * Returns the default collapsed state for the folding region related to the specified node. diff --git a/platform/lang-api/src/com/intellij/lang/folding/FoldingDescriptor.java b/platform/lang-api/src/com/intellij/lang/folding/FoldingDescriptor.java index d1c9dbb1f564..5833f4621267 100644 --- a/platform/lang-api/src/com/intellij/lang/folding/FoldingDescriptor.java +++ b/platform/lang-api/src/com/intellij/lang/folding/FoldingDescriptor.java @@ -47,7 +47,7 @@ public class FoldingDescriptor { * Creates a folding region related to the specified AST node and covering the specified * text range. * @param node The node to which the folding region is related. The node is then passed to - * {@link FoldingBuilder#getPlaceholderText(com.intellij.lang.ASTNode, com.intellij.openapi.util.TextRange)} and + * {@link FoldingBuilder#getPlaceholderText(com.intellij.lang.ASTNode)} and * {@link FoldingBuilder#isCollapsedByDefault(com.intellij.lang.ASTNode)}. * @param range The folded text range. */ @@ -67,7 +67,7 @@ public class FoldingDescriptor { * Creates a folding region related to the specified AST node and covering the specified * text range. * @param node The node to which the folding region is related. The node is then passed to - * {@link FoldingBuilder#getPlaceholderText(com.intellij.lang.ASTNode, com.intellij.openapi.util.TextRange)} and + * {@link com.intellij.lang.folding.FoldingBuilder#getPlaceholderText(com.intellij.lang.ASTNode)} and * {@link com.intellij.lang.folding.FoldingBuilder#isCollapsedByDefault(com.intellij.lang.ASTNode)}. * @param range The folded text range. * @param group Regions with the same group instance expand and collapse together. @@ -82,7 +82,7 @@ public class FoldingDescriptor { * Creates a folding region related to the specified AST node and covering the specified * text range. * @param node The node to which the folding region is related. The node is then passed to - * {@link FoldingBuilder#getPlaceholderText(com.intellij.lang.ASTNode, com.intellij.openapi.util.TextRange)} and + * {@link com.intellij.lang.folding.FoldingBuilder#getPlaceholderText(com.intellij.lang.ASTNode)} and * {@link com.intellij.lang.folding.FoldingBuilder#isCollapsedByDefault(com.intellij.lang.ASTNode)}. * @param range The folded text range. * @param group Regions with the same group instance expand and collapse together. @@ -134,7 +134,7 @@ public class FoldingDescriptor { final Language lang = psiElement.getLanguage(); final FoldingBuilder foldingBuilder = LanguageFolding.INSTANCE.forLanguage(lang); if (foldingBuilder != null) { - return foldingBuilder.getPlaceholderText(myElement, myRange); + return foldingBuilder.getPlaceholderText(myElement); } return null; } diff --git a/platform/lang-impl/src/com/intellij/indentation/IndentationFoldingBuilder.java b/platform/lang-impl/src/com/intellij/indentation/IndentationFoldingBuilder.java index e2024bd96078..5322803129ac 100644 --- a/platform/lang-impl/src/com/intellij/indentation/IndentationFoldingBuilder.java +++ b/platform/lang-impl/src/com/intellij/indentation/IndentationFoldingBuilder.java @@ -5,7 +5,6 @@ import com.intellij.lang.folding.FoldingBuilder; import com.intellij.lang.folding.FoldingDescriptor; import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.DumbAware; -import com.intellij.openapi.util.TextRange; import com.intellij.psi.tree.TokenSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -43,7 +42,7 @@ public abstract class IndentationFoldingBuilder implements FoldingBuilder, DumbA } @Nullable - public String getPlaceholderText(@NotNull final ASTNode node, TextRange range) { + public String getPlaceholderText(@NotNull final ASTNode node) { final StringBuilder builder = new StringBuilder(); ASTNode child = node.getFirstChildNode(); String text; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java index 1b2ee13fbeff..7551466bd588 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java @@ -223,7 +223,7 @@ public class GroovyFoldingBuilder implements FoldingBuilder, GroovyElementTypes, return text.contains("\n") || text.contains("\r") || text.contains("\r\n"); } - public String getPlaceholderText(@NotNull ASTNode node, TextRange range) { + public String getPlaceholderText(@NotNull ASTNode node) { final IElementType elemType = node.getElementType(); if (BLOCK_SET.contains(elemType) || elemType == CLOSABLE_BLOCK) { return "{...}"; diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/folding/PropertyFoldingBuilder.java b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/folding/PropertyFoldingBuilder.java index 65b1119d5fee..97ad87b3771c 100644 --- a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/folding/PropertyFoldingBuilder.java +++ b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/folding/PropertyFoldingBuilder.java @@ -28,7 +28,6 @@ import com.intellij.lang.properties.psi.impl.PropertyImpl; import com.intellij.lang.properties.psi.impl.PropertyStubImpl; import com.intellij.openapi.editor.Document; import com.intellij.openapi.util.Key; -import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.impl.JavaConstantExpressionEvaluator; @@ -113,7 +112,7 @@ public class PropertyFoldingBuilder extends FoldingBuilderEx { } - public String getPlaceholderText(@NotNull ASTNode node, TextRange range) { + public String getPlaceholderText(@NotNull ASTNode node) { final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(node); if (element instanceof PsiLiteralExpression) { return getI18nMessage((PsiLiteralExpression)element); diff --git a/plugins/relaxng/src/org/intellij/plugins/relaxNG/compact/folding/RncFoldingBuilder.java b/plugins/relaxng/src/org/intellij/plugins/relaxNG/compact/folding/RncFoldingBuilder.java index 928b8783fb05..94ddafe1aa76 100644 --- a/plugins/relaxng/src/org/intellij/plugins/relaxNG/compact/folding/RncFoldingBuilder.java +++ b/plugins/relaxng/src/org/intellij/plugins/relaxNG/compact/folding/RncFoldingBuilder.java @@ -52,7 +52,7 @@ public class RncFoldingBuilder implements FoldingBuilder { : FoldingDescriptor.EMPTY; } - public String getPlaceholderText(@NotNull ASTNode node, TextRange range) { + public String getPlaceholderText(@NotNull ASTNode node) { final IElementType type = node.getElementType(); if (type == RncTokenTypes.LBRACE) { return "{ ... }"; diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/binding/GeneratedCodeFoldingBuilder.java b/plugins/ui-designer/src/com/intellij/uiDesigner/binding/GeneratedCodeFoldingBuilder.java index be21555ff911..cc8a8836180a 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/binding/GeneratedCodeFoldingBuilder.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/binding/GeneratedCodeFoldingBuilder.java @@ -40,7 +40,7 @@ public class GeneratedCodeFoldingBuilder extends FoldingBuilderEx { return visitor.myFoldingData.toArray(new FoldingDescriptor[visitor.myFoldingData.size()]); } - public String getPlaceholderText(@NotNull ASTNode node, TextRange range) { + public String getPlaceholderText(@NotNull ASTNode node) { return UIDesignerBundle.message("uidesigner.generated.code.folding.placeholder.text"); } diff --git a/xml/impl/src/com/intellij/lang/xml/XmlFoldingBuilder.java b/xml/impl/src/com/intellij/lang/xml/XmlFoldingBuilder.java index fca7eb082d1f..32d44782ca7f 100644 --- a/xml/impl/src/com/intellij/lang/xml/XmlFoldingBuilder.java +++ b/xml/impl/src/com/intellij/lang/xml/XmlFoldingBuilder.java @@ -206,7 +206,7 @@ public class XmlFoldingBuilder implements FoldingBuilder, DumbAware { return false; } - public String getPlaceholderText(@NotNull ASTNode node, TextRange range) { + public String getPlaceholderText(@NotNull ASTNode node) { final PsiElement psi = node.getPsi(); if (psi instanceof XmlTag || psi instanceof XmlComment || From 284490f44f9e55fde4b594b8189e52cf487aff4a Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 21 Feb 2011 12:25:20 +0100 Subject: [PATCH 012/169] fix assertions when hitting ctrl+space with hint autopopup active --- .../codeInsight/completion/CodeCompletionHandlerBase.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java index 106e016d7b86..c2f09f4c935c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -239,11 +239,10 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler { @NotNull private LookupImpl obtainLookup(Editor editor) { LookupImpl existing = (LookupImpl)LookupManager.getActiveLookup(editor); - if (existing != null && existing.isCompletion()) { + if (existing != null && existing.isCompletion() && !existing.isHintMode()) { existing.markReused(); if (!autopopup) { existing.setFocused(true); - existing.setHintMode(false); } return existing; } From 32c75aa3b3165dce447ce4fe7c9bfa6baed80123 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 21 Feb 2011 12:29:54 +0100 Subject: [PATCH 013/169] extract non-language-dependent part of dictionary generator --- .../SpellCheckerDictionaryGenerator.java | 184 ++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 plugins/spellchecker/src/com/intellij/spellchecker/generator/SpellCheckerDictionaryGenerator.java diff --git a/plugins/spellchecker/src/com/intellij/spellchecker/generator/SpellCheckerDictionaryGenerator.java b/plugins/spellchecker/src/com/intellij/spellchecker/generator/SpellCheckerDictionaryGenerator.java new file mode 100644 index 000000000000..e3cb4794271d --- /dev/null +++ b/plugins/spellchecker/src/com/intellij/spellchecker/generator/SpellCheckerDictionaryGenerator.java @@ -0,0 +1,184 @@ +package com.intellij.spellchecker.generator; + +import com.intellij.lang.refactoring.NamesValidator; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.spellchecker.SpellCheckerManager; +import com.intellij.spellchecker.inspections.CheckArea; +import com.intellij.spellchecker.inspections.SpellCheckingInspection; +import com.intellij.spellchecker.tokenizer.Token; +import com.intellij.util.containers.MultiMap; +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.*; + +public abstract class SpellCheckerDictionaryGenerator { + private static final Logger LOG = Logger.getInstance("#com.intellij.spellchecker.generator.SpellCheckerDictionaryGenerator"); + private final Set globalSeenNames = new HashSet(); + protected final Project myProject; + private final String myDefaultDictName; + protected final String myDictOutputFolder; + protected final MultiMap myDict2FolderMap; + protected SpellCheckerManager mySpellCheckerManager; + protected NamesValidator[] myNamesValidators; + + public SpellCheckerDictionaryGenerator(final MultiMap dict2FolderMap, final Project project, + final String dictOutputFolder, final String defaultDictName) { + myDict2FolderMap = dict2FolderMap; + myProject = project; + myDefaultDictName = defaultDictName; + mySpellCheckerManager = SpellCheckerManager.getInstance(myProject); + myNamesValidators = SpellCheckingInspection.getNamesValidators(); + myDictOutputFolder = dictOutputFolder; + SpellCheckingInspection.ensureFactoriesAreLoaded(); + } + + public void generate() { + // let's do result a bit more predictable + + // ruby dictionary + generate(myDefaultDictName); + + // other gem-related dictionaries in alphabet order + final List dictsList = new ArrayList(myDict2FolderMap.keySet()); + Collections.sort(dictsList); + + for (String dict : dictsList) { + if (myDefaultDictName.equals(dict)) { + continue; + } + generate(dict); + } + } + + private void generate(@NotNull String dict) { + System.out.println("Processing dictionary: " + dict); + generateDictionary(myProject, myDict2FolderMap.get(dict), myDictOutputFolder + "/" + dict + ".dic"); + System.out.println("Done"); + } + + private void generateDictionary(final Project project, final Collection folderPaths, final String outFile) { + final HashSet seenNames = new HashSet(); + // Collect stuff + for (String folderPath : folderPaths) { + System.out.println(" Scanning folder: " + folderPath); + final PsiManager manager = PsiManager.getInstance(project); + final VirtualFile folder = LocalFileSystem.getInstance().findFileByPath(folderPath); + processFolder(seenNames, manager, folder); + } + + if (seenNames.isEmpty()) { + System.out.println(" No new words was found."); + return; + } + + final StringBuilder builder = new StringBuilder(); + // Sort names + final ArrayList names = new ArrayList(seenNames); + Collections.sort(names); + for (String name : names) { + if (builder.length() > 0){ + builder.append("\n"); + } + builder.append(name); + } + try { + final File dictionaryFile = new File(outFile); + FileUtil.createIfDoesntExist(dictionaryFile); + final FileWriter writer = new FileWriter(dictionaryFile.getPath()); + writer.write(builder.toString()); + writer.close(); + } + catch (IOException e) { + LOG.error(e); + } + } + + private void processFolder(final HashSet seenNames, final PsiManager manager, + final VirtualFile folder) { + for (VirtualFile virtualFile : folder.getChildren()) { + if (virtualFile.isDirectory()){ + processFolder(seenNames, manager, virtualFile); + continue; + } + final PsiFile file = manager.findFile(virtualFile); + assert file != null; + processFile(file, seenNames); + } + } + + protected abstract void processFile(PsiFile file, HashSet seenNames); + + protected void process(final PsiElement element, @NotNull final HashSet seenNames) { + final int endOffset = element.getTextRange().getEndOffset(); + + // collect leafs (spell checker inspection works with leafs) + final List leafs = new ArrayList(); + if (element.getChildren().length == 0) { + // if no children - it is a leaf! + leafs.add(element); + } else { + // else collect leafs under given element + PsiElement currentLeaf = PsiTreeUtil.firstChild(element); + while (currentLeaf != null && currentLeaf.getTextRange().getEndOffset() <= endOffset) { + leafs.add(currentLeaf); + currentLeaf = PsiTreeUtil.nextLeaf(currentLeaf); + } + } + + for (PsiElement leaf : leafs) { + processLeafsNames(leaf, seenNames); + } + } + + protected void processLeafsNames(@NotNull final PsiElement leafElement, @NotNull final HashSet seenNames) { + final Token[] tokens = SpellCheckingInspection.tokenize(leafElement, leafElement.getLanguage()); + if (tokens != null) { + for (Token token : tokens) { + final List areas = token.getAreas(); + if (areas == null) { + continue; + } + + for (CheckArea area : areas) { + boolean ignored = area.isIgnored(); + final TextRange textRange = area.getTextRange(); + + if (ignored || textRange ==null){ + continue; + } + + final String word = area.getWord(); + if (word == null) { + continue; + } + + final String lowerWord = word.toLowerCase(); + if (globalSeenNames.contains(lowerWord)) { + continue; + } + + boolean keyword = SpellCheckingInspection.isKeyword(myNamesValidators, token.getElement(), word); + if (keyword){ + continue; + } + globalSeenNames.add(lowerWord); + if (mySpellCheckerManager.hasProblem(lowerWord)){ + seenNames.add(lowerWord); + } + } + } + } + } +} From a831a7cd1230fe8b9742ff1182a6132688a286d0 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 21 Feb 2011 12:40:25 +0100 Subject: [PATCH 014/169] [rev=yole] revert up/down arrows in non-focused lookups to the old behavior --- .../codeInsight/completion/JavaAutoPopupTest.groovy | 6 +++--- .../codeInsight/lookup/impl/LookupActionHandler.java | 12 +++--------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy index 1439b3b55f83..64ed0eedb9e9 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy @@ -429,9 +429,9 @@ class JavaAutoPopupTest extends CompletionAutoPopupTestCase { public void testVerticalArrows() { testArrows false, false, 0, -1 - testArrows false, true, -1, 1 - testArrows true, false, 0, -1 - testArrows true, true, -1, 1 + testArrows false, true, 0, -1 + testArrows true, false, 0, 1 + testArrows true, true, 0, 1 } public void testHideOnOnePrefixVariant() { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupActionHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupActionHandler.java index de8e1eb23ab0..b00d961853ef 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupActionHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupActionHandler.java @@ -17,6 +17,7 @@ package com.intellij.codeInsight.lookup.impl; import com.intellij.codeInsight.lookup.LookupManager; +import com.intellij.ide.ui.UISettings; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; @@ -73,11 +74,6 @@ public abstract class LookupActionHandler extends EditorActionHandler { protected void executeInLookup(final LookupImpl lookup, DataContext context) { if (!lookup.isFocused()) { - if (lookup.isPositionedAboveCaret()) { - myOriginalHandler.execute(lookup.getEditor(), context); - return; - } - lookup.setFocused(true); lookup.getList().setSelectedIndex(0); lookup.refreshUi(); @@ -94,16 +90,14 @@ public abstract class LookupActionHandler extends EditorActionHandler { protected void executeInLookup(final LookupImpl lookup, DataContext context) { if (!lookup.isFocused()) { - if (!lookup.isPositionedAboveCaret()) { + if (!UISettings.getInstance().CYCLE_SCROLLING) { myOriginalHandler.execute(lookup.getEditor(), context); return; } lookup.setFocused(true); - final int index = ApplicationManager.getApplication().isUnitTestMode() ? lookup.getItems().size() - 1 : lookup.getList().getLastVisibleIndex(); - lookup.getList().setSelectedIndex(index); + lookup.getList().setSelectedIndex(0); lookup.refreshUi(); - return; } ListScrollingUtil.moveUp(lookup.getList(), 0); } From 2d42753622677a8cfa2cbcc77b818abdcddb524f Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 21 Feb 2011 12:40:33 +0100 Subject: [PATCH 015/169] nicer API --- .../generator/SpellCheckerDictionaryGenerator.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/plugins/spellchecker/src/com/intellij/spellchecker/generator/SpellCheckerDictionaryGenerator.java b/plugins/spellchecker/src/com/intellij/spellchecker/generator/SpellCheckerDictionaryGenerator.java index e3cb4794271d..43156482037a 100644 --- a/plugins/spellchecker/src/com/intellij/spellchecker/generator/SpellCheckerDictionaryGenerator.java +++ b/plugins/spellchecker/src/com/intellij/spellchecker/generator/SpellCheckerDictionaryGenerator.java @@ -33,9 +33,8 @@ public abstract class SpellCheckerDictionaryGenerator { protected SpellCheckerManager mySpellCheckerManager; protected NamesValidator[] myNamesValidators; - public SpellCheckerDictionaryGenerator(final MultiMap dict2FolderMap, final Project project, - final String dictOutputFolder, final String defaultDictName) { - myDict2FolderMap = dict2FolderMap; + public SpellCheckerDictionaryGenerator(final Project project, final String dictOutputFolder, final String defaultDictName) { + myDict2FolderMap = new MultiMap(); myProject = project; myDefaultDictName = defaultDictName; mySpellCheckerManager = SpellCheckerManager.getInstance(myProject); @@ -44,6 +43,10 @@ public abstract class SpellCheckerDictionaryGenerator { SpellCheckingInspection.ensureFactoriesAreLoaded(); } + public void addFolder(String dictName, String path) { + myDict2FolderMap.putValue(dictName, path); + } + public void generate() { // let's do result a bit more predictable From 3f90c19312ce291e9309c7de8849f97587c196bb Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 21 Feb 2011 12:48:51 +0100 Subject: [PATCH 016/169] nicer API --- .../generator/SpellCheckerDictionaryGenerator.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/plugins/spellchecker/src/com/intellij/spellchecker/generator/SpellCheckerDictionaryGenerator.java b/plugins/spellchecker/src/com/intellij/spellchecker/generator/SpellCheckerDictionaryGenerator.java index 43156482037a..21c6b6b815ac 100644 --- a/plugins/spellchecker/src/com/intellij/spellchecker/generator/SpellCheckerDictionaryGenerator.java +++ b/plugins/spellchecker/src/com/intellij/spellchecker/generator/SpellCheckerDictionaryGenerator.java @@ -5,7 +5,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; @@ -29,12 +28,12 @@ public abstract class SpellCheckerDictionaryGenerator { protected final Project myProject; private final String myDefaultDictName; protected final String myDictOutputFolder; - protected final MultiMap myDict2FolderMap; + protected final MultiMap myDict2FolderMap; protected SpellCheckerManager mySpellCheckerManager; protected NamesValidator[] myNamesValidators; public SpellCheckerDictionaryGenerator(final Project project, final String dictOutputFolder, final String defaultDictName) { - myDict2FolderMap = new MultiMap(); + myDict2FolderMap = new MultiMap(); myProject = project; myDefaultDictName = defaultDictName; mySpellCheckerManager = SpellCheckerManager.getInstance(myProject); @@ -43,7 +42,7 @@ public abstract class SpellCheckerDictionaryGenerator { SpellCheckingInspection.ensureFactoriesAreLoaded(); } - public void addFolder(String dictName, String path) { + public void addFolder(String dictName, VirtualFile path) { myDict2FolderMap.putValue(dictName, path); } @@ -71,13 +70,12 @@ public abstract class SpellCheckerDictionaryGenerator { System.out.println("Done"); } - private void generateDictionary(final Project project, final Collection folderPaths, final String outFile) { + private void generateDictionary(final Project project, final Collection folderPaths, final String outFile) { final HashSet seenNames = new HashSet(); // Collect stuff - for (String folderPath : folderPaths) { - System.out.println(" Scanning folder: " + folderPath); + for (VirtualFile folder : folderPaths) { + System.out.println(" Scanning folder: " + folder.getPath()); final PsiManager manager = PsiManager.getInstance(project); - final VirtualFile folder = LocalFileSystem.getInstance().findFileByPath(folderPath); processFolder(seenNames, manager, folder); } From 57697fb7d087485e8822ccfb3dcd4664d45ca6bb Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Mon, 21 Feb 2011 13:07:41 +0100 Subject: [PATCH 017/169] do not fail with OOME when rendering large strings --- .../intellij/debugger/ui/tree/render/ToStringRenderer.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ToStringRenderer.java b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ToStringRenderer.java index 363e7ef64adb..75830bc64d23 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ToStringRenderer.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ToStringRenderer.java @@ -15,9 +15,8 @@ */ package com.intellij.debugger.ui.tree.render; -import com.intellij.ui.classFilter.ClassFilter; -import com.intellij.debugger.DebuggerContext; import com.intellij.debugger.DebuggerBundle; +import com.intellij.debugger.DebuggerContext; import com.intellij.debugger.engine.DebugProcessImpl; import com.intellij.debugger.engine.evaluation.EvaluateException; import com.intellij.debugger.engine.evaluation.EvaluationContext; @@ -29,6 +28,7 @@ import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.JDOMExternalizerUtil; import com.intellij.openapi.util.WriteExternalException; import com.intellij.psi.PsiExpression; +import com.intellij.ui.classFilter.ClassFilter; import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants; import com.sun.jdi.*; import org.jdom.Element; @@ -73,7 +73,7 @@ public class ToStringRenderer extends NodeRendererImpl { final Value value = valueDescriptor.getValue(); BatchEvaluator.getBatchEvaluator(evaluationContext.getDebugProcess()).invoke(new ToStringCommand(evaluationContext, value) { public void evaluationResult(String message) { - valueDescriptor.setValueLabel(message != null ? "\"" + message + "\"" : ""); + valueDescriptor.setValueLabel(message != null ? "\"" + DebuggerUtilsEx.truncateString(message) + "\"" : ""); labelListener.labelChanged(); } From 2d341f6912ca85a71e05fd5f188e78dbeda7a638 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 21 Feb 2011 13:15:56 +0100 Subject: [PATCH 018/169] fixes --- .../generator/SpellCheckerDictionaryGenerator.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/plugins/spellchecker/src/com/intellij/spellchecker/generator/SpellCheckerDictionaryGenerator.java b/plugins/spellchecker/src/com/intellij/spellchecker/generator/SpellCheckerDictionaryGenerator.java index 21c6b6b815ac..066a1258e0f0 100644 --- a/plugins/spellchecker/src/com/intellij/spellchecker/generator/SpellCheckerDictionaryGenerator.java +++ b/plugins/spellchecker/src/com/intellij/spellchecker/generator/SpellCheckerDictionaryGenerator.java @@ -98,8 +98,12 @@ public abstract class SpellCheckerDictionaryGenerator { final File dictionaryFile = new File(outFile); FileUtil.createIfDoesntExist(dictionaryFile); final FileWriter writer = new FileWriter(dictionaryFile.getPath()); - writer.write(builder.toString()); - writer.close(); + try { + writer.write(builder.toString()); + } + finally { + writer.close(); + } } catch (IOException e) { LOG.error(e); @@ -114,8 +118,9 @@ public abstract class SpellCheckerDictionaryGenerator { continue; } final PsiFile file = manager.findFile(virtualFile); - assert file != null; - processFile(file, seenNames); + if (file != null) { + processFile(file, seenNames); + } } } From fcea023d50d34399688246443b15f34fb61f7bc8 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 18 Feb 2011 17:49:28 +0300 Subject: [PATCH 019/169] dependencies --- .../openapi/vfs/LocalFileSystemTest.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/java/java-tests/testSrc/com/intellij/openapi/vfs/LocalFileSystemTest.java b/java/java-tests/testSrc/com/intellij/openapi/vfs/LocalFileSystemTest.java index 820ddfd6d8d6..017070824b74 100644 --- a/java/java-tests/testSrc/com/intellij/openapi/vfs/LocalFileSystemTest.java +++ b/java/java-tests/testSrc/com/intellij/openapi/vfs/LocalFileSystemTest.java @@ -1,14 +1,19 @@ package com.intellij.openapi.vfs; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.vfs.impl.win32.Win32LocalFileSystem; import com.intellij.openapi.vfs.newvfs.ManagingFS; import com.intellij.testFramework.IdeaTestCase; import com.intellij.testFramework.IdeaTestUtil; +import org.jetbrains.annotations.NonNls; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStreamWriter; +import java.nio.charset.Charset; import java.util.Arrays; public class LocalFileSystemTest extends IdeaTestCase{ @@ -219,4 +224,20 @@ public class LocalFileSystemTest extends IdeaTestCase{ ); } + + public static void setContentOnDisk(File file, byte[] bom, String content, Charset charset) throws IOException { + FileOutputStream stream = new FileOutputStream(file); + stream.write(bom); + OutputStreamWriter writer = new OutputStreamWriter(stream, charset); + writer.write(content); + writer.close(); + } + + public static VirtualFile createTempFile(@NonNls String ext, byte[] bom, @NonNls String content, Charset charset) throws IOException { + File temp = FileUtil.createTempFile("copy", "." + ext); + setContentOnDisk(temp, bom, content, charset); + + myFilesToDelete.add(temp); + return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(temp); + } } From 76f2bcfc0dbae64406d97219fd8a245d3fe6da29 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 18 Feb 2011 18:48:28 +0300 Subject: [PATCH 020/169] duplicate usage fixed --- .../usageView/src/com/intellij/usages/impl/GroupNode.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/usageView/src/com/intellij/usages/impl/GroupNode.java b/platform/usageView/src/com/intellij/usages/impl/GroupNode.java index 583fce9f8caa..991a365e5f9c 100644 --- a/platform/usageView/src/com/intellij/usages/impl/GroupNode.java +++ b/platform/usageView/src/com/intellij/usages/impl/GroupNode.java @@ -105,7 +105,10 @@ public class GroupNode extends Node implements Navigatable, Comparable Date: Mon, 21 Feb 2011 14:07:53 +0300 Subject: [PATCH 021/169] assertions added --- .../openapi/editor/impl/MarkupModelImpl.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/MarkupModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/MarkupModelImpl.java index ecce8d321218..04812916c5e3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/MarkupModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/MarkupModelImpl.java @@ -24,6 +24,7 @@ */ package com.intellij.openapi.editor.impl; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.ex.MarkupModelEx; @@ -54,11 +55,13 @@ public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx private final RangeHighlighterTree myHighlighterTree; MarkupModelImpl(DocumentImpl document) { + ApplicationManager.getApplication().assertIsDispatchThread(); myDocument = document; myHighlighterTree = new RangeHighlighterTree(myDocument); } public void dispose() { + ApplicationManager.getApplication().assertIsDispatchThread(); myHighlighterTree.dispose(); } @@ -98,9 +101,11 @@ public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx @NotNull public RangeHighlighter[] getAllHighlighters() { + ApplicationManager.getApplication().assertIsDispatchThread(); if (myCachedHighlighters == null) { - if (myHighlighterTree.size() == 0) return RangeHighlighter.EMPTY_ARRAY; - List list = new ArrayList(); + int size = myHighlighterTree.size(); + if (size == 0) return RangeHighlighter.EMPTY_ARRAY; + List list = new ArrayList(size); myHighlighterTree.process(new CommonProcessors.CollectProcessor(list)); myCachedHighlighters = list.toArray(new RangeHighlighter[list.size()]); } @@ -115,6 +120,7 @@ public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx @NotNull HighlighterTargetArea targetArea, boolean isPersistent, @Nullable Consumer changeAttributesAction) { + ApplicationManager.getApplication().assertIsDispatchThread(); RangeHighlighterEx highlighter = isPersistent ? new PersistentRangeHighlighterImpl(this, startOffset, layer, targetArea, textAttributes) : new RangeHighlighterImpl(this, startOffset, endOffset, layer, targetArea, textAttributes); @@ -134,6 +140,7 @@ public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx @Override public void changeAttributesInBatch(@NotNull RangeHighlighterEx highlighter, @NotNull Consumer changeAttributesAction) { + ApplicationManager.getApplication().assertIsDispatchThread(); boolean changed = highlighter instanceof PersistentRangeHighlighterImpl ? ((PersistentRangeHighlighterImpl)highlighter).changeAttributesInBatch(changeAttributesAction) : ((RangeHighlighterImpl)highlighter).changeAttributesInBatch(changeAttributesAction); @@ -143,6 +150,7 @@ public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx } void addRangeHighlighter(RangeHighlighterEx marker, int start, int end, RangeHighlighterData data) { + ApplicationManager.getApplication().assertIsDispatchThread(); myHighlighterTree.addInterval(marker, start, end, data); } @@ -156,6 +164,7 @@ public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx } public void removeHighlighter(@NotNull RangeHighlighter segmentHighlighter) { + ApplicationManager.getApplication().assertIsDispatchThread(); myCachedHighlighters = null; if (!segmentHighlighter.isValid()) return; @@ -166,6 +175,7 @@ public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx } public void removeAllHighlighters() { + ApplicationManager.getApplication().assertIsDispatchThread(); myHighlighterTree.process(new Processor() { public boolean process(RangeMarkerEx rangeMarkerEx) { fireBeforeRemoved((RangeHighlighterEx)rangeMarkerEx); @@ -191,6 +201,7 @@ public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx } public void setRangeHighlighterAttributes(@NotNull final RangeHighlighter highlighter, final TextAttributes textAttributes) { + ApplicationManager.getApplication().assertIsDispatchThread(); ((RangeHighlighterImpl)highlighter).setTextAttributes(textAttributes); } @@ -211,6 +222,7 @@ public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx } public boolean containsHighlighter(@NotNull final RangeHighlighter highlighter) { + ApplicationManager.getApplication().assertIsDispatchThread(); return !myHighlighterTree.processOverlappingWith(highlighter.getStartOffset(), highlighter.getEndOffset(), new Processor() { public boolean process(RangeHighlighterEx h) { return h.getId() != ((RangeHighlighterEx)highlighter).getId(); @@ -236,6 +248,7 @@ public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx } public void normalize() { + ApplicationManager.getApplication().assertIsDispatchThread(); myHighlighterTree.normalize(); } } From b43904cb354f175c3323b64ae207b3b7d631603d Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 21 Feb 2011 15:37:41 +0300 Subject: [PATCH 022/169] tree tests --- .../StructureViewUpdatingTest.java | 180 +++++++++--------- .../projectView/BaseProjectViewTestCase.java | 7 +- .../ide/fileTemplates/FileTemplateUtil.java | 5 +- .../testFramework/PlatformTestUtil.java | 25 ++- .../util/containers/TransferToEDTQueue.java | 2 +- 5 files changed, 116 insertions(+), 103 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/projectView/StructureViewUpdatingTest.java b/java/java-tests/testSrc/com/intellij/projectView/StructureViewUpdatingTest.java index d7ee434b124c..81a61b14b0ad 100644 --- a/java/java-tests/testSrc/com/intellij/projectView/StructureViewUpdatingTest.java +++ b/java/java-tests/testSrc/com/intellij/projectView/StructureViewUpdatingTest.java @@ -34,11 +34,9 @@ package com.intellij.projectView; import com.intellij.JavaTestUtil; import com.intellij.ide.structureView.impl.java.InheritedMembersFilter; import com.intellij.ide.structureView.newStructureView.StructureViewComponent; -import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; -import com.intellij.testFramework.IdeaTestUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.fileEditor.FileEditorManager; @@ -48,6 +46,7 @@ import com.intellij.psi.JavaDirectoryService; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiField; +import com.intellij.testFramework.PlatformTestUtil; import com.intellij.testFramework.TestSourceBasedTestCase; import com.intellij.util.IncorrectOperationException; @@ -69,55 +68,55 @@ public class StructureViewUpdatingTest extends TestSourceBasedTestCase { final StructureViewComponent structureViewComponent = (StructureViewComponent)fileEditor.getStructureViewBuilder().createStructureView(fileEditor, myProject); final Document document = PsiDocumentManager.getInstance(myProject).getDocument(psiClass.getContainingFile()); - IdeaTestUtil.assertTreeEqual(structureViewComponent.getTree(), - "-Class1.java\n" + - " -Class1\n" + - " getValue():int\n" + - " getClass():Class\n" + - " hashCode():int\n" + - " equals(Object):boolean\n" + - " clone():Object\n" + - " toString():String\n" + - " notify():void\n" + - " notifyAll():void\n" + - " wait(long):void\n" + - " wait(long, int):void\n" + - " wait():void\n" + - " finalize():void\n" + - " myField1:boolean\n" + - " myField2:boolean\n"); + PlatformTestUtil.assertTreeEqual(structureViewComponent.getTree(), + "-Class1.java\n" + + " -Class1\n" + + " getValue():int\n" + + " getClass():Class\n" + + " hashCode():int\n" + + " equals(Object):boolean\n" + + " clone():Object\n" + + " toString():String\n" + + " notify():void\n" + + " notifyAll():void\n" + + " wait(long):void\n" + + " wait(long, int):void\n" + + " wait():void\n" + + " finalize():void\n" + + " myField1:boolean\n" + + " myField2:boolean\n"); - CommandProcessor.getInstance().executeCommand(myProject, new Runnable() { + new WriteCommandAction.Simple(getProject()) { @Override - public void run() { - + protected void run() throws Throwable { final int offset = document.getLineStartOffset(5); document.insertString(offset, " boolean myNewField = false;\n"); } - }, null, null); + }.execute().throwException(); + PsiDocumentManager.getInstance(myProject).commitDocument(document); - IdeaTestUtil.waitForAlarm(600); + PlatformTestUtil.waitForAlarm(600); //TreeUtil.expand(structureViewComponent.getTree(), 3); - IdeaTestUtil.assertTreeEqual(structureViewComponent.getTree(), "-Class1.java\n" + - " -Class1\n" + " getValue():int\n" + - " getClass():Class\n" + - " hashCode():int\n" + - " equals(Object):boolean\n" + - " clone():Object\n" + - " toString():String\n" + - " notify():void\n" + - " notifyAll():void\n" + - " wait(long):void\n" + - " wait(long, int):void\n" + - " wait():void\n" + - " finalize():void\n" + - " myField1:boolean\n" + - " myField2:boolean\n" + - " myNewField:boolean = false\n"); + PlatformTestUtil.assertTreeEqual(structureViewComponent.getTree(), "-Class1.java\n" + + " -Class1\n" + " getValue():int\n" + + " getClass():Class\n" + + " hashCode():int\n" + + " equals(Object):boolean\n" + + " clone():Object\n" + + " toString():String\n" + + " notify():void\n" + + " notifyAll():void\n" + + " wait(long):void\n" + + " wait(long, int):void\n" + + " wait():void\n" + + " finalize():void\n" + + " myField1:boolean\n" + + " myField2:boolean\n" + + " myNewField:boolean = false\n"); Disposer.dispose(structureViewComponent); @@ -138,31 +137,31 @@ public class StructureViewUpdatingTest extends TestSourceBasedTestCase { try { structureViewComponent.setActionActive(InheritedMembersFilter.ID, true); - IdeaTestUtil.assertTreeEqual(structureViewComponent.getTree(), "-Class2.java\n" + - " -Class2\n" + - " +InnerClass1\n" + - " +InnerClass2\n" + - " getValue():int\n" + - " myField1:boolean\n" + - " myField2:boolean\n" + - " myField3:boolean\n" + - " myField4:boolean\n"); + PlatformTestUtil.assertTreeEqual(structureViewComponent.getTree(), "-Class2.java\n" + + " -Class2\n" + + " +InnerClass1\n" + + " +InnerClass2\n" + + " getValue():int\n" + + " myField1:boolean\n" + + " myField2:boolean\n" + + " myField3:boolean\n" + + " myField4:boolean\n"); final PsiField innerClassField = psiClass.getInnerClasses()[0].getFields()[0]; structureViewComponent.select(innerClassField, true); - IdeaTestUtil.assertTreeEqual(structureViewComponent.getTree(), "-Class2.java\n" + - " -Class2\n" + - " -InnerClass1\n" + - " +InnerClass12\n" + - " myInnerClassField:int\n" + - " +InnerClass2\n" + - " getValue():int\n" + - " myField1:boolean\n" + - " myField2:boolean\n" + - " myField3:boolean\n" + - " myField4:boolean\n"); + PlatformTestUtil.assertTreeEqual(structureViewComponent.getTree(), "-Class2.java\n" + + " -Class2\n" + + " -InnerClass1\n" + + " +InnerClass12\n" + + " myInnerClassField:int\n" + + " +InnerClass2\n" + + " getValue():int\n" + + " myField1:boolean\n" + + " myField2:boolean\n" + + " myField3:boolean\n" + + " myField4:boolean\n"); CommandProcessor.getInstance().executeCommand(myProject, new Runnable() { @Override @@ -175,25 +174,25 @@ public class StructureViewUpdatingTest extends TestSourceBasedTestCase { innerClassField.delete(); } catch (IncorrectOperationException e) { - assertTrue(e.getLocalizedMessage(), false); + fail(e.getLocalizedMessage()); } } }); } }, null, null); - IdeaTestUtil.waitForAlarm(600); + PlatformTestUtil.waitForAlarm(600); - IdeaTestUtil.assertTreeEqual(structureViewComponent.getTree(), "-Class2.java\n" + - " -Class2\n" + - " -InnerClass1\n" + - " +InnerClass12\n" + - " +InnerClass2\n" + - " getValue():int\n" + - " myField1:boolean\n" + - " myField2:boolean\n" + - " myField3:boolean\n" + - " myField4:boolean\n"); + PlatformTestUtil.assertTreeEqual(structureViewComponent.getTree(), "-Class2.java\n" + + " -Class2\n" + + " -InnerClass1\n" + + " +InnerClass12\n" + + " +InnerClass2\n" + + " getValue():int\n" + + " myField1:boolean\n" + + " myField2:boolean\n" + + " myField3:boolean\n" + + " myField4:boolean\n"); } finally { @@ -213,26 +212,26 @@ public class StructureViewUpdatingTest extends TestSourceBasedTestCase { (StructureViewComponent)fileEditor.getStructureViewBuilder().createStructureView(fileEditor, myProject); final JTree tree = structureViewComponent.getTree(); - IdeaTestUtil.assertTreeEqual(tree, "-test.xml\n" + - " -test\n" + - " +level1\n" + - " +level1\n" + - " +level1\n" + - " +level1\n"); + PlatformTestUtil.assertTreeEqual(tree, "-test.xml\n" + + " -test\n" + + " +level1\n" + + " +level1\n" + + " +level1\n" + + " +level1\n"); tree.expandPath(tree.getPathForRow(3)); - IdeaTestUtil.waitForAlarm(600); + PlatformTestUtil.waitForAlarm(600); - IdeaTestUtil.assertTreeEqual(tree, - "-test.xml\n" + - " -test\n" + - " +level1\n" + - " -level1\n" + - " +level2\n" + - " +level1\n" + - " +level1\n"); + PlatformTestUtil.assertTreeEqual(tree, + "-test.xml\n" + + " -test\n" + + " +level1\n" + + " -level1\n" + + " +level2\n" + + " +level1\n" + + " +level1\n"); Disposer.dispose(structureViewComponent); } @@ -246,4 +245,9 @@ public class StructureViewUpdatingTest extends TestSourceBasedTestCase { protected String getTestDataPath() { return JavaTestUtil.getJavaTestDataPath(); } + + @Override + protected boolean isRunInWriteAction() { + return false; + } } diff --git a/java/testFramework/src/com/intellij/projectView/BaseProjectViewTestCase.java b/java/testFramework/src/com/intellij/projectView/BaseProjectViewTestCase.java index cbe0eb8c9a30..c1c6510b24d3 100644 --- a/java/testFramework/src/com/intellij/projectView/BaseProjectViewTestCase.java +++ b/java/testFramework/src/com/intellij/projectView/BaseProjectViewTestCase.java @@ -25,8 +25,6 @@ import com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode; import com.intellij.ide.util.treeView.*; import com.intellij.openapi.application.ex.PathManagerEx; import com.intellij.openapi.project.DumbAwareRunnable; -import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.ui.Queryable; import com.intellij.openapi.util.Disposer; @@ -300,4 +298,9 @@ public abstract class BaseProjectViewTestCase extends TestSourceBasedTestCase { protected String getTestDataPath() { return PathManagerEx.getTestDataPath(getClass()); } + + @Override + protected boolean isRunInWriteAction() { + return false; + } } diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplateUtil.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplateUtil.java index 77a277ac7546..92badac379be 100644 --- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplateUtil.java +++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplateUtil.java @@ -311,7 +311,7 @@ public class FileTemplateUtil{ final Properties finalProps = props; CommandProcessor.getInstance().executeCommand(project, new Runnable(){ public void run(){ - final Runnable run = new Runnable(){ + ApplicationManager.getApplication().runWriteAction(new Runnable(){ public void run(){ try{ CreateFromTemplateHandler handler = findHandler(template); @@ -321,8 +321,7 @@ public class FileTemplateUtil{ commandException[0] = ex; } } - }; - ApplicationManager.getApplication().runWriteAction(run); + }); } }, template.isJavaClassTemplate() ? IdeBundle.message("command.create.class.from.template") diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java index ee6627924f92..e455ec2534fe 100644 --- a/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java +++ b/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java @@ -15,7 +15,8 @@ */ package com.intellij.testFramework; -import com.intellij.ide.*; +import com.intellij.ide.DataManager; +import com.intellij.ide.IdeEventQueue; import com.intellij.ide.util.treeView.AbstractTreeNode; import com.intellij.ide.util.treeView.AbstractTreeStructure; import com.intellij.idea.Bombed; @@ -48,9 +49,10 @@ import org.jetbrains.annotations.TestOnly; import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreePath; -import java.util.*; import java.awt.*; import java.awt.event.InvocationEvent; +import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; /** @@ -99,14 +101,14 @@ public class PlatformTestUtil { } public static String print(JTree tree, boolean withSelection, Condition nodePrintCondition) { - StringBuffer buffer = new StringBuffer(); + StringBuilder buffer = new StringBuilder(); Object root = tree.getModel().getRoot(); printImpl(tree, root, buffer, 0, withSelection, nodePrintCondition); return buffer.toString(); } - private static void printImpl(JTree tree, Object root, StringBuffer buffer, int level, boolean withSelection, @Nullable Condition nodePrintCondition) { + private static void printImpl(JTree tree, Object root, StringBuilder buffer, int level, boolean withSelection, @Nullable Condition nodePrintCondition) { DefaultMutableTreeNode defaultMutableTreeNode = (DefaultMutableTreeNode)root; @@ -116,7 +118,7 @@ public class PlatformTestUtil { nodeText = toString(userObject, null); } else { - nodeText = defaultMutableTreeNode + ""; + nodeText = String.valueOf(defaultMutableTreeNode); } @@ -163,8 +165,10 @@ public class PlatformTestUtil { Assert.assertEquals(expected, treeStringPresentation); } + @TestOnly public static void waitForAlarm(final int delay) throws InterruptedException { - final boolean[] invoked = new boolean[]{false}; + assert !ApplicationManager.getApplication().isWriteAccessAllowed(): "It's a bad idea to wait for an alarm under the write action. Somebody creates an alarm which requires read action and you are deadlocked."; + final AtomicBoolean invoked = new AtomicBoolean(); final Alarm alarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); alarm.addRequest(new Runnable() { @Override @@ -175,7 +179,7 @@ public class PlatformTestUtil { alarm.addRequest(new Runnable() { @Override public void run() { - invoked[0] = true; + invoked.set(true); } }, delay); } @@ -185,10 +189,13 @@ public class PlatformTestUtil { UIUtil.dispatchAllInvocationEvents(); - while (!invoked[0]) { + boolean sleptAlready = false; + while (!invoked.get()) { UIUtil.dispatchAllInvocationEvents(); - Thread.sleep(delay); + Thread.sleep(sleptAlready ? 10 : delay); + sleptAlready = true; } + UIUtil.dispatchAllInvocationEvents(); } @TestOnly diff --git a/platform/util/src/com/intellij/util/containers/TransferToEDTQueue.java b/platform/util/src/com/intellij/util/containers/TransferToEDTQueue.java index 4f374caaa6c0..abe2edbb296e 100644 --- a/platform/util/src/com/intellij/util/containers/TransferToEDTQueue.java +++ b/platform/util/src/com/intellij/util/containers/TransferToEDTQueue.java @@ -52,7 +52,7 @@ public class TransferToEDTQueue { T thing = myQueue.poll(); if (thing == null) break; if (!myProcessor.process(thing)) { - myQueue.clear(); + stop(); return; } processed++; From c0eb2f31081013559acb974c42294a339677a616 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 21 Feb 2011 15:41:45 +0300 Subject: [PATCH 023/169] cleanup --- .../impl/quickfix/CreateMethodQuickFix.java | 26 ++++---- .../daemon/impl/quickfix/OrderEntryFix.java | 10 +--- .../impl/StructureNodeRenderer.java | 26 ++++---- .../impl/java/JavaClassTreeElement.java | 5 +- .../impl/java/JavaFileTreeElement.java | 1 - .../pom/java/impl/PomJavaAspectImpl.java | 2 +- .../java/events/PomJavaAspectChangeSet.java | 13 +--- .../util/indexing/FileBasedIndex.java | 9 ++- .../util/treeView/AbstractTreeUpdater.java | 21 +++---- .../util/ui/update/MergingUpdateQueue.java | 7 +-- .../BreadcrumbsLoaderComponent.java | 30 ++++------ .../breadcrumbs/BreadcrumbsXmlWrapper.java | 59 ++++++++++++------- 12 files changed, 92 insertions(+), 117 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodQuickFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodQuickFix.java index b232cb7dce86..2826cec4c910 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodQuickFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodQuickFix.java @@ -24,7 +24,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; -import com.intellij.psi.impl.JavaPsiFacadeEx; import com.intellij.psi.util.PsiFormatUtil; import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; @@ -61,23 +60,18 @@ public class CreateMethodQuickFix implements LocalQuickFix { } public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) { - try { - if (!CodeInsightUtilBase.preparePsiElementForWrite(myTargetClass.getContainingFile())) return; + if (!CodeInsightUtilBase.preparePsiElementForWrite(myTargetClass.getContainingFile())) return; - PsiMethod method = createMethod(project); - List> arguments = - ContainerUtil.map2List(method.getParameterList().getParameters(), new Function>() { - public Pair fun(PsiParameter psiParameter) { - return Pair.create(null, psiParameter.getType()); - } - }); + PsiMethod method = createMethod(project); + List> arguments = + ContainerUtil.map2List(method.getParameterList().getParameters(), new Function>() { + public Pair fun(PsiParameter psiParameter) { + return Pair.create(null, psiParameter.getType()); + } + }); - method = (PsiMethod)JavaCodeStyleManager.getInstance(project).shortenClassReferences((PsiMethod)myTargetClass.add(method)); - CreateMethodFromUsageFix.doCreate(myTargetClass, method, arguments, PsiSubstitutor.EMPTY, ExpectedTypeInfo.EMPTY_ARRAY, method); - } - catch (IncorrectOperationException e) { - throw new RuntimeException(e); - } + method = (PsiMethod)JavaCodeStyleManager.getInstance(project).shortenClassReferences((PsiMethod)myTargetClass.add(method)); + CreateMethodFromUsageFix.doCreate(myTargetClass, method, arguments, PsiSubstitutor.EMPTY, ExpectedTypeInfo.EMPTY_ARRAY, method); } private PsiMethod createMethod(Project project) { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/OrderEntryFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/OrderEntryFix.java index 0c1b429466db..9c9e93c96193 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/OrderEntryFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/OrderEntryFix.java @@ -22,6 +22,7 @@ import com.intellij.codeInsight.daemon.impl.actions.AddImportAction; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.compiler.ModuleCompilerUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.application.Result; @@ -42,8 +43,6 @@ import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; -import com.intellij.util.IncorrectOperationException; -import com.intellij.compiler.ModuleCompilerUtil; import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -72,12 +71,7 @@ public abstract class OrderEntryFix implements IntentionAction, LocalQuickFix { } public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) { - try { - invoke(project, null, descriptor.getPsiElement().getContainingFile()); - } - catch (IncorrectOperationException e) { - throw new RuntimeException(e); - } + invoke(project, null, descriptor.getPsiElement().getContainingFile()); } @Nullable diff --git a/java/java-impl/src/com/intellij/ide/structureView/impl/StructureNodeRenderer.java b/java/java-impl/src/com/intellij/ide/structureView/impl/StructureNodeRenderer.java index 74af60cec239..35cc77e12166 100644 --- a/java/java-impl/src/com/intellij/ide/structureView/impl/StructureNodeRenderer.java +++ b/java/java-impl/src/com/intellij/ide/structureView/impl/StructureNodeRenderer.java @@ -23,6 +23,7 @@ import com.intellij.openapi.roots.ui.util.ModifiableCellAppearance; import com.intellij.openapi.util.Iconable; import com.intellij.psi.*; import com.intellij.psi.util.PsiFormatUtil; +import com.intellij.psi.util.PsiFormatUtilBase; import com.intellij.ui.ColoredTreeCellRenderer; import com.intellij.ui.SimpleTextAttributes; @@ -51,7 +52,8 @@ public class StructureNodeRenderer extends ColoredTreeCellRenderer { ModifiableCellAppearance result; if (psiElement instanceof PsiElement && !((PsiElement)psiElement).isValid()) { result = CompositeAppearance.single(name); - } else { + } + else { PsiClass psiClass = getContainingClass(psiElement); if (isInheritedMember(node, psiClass) && psiClass != null) { CompositeAppearance.DequeEnd ending = new CompositeAppearance().getEnding(); @@ -84,13 +86,13 @@ public class StructureNodeRenderer extends ColoredTreeCellRenderer { } } - public static String getNameOf(PsiElement psiElement) { + private static String getNameOf(PsiElement psiElement) { if (psiElement instanceof PsiMethod) return PsiFormatUtil.formatMethod((PsiMethod)psiElement, PsiSubstitutor.EMPTY, - PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_TYPE | PsiFormatUtil.TYPE_AFTER | - PsiFormatUtil.SHOW_PARAMETERS, - PsiFormatUtil.SHOW_TYPE + PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_TYPE | PsiFormatUtilBase.TYPE_AFTER | + PsiFormatUtilBase.SHOW_PARAMETERS, + PsiFormatUtilBase.SHOW_TYPE ); return psiElement.toString(); } @@ -109,23 +111,17 @@ public class StructureNodeRenderer extends ColoredTreeCellRenderer { return new SimpleTextAttributes(nameAttributes.getStyle() | SimpleTextAttributes.STYLE_STRIKEOUT, nameAttributes.getFgColor()); } - public static boolean isDeprecated(Object psiElement) { - if (psiElement instanceof PsiDocCommentOwner) - return ((PsiDocCommentOwner) psiElement).isDeprecated(); - return false; + private static boolean isDeprecated(Object psiElement) { + return psiElement instanceof PsiDocCommentOwner && ((PsiDocCommentOwner)psiElement).isDeprecated(); } - public static PsiClass getContainingClass(Object element) { + private static PsiClass getContainingClass(Object element) { if (element instanceof PsiMember) return ((PsiMember) element).getContainingClass(); - if (element instanceof PsiClass) { - PsiElement parent = ((PsiClass) element).getParent(); - return (PsiClass) (parent instanceof PsiClass ? parent : null); - } return null; } - public static PsiClass getTreeParentClass(Object value) { + private static PsiClass getTreeParentClass(Object value) { if (!(value instanceof TreeNode)) return null; for (TreeNode treeNode = ((TreeNode) value).getParent(); treeNode != null; treeNode = treeNode.getParent()) { diff --git a/java/java-impl/src/com/intellij/ide/structureView/impl/java/JavaClassTreeElement.java b/java/java-impl/src/com/intellij/ide/structureView/impl/java/JavaClassTreeElement.java index b97433a98ca3..80951de253bd 100644 --- a/java/java-impl/src/com/intellij/ide/structureView/impl/java/JavaClassTreeElement.java +++ b/java/java-impl/src/com/intellij/ide/structureView/impl/java/JavaClassTreeElement.java @@ -35,10 +35,8 @@ public class JavaClassTreeElement extends JavaClassTreeElementBase { } private Collection getClassChildren() { - ArrayList array = new ArrayList(); - final PsiClass aClass = getElement(); - if (aClass == null) return array; + if (aClass == null) return Collections.emptyList(); List children = Arrays.asList(aClass.getChildren()); Collection ownChildren = new THashSet(); @@ -47,6 +45,7 @@ public class JavaClassTreeElement extends JavaClassTreeElementBase { ContainerUtil.addAll(ownChildren, aClass.getInnerClasses()); ContainerUtil.addAll(ownChildren, aClass.getInitializers()); Collection inherited = new LinkedHashSet(children); + List array = new ArrayList(inherited.size()); aClass.processDeclarations(new AddAllMembersProcessor(inherited, aClass), ResolveState.initial(), null, aClass); diff --git a/java/java-impl/src/com/intellij/ide/structureView/impl/java/JavaFileTreeElement.java b/java/java-impl/src/com/intellij/ide/structureView/impl/java/JavaFileTreeElement.java index 1a5bb59cf538..98a587a369c2 100644 --- a/java/java-impl/src/com/intellij/ide/structureView/impl/java/JavaFileTreeElement.java +++ b/java/java-impl/src/com/intellij/ide/structureView/impl/java/JavaFileTreeElement.java @@ -26,7 +26,6 @@ import java.util.ArrayList; import java.util.Collection; public class JavaFileTreeElement extends PsiTreeElementBase implements ItemPresentation { - public JavaFileTreeElement(PsiJavaFile file) { super(file); } diff --git a/java/java-impl/src/com/intellij/pom/java/impl/PomJavaAspectImpl.java b/java/java-impl/src/com/intellij/pom/java/impl/PomJavaAspectImpl.java index 9d128cb0c178..e3d0276469e1 100644 --- a/java/java-impl/src/com/intellij/pom/java/impl/PomJavaAspectImpl.java +++ b/java/java-impl/src/com/intellij/pom/java/impl/PomJavaAspectImpl.java @@ -68,7 +68,7 @@ public class PomJavaAspectImpl extends PomJavaAspect implements ProjectComponent if(changeSet == null) return; final PsiFile containingFile = changeSet.getRootElement().getPsi().getContainingFile(); if(!(containingFile.getLanguage() instanceof JavaLanguage)) return; - final PomJavaAspectChangeSet set = new PomJavaAspectChangeSet(myPomModel, containingFile); + final PomJavaAspectChangeSet set = new PomJavaAspectChangeSet(myPomModel); set.addChange(new JavaTreeChanged(containingFile)); event.registerChangeSet(this, set); } diff --git a/java/openapi/src/com/intellij/pom/java/events/PomJavaAspectChangeSet.java b/java/openapi/src/com/intellij/pom/java/events/PomJavaAspectChangeSet.java index d1e2792219f9..2625a48a6144 100644 --- a/java/openapi/src/com/intellij/pom/java/events/PomJavaAspectChangeSet.java +++ b/java/openapi/src/com/intellij/pom/java/events/PomJavaAspectChangeSet.java @@ -20,7 +20,6 @@ import com.intellij.pom.PomModel; import com.intellij.pom.PomModelAspect; import com.intellij.pom.event.PomChangeSet; import com.intellij.pom.java.PomJavaAspect; -import com.intellij.psi.PsiFile; import java.util.ArrayList; import java.util.List; @@ -28,22 +27,16 @@ import java.util.List; public class PomJavaAspectChangeSet implements PomChangeSet{ private final PomModel myModel; private final List myChanges = new ArrayList(); - private final PsiFile myChangedFile; - public PomJavaAspectChangeSet(PomModel model, PsiFile fileChanged) { + public PomJavaAspectChangeSet(PomModel model) { myModel = model; - myChangedFile = fileChanged; } public void addChange(PomJavaChange change) { myChanges.add(change); } - public List getChanges() { - return myChanges; - } - public PomModelAspect getAspect() { return myModel.getModelAspect(PomJavaAspect.class); } @@ -53,8 +46,4 @@ public class PomJavaAspectChangeSet implements PomChangeSet{ final PomJavaAspectChangeSet blockedJavaChange = (PomJavaAspectChangeSet)blocked; myChanges.addAll(blockedJavaChange.myChanges); } - - public PsiFile getChangedFile() { - return myChangedFile; - } } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java index d54a659b2deb..07591f7c4d6f 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java @@ -102,8 +102,9 @@ public class FileBasedIndex implements ApplicationComponent { private final Set myNoLimitCheckTypes = new HashSet(); private final PerIndexDocumentMap myLastIndexedDocStamps = new PerIndexDocumentMap() { + @NotNull @Override - protected Long createDefault(Document document) { + protected Long createDefault(@NotNull Document document) { return 0L; } }; @@ -1161,7 +1162,7 @@ public class FileBasedIndex implements ApplicationComponent { } // returns false if doc was not indexed because the file does not fit in scope - private boolean indexUnsavedDocument(final Document document, final ID requestedIndexId, final Project project, GlobalSearchScope filter) throws StorageException { + private boolean indexUnsavedDocument(@NotNull final Document document, @NotNull final ID requestedIndexId, final Project project, GlobalSearchScope filter) throws StorageException { final VirtualFile vFile = myFileDocumentManager.getFile(document); if (!(vFile instanceof VirtualFileWithId) || !vFile.isValid()) { return true; @@ -1253,9 +1254,7 @@ public class FileBasedIndex implements ApplicationComponent { } private void cleanupMemoryStorage() { - synchronized (myLastIndexedDocStamps) { - myLastIndexedDocStamps.clear(); - } + myLastIndexedDocStamps.clear(); for (ID indexId : myIndices.keySet()) { final MapReduceIndex index = (MapReduceIndex)getIndex(indexId); assert index != null; diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUpdater.java b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUpdater.java index c076a99d3013..a6bfe1507455 100644 --- a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUpdater.java +++ b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUpdater.java @@ -86,7 +86,7 @@ public class AbstractTreeUpdater implements Disposable, Activatable { } public boolean hasNodesToUpdate() { - return myNodeQueue.size() > 0 || !myUpdateQueue.isEmpty(); + return !myNodeQueue.isEmpty() || !myUpdateQueue.isEmpty(); } public void dispose() { @@ -114,15 +114,15 @@ public class AbstractTreeUpdater implements Disposable, Activatable { toAdd.expire(); break; } - else if (passInQueue.getNode() == toAdd.getNode()) { + if (passInQueue.getNode() == toAdd.getNode()) { toAdd.expire(); break; } - else if (toAdd.getNode().isNodeAncestor(passInQueue.getNode())) { + if (toAdd.getNode().isNodeAncestor(passInQueue.getNode())) { toAdd.expire(); break; } - else if (passInQueue.getNode().isNodeAncestor(toAdd.getNode())) { + if (passInQueue.getNode().isNodeAncestor(toAdd.getNode())) { iterator.remove(); passInQueue.expire(); } @@ -133,9 +133,7 @@ public class AbstractTreeUpdater implements Disposable, Activatable { if (!toAdd.isExpired()) { final Collection yielding = ui.getYeildingPasses(); - for (Iterator iterator = yielding.iterator(); iterator.hasNext();) { - TreeUpdatePass eachYielding = iterator.next(); - + for (TreeUpdatePass eachYielding : yielding) { final DefaultMutableTreeNode eachNode = eachYielding.getCurrentNode(); if (eachNode != null) { if (eachNode.isNodeAncestor(toAdd.getNode())) { @@ -228,8 +226,7 @@ public class AbstractTreeUpdater implements Disposable, Activatable { try { myTreeBuilder.getUi().updateSubtreeNow(eachPass, false); } - catch (ProcessCanceledException e) { - return; + catch (ProcessCanceledException ignored) { } } }); @@ -348,10 +345,8 @@ public class AbstractTreeUpdater implements Disposable, Activatable { } public boolean isEnqueuedToUpdate(DefaultMutableTreeNode node) { - Iterator nodes = myNodeQueue.iterator(); - while (nodes.hasNext()) { - TreeUpdatePass each = nodes.next(); - if (each.willUpdate(node)) return true; + for (TreeUpdatePass pass : myNodeQueue) { + if (pass.willUpdate(node)) return true; } return false; } diff --git a/platform/platform-api/src/com/intellij/util/ui/update/MergingUpdateQueue.java b/platform/platform-api/src/com/intellij/util/ui/update/MergingUpdateQueue.java index bcb2e34055f7..c6fec60254d8 100644 --- a/platform/platform-api/src/com/intellij/util/ui/update/MergingUpdateQueue.java +++ b/platform/platform-api/src/com/intellij/util/ui/update/MergingUpdateQueue.java @@ -123,8 +123,7 @@ public class MergingUpdateQueue implements Runnable, Disposable, Activatable { try { each.setRejected(); } - catch (ProcessCanceledException e) { - continue; + catch (ProcessCanceledException ignored) { } } myScheduledUpdates.clear(); @@ -237,7 +236,7 @@ public class MergingUpdateQueue implements Runnable, Disposable, Activatable { } }; - if (myExecuteInDispatchThread && invokeLaterIfNotDispatch && !ApplicationManager.getApplication().isDispatchThread()) { + if (myExecuteInDispatchThread && invokeLaterIfNotDispatch) { UIUtil.invokeLaterIfNeeded(toRun); } else { @@ -394,7 +393,7 @@ public class MergingUpdateQueue implements Runnable, Disposable, Activatable { public boolean isEmpty() { synchronized (myScheduledUpdates) { - return myScheduledUpdates.size() == 0; + return myScheduledUpdates.isEmpty(); } } diff --git a/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsLoaderComponent.java b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsLoaderComponent.java index 236d5cd730c4..17d5aa1007da 100644 --- a/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsLoaderComponent.java +++ b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsLoaderComponent.java @@ -48,20 +48,20 @@ public class BreadcrumbsLoaderComponent extends AbstractProjectComponent { return webEditorOptions.isBreadcrumbsEnabled() || webEditorOptions.isBreadcrumbsEnabledInXml(); } - private static class MyFileEditorManagerListener implements FileEditorManagerListener { + private static class MyFileEditorManagerListener extends FileEditorManagerAdapter { public void fileOpened(final FileEditorManager source, final VirtualFile file) { if (isEnabled() && isSuitable(source.getProject(), file)) { final FileEditor[] fileEditors = source.getEditors(file); - for (final FileEditor each : fileEditors) { - if (each instanceof TextEditor) { - final BreadcrumbsXmlWrapper wrapper = new BreadcrumbsXmlWrapper(((TextEditor)each).getEditor()); + for (final FileEditor fileEditor : fileEditors) { + if (fileEditor instanceof TextEditor) { + final BreadcrumbsXmlWrapper wrapper = new BreadcrumbsXmlWrapper(((TextEditor)fileEditor).getEditor()); final JComponent c = wrapper.getComponent(); - source.addTopComponent(each, c); + source.addTopComponent(fileEditor, c); - Disposer.register(each, wrapper); - Disposer.register(each, new Disposable() { + Disposer.register(fileEditor, wrapper); + Disposer.register(fileEditor, new Disposable() { public void dispose() { - source.removeTopComponent(each, c); + source.removeTopComponent(fileEditor, c); } }); } @@ -74,11 +74,11 @@ public class BreadcrumbsLoaderComponent extends AbstractProjectComponent { return false; } - final FileViewProvider psiFile = PsiManager.getInstance(project).findViewProvider(file); + final FileViewProvider provider = PsiManager.getInstance(project).findViewProvider(file); - return psiFile != null - && hasNonEmptyHtml(psiFile) - && BreadcrumbsXmlWrapper.findInfoProvider(psiFile) != null; + return provider != null + && hasNonEmptyHtml(provider) + && BreadcrumbsXmlWrapper.findInfoProvider(provider) != null; } public static boolean hasNonEmptyHtml(FileViewProvider viewProvider) { @@ -94,11 +94,5 @@ public class BreadcrumbsLoaderComponent extends AbstractProjectComponent { } return false; } - - public void fileClosed(final FileEditorManager source, final VirtualFile file) { - } - - public void selectionChanged(final FileEditorManagerEvent event) { - } } } diff --git a/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java index 95b2b2815ecd..ea00e02f2023 100644 --- a/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java +++ b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java @@ -34,13 +34,6 @@ import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vcs.FileStatusListener; import com.intellij.openapi.vcs.FileStatusManager; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.pom.PomManager; -import com.intellij.pom.PomModelAspect; -import com.intellij.pom.event.PomChangeSet; -import com.intellij.pom.event.PomModelEvent; -import com.intellij.pom.event.PomModelListener; -import com.intellij.pom.xml.XmlAspect; -import com.intellij.pom.xml.XmlChangeSet; import com.intellij.psi.*; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.update.MergingUpdateQueue; @@ -103,8 +96,7 @@ public class BreadcrumbsXmlWrapper implements BreadcrumbsItemListener(); myComponent.addBreadcrumbsItemListener(this); @@ -140,8 +153,7 @@ public class BreadcrumbsXmlWrapper implements BreadcrumbsItemListener Date: Mon, 21 Feb 2011 13:50:37 +0100 Subject: [PATCH 024/169] cleanup and refactoring --- .../SpellCheckerDictionaryGenerator.java | 116 +++++++++++------- .../inspections/SpellCheckingInspection.java | 7 +- 2 files changed, 74 insertions(+), 49 deletions(-) diff --git a/plugins/spellchecker/src/com/intellij/spellchecker/generator/SpellCheckerDictionaryGenerator.java b/plugins/spellchecker/src/com/intellij/spellchecker/generator/SpellCheckerDictionaryGenerator.java index 066a1258e0f0..086b414348af 100644 --- a/plugins/spellchecker/src/com/intellij/spellchecker/generator/SpellCheckerDictionaryGenerator.java +++ b/plugins/spellchecker/src/com/intellij/spellchecker/generator/SpellCheckerDictionaryGenerator.java @@ -2,6 +2,8 @@ package com.intellij.spellchecker.generator; import com.intellij.lang.refactoring.NamesValidator; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.io.FileUtil; @@ -29,6 +31,7 @@ public abstract class SpellCheckerDictionaryGenerator { private final String myDefaultDictName; protected final String myDictOutputFolder; protected final MultiMap myDict2FolderMap; + protected final Set myExcludedFolders = new HashSet(); protected SpellCheckerManager mySpellCheckerManager; protected NamesValidator[] myNamesValidators; @@ -46,35 +49,45 @@ public abstract class SpellCheckerDictionaryGenerator { myDict2FolderMap.putValue(dictName, path); } + public void excludeFolder(VirtualFile folder) { + myExcludedFolders.add(folder); + } + public void generate() { - // let's do result a bit more predictable + ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { + @Override + public void run() { + ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator(); + // let's do result a bit more predictable - // ruby dictionary - generate(myDefaultDictName); + // ruby dictionary + generate(myDefaultDictName, progressIndicator); - // other gem-related dictionaries in alphabet order - final List dictsList = new ArrayList(myDict2FolderMap.keySet()); - Collections.sort(dictsList); + // other gem-related dictionaries in alphabet order + final List dictsList = new ArrayList(myDict2FolderMap.keySet()); + Collections.sort(dictsList); - for (String dict : dictsList) { - if (myDefaultDictName.equals(dict)) { - continue; + for (String dict : dictsList) { + if (myDefaultDictName.equals(dict)) { + continue; + } + generate(dict, progressIndicator); + } } - generate(dict); - } + }, "Generating Dictionaries", false, myProject); } - private void generate(@NotNull String dict) { - System.out.println("Processing dictionary: " + dict); - generateDictionary(myProject, myDict2FolderMap.get(dict), myDictOutputFolder + "/" + dict + ".dic"); - System.out.println("Done"); + private void generate(@NotNull String dict, ProgressIndicator progressIndicator) { + progressIndicator.setText("Processing dictionary: " + dict); + generateDictionary(myProject, myDict2FolderMap.get(dict), myDictOutputFolder + "/" + dict + ".dic", progressIndicator); } - private void generateDictionary(final Project project, final Collection folderPaths, final String outFile) { + private void generateDictionary(final Project project, final Collection folderPaths, final String outFile, + final ProgressIndicator progressIndicator) { final HashSet seenNames = new HashSet(); // Collect stuff for (VirtualFile folder : folderPaths) { - System.out.println(" Scanning folder: " + folder.getPath()); + progressIndicator.setText2("Scanning folder: " + folder.getPath()); final PsiManager manager = PsiManager.getInstance(project); processFolder(seenNames, manager, folder); } @@ -110,10 +123,13 @@ public abstract class SpellCheckerDictionaryGenerator { } } - private void processFolder(final HashSet seenNames, final PsiManager manager, + protected void processFolder(final HashSet seenNames, final PsiManager manager, final VirtualFile folder) { + if (myExcludedFolders.contains(folder)) { + return; + } for (VirtualFile virtualFile : folder.getChildren()) { - if (virtualFile.isDirectory()){ + if (virtualFile.isDirectory()) { processFolder(seenNames, manager, virtualFile); continue; } @@ -157,34 +173,42 @@ public abstract class SpellCheckerDictionaryGenerator { continue; } - for (CheckArea area : areas) { - boolean ignored = area.isIgnored(); - final TextRange textRange = area.getTextRange(); - - if (ignored || textRange ==null){ - continue; - } - - final String word = area.getWord(); - if (word == null) { - continue; - } - - final String lowerWord = word.toLowerCase(); - if (globalSeenNames.contains(lowerWord)) { - continue; - } - - boolean keyword = SpellCheckingInspection.isKeyword(myNamesValidators, token.getElement(), word); - if (keyword){ - continue; - } - globalSeenNames.add(lowerWord); - if (mySpellCheckerManager.hasProblem(lowerWord)){ - seenNames.add(lowerWord); - } - } + processCheckAreas(areas, seenNames); } } } + + protected void processCheckAreas(List areas, HashSet seenNames) { + for (CheckArea area : areas) { + boolean ignored = area.isIgnored(); + final TextRange textRange = area.getTextRange(); + + if (ignored || textRange ==null){ + continue; + } + + final String word = area.getWord(); + if (word == null) { + continue; + } + + addSeenWord(seenNames, word); + } + } + + private void addSeenWord(HashSet seenNames, String word) { + final String lowerWord = word.toLowerCase(); + if (globalSeenNames.contains(lowerWord)) { + return; + } + + boolean keyword = SpellCheckingInspection.isKeyword(myProject, myNamesValidators, word); + if (keyword){ + return; + } + globalSeenNames.add(lowerWord); + if (mySpellCheckerManager.hasProblem(lowerWord)){ + seenNames.add(lowerWord); + } + } } diff --git a/plugins/spellchecker/src/com/intellij/spellchecker/inspections/SpellCheckingInspection.java b/plugins/spellchecker/src/com/intellij/spellchecker/inspections/SpellCheckingInspection.java index f6a75cb6e492..81ccdd9853c1 100644 --- a/plugins/spellchecker/src/com/intellij/spellchecker/inspections/SpellCheckingInspection.java +++ b/plugins/spellchecker/src/com/intellij/spellchecker/inspections/SpellCheckingInspection.java @@ -26,6 +26,7 @@ import com.intellij.lang.refactoring.NamesValidator; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileTypes.PlainTextLanguage; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; @@ -192,7 +193,7 @@ public class SpellCheckingInspection extends LocalInspectionTool { continue; } - boolean keyword = isKeyword(validators, token.getElement(), word); + boolean keyword = isKeyword(token.getElement().getProject(), validators, word); if (keyword){ continue; } @@ -265,12 +266,12 @@ public class SpellCheckingInspection extends LocalInspectionTool { return validators; } - public static boolean isKeyword(NamesValidator[] validators, PsiElement element, String word) { + public static boolean isKeyword(Project project, NamesValidator[] validators, String word) { if (validators == null) { return false; } for (NamesValidator validator : validators) { - if (validator.isKeyword(word, element.getProject())) { + if (validator.isKeyword(word, project)) { return true; } } From 8ba5d2f75c521863c4e6dd66f7b270b549aa7e0e Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Mon, 21 Feb 2011 16:08:51 +0300 Subject: [PATCH 025/169] IDEA-65747 Javadoc: Don't use attribute value on javadoc tag autocompletion 1. Tag name only is used during javadoc tag auto completion; 2. Corresponding test is added; 3. java-impl module config file is corrected in order to define test source root; --- java/java-impl/java-impl.iml | 1 + .../codeInsight/editorActions/JavadocTypedHandler.java | 5 +++++ .../codeInsight/editorActions/JavadocTypedHandlerTest.java | 6 ++++++ 3 files changed, 12 insertions(+) diff --git a/java/java-impl/java-impl.iml b/java/java-impl/java-impl.iml index c52f97bf075d..f5bd5cce2b5f 100644 --- a/java/java-impl/java-impl.iml +++ b/java/java-impl/java-impl.iml @@ -4,6 +4,7 @@ + diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavadocTypedHandler.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavadocTypedHandler.java index f8de3b44ae76..8e792448c65f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavadocTypedHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavadocTypedHandler.java @@ -117,6 +117,11 @@ public class JavadocTypedHandler extends TypedHandlerDelegate { return null; } return text.subSequence(i + 1, endOffset).toString(); + + // There is a possible case that opening tag has attributes, e.g. [offset]. We want to extract + // only tag name then. + case ' ': + case '\t': endOffset = i; } } return null; diff --git a/java/java-impl/testSrc/com/intellij/codeInsight/editorActions/JavadocTypedHandlerTest.java b/java/java-impl/testSrc/com/intellij/codeInsight/editorActions/JavadocTypedHandlerTest.java index 891157c1bdaa..b5935250a698 100644 --- a/java/java-impl/testSrc/com/intellij/codeInsight/editorActions/JavadocTypedHandlerTest.java +++ b/java/java-impl/testSrc/com/intellij/codeInsight/editorActions/JavadocTypedHandlerTest.java @@ -37,6 +37,12 @@ public class JavadocTypedHandlerTest { doTest("", null); } + @Test + public void tagWithAttribute() { + doTest("", "a"); + //TODO den implement + } + private static void doTest(String text, String expected) { StringBuilder normalized = new StringBuilder(); int offset = text.indexOf(CARET_MARKER); From c712ffb5cc8ceba45931b588f1344cc4f970b0e9 Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Mon, 21 Feb 2011 16:54:25 +0300 Subject: [PATCH 026/169] missing error logging inside IdeEventQueue added --- .../platform-impl/src/com/intellij/ide/IdeEventQueue.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java index e978cc84e260..f222cd4772cd 100644 --- a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java +++ b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java @@ -366,6 +366,12 @@ public class IdeEventQueue extends EventQueue { try { _dispatchEvent(e); + } catch (ProcessCanceledException pce) { + throw pce; + } catch (Throwable exc) { + if (!myToolkitBugsProcessor.process(exc)) { + LOG.error("Error during dispatching of " + e, exc); + } } finally { myIsInInputEvent = wasInputEvent; From 4a73acca9622a85518f241e281636276d3851807 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Mon, 21 Feb 2011 13:50:20 +0300 Subject: [PATCH 027/169] synchronization --- .../execution/runners/ConsoleExecuteActionHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java b/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java index 6f4571eb3502..bbc4c9271ede 100644 --- a/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java +++ b/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java @@ -57,10 +57,10 @@ public class ConsoleExecuteActionHandler { } public void processLine(String line) { - sendLine(line + "\n"); + sendText(line + "\n"); } - public void sendLine(String line) { + public void sendText(String line) { //final Charset charset = myProcessHandler.getCharset(); final OutputStream outputStream = myProcessHandler.getProcessInput(); try { From e29bf9f509f79a6e8b397627ec0499e66f829e35 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 21 Feb 2011 10:52:15 +0100 Subject: [PATCH 028/169] diamonds inference: test data just-in-case --- .../advHighlighting7/DiamondMisc.java | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java index 30b750e35c9f..d802f473b299 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java @@ -42,4 +42,28 @@ class Test1 { } class FF extends F{} -class F {} \ No newline at end of file +class F {} + +class MyTest { + static class Foo { + Foo(X x) {} + } + + static interface Base {} + static class A extends Exception implements Base {} + static class B extends Exception implements Base {} + + void m() throws B { + try { + if (true) { + throw new A(); + } + else { + throw new B(); + } + } catch (A ex) { + Foo> foo1 = new Foo<>(ex); // ok + Foo> foo2 = new Foo<>(ex); // should be error + } + } +} From 405c72fe2cf5171ee0feac24dc27bdec720ecb36 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 21 Feb 2011 12:04:39 +0100 Subject: [PATCH 029/169] do not register palette toolwindow in headless mode --- .../ide/palette/impl/PaletteManager.java | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/java/idea-ui/src/com/intellij/ide/palette/impl/PaletteManager.java b/java/idea-ui/src/com/intellij/ide/palette/impl/PaletteManager.java index afdc835518e1..b6f2063a7043 100644 --- a/java/idea-ui/src/com/intellij/ide/palette/impl/PaletteManager.java +++ b/java/idea-ui/src/com/intellij/ide/palette/impl/PaletteManager.java @@ -19,6 +19,7 @@ package com.intellij.ide.palette.impl; import com.intellij.ide.IdeBundle; import com.intellij.ide.palette.PaletteDragEventListener; import com.intellij.ide.palette.PaletteItem; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ProjectComponent; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.FileEditorManagerEvent; @@ -60,20 +61,22 @@ public class PaletteManager implements ProjectComponent { } public void projectOpened() { - StartupManager.getInstance(myProject).registerPostStartupActivity(new Runnable() { - public void run() { - myPaletteWindow = new PaletteWindow(myProject); - myPaletteToolWindow = ToolWindowManager.getInstance(myProject).registerToolWindow(IdeBundle.message("toolwindow.palette"), - myPaletteWindow, - ToolWindowAnchor.RIGHT, - myProject, - true); - myPaletteToolWindow.setIcon(IconLoader.getIcon("/general/toolWindowPalette.png")); - myPaletteToolWindow.setAvailable(false, null); - final MyFileEditorManagerListener myListener = new MyFileEditorManagerListener(); - myFileEditorManager.addFileEditorManagerListener(myListener, myProject); - } - }); + if (!ApplicationManager.getApplication().isHeadlessEnvironment()) { + StartupManager.getInstance(myProject).registerPostStartupActivity(new Runnable() { + public void run() { + myPaletteWindow = new PaletteWindow(myProject); + myPaletteToolWindow = ToolWindowManager.getInstance(myProject).registerToolWindow(IdeBundle.message("toolwindow.palette"), + myPaletteWindow, + ToolWindowAnchor.RIGHT, + myProject, + true); + myPaletteToolWindow.setIcon(IconLoader.getIcon("/general/toolWindowPalette.png")); + myPaletteToolWindow.setAvailable(false, null); + final MyFileEditorManagerListener myListener = new MyFileEditorManagerListener(); + myFileEditorManager.addFileEditorManagerListener(myListener, myProject); + } + }); + } } public void projectClosed() { From cba89d3a297bba439a35cfa399422962459ea34f Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 21 Feb 2011 12:34:35 +0100 Subject: [PATCH 030/169] analysis scope: do not ignore test sources on/off for global scope --- platform/lang-api/src/com/intellij/analysis/AnalysisScope.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/lang-api/src/com/intellij/analysis/AnalysisScope.java b/platform/lang-api/src/com/intellij/analysis/AnalysisScope.java index 9460a5791b6b..b7fc38cdbc95 100644 --- a/platform/lang-api/src/com/intellij/analysis/AnalysisScope.java +++ b/platform/lang-api/src/com/intellij/analysis/AnalysisScope.java @@ -237,7 +237,9 @@ public class AnalysisScope { protected void accept(final PsiElementVisitor visitor, final boolean needReadAction) { if (myType == VIRTUAL_FILES) { final PsiManager psiManager = PsiManager.getInstance(myProject); + final FileIndex index = ProjectRootManager.getInstance(myProject).getFileIndex(); for (final VirtualFile file : myFilesSet) { + if (!myIncludeTestSource && index.isInTestSourceContent(file)) continue; if (!processFile(file, visitor, psiManager, needReadAction)) return; } } else if (myScope instanceof GlobalSearchScope) { @@ -247,6 +249,7 @@ public class AnalysisScope { public boolean processFile(final VirtualFile fileOrDir) { final boolean isInScope = ApplicationManager.getApplication().runReadAction(new Computable() { public Boolean compute() { + if (!myIncludeTestSource && projectFileIndex.isInTestSourceContent(fileOrDir)) return false; return ((GlobalSearchScope)myScope).contains(fileOrDir); } }).booleanValue(); From 25e7ff1ef455539f281bf7707263b003b63aa26b Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 21 Feb 2011 12:39:58 +0100 Subject: [PATCH 031/169] NPE (IDEA-65565) --- .../changeSignature/ChangeSignatureGestureDetector.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureGestureDetector.java b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureGestureDetector.java index 189f15b8742a..0caed03d9f5c 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureGestureDetector.java +++ b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureGestureDetector.java @@ -199,7 +199,9 @@ public class ChangeSignatureGestureDetector extends PsiTreeChangeAdapter impleme if (changeBean != null && changeBean.getInitialText() != null) { final Editor editor = myFileEditorManager.getSelectedTextEditor(); if (editor != null && myTemplateManager.getActiveTemplate(editor) != null) return; - if (LanguageChangeSignatureDetectors.INSTANCE.forLanguage(child.getLanguage()).ignoreChanges(child)) return; + final LanguageChangeSignatureDetector detector = LanguageChangeSignatureDetectors.INSTANCE.forLanguage(child.getLanguage()); + if (detector == null) return; + if (detector.ignoreChanges(child)) return; final ChangeInfo info = LanguageChangeSignatureDetectors.createCurrentChangeInfo(child, changeBean.getInitialChangeInfo()); if (info == null) { changeBean.reinit(); From 0749a3c3bf8caacc51254de4a85927e765968be5 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Mon, 21 Feb 2011 15:17:35 +0100 Subject: [PATCH 032/169] fix ant meta-target naming issue (IDEA-38634) --- .../intellij/lang/ant/config/impl/AntConfigurationImpl.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntConfigurationImpl.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntConfigurationImpl.java index cefc93e4dcfe..c20ac8d33c29 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntConfigurationImpl.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntConfigurationImpl.java @@ -343,9 +343,9 @@ public class AntConfigurationImpl extends AntConfigurationBase implements Persis return null; } for (ExecutionEvent ev : events) { - final String presentableName = ev.getPresentableName(); - if (Comparing.strEqual(targetName, presentableName)) { - return new MetaTarget(buildFile, presentableName, ((ExecuteCompositeTargetEvent)ev).getTargetNames()); + final String name = ExecuteCompositeTargetEvent.TYPE_ID.equals(ev.getTypeId())? ((ExecuteCompositeTargetEvent)ev).getMetaTargetName() : ev.getPresentableName(); + if (Comparing.strEqual(targetName, name)) { + return new MetaTarget(buildFile, ev.getPresentableName(), ((ExecuteCompositeTargetEvent)ev).getTargetNames()); } } return null; From 05bf505396a99e565024e09bfcbd0f7b64c60d74 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 21 Feb 2011 13:08:48 +0100 Subject: [PATCH 033/169] tab chooses the selected element in goto actions --- .../com/intellij/ide/util/gotoByName/ChooseByNameBase.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java index 169a393956a8..53a2008b05a2 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java @@ -447,6 +447,9 @@ public abstract class ChooseByNameBase { case KeyEvent.VK_PAGE_DOWN: ListScrollingUtil.movePageDown(myList); break; + case KeyEvent.VK_TAB: + close(true); + break; case KeyEvent.VK_ENTER: if (myList.getSelectedValue() == EXTRA_ELEM) { myMaximumListSizeLimit += MAXIMUM_LIST_SIZE_LIMIT; @@ -992,7 +995,7 @@ public abstract class ChooseByNameBase { myCompletionKeyStroke = getShortcut(IdeActions.ACTION_CODE_COMPLETION); forwardStroke = getShortcut(IdeActions.ACTION_GOTO_FORWARD); backStroke = getShortcut(IdeActions.ACTION_GOTO_BACK); - + setFocusTraversalKeysEnabled(false); } private KeyStroke getShortcut(String actionCodeCompletion) { From 3770f00baeb94db9bfe7917a14d27e225df22e4a Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 21 Feb 2011 14:15:34 +0100 Subject: [PATCH 034/169] remove duplication from goto actions --- .../actions/RunInspectionAction.java | 36 ++++++++--------- .../ide/actions/GotoActionAction.java | 15 ++----- .../intellij/ide/actions/GotoActionBase.java | 40 +++++++++++++++++++ .../intellij/ide/actions/GotoClassAction.java | 23 +++++------ .../intellij/ide/actions/GotoFileAction.java | 23 +++++------ .../ide/actions/GotoSymbolAction.java | 27 +++++-------- 6 files changed, 92 insertions(+), 72 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInspection/actions/RunInspectionAction.java b/platform/lang-impl/src/com/intellij/codeInspection/actions/RunInspectionAction.java index b5dbefcb4d96..0e074c0538a9 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/actions/RunInspectionAction.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/actions/RunInspectionAction.java @@ -27,20 +27,16 @@ import com.intellij.codeInspection.ex.InspectionProfileImpl; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.ide.IdeBundle; import com.intellij.ide.actions.GotoActionBase; +import com.intellij.ide.util.gotoByName.ChooseByNameFilter; import com.intellij.ide.util.gotoByName.ChooseByNamePopup; -import com.intellij.ide.util.gotoByName.ChooseByNamePopupComponent; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.LangDataKeys; import com.intellij.openapi.actionSystem.PlatformDataKeys; -import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiDirectory; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiManager; +import com.intellij.psi.*; import org.jdom.Element; import org.jetbrains.annotations.NotNull; @@ -57,26 +53,30 @@ public class RunInspectionAction extends GotoActionBase { @Override protected void gotoActionPerformed(final AnActionEvent e) { final Project project = e.getData(PlatformDataKeys.PROJECT); + if (project == null) return; + + PsiDocumentManager.getInstance(project).commitAllDocuments(); + final PsiElement psiElement = LangDataKeys.PSI_ELEMENT.getData(e.getDataContext()); final PsiFile psiFile = LangDataKeys.PSI_FILE.getData(e.getDataContext()); final VirtualFile virtualFile = LangDataKeys.VIRTUAL_FILE.getData(e.getDataContext()); - if (project == null || virtualFile == null) return; + if (virtualFile == null) return; + FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.goto.inspection"); - final ChooseByNamePopup popup = ChooseByNamePopup.createPopup(project, new GotoInspectionModel(project), getPsiContext(e)); - popup.setSearchInAnyPlace(true); - popup.invoke(new ChooseByNamePopupComponent.Callback() { - public void onClose() { - if (RunInspectionAction.class.equals(myInAction)) { - myInAction = null; - } + final GotoInspectionModel model = new GotoInspectionModel(project); + showNavigationPopup(e, model, new GotoActionCallback() { + @Override + protected ChooseByNameFilter createFilter(ChooseByNamePopup popup) { + popup.setSearchInAnyPlace(true); + return super.createFilter(popup); } - public void elementChosen(Object element) { - final InspectionProfileEntry profileEntry = (InspectionProfileEntry)element; - runInspection(project, profileEntry, virtualFile, psiElement, psiFile); + @Override + public void elementChosen(ChooseByNamePopup popup, Object element) { + runInspection(project, (InspectionProfileEntry)element, virtualFile, psiElement, psiFile); } - }, ModalityState.current(), true); + }); } private static void runInspection(@NotNull Project project, diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoActionAction.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoActionAction.java index 94df0b906239..aea4d046417c 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/GotoActionAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoActionAction.java @@ -19,7 +19,6 @@ package com.intellij.ide.actions; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.ide.DataManager; import com.intellij.ide.util.gotoByName.ChooseByNamePopup; -import com.intellij.ide.util.gotoByName.ChooseByNamePopupComponent; import com.intellij.ide.util.gotoByName.GotoActionModel; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.ActionUtil; @@ -38,15 +37,9 @@ public class GotoActionAction extends GotoActionBase implements DumbAware { FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.popup.action"); - final ChooseByNamePopup popup = ChooseByNamePopup.createPopup(project, new GotoActionModel(project, component), getPsiContext(e)); - popup.invoke(new ChooseByNamePopupComponent.Callback() { - public void onClose() { - if (GotoActionAction.class.equals(myInAction)) { - myInAction = null; - } - } - - public void elementChosen(Object element) { + showNavigationPopup(e, new GotoActionModel(project, component), new GotoActionCallback() { + @Override + public void elementChosen(ChooseByNamePopup popup, Object element) { final AnAction action = (AnAction)((Map.Entry)element).getKey(); if (action != null) { ApplicationManager.getApplication().invokeLater(new Runnable() { @@ -62,7 +55,7 @@ public class GotoActionAction extends GotoActionBase implements DumbAware { }, ModalityState.NON_MODAL); } } - }, ModalityState.current(), true); + }); } } \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoActionBase.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoActionBase.java index 4c69b3a20065..6b185478428d 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/GotoActionBase.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoActionBase.java @@ -16,7 +16,9 @@ package com.intellij.ide.actions; +import com.intellij.ide.util.gotoByName.*; import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -25,6 +27,7 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.Nullable; /** * Author: msk @@ -71,6 +74,7 @@ public abstract class GotoActionBase extends AnAction { return true; } + @Nullable public static PsiElement getPsiContext(final AnActionEvent e) { PsiFile file = e.getData(LangDataKeys.PSI_FILE); if (file != null) return file; @@ -78,6 +82,7 @@ public abstract class GotoActionBase extends AnAction { return getPsiContext(project); } + @Nullable public static PsiElement getPsiContext(final Project project) { if (project == null) return null; Editor selectedEditor = FileEditorManager.getInstance(project).getSelectedTextEditor(); @@ -85,4 +90,39 @@ public abstract class GotoActionBase extends AnAction { Document document = selectedEditor.getDocument(); return PsiDocumentManager.getInstance(project).getPsiFile(document); } + + protected static abstract class GotoActionCallback { + @Nullable + protected ChooseByNameFilter createFilter(ChooseByNamePopup popup) { + return null; + } + + public abstract void elementChosen(ChooseByNamePopup popup, Object element); + } + + protected static void showNavigationPopup(AnActionEvent e, ChooseByNameModel model, final GotoActionCallback callback) { + final Project project = e.getData(PlatformDataKeys.PROJECT); + + final Class startedAction = myInAction; + final ChooseByNamePopup popup = ChooseByNamePopup.createPopup(project, model, getPsiContext(e), getInitialText(e.getData(PlatformDataKeys.EDITOR))); + final ChooseByNameFilter filter = callback.createFilter(popup); + popup.invoke(new ChooseByNamePopupComponent.Callback() { + + @Override + public void onClose() { + if (startedAction.equals(myInAction)) { + myInAction = null; + } + if (filter != null) { + filter.close(); + } + } + + @Override + public void elementChosen(Object element) { + callback.elementChosen(popup, element); + } + }, ModalityState.current(), true); + + } } diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoClassAction.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoClassAction.java index 7dd49cbbf3c5..0e2923d92742 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/GotoClassAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoClassAction.java @@ -19,12 +19,12 @@ package com.intellij.ide.actions; import com.intellij.codeInsight.navigation.NavigationUtil; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.ide.util.gotoByName.*; +import com.intellij.lang.Language; import com.intellij.navigation.ChooseByNameRegistry; import com.intellij.navigation.NavigationItem; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.PlatformDataKeys; -import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; @@ -43,23 +43,18 @@ public class GotoClassAction extends GotoActionBase implements DumbAware { return; } - FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.popup.class"); PsiDocumentManager.getInstance(project).commitAllDocuments(); + FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.popup.class"); final GotoClassModel2 model = new GotoClassModel2(project); - final ChooseByNamePopup popup = ChooseByNamePopup.createPopup(project, model, getPsiContext(e), - getInitialText(e.getData(PlatformDataKeys.EDITOR))); - final ChooseByNameFilter filterUI = new ChooseByNameLanguageFilter(popup, model, GotoClassSymbolConfiguration.getInstance(project), project); - - popup.invoke(new ChooseByNamePopupComponent.Callback() { - public void onClose() { - if (GotoClassAction.class.equals(myInAction)) { - myInAction = null; - } - filterUI.close(); + showNavigationPopup(e, model, new GotoActionCallback() { + @Override + protected ChooseByNameFilter createFilter(ChooseByNamePopup popup) { + return new ChooseByNameLanguageFilter(popup, model, GotoClassSymbolConfiguration.getInstance(project), project); } - public void elementChosen(Object element) { + @Override + public void elementChosen(ChooseByNamePopup popup, Object element) { if (element instanceof PsiElement) { NavigationUtil.activateFileWithPsiElement((PsiElement)element); } @@ -67,7 +62,7 @@ public class GotoClassAction extends GotoActionBase implements DumbAware { ((NavigationItem)element).navigate(true); } } - }, ModalityState.current(), true); + }); } protected boolean hasContributors(DataContext dataContext) { diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoFileAction.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoFileAction.java index 823b1e8a7b72..4e79629b59b8 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/GotoFileAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoFileAction.java @@ -17,7 +17,10 @@ package com.intellij.ide.actions; import com.intellij.featureStatistics.FeatureUsageTracker; -import com.intellij.ide.util.gotoByName.*; +import com.intellij.ide.util.gotoByName.ChooseByNameFilter; +import com.intellij.ide.util.gotoByName.ChooseByNamePopup; +import com.intellij.ide.util.gotoByName.GotoFileConfiguration; +import com.intellij.ide.util.gotoByName.GotoFileModel; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.application.ApplicationManager; @@ -52,18 +55,14 @@ public class GotoFileAction extends GotoActionBase implements DumbAware { FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.popup.file"); final Project project = e.getData(PlatformDataKeys.PROJECT); final GotoFileModel gotoFileModel = new GotoFileModel(project); - final ChooseByNamePopup popup = ChooseByNamePopup.createPopup(project, gotoFileModel, getPsiContext(e), - getInitialText(e.getData(PlatformDataKeys.EDITOR))); - final ChooseByNameFilter filterUI = new GotoFileFilter(popup, gotoFileModel, project); - popup.invoke(new ChooseByNamePopupComponent.Callback() { - public void onClose() { - if (GotoFileAction.class.equals(myInAction)) { - myInAction = null; - } - filterUI.close(); + showNavigationPopup(e, gotoFileModel, new GotoActionCallback() { + @Override + protected ChooseByNameFilter createFilter(ChooseByNamePopup popup) { + return new GotoFileFilter(popup, gotoFileModel, project); } - public void elementChosen(final Object element) { + @Override + public void elementChosen(final ChooseByNamePopup popup, final Object element) { if (element == null) return; ApplicationManager.getApplication().invokeLater(new Runnable() { public void run() { @@ -81,7 +80,7 @@ public class GotoFileAction extends GotoActionBase implements DumbAware { } }, ModalityState.NON_MODAL); } - }, ModalityState.current(), true); + }); } protected static class GotoFileFilter extends ChooseByNameFilter { diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoSymbolAction.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoSymbolAction.java index ef2d7197d441..65ac622cf6ba 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/GotoSymbolAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoSymbolAction.java @@ -18,12 +18,12 @@ package com.intellij.ide.actions; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.ide.util.gotoByName.*; -import com.intellij.navigation.NavigationItem; +import com.intellij.lang.Language; import com.intellij.navigation.ChooseByNameRegistry; +import com.intellij.navigation.NavigationItem; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.PlatformDataKeys; -import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDocumentManager; @@ -32,26 +32,19 @@ public class GotoSymbolAction extends GotoActionBase { public void gotoActionPerformed(AnActionEvent e) { FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.popup.symbol"); final Project project = e.getData(PlatformDataKeys.PROJECT); - - PsiDocumentManager.getInstance(project).commitAllDocuments(); - final GotoSymbolModel2 model = new GotoSymbolModel2(project); - final ChooseByNamePopup popup = ChooseByNamePopup.createPopup(project, model, getPsiContext(e), - getInitialText(e.getData(PlatformDataKeys.EDITOR))); - final ChooseByNameFilter filterUI = new ChooseByNameLanguageFilter(popup, model, GotoClassSymbolConfiguration.getInstance(project), - project); - popup.invoke(new ChooseByNamePopupComponent.Callback() { - public void onClose() { - if (GotoSymbolAction.class.equals(myInAction)) { - myInAction = null; - } - filterUI.close(); + PsiDocumentManager.getInstance(project).commitAllDocuments(); + showNavigationPopup(e, model, new GotoActionCallback() { + @Override + protected ChooseByNameFilter createFilter(ChooseByNamePopup popup) { + return new ChooseByNameLanguageFilter(popup, model, GotoClassSymbolConfiguration.getInstance(project), project); } - public void elementChosen(Object element) { + @Override + public void elementChosen(ChooseByNamePopup popup, Object element) { ((NavigationItem)element).navigate(true); } - }, ModalityState.current(), true); + }); } protected boolean hasContributors(DataContext dataContext) { From 3e3ab163acfe324abf0f84813015bb99ef31c195 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 21 Feb 2011 14:19:17 +0100 Subject: [PATCH 035/169] remember the last string in goto actions --- .../intellij/ide/actions/GotoActionBase.java | 38 +++++++++++++------ 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoActionBase.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoActionBase.java index 6b185478428d..d55ddc3209ce 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/GotoActionBase.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoActionBase.java @@ -16,7 +16,10 @@ package com.intellij.ide.actions; -import com.intellij.ide.util.gotoByName.*; +import com.intellij.ide.util.gotoByName.ChooseByNameFilter; +import com.intellij.ide.util.gotoByName.ChooseByNameModel; +import com.intellij.ide.util.gotoByName.ChooseByNamePopup; +import com.intellij.ide.util.gotoByName.ChooseByNamePopupComponent; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; @@ -29,6 +32,9 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import org.jetbrains.annotations.Nullable; +import java.util.HashMap; +import java.util.Map; + /** * Author: msk */ @@ -36,17 +42,8 @@ public abstract class GotoActionBase extends AnAction { private static final Logger LOG = Logger.getInstance("#com.intellij.ide.actions.GotoActionBase"); protected static Class myInAction = null; + private static Map ourLastStrings = new HashMap(); - public static String getInitialText(Editor editor) { - if (editor == null) { - return ""; - } - final String selectedText = editor.getSelectionModel().getSelectedText(); - if (selectedText != null && selectedText.indexOf("\n") < 0) { - return selectedText; - } - return ""; - } public final void actionPerformed(AnActionEvent e) { LOG.assertTrue (!getClass ().equals (myInAction)); @@ -100,6 +97,24 @@ public abstract class GotoActionBase extends AnAction { public abstract void elementChosen(ChooseByNamePopup popup, Object element); } + private static String getInitialText(Editor editor) { + if (editor != null) { + final String selectedText = editor.getSelectionModel().getSelectedText(); + if (selectedText != null && selectedText.indexOf("\n") < 0) { + return selectedText; + } + } + + if (myInAction != null) { + final String lastString = ourLastStrings.get(myInAction); + if (lastString != null) { + return lastString; + } + } + + return ""; + } + protected static void showNavigationPopup(AnActionEvent e, ChooseByNameModel model, final GotoActionCallback callback) { final Project project = e.getData(PlatformDataKeys.PROJECT); @@ -110,6 +125,7 @@ public abstract class GotoActionBase extends AnAction { @Override public void onClose() { + ourLastStrings.put(myInAction, popup.getEnteredText()); if (startedAction.equals(myInAction)) { myInAction = null; } From b0e362055cb615d5eb1d0e15c8a3cd65a5baa218 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 21 Feb 2011 15:50:02 +0100 Subject: [PATCH 036/169] don't let the live templates overwrite the identifier --- .../lookup/impl/actions/ChooseItemReplaceAction.java | 6 ++++-- .../codeInsight/template/impl/ListTemplatesHandler.java | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/actions/ChooseItemReplaceAction.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/actions/ChooseItemReplaceAction.java index 54c84064dc0a..53a3fe3acd77 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/actions/ChooseItemReplaceAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/actions/ChooseItemReplaceAction.java @@ -22,6 +22,7 @@ import com.intellij.codeInsight.completion.CompletionService; import com.intellij.codeInsight.lookup.Lookup; import com.intellij.codeInsight.lookup.LookupManager; import com.intellij.codeInsight.lookup.impl.LookupImpl; +import com.intellij.codeInsight.template.impl.ListTemplatesHandler; import com.intellij.codeInsight.template.impl.LiveTemplateCompletionContributor; import com.intellij.codeInsight.template.impl.TemplateImpl; import com.intellij.codeInsight.template.impl.TemplateSettings; @@ -51,6 +52,8 @@ public class ChooseItemReplaceAction extends EditorAction { public boolean isEnabled(Editor editor, DataContext dataContext) { LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(editor); if (lookup != null) { + lookup.refreshUi(); // to bring the list model up to date + CompletionProcess completion = CompletionService.getCompletionService().getCurrentCompletion(); if (completion != null && completion.isAutopopupCompletion() && hasTemplatePrefix(lookup, TemplateSettings.TAB_CHAR)) { return false; @@ -60,7 +63,6 @@ public class ChooseItemReplaceAction extends EditorAction { return true; } - lookup.refreshUi(); // to bring the list model up to date return !lookup.getItems().isEmpty(); } return false; @@ -76,7 +78,7 @@ public class ChooseItemReplaceAction extends EditorAction { final int end = editor.getCaretModel().getOffset(); final int start = lookup.getLookupStart(); - final String prefix = editor.getDocument().getText(TextRange.create(start, end)); + final String prefix = !lookup.getItems().isEmpty() ? editor.getDocument().getText(TextRange.create(start, end)) : ListTemplatesHandler.getPrefix(editor.getDocument(), end); final TemplateImpl template = LiveTemplateCompletionContributor.findApplicableTemplate(file, end, prefix); return template != null && shortcutChar == TemplateSettings.getInstance().getShortcutChar(template); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/ListTemplatesHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/ListTemplatesHandler.java index 2d2e49487640..12a3b0760a57 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/ListTemplatesHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/ListTemplatesHandler.java @@ -107,7 +107,7 @@ public class ListTemplatesHandler implements CodeInsightActionHandler { return true; } - private static String getPrefix(Document document, int offset) { + public static String getPrefix(Document document, int offset) { CharSequence chars = document.getCharsSequence(); int start = offset; while (true) { From d73f75678ccd7d646cc51df523203738c9bb22ef Mon Sep 17 00:00:00 2001 From: "Kirill.Safonov" Date: Mon, 21 Feb 2011 18:21:35 +0300 Subject: [PATCH 037/169] Inline action works from Structure view --- .../intellij/refactoring/inline/GenericInlineHandler.java | 7 ++++--- .../refactoring/inline/InlineRefactoringActionHandler.java | 5 ++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/refactoring/inline/GenericInlineHandler.java b/platform/lang-impl/src/com/intellij/refactoring/inline/GenericInlineHandler.java index bbc2945dac1a..875bee27ff72 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/inline/GenericInlineHandler.java +++ b/platform/lang-impl/src/com/intellij/refactoring/inline/GenericInlineHandler.java @@ -38,6 +38,7 @@ import com.intellij.usageView.UsageInfo; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.HashSet; import com.intellij.util.containers.MultiMap; +import org.jetbrains.annotations.Nullable; import java.util.*; @@ -47,8 +48,8 @@ import java.util.*; @SuppressWarnings({"UtilityClassWithoutPrivateConstructor"}) public class GenericInlineHandler { - public static boolean invoke(final PsiElement element, final Editor editor, final InlineHandler languageSpecific) { - final PsiReference invocationReference = TargetElementUtilBase.findReference(editor); + public static boolean invoke(final PsiElement element, @Nullable Editor editor, final InlineHandler languageSpecific) { + final PsiReference invocationReference = editor != null ? TargetElementUtilBase.findReference(editor) : null; final InlineHandler.Settings settings = languageSpecific.prepareInlineElement(element, editor, invocationReference != null); if (settings == null || settings == InlineHandler.Settings.CANNOT_INLINE_SETTINGS) { return settings != null; @@ -65,7 +66,7 @@ public class GenericInlineHandler { public void run() { usagesRef.set(ReferencesSearch.search(element).findAll()); } - }, "Find Usages", false, editor.getProject()); + }, "Find Usages", false, element.getProject()); allReferences = usagesRef.get(); } diff --git a/platform/lang-impl/src/com/intellij/refactoring/inline/InlineRefactoringActionHandler.java b/platform/lang-impl/src/com/intellij/refactoring/inline/InlineRefactoringActionHandler.java index 4bd9427af015..db3ccfa481a9 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/inline/InlineRefactoringActionHandler.java +++ b/platform/lang-impl/src/com/intellij/refactoring/inline/InlineRefactoringActionHandler.java @@ -38,6 +38,7 @@ import com.intellij.refactoring.RefactoringActionHandler; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.util.CommonRefactoringUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; @@ -57,6 +58,8 @@ public class InlineRefactoringActionHandler implements RefactoringActionHandler return; } } + + invokeInliner(editor, elements[0]); } public void invoke(@NotNull final Project project, Editor editor, PsiFile file, DataContext dataContext) { @@ -78,7 +81,7 @@ public class InlineRefactoringActionHandler implements RefactoringActionHandler } } - public static boolean invokeInliner(Editor editor, PsiElement element) { + public static boolean invokeInliner(@Nullable Editor editor, PsiElement element) { final List handlers = InlineHandlers.getInlineHandlers(element.getLanguage()); for (InlineHandler handler : handlers) { if (GenericInlineHandler.invoke(element, editor, handler)) { From f2956e286c9be3011f66baf0d79b22baa1e8e6a6 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Mon, 21 Feb 2011 18:34:52 +0300 Subject: [PATCH 038/169] Groovy: introduce field & constant on variable declaration --- .../utils/ControlFlowUtils.java | 16 ++ .../controlFlow/impl/ControlFlowBuilder.java | 15 +- .../GroovyRefactoringBundle.properties | 3 +- .../introduce/GrIntroduceContext.java | 16 +- .../introduce/GrIntroduceHandlerBase.java | 200 ++++++++++++++---- .../introduce/GrIntroduceValidatorEngine.java | 18 +- .../constant/GrIntroduceConstantDialog.java | 25 ++- .../constant/GrIntroduceConstantHandler.java | 32 ++- .../field/GrIntroduceFieldDialog.java | 44 ++-- .../field/GrIntroduceFieldHandler.java | 59 +++--- .../variable/GroovyIntroduceVariableBase.java | 16 +- .../groovy/refactoring/ui/GrTypeComboBox.java | 12 +- .../refactoring/IntroduceConstantTest.java | 2 +- .../introduce/field/GrIntroduceFieldTest.java | 4 + .../IntroduceVariableTest.java | 2 +- .../IntroduceVariableValidatorTest.java | 2 +- .../IntroduceLocalVarByDeclaration.groovy | 12 ++ ...ntroduceLocalVarByDeclaration_after.groovy | 13 ++ 18 files changed, 353 insertions(+), 138 deletions(-) create mode 100644 plugins/groovy/testdata/refactoring/introduceField/IntroduceLocalVarByDeclaration.groovy create mode 100644 plugins/groovy/testdata/refactoring/introduceField/IntroduceLocalVarByDeclaration_after.groovy diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java index 172e0c27d508..eceac6bbfec4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java @@ -16,9 +16,11 @@ package org.jetbrains.plugins.groovy.codeInspection.utils; import com.intellij.psi.PsiElement; +import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner; import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; @@ -34,6 +36,9 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnState import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrThrowStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrCaseSection; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrPostfixExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrUnaryExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.ControlFlowBuilder; @@ -482,6 +487,17 @@ public class ControlFlowUtils { return null; } + public static boolean isIncOrDecOperand(GrReferenceExpression referenceExpression) { + final PsiElement parent = referenceExpression.getParent(); + if (parent instanceof GrPostfixExpression) return true; + if (parent instanceof GrUnaryExpression) { + final IElementType opType = ((GrUnaryExpression)parent).getOperationTokenType(); + return opType == GroovyElementTypes.mDEC || opType == GroovyElementTypes.mINC; + } + + return false; + } + private static class ReturnFinder extends GroovyRecursiveElementVisitor { private boolean m_found = false; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java index f9de874dc658..89f3c13880e1 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java @@ -21,9 +21,9 @@ import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiConstantEvaluationHelper; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiType; -import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; @@ -359,7 +359,7 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { public void visitReferenceExpression(GrReferenceExpression referenceExpression) { super.visitReferenceExpression(referenceExpression); if (referenceExpression.getQualifierExpression() == null) { - if (isIncOrDecOperand(referenceExpression) && !myAssertionsOnly) { + if (ControlFlowUtils.isIncOrDecOperand(referenceExpression) && !myAssertionsOnly) { final ReadWriteVariableInstructionImpl i = new ReadWriteVariableInstructionImpl(referenceExpression, myInstructionNumber++, false); addNode(i); addNode(new ReadWriteVariableInstructionImpl(referenceExpression, myInstructionNumber++, true)); @@ -377,17 +377,6 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { } } - private static boolean isIncOrDecOperand(GrReferenceExpression referenceExpression) { - final PsiElement parent = referenceExpression.getParent(); - if (parent instanceof GrPostfixExpression) return true; - if (parent instanceof GrUnaryExpression) { - final IElementType opType = ((GrUnaryExpression)parent).getOperationTokenType(); - return opType == GroovyElementTypes.mDEC || opType == GroovyElementTypes.mINC; - } - - return false; - } - public void visitIfStatement(GrIfStatement ifStatement) { InstructionImpl ifInstruction = startNode(ifStatement); final GrCondition condition = ifStatement.getCondition(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties index 5272d82ebb20..5e3e6a7a15af 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties @@ -150,6 +150,7 @@ expression.contains.errors=Expression contains errors field.0.is.already.defined=Field {0} is already defined access.to.created.field.0.will.be.overriden.by.method.1=Access to field {0} will be overriden by {1} final.field.cant.be.initialized.in.cur.method=Final field cannot be initialized in current method -Field.cannot.be.final.because.replaced.variable.has.lhs.usages=Field cannot be final because replaced variable is assigned new values several times +Field.cannot.be.final.because.replaced.variable.has.lhs.usages=Selected variable is used for write field.cannot.be.initialized.in.field.declaration=Field cannot be initialized in declaration field.cannot.be.initialized.in.constructor(s)=Field cannot be initialized in constructor(s) +selected.variable.is.used.for.write=Selected variable is used for write diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceContext.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceContext.java index d6937db28b17..184289237cb9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceContext.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceContext.java @@ -15,6 +15,9 @@ package org.jetbrains.plugins.groovy.refactoring.introduce; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; /** @@ -23,15 +26,24 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpres public class GrIntroduceContext { public final Project project; public final Editor editor; - public final GrExpression expression; + @Nullable public final GrExpression expression; public final PsiElement[] occurrences; public final PsiElement scope; + @Nullable public final GrVariable var; + @NotNull public final PsiElement place; - public GrIntroduceContext(Project project, Editor editor, GrExpression expression, PsiElement[] occurrences, PsiElement scope) { + public GrIntroduceContext(Project project, + Editor editor, + GrExpression expression, + PsiElement[] occurrences, + PsiElement scope, + @Nullable GrVariable var) { this.project = project; this.editor = editor; this.expression = expression; this.occurrences = occurrences; this.scope = scope; + this.var = var; + this.place = expression == null ? var : expression; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java index db95a9fc2bfb..02005c549138 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java @@ -24,10 +24,13 @@ import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Pass; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.wm.WindowManager; import com.intellij.psi.*; +import com.intellij.psi.search.LocalSearchScope; +import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.refactoring.IntroduceTargetChooser; @@ -35,19 +38,23 @@ import com.intellij.refactoring.RefactoringActionHandler; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.util.Function; +import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrForStatement; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrIfStatement; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrWhileStatement; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.*; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrStringInjection; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; import org.jetbrains.plugins.groovy.refactoring.NameValidator; +import org.jetbrains.plugins.groovy.refactoring.introduce.field.GrIntroduceFieldHandler; import java.util.ArrayList; import java.util.List; @@ -61,36 +68,21 @@ public abstract class GrIntroduceHandlerBase getDialog(GrIntroduceContext context); - public abstract void runRefactoring(GrIntroduceContext context, Settings settings); + @Nullable + public abstract GrVariable runRefactoring(GrIntroduceContext context, Settings settings); public static List collectExpressions(final PsiFile file, final Editor editor, final int offset) { - Document document = editor.getDocument(); - CharSequence text = document.getCharsSequence(); - int correctedOffset = offset; - int textLength = document.getTextLength(); - if (offset >= textLength) { - correctedOffset = textLength - 1; - } - else if (!Character.isJavaIdentifierPart(text.charAt(offset))) { - correctedOffset--; - } - if (correctedOffset < 0) { - correctedOffset = offset; - } - else if (!Character.isJavaIdentifierPart(text.charAt(correctedOffset))) { - if (text.charAt(correctedOffset) == ';') {//initially caret on the end of line - correctedOffset--; - } - if (text.charAt(correctedOffset) != ')') { - correctedOffset = offset; - } - } + int correctedOffset = correctOffset(editor, offset); final PsiElement elementAtCaret = file.findElementAt(correctedOffset); final List expressions = new ArrayList(); @@ -113,6 +105,40 @@ public abstract class GrIntroduceHandlerBase= textLength) { + correctedOffset = textLength - 1; + } + else if (!Character.isJavaIdentifierPart(text.charAt(offset))) { + correctedOffset--; + } + if (correctedOffset < 0) { + correctedOffset = offset; + } + else if (!Character.isJavaIdentifierPart(text.charAt(correctedOffset))) { + if (text.charAt(correctedOffset) == ';') {//initially caret on the end of line + correctedOffset--; + } + if (text.charAt(correctedOffset) != ')') { + correctedOffset = offset; + } + } + return correctedOffset; + } + + @Nullable + private static GrVariable findVariableAtCaret(final PsiFile file, final Editor editor, final int offset) { + final int correctOffset = correctOffset(editor, offset); + final PsiElement elementAtCaret = file.findElementAt(correctOffset); + final GrVariable variable = PsiTreeUtil.getParentOfType(elementAtCaret, GrVariable.class); + if (variable != null && variable.getNameIdentifierGroovy().getTextRange().contains(correctOffset)) return variable; + return null; + } + public void invoke(final @NotNull Project project, final Editor editor, final PsiFile file, final @Nullable DataContext dataContext) { final SelectionModel selectionModel = editor.getSelectionModel(); if (!selectionModel.hasSelection()) { @@ -120,7 +146,14 @@ public abstract class GrIntroduceHandlerBase expressions = collectExpressions(file, editor, offset); if (expressions.isEmpty()) { - selectionModel.selectLineAtCaret(); + final GrVariable variable = findVariableAtCaret(file, editor, offset); + if (variable == null || variable instanceof GrField || variable instanceof GrParameter) { + selectionModel.selectLineAtCaret(); + } + else { + final TextRange textRange = variable.getTextRange(); + selectionModel.setSelection(textRange.getStartOffset(), textRange.getEndOffset()); + } } else if (expressions.size() == 1) { final TextRange textRange = expressions.get(0).getTextRange(); @@ -151,11 +184,29 @@ public abstract class GrIntroduceHandlerBase list = new ArrayList(); + ReferencesSearch.search(variable, new LocalSearchScope(scope)).forEach(new Processor() { + @Override + public boolean process(PsiReference psiReference) { + final PsiElement element = psiReference.getElement(); + if (element != null) { + list.add(element); + } + return true; + } + }); + return new GrIntroduceContext(project, editor, variable.getInitializerGroovy(), list.toArray(new PsiElement[list.size()]), scope, + variable); + } } protected PsiElement[] findOccurences(GrExpression expression, PsiElement scope) { @@ -177,20 +228,34 @@ public abstract class GrIntroduceHandlerBase() { + public GrVariable compute() { + return runRefactoring(context, settings); } }); + + if (editor != null && created != null) { + PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument()); + editor.getCaretModel().moveToOffset(created.getNameIdentifierGroovy().getTextOffset()); + } } }, getRefactoringName(), null); @@ -203,10 +268,29 @@ public abstract class GrIntroduceHandlerBase isOKImpl(String varName, boolean replaceAllOccurrences) { - GrExpression firstOccurence; + PsiElement firstOccurence; if (replaceAllOccurrences) { - GroovyRefactoringUtil.sortOccurrences(myContext.occurrences); - firstOccurence = ((GrExpression)myContext.occurrences[0]); + if (myContext.occurrences.length > 0) { + GroovyRefactoringUtil.sortOccurrences(myContext.occurrences); + firstOccurence = myContext.occurrences[0]; + } + else { + firstOccurence = myContext.place; + } } else { firstOccurence = myContext.expression; } final MultiMap conflicts = new MultiMap(); assert varName != null; - validateOccurrencesDown(myContext.scope, conflicts, varName, firstOccurence.getTextRange().getStartOffset()); + + final int offset = firstOccurence.getTextRange().getStartOffset(); + validateOccurrencesDown(myContext.scope, conflicts, varName, offset); if (!(myContext.scope instanceof GroovyFileBase)) { - validateVariableOccurrencesUp(myContext.scope, conflicts, varName, firstOccurence.getTextRange().getStartOffset()); + validateVariableOccurrencesUp(myContext.scope, conflicts, varName, offset); } return conflicts; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.java index 90511719c3b2..649cfaf12adf 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.java @@ -102,7 +102,7 @@ public class GrIntroduceConstantDialog extends DialogWrapper myTypeCombo.setEnabled(mySpecifyType.isSelected()); } }); - mySpecifyType.setSelected(context.expression.getType() != null); + mySpecifyType.setSelected(context.expression == null ? context.var.getDeclaredType() != null : context.expression.getType() != null); myTypeCombo.setEnabled(mySpecifyType.isSelected()); updateVisibilityPanel(); updateOkStatus(); @@ -121,7 +121,11 @@ public class GrIntroduceConstantDialog extends DialogWrapper initializeName(); initializeTargetClassEditor(); - if (myContext.occurrences.length < 2) { + if (myContext.var != null) { + myReplaceAllOccurences.setEnabled(false); + myReplaceAllOccurences.setSelected(true); + } + else if (myContext.occurrences.length < 2) { myReplaceAllOccurences.setVisible(false); } return myPanel; @@ -196,6 +200,9 @@ public class GrIntroduceConstantDialog extends DialogWrapper } }, KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.ALT_MASK), JComponent.WHEN_IN_FOCUSED_WINDOW); + if (myContext.var != null) { + myNameComboBox.addItem(myContext.var.getName()); + } String[] possibleNames = GroovyNameSuggestionUtil.suggestVariableNames(myContext.expression, new GroovyVariableValidator(myContext), true); for (String possibleName : possibleNames) { myNameComboBox.addItem(possibleName); @@ -221,7 +228,13 @@ public class GrIntroduceConstantDialog extends DialogWrapper private void initializeTypeCombo() { - final PsiType expressionType = myContext.expression.getType(); + final PsiType expressionType; + if (myContext.expression != null) { + expressionType = myContext.expression.getType(); + } + else { + expressionType = myContext.var.getDeclaredType(); + } if (expressionType != null) { myTypes = GroovyRefactoringUtil.getCompatibleTypeNames(expressionType); for (String typeName : myTypes.keySet()) { @@ -358,7 +371,7 @@ public class GrIntroduceConstantDialog extends DialogWrapper if (myDefaultTargetClass == null || !"".equals(targetClassName) && !Comparing.strEqual(targetClassName, myDefaultTargetClass.getQualifiedName())) { - final Module module = ModuleUtil.findModuleForPsiElement(myContext.expression); + final Module module = ModuleUtil.findModuleForPsiElement(myContext.place); newClass = JavaPsiFacade.getInstance(myContext.project).findClass(targetClassName, module.getModuleScope()); if (newClass == null) { if (Messages.showOkCancelDialog(myContext.project, GroovyRefactoringBundle.message("class.does.not.exist.in.the.module"), @@ -366,12 +379,12 @@ public class GrIntroduceConstantDialog extends DialogWrapper return; } myTargetClass = - getTargetClass(targetClassName, myContext.expression.getContainingFile().getContainingDirectory(), myContext.project, module); + getTargetClass(targetClassName, myContext.place.getContainingFile().getContainingDirectory(), myContext.project, module); if (myTargetClass == null) return; } else { myTargetClass = - getTargetClass(targetClassName, myContext.expression.getContainingFile().getContainingDirectory(), myContext.project, module); + getTargetClass(targetClassName, myContext.place.getContainingFile().getContainingDirectory(), myContext.project, module); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java index b307e4a21383..3e59ee304806 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java @@ -25,6 +25,7 @@ import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; @@ -58,8 +59,9 @@ public class GrIntroduceConstantHandler extends GrIntroduceHandlerBase getDialog(GrIntroduceContext context) { return new GrIntroduceFieldDialog(context); } @Override - public void runRefactoring(GrIntroduceContext context, GrIntroduceFieldSettings settings) { + public GrField runRefactoring(GrIntroduceContext context, GrIntroduceFieldSettings settings) { final PsiClass targetClass = (PsiClass)context.scope; - if (targetClass == null) return; + if (targetClass == null) return null; final GrVariableDeclaration declaration = createField(context, settings); @@ -126,6 +141,7 @@ public class GrIntroduceFieldHandler extends GrIntroduceHandlerBase elements = ContainerUtil.findAll(context.occurrences, new Condition() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GroovyIntroduceVariableBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GroovyIntroduceVariableBase.java index 9072b19755b4..36fcef9941fc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GroovyIntroduceVariableBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GroovyIntroduceVariableBase.java @@ -56,7 +56,7 @@ public abstract class GroovyIntroduceVariableBase extends GrIntroduceHandlerBase @NotNull @Override - protected PsiElement findScope(GrExpression selectedExpr) { + protected PsiElement findScope(GrExpression selectedExpr, GrVariable variable) { // Get container element final PsiElement scope = GroovyRefactoringUtil.getEnclosingContainer(selectedExpr); @@ -88,6 +88,16 @@ public abstract class GroovyIntroduceVariableBase extends GrIntroduceHandlerBase } } + @Override + protected void checkVariable(GrVariable variable) throws GrIntroduceRefactoringError { + throw new GrIntroduceRefactoringError(null); + } + + @Override + protected void checkOccurrences(PsiElement[] occurrences) { + //nothing to do + } + private static boolean checkInFieldInitializer(GrExpression expr) { PsiElement parent = expr.getParent(); if (parent instanceof GrClosableBlock) { @@ -105,7 +115,7 @@ public abstract class GroovyIntroduceVariableBase extends GrIntroduceHandlerBase /** * Inserts new variable declaratrions and replaces occurrences */ - public void runRefactoring(final GrIntroduceContext context, final GroovyIntroduceVariableSettings settings) { + public GrVariable runRefactoring(final GrIntroduceContext context, final GroovyIntroduceVariableSettings settings) { // Generating varibable declaration final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(context.project); @@ -190,10 +200,12 @@ public abstract class GroovyIntroduceVariableBase extends GrIntroduceHandlerBase context.editor.getCaretModel().moveToOffset(getPositionMarker().getTextRange().getEndOffset()); context.editor.getSelectionModel().removeSelection(); } + return insertedVar; } catch (IncorrectOperationException e) { LOG.error(e); } + return null; } private static void resolveLocalConflicts(PsiElement tempContainer, String varName) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrTypeComboBox.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrTypeComboBox.java index 1c069d9ebc83..80c3c2eb6276 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrTypeComboBox.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrTypeComboBox.java @@ -17,7 +17,6 @@ package org.jetbrains.plugins.groovy.refactoring.ui; import com.intellij.psi.PsiType; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; import javax.swing.*; @@ -27,19 +26,18 @@ import java.util.Map; * @author Maxim.Medvedev */ public class GrTypeComboBox extends JComboBox { - private final GrExpression myExpr; + private final PsiType myType; - public GrTypeComboBox(GrExpression expr) { + public GrTypeComboBox(PsiType type) { super(); - myExpr = expr; + myType = type; initialize(); } private void initialize() { - final PsiType expressionType = myExpr.getType(); addItem(new PsiTypeItem(null)); - if (expressionType != null) { - final Map myTypes = GroovyRefactoringUtil.getCompatibleTypeNames(expressionType); + if (myType != null) { + final Map myTypes = GroovyRefactoringUtil.getCompatibleTypeNames(myType); for (String typeName : myTypes.keySet()) { addItem(new PsiTypeItem(myTypes.get(typeName))); } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/IntroduceConstantTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/IntroduceConstantTest.java index bfbf3eb07a8d..d0befb488aa4 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/IntroduceConstantTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/IntroduceConstantTest.java @@ -76,7 +76,7 @@ public class IntroduceConstantTest extends LightCodeInsightFixtureTestCase { final GrExpression expression = findExpression(editor); - final GrIntroduceContext context = handler.getContext(getProject(), editor, expression); + final GrIntroduceContext context = handler.getContext(getProject(), editor, expression, null); PsiClass targetClass; if (targetClassName == null) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldTest.java index 16738ad4cc16..3fb1d816b8e4 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldTest.java @@ -61,6 +61,10 @@ public class GrIntroduceFieldTest extends LightCodeInsightFixtureTestCase { doTest(false, true, false, CUR_METHOD, true, null); } + public void testIntroduceLocalVarByDeclaration() { + doTest(false, true, false, FIELD_DECLARATION, true, null); + } + private void doTest(final boolean isStatic, final boolean removeLocal, final boolean declareFinal, diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/IntroduceVariableTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/IntroduceVariableTest.java index 3a365236df9a..2d0f7b0d0821 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/IntroduceVariableTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/IntroduceVariableTest.java @@ -119,7 +119,7 @@ public class IntroduceVariableTest extends LightCodeInsightFixtureTestCase { varType = null; } - final GrIntroduceContext context = new GrIntroduceContext(getProject(), myEditor, selectedExpr, occurences, tempContainer); + final GrIntroduceContext context = new GrIntroduceContext(getProject(), myEditor, selectedExpr, occurences, tempContainer, null); ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/IntroduceVariableValidatorTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/IntroduceVariableValidatorTest.java index f44fc3636c51..2306f8f6008c 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/IntroduceVariableValidatorTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/IntroduceVariableValidatorTest.java @@ -88,7 +88,7 @@ public class IntroduceVariableValidatorTest extends LightCodeInsightFixtureTestC PsiElement[] occurences = GroovyRefactoringUtil.getExpressionOccurrences(PsiUtil.skipParentheses(selectedExpr, false), tempContainer); String varName = "preved"; GroovyVariableValidator validator = - new GroovyVariableValidator(new GrIntroduceContext(getProject(), myEditor, selectedExpr, occurences, tempContainer)); + new GroovyVariableValidator(new GrIntroduceContext(getProject(), myEditor, selectedExpr, occurences, tempContainer, null)); result = validator.isOKTest(varName, replaceAllOccurences); return result; } diff --git a/plugins/groovy/testdata/refactoring/introduceField/IntroduceLocalVarByDeclaration.groovy b/plugins/groovy/testdata/refactoring/introduceField/IntroduceLocalVarByDeclaration.groovy new file mode 100644 index 000000000000..ecb4e7fa0218 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/introduceField/IntroduceLocalVarByDeclaration.groovy @@ -0,0 +1,12 @@ +class Foo { + def bar = 3 + def foo() { + print "a" + + def a = 4 - bar + print a + a++ + a-=4 + print a + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/introduceField/IntroduceLocalVarByDeclaration_after.groovy b/plugins/groovy/testdata/refactoring/introduceField/IntroduceLocalVarByDeclaration_after.groovy new file mode 100644 index 000000000000..ca6ba2a27983 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/introduceField/IntroduceLocalVarByDeclaration_after.groovy @@ -0,0 +1,13 @@ +class Foo { + def bar = 3 + def f = 4 - bar + + def foo() { + print "a" + + print f + f++ + f -=4 + print f + } +} \ No newline at end of file From 33f7f240c7001f6a8c4dff427066644d838966b1 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Mon, 21 Feb 2011 19:15:16 +0300 Subject: [PATCH 039/169] Fix: EA-25403 - assert: GroovyScriptTypeDetector.getScriptType --- .../groovy/runner/GroovyScriptRunConfigurationProducer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunConfigurationProducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunConfigurationProducer.java index f61eb23d3341..f7ab6d15a5cc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunConfigurationProducer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunConfigurationProducer.java @@ -154,7 +154,7 @@ public class GroovyScriptRunConfigurationProducer extends RuntimeConfigurationPr final String path = existing.getScriptPath(); if (path != null) { final PsiFile file = location.getPsiElement().getContainingFile(); - if (file instanceof GroovyFile) { + if (file instanceof GroovyFile && ((GroovyFile)file).isScript()) { final VirtualFile vfile = file.getVirtualFile(); if (vfile != null && FileUtil.toSystemIndependentName(path).equals(vfile.getPath())) { if (GroovyScriptTypeDetector.getScriptType((GroovyFile)file).isConfigurationByLocation(existing, location)) { From 308455ec7082810826cf46289fbe21d6d13f56e9 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 21 Feb 2011 19:57:52 +0300 Subject: [PATCH 040/169] Merge Switcher and Next Splitter action (IDEA-23698, IDEA-63978, IDEA-25757) --- .../com/intellij/ui/tabs/TabsListener.java | 3 + .../com/intellij/ui/tabs/impl/JBTabsImpl.java | 7 +- .../com/intellij/ide/actions/Switcher.java | 150 +++++++++++------- .../openapi/fileEditor/impl/EditorWindow.java | 18 ++- .../fileEditor/impl/EditorWindowHolder.java | 23 +++ .../impl/FileEditorManagerImpl.java | 51 +++++- 6 files changed, 187 insertions(+), 65 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindowHolder.java diff --git a/platform/platform-api/src/com/intellij/ui/tabs/TabsListener.java b/platform/platform-api/src/com/intellij/ui/tabs/TabsListener.java index 08888ee75160..ee3bc4a8f2af 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/TabsListener.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/TabsListener.java @@ -15,7 +15,10 @@ */ package com.intellij.ui.tabs; +import com.intellij.util.messages.Topic; + public interface TabsListener { + Topic TOPIC = Topic.create("TabsListener", TabsListener.class); void selectionChanged(TabInfo oldSelection, TabInfo newSelection); diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java index ef1716c324ca..12aaa3da4acd 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java @@ -243,7 +243,9 @@ public class JBTabsImpl extends JComponent new LazyUiDisposable(parent, this, this) { protected void initialize(@NotNull Disposable parent, @NotNull JBTabsImpl child, @Nullable Project project) { - myProject = project; + if (project != null) { + myProject = project; + } Disposer.register(child, myAnimator); Disposer.register(child, new Disposable() { @@ -793,6 +795,9 @@ public class JBTabsImpl extends JComponent private void fireSelectionChanged(TabInfo oldInfo, TabInfo newInfo) { if (oldInfo != newInfo) { + if (myProject != null) { + myProject.getMessageBus().syncPublisher(TabsListener.TOPIC).selectionChanged(oldInfo, newInfo); + } for (TabsListener eachListener : myTabListeners) { if (eachListener != null) { eachListener.selectionChanged(oldInfo, newInfo); diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index 3be56bce173b..ee52597d0427 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -22,13 +22,9 @@ import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.markup.EffectType; import com.intellij.openapi.editor.markup.TextAttributes; -import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; -import com.intellij.openapi.fileEditor.impl.EditorHistoryManager; -import com.intellij.openapi.fileEditor.impl.EditorWindow; -import com.intellij.openapi.fileEditor.impl.EditorsSplitters; -import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl; +import com.intellij.openapi.fileEditor.impl.*; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; @@ -48,6 +44,7 @@ import com.intellij.ui.ColoredListCellRenderer; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.SimpleTextAttributes; import com.intellij.ui.components.JBList; +import com.intellij.ui.tabs.TabInfo; import com.intellij.util.ArrayUtil; import com.intellij.util.IconUtil; import com.intellij.util.Icons; @@ -158,7 +155,7 @@ public class Switcher extends AnAction implements DumbAware { final JLabel pathLabel = new JLabel(" "); final JPanel descriptions; final Project project; - final Map files2editors; + //final Map files2editors; final Map twShortcuts; @SuppressWarnings({"ManualArrayToCollectionCopy"}) @@ -250,38 +247,37 @@ public class Switcher extends AnAction implements DumbAware { return new Dimension(5, max.height); } }; - separator.setBackground(Color.WHITE); + separator.setBackground(Color.WHITE); - final FileEditorManager editorManager = FileEditorManager.getInstance(project); - final FileEditor[] allEditors = editorManager.getAllEditors(); - files2editors = new HashMap(); - for (FileEditor editor : allEditors) { - files2editors.put(((FileEditorManagerImpl)editorManager).getFile(editor), editor); + final FileEditorManagerImpl editorManager = (FileEditorManagerImpl)FileEditorManager.getInstance(project); + final ArrayList filesData = new ArrayList(); + final ArrayList editors = new ArrayList(); + for (EditorsSplitters splitters : editorManager.getAllSplitters()) { + for (EditorWindow window : splitters.getWindows()) { + for (VirtualFile file : window.getFiles()) { + editors.add(new FileEditorInfo(file, window)); + } + } } - final ArrayList openFiles = new ArrayList(); - final ArrayList editorFiles = new ArrayList(); - for (EditorsSplitters splitters : ((FileEditorManagerImpl)editorManager).getAllSplitters()) { - editorFiles.addAll(Arrays.asList(splitters.getOpenFiles())); - } - if (editorFiles.size() < 2) { + if (editors.size() < 2) { final VirtualFile[] recentFiles = ArrayUtil.reverseArray(EditorHistoryManager.getInstance(project).getFiles()); - final int len = Math.min(toolWindows.getModel().getSize(), Math.max(editorFiles.size(), recentFiles.length)); + final int len = Math.min(toolWindows.getModel().getSize(), Math.max(editors.size(), recentFiles.length)); for (int i = 0; i < len; i++) { - openFiles.add(recentFiles[i]); + filesData.add(new FileEditorInfo(recentFiles[i], null)); } } else { try { - ContainerUtil.sort(editorFiles, new RecentFilesComparator(project)); + ContainerUtil.sort(editors, new RecentFilesComparator(project)); } catch (Exception e) {// IndexNotReadyException } - for (int i = 0; i < Math.min(MAX_FILES, editorFiles.size()); i++) { - openFiles.add(editorFiles.get(i)); + for (int i = 0; i < Math.min(MAX_FILES, editors.size()); i++) { + filesData.add(editors.get(i)); } } final DefaultListModel filesModel = new DefaultListModel(); - for (VirtualFile openFile : openFiles) { - filesModel.addElement(openFile); + for (FileEditorInfo editor : filesData) { + filesModel.addElement(editor); } files = new JBList(filesModel); @@ -346,7 +342,7 @@ public class Switcher extends AnAction implements DumbAware { private void updatePathLabel() { final Object[] values = files.getSelectedValues(); if (values != null && values.length == 1) { - final VirtualFile parent = ((VirtualFile)values[0]).getParent(); + final VirtualFile parent = ((FileEditorInfo)values[0]).file.getParent(); if (parent != null) { pathLabel.setText(getTitle2Text(parent.getPresentableUrl())); } else { @@ -460,25 +456,28 @@ public class Switcher extends AnAction implements DumbAware { private void closeTabOrToolWindow() { final Object value = getSelectedList().getSelectedValue(); - if (value instanceof VirtualFile) { - final VirtualFile virtualFile = (VirtualFile)value; - final FileEditorManager editorManager = FileEditorManager.getInstance(project); - if (editorManager instanceof FileEditorManagerImpl) { - final JList jList = getSelectedList(); - ((FileEditorManagerImpl)editorManager).closeFile(virtualFile, false); - final int selectedIndex = jList.getSelectedIndex(); - if (jList.getModel().getSize() == 1) { - goLeft(); - ((DefaultListModel)jList.getModel()).removeElementAt(selectedIndex); - this.remove(jList); - this.remove(separator); - } else { - goForward(); - ((DefaultListModel)jList.getModel()).removeElementAt(selectedIndex); - jList.setSize(jList.getPreferredSize()); - } - pack(); + if (value instanceof FileEditorInfo) { + final FileEditorInfo info = (FileEditorInfo)value; + final VirtualFile virtualFile = info.file; + final FileEditorManagerImpl editorManager = ((FileEditorManagerImpl)FileEditorManager.getInstance(project)); + final JList jList = getSelectedList(); + if (info.window == null) { + editorManager.closeFile(virtualFile, false); + } else { + editorManager.closeFile(virtualFile, info.window, false); } + final int selectedIndex = jList.getSelectedIndex(); + if (jList.getModel().getSize() == 1) { + goLeft(); + ((DefaultListModel)jList.getModel()).removeElementAt(selectedIndex); + this.remove(jList); + this.remove(separator); + } else { + goForward(); + ((DefaultListModel)jList.getModel()).removeElementAt(selectedIndex); + jList.setSize(jList.getPreferredSize()); + } + pack(); } else if (value instanceof ToolWindow) { final ToolWindow toolWindow = (ToolWindow)value; if (twManager instanceof ToolWindowManagerImpl) { @@ -587,26 +586,39 @@ public class Switcher extends AnAction implements DumbAware { if (value instanceof ToolWindow) { ((ToolWindow)value).activate(null, true, true); } - else if (value instanceof VirtualFile) { - final VirtualFile file = (VirtualFile)value; + else if (value instanceof FileEditorInfo) { + final FileEditorInfo info = (FileEditorInfo)value; IdeFocusManager.getInstance(project).doWhenFocusSettlesDown(new Runnable() { @Override public void run() { - FileEditorManager.getInstance(project).openFile(file, true, true); + final FileEditorManagerImpl manager = (FileEditorManagerImpl)FileEditorManager.getInstance(project); + if (info.window != null) { + manager.openFileImpl2(info.window, info.file, true); + } else { + manager.openFile(info.file, true); + } } }); } } - private class RecentFilesComparator implements Comparator { - private final VirtualFile[] recentFiles; + private class RecentFilesComparator implements Comparator { + private Map tabs = new HashMap(); public RecentFilesComparator(Project project) { - recentFiles = EditorHistoryManager.getInstance(project).getFiles(); + final List history = ((FileEditorManagerImpl)FileEditorManager.getInstance(project)).getTabsHistory(); + for (int i = 0; i < history.size(); i++) { + final TabInfo info = history.get(i); + if (info.getObject() instanceof VirtualFile && info.getComponent() instanceof EditorWindowHolder) { + tabs.put(new FileEditorInfo((VirtualFile)info.getObject(), ((EditorWindowHolder)info.getComponent()).getEditorWindow()), i); + } + } } - public int compare(VirtualFile vf1, VirtualFile vf2) { - return ArrayUtil.find(recentFiles, vf2) - ArrayUtil.find(recentFiles, vf1); + public int compare(FileEditorInfo vf1, FileEditorInfo vf2) { + final Integer index1 = tabs.get(vf1); + final Integer index2 = tabs.get(vf2); + return index1 == null && index2 == null ? 0 : index1 == null ? 1 : index2 == null ? -1 : index1 - index2; } } @@ -673,8 +685,8 @@ public class Switcher extends AnAction implements DumbAware { } protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) { - if (value instanceof VirtualFile) { - final VirtualFile virtualFile = (VirtualFile)value; + if (value instanceof FileEditorInfo) { + final VirtualFile virtualFile = ((FileEditorInfo)value).file; final String name = virtualFile.getPresentableName(); setIcon(IconUtil.getIcon(virtualFile, Iconable.ICON_FLAG_READ_STATUS, myProject)); @@ -745,4 +757,34 @@ public class Switcher extends AnAction implements DumbAware { return new ImageIcon(img); } } + + private static class FileEditorInfo { + final VirtualFile file; + final EditorWindow window; + + private FileEditorInfo(VirtualFile file, EditorWindow window) { + this.file = file; + this.window = window; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + FileEditorInfo that = (FileEditorInfo)o; + + if (!file.equals(that.file)) return false; + if (!window.equals(that.window)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = file.hashCode(); + result = 31 * result + window.hashCode(); + return result; + } + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java index 138b9ef0fb91..2d38e718986d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java @@ -325,15 +325,22 @@ public class EditorWindow { return myTabbedPane; } - protected static class TComp extends JPanel implements DataProvider{ + protected static class TComp extends JPanel implements DataProvider, EditorWindowHolder { final EditorWithProviderComposite myEditor; + protected final EditorWindow myWindow; - TComp(final EditorWithProviderComposite editor) { + TComp(final EditorWindow window, final EditorWithProviderComposite editor) { super(new BorderLayout()); myEditor = editor; + myWindow = window; add(editor.getComponent(), BorderLayout.CENTER); } + @Override + public EditorWindow getEditorWindow() { + return myWindow; + } + public Object getData(String dataId) { if (PlatformDataKeys.VIRTUAL_FILE.is(dataId)){ final VirtualFile virtualFile = myEditor.getFile(); @@ -347,11 +354,8 @@ public class EditorWindow { } protected static class TCompForTablessMode extends TComp{ - private final EditorWindow myWindow; - TCompForTablessMode(final EditorWindow window, final EditorWithProviderComposite editor) { - super(editor); - myWindow = window; + super(window, editor); } public Object getData(String dataId) { @@ -434,7 +438,7 @@ public class EditorWindow { final int indexToInsert = initialIndex == null ? myTabbedPane.getSelectedIndex() + 1 : initialIndex; final VirtualFile file = editor.getFile(); final Icon template = IconLoader.getIcon("/fileTypes/text.png"); - myTabbedPane.insertTab(file, new EmptyIcon(template.getIconWidth(), template.getIconHeight()), new TComp(editor), null, indexToInsert); + myTabbedPane.insertTab(file, new EmptyIcon(template.getIconWidth(), template.getIconHeight()), new TComp(this, editor), null, indexToInsert); trimToSize(UISettings.getInstance().EDITOR_TAB_LIMIT, file, false); setSelectedEditor(editor, focusEditor); myOwner.updateFileIcon(file); diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindowHolder.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindowHolder.java new file mode 100644 index 000000000000..c708d058b63b --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindowHolder.java @@ -0,0 +1,23 @@ +/* + * Copyright 2000-2011 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 com.intellij.openapi.fileEditor.impl; + +/** + * @author Konstantin Bulenkov + */ +public interface EditorWindowHolder { + EditorWindow getEditorWindow(); +} diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java index 36b48a92bd06..d758df4030d3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java @@ -60,6 +60,8 @@ import com.intellij.openapi.wm.WindowManager; import com.intellij.openapi.wm.ex.StatusBarEx; import com.intellij.ui.docking.DockContainer; import com.intellij.ui.docking.DockManager; +import com.intellij.ui.tabs.TabInfo; +import com.intellij.ui.tabs.TabsListener; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.messages.impl.MessageListenerList; @@ -82,7 +84,7 @@ import java.util.List; * @author Eugene Belyaev * @author Vladimir Kondratyev */ -public class FileEditorManagerImpl extends FileEditorManagerEx implements ProjectComponent, JDOMExternalizable { +public class FileEditorManagerImpl extends FileEditorManagerEx implements ProjectComponent, JDOMExternalizable, TabsListener { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl"); private static final Key WATCH_REQUEST_KEY = Key.create("WATCH_REQUEST_KEY"); private static final Key DUMB_AWARE = Key.create("DUMB_AWARE"); @@ -93,6 +95,8 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec private volatile JPanel myPanels; private EditorsSplitters mySplitters; private final Project myProject; + private final List myTabsHistory = new ArrayList(); + private final MergingUpdateQueue myQueue = new MergingUpdateQueue("FileEditorManagerUpdateQueue", 50, true, null); @@ -102,6 +106,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec private final MyEditorPropertyChangeListener myEditorPropertyChangeListener = new MyEditorPropertyChangeListener(); private DockManager myDockManager; private DockableEditorContainerFactory myContentFactory; + private MessageBusConnection myBusConnection; public FileEditorManagerImpl(final Project project, DockManager dockManager) { /* ApplicationManager.getApplication().assertIsDispatchThread(); */ @@ -109,6 +114,8 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec myDockManager = dockManager; myListenerList = new MessageListenerList(myProject.getMessageBus(), FileEditorManagerListener.FILE_EDITOR_MANAGER); + myBusConnection = project.getMessageBus().connect(project); + myBusConnection.subscribe(TabsListener.TOPIC, this); } private void initDockableContentFactory() { @@ -473,13 +480,13 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec getSplitters().setCurrentWindow(window, true); } - public void closeFile(@NotNull final VirtualFile file, @NotNull final EditorWindow window) { + public void closeFile(@NotNull final VirtualFile file, @NotNull final EditorWindow window, final boolean transferFocus) { assertDispatchThread(); CommandProcessor.getInstance().executeCommand(myProject, new Runnable() { public void run() { if (window.isFileOpen(file)) { - window.closeFile(file); + window.closeFile(file, true, transferFocus); final List windows = window.getOwner().findWindows(file); if (windows.isEmpty()) { // no more windows containing this file left final LocalFileSystem.WatchRequest request = file.getUserData(WATCH_REQUEST_KEY); @@ -490,6 +497,22 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec } } }, IdeBundle.message("command.close.active.editor"), null); + removeHistory(file, window); + } + + private void removeHistory(VirtualFile file, EditorWindow window) { + for (Iterator i = myTabsHistory.iterator(); i.hasNext();) { + final TabInfo info = i.next(); + final JComponent c = info.getComponent(); + if (info.getObject() == file && c instanceof EditorWindowHolder && ((EditorWindowHolder)c).getEditorWindow() == window) { + i.remove(); + break; + } + } + } + + public void closeFile(@NotNull final VirtualFile file, @NotNull final EditorWindow window) { + closeFile(file, window, true); } //============================= EditorManager methods ================================ @@ -1182,6 +1205,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec // Dispose created editors. We do not use use closeEditor method because // it fires event and changes history. closeAllFiles(); + myBusConnection.disconnect(); } // BaseCompomemnt methods @@ -1600,4 +1624,25 @@ private final class MyVirtualFileListener extends VirtualFileAdapter { return splitters; } + @Override + public void selectionChanged(TabInfo oldSelection, TabInfo newSelection) { + final JComponent selected = newSelection.getComponent(); + final Iterator i = myTabsHistory.iterator(); + while (i.hasNext()) { + final TabInfo info = i.next(); + if (info.getComponent() == selected) { + i.remove(); + break; + } + } + myTabsHistory.add(0, newSelection); + } + + public List getTabsHistory() { + return myTabsHistory; + } + + @Override + public void beforeSelectionChanged(TabInfo oldSelection, TabInfo newSelection) { + } } From bf77b2f2160b93fa94465c4d6b0545eeb048a552 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 21 Feb 2011 18:12:53 +0100 Subject: [PATCH 041/169] Python also has its own regexp dialect; correct parsing of character classes for Python (PY-2908) --- .../org/intellij/lang/regexp/RegExpLexer.java | 4 +- .../lang/regexp/RegExpParserDefinition.java | 2 +- .../org/intellij/lang/regexp/_RegExLexer.java | 337 +++++++++--------- .../intellij/lang/regexp/regexp-lexer.flex | 42 ++- 4 files changed, 220 insertions(+), 165 deletions(-) diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java index 82642e336963..806b9393ef6a 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java @@ -21,8 +21,8 @@ public class RegExpLexer extends FlexAdapter { private static final int COMMENT_MODE = 1 << 14; - public RegExpLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters) { - super(new _RegExLexer(xmlSchemaMode, allowDanglingMetacharacters)); + public RegExpLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters, boolean allowRBracketInCharacterClass) { + super(new _RegExLexer(xmlSchemaMode, allowDanglingMetacharacters, allowRBracketInCharacterClass)); } public void start(CharSequence buffer, int startOffset, int endOffset, int initialState) { diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpParserDefinition.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpParserDefinition.java index 5b04474edb17..1788d325e090 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/RegExpParserDefinition.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/RegExpParserDefinition.java @@ -36,7 +36,7 @@ public class RegExpParserDefinition implements ParserDefinition { @NotNull public Lexer createLexer(Project project) { - return new RegExpLexer(false, false); + return new RegExpLexer(false, false, true); } public PsiParser createParser(Project project) { diff --git a/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java b/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java index adc8fd993c63..492a35a3215c 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java @@ -1,13 +1,12 @@ -/* The following code was generated by JFlex 1.4.3 on 01.06.10 15:51 */ +/* The following code was generated by JFlex 1.4.3 on 21.02.11 18:10 */ /* It's an automatically generated code. Do not modify it. */ package org.intellij.lang.regexp; import com.intellij.lexer.FlexLexer; -import com.intellij.psi.StringEscapesTokenTypes; import com.intellij.psi.tree.IElementType; - import java.util.LinkedList; +import com.intellij.psi.StringEscapesTokenTypes; // IDEADEV-11055 @SuppressWarnings({ "ALL", "SameParameterValue", "WeakerAccess", "SameReturnValue", "RedundantThrows", "UnusedDeclaration", "UnusedDeclaration" }) @@ -15,8 +14,8 @@ import java.util.LinkedList; /** * This class is a scanner generated by * JFlex 1.4.3 - * on 01.06.10 15:51 from the specification file - * C:/JetBrains/idea.branches/maia/tools/lexer/../../community/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex + * on 21.02.11 18:10 from the specification file + * C:/JetBrains/IDEA/tools/lexer/../../community/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex */ class _RegExLexer implements FlexLexer { /** initial size of the lookahead buffer */ @@ -24,17 +23,18 @@ class _RegExLexer implements FlexLexer { /** lexical states */ public static final int EMBRACED = 4; - public static final int PY_NAMED_GROUP_REF = 20; + public static final int PY_NAMED_GROUP_REF = 22; public static final int QUOTED = 2; - public static final int OPTIONS = 12; - public static final int PY_COND_REF = 22; + public static final int CLASS2PY = 10; + public static final int OPTIONS = 14; + public static final int PY_COND_REF = 24; public static final int YYINITIAL = 0; - public static final int NAMED_GROUP = 16; + public static final int NAMED_GROUP = 18; public static final int CLASS2 = 8; public static final int CLASS1 = 6; - public static final int COMMENT = 14; - public static final int QUOTED_NAMED_GROUP = 18; - public static final int PROP = 10; + public static final int COMMENT = 16; + public static final int QUOTED_NAMED_GROUP = 20; + public static final int PROP = 12; /** * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l @@ -44,7 +44,7 @@ class _RegExLexer implements FlexLexer { */ private static final int ZZ_LEXSTATE[] = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, - 8, 8, 9, 9, 10, 10, 11, 11 + 8, 8, 9, 9, 10, 10, 11, 11, 12, 12 }; /** @@ -130,20 +130,20 @@ class _RegExLexer implements FlexLexer { private static final int [] ZZ_ACTION = zzUnpackAction(); private static final String ZZ_ACTION_PACKED_0 = - "\6\0\1\1\1\2\4\0\1\3\1\4\1\5\1\6"+ + "\7\0\1\1\1\2\4\0\1\3\1\4\1\5\1\6"+ "\1\7\1\10\1\11\1\12\1\13\1\14\1\15\1\16"+ "\1\17\1\20\1\21\1\22\1\23\1\3\1\24\1\25"+ - "\1\26\1\27\1\30\1\31\1\32\1\33\1\34\1\3"+ - "\1\35\1\36\1\35\1\37\1\40\1\1\1\41\1\42"+ - "\1\2\1\43\1\44\1\45\1\46\1\47\1\50\1\51"+ - "\1\52\1\53\1\54\1\55\1\56\2\57\1\60\1\11"+ - "\1\61\1\62\1\63\1\64\1\65\1\66\1\0\1\67"+ - "\1\70\1\71\1\72\1\0\1\73\1\74\1\75\2\62"+ - "\2\63\1\76\1\77\1\100\1\101\1\0\1\74\1\62"+ - "\1\102\2\63\1\103\1\74\3\63\1\104"; + "\1\26\1\27\1\30\1\31\1\32\1\33\1\34\2\3"+ + "\1\11\1\35\1\36\1\35\1\37\1\40\1\1\1\41"+ + "\1\42\1\2\1\43\1\44\1\45\1\46\1\47\1\50"+ + "\1\51\1\52\1\53\1\54\1\55\1\56\2\57\1\60"+ + "\1\11\1\61\1\62\1\63\1\64\1\65\1\66\1\0"+ + "\1\67\1\70\1\71\1\72\1\0\1\73\1\74\1\75"+ + "\2\62\2\63\1\76\1\77\1\100\1\101\1\0\1\74"+ + "\1\62\1\102\2\63\1\103\1\74\3\63\1\104"; private static int [] zzUnpackAction() { - int [] result = new int[100]; + int [] result = new int[103]; int offset = 0; offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); return result; @@ -169,21 +169,21 @@ class _RegExLexer implements FlexLexer { private static final String ZZ_ROWMAP_PACKED_0 = "\0\0\0\63\0\146\0\231\0\314\0\377\0\u0132\0\u0165"+ - "\0\u0198\0\u01cb\0\u01fe\0\u0231\0\u0264\0\u0264\0\u0297\0\u0264"+ - "\0\u0264\0\u02ca\0\u02fd\0\u0264\0\u0264\0\u0264\0\u0264\0\u0264"+ - "\0\u0264\0\u0264\0\u0264\0\u0264\0\u0264\0\u0330\0\u0264\0\u0363"+ - "\0\u0264\0\u0396\0\u0264\0\u0264\0\u0264\0\u0264\0\u0264\0\u03c9"+ - "\0\u0264\0\u0264\0\u02ca\0\u0264\0\u0264\0\u03fc\0\u042f\0\u0264"+ - "\0\u0264\0\u0264\0\u0264\0\u0462\0\u0264\0\u0264\0\u0495\0\u04c8"+ - "\0\u0264\0\u0264\0\u0264\0\u0264\0\u0264\0\u0264\0\u04fb\0\u0264"+ - "\0\u0264\0\u0264\0\u052e\0\u0561\0\u0264\0\u0264\0\u0264\0\u0594"+ - "\0\u0264\0\u0264\0\u0264\0\u05c7\0\u05fa\0\u0264\0\u062d\0\u0264"+ - "\0\u0660\0\u0693\0\u06c6\0\u06f9\0\u0264\0\u0264\0\u0264\0\u0264"+ - "\0\u072c\0\u075f\0\u0264\0\u0264\0\u0792\0\u07c5\0\u0264\0\u0264"+ - "\0\u07f8\0\u082b\0\u0264\0\u0264"; + "\0\u0198\0\u01cb\0\u01fe\0\u0231\0\u0264\0\u0297\0\u0297\0\u02ca"+ + "\0\u0297\0\u0297\0\u02fd\0\u0330\0\u0297\0\u0297\0\u0297\0\u0297"+ + "\0\u0297\0\u0297\0\u0297\0\u0297\0\u0297\0\u0297\0\u0363\0\u0297"+ + "\0\u0396\0\u0297\0\u03c9\0\u0297\0\u0297\0\u0297\0\u0297\0\u0297"+ + "\0\u03fc\0\u02fd\0\u042f\0\u0297\0\u0297\0\u02fd\0\u0297\0\u0297"+ + "\0\u0462\0\u0495\0\u0297\0\u0297\0\u0297\0\u0297\0\u04c8\0\u0297"+ + "\0\u0297\0\u04fb\0\u052e\0\u0297\0\u0297\0\u0297\0\u0297\0\u0297"+ + "\0\u0297\0\u0561\0\u0297\0\u0297\0\u0297\0\u0594\0\u05c7\0\u0297"+ + "\0\u0297\0\u0297\0\u05fa\0\u0297\0\u0297\0\u0297\0\u062d\0\u0660"+ + "\0\u0297\0\u0693\0\u0297\0\u06c6\0\u06f9\0\u072c\0\u075f\0\u0297"+ + "\0\u0297\0\u0297\0\u0297\0\u0792\0\u07c5\0\u0297\0\u0297\0\u07f8"+ + "\0\u082b\0\u0297\0\u0297\0\u085e\0\u0891\0\u0297\0\u0297"; private static int [] zzUnpackRowMap() { - int [] result = new int[100]; + int [] result = new int[103]; int offset = 0; offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); return result; @@ -206,47 +206,52 @@ class _RegExLexer implements FlexLexer { private static final int [] ZZ_TRANS = zzUnpackTrans(); private static final String ZZ_TRANS_PACKED_0 = - "\3\15\1\16\1\17\1\20\1\21\1\15\1\22\1\15"+ - "\1\23\1\24\1\25\1\26\1\27\1\30\1\31\1\32"+ - "\21\15\1\33\1\15\1\34\4\15\1\24\5\15\1\35"+ - "\1\15\1\24\12\15\1\36\1\0\47\15\1\37\2\40"+ - "\4\37\1\41\12\37\20\42\1\40\1\37\1\42\2\37"+ - "\1\40\1\43\12\37\11\44\1\45\1\44\1\0\47\44"+ - "\6\15\1\21\1\15\1\22\1\46\1\23\1\47\1\25"+ - "\26\15\1\33\5\15\1\50\1\47\7\15\1\47\6\51"+ - "\1\52\1\51\1\53\1\51\1\23\50\51\5\54\1\55"+ - "\14\54\20\56\1\54\1\57\1\56\6\54\1\60\7\54"+ - "\13\10\1\61\46\10\1\61\22\54\20\42\2\54\1\42"+ - "\7\54\1\62\30\54\20\42\2\54\1\42\14\54\1\63"+ - "\6\54\1\55\14\54\20\42\2\54\1\42\17\54\2\40"+ - "\2\54\1\55\14\54\20\42\1\40\1\54\1\42\2\54"+ - "\1\40\13\54\101\0\1\64\55\0\1\65\51\0\1\66"+ - "\1\67\1\70\4\71\1\66\1\71\1\66\1\71\1\72"+ - "\6\71\2\73\2\74\2\75\1\76\1\77\1\76\2\100"+ - "\1\101\1\102\1\101\1\103\1\104\1\67\1\71\1\101"+ - "\1\72\4\66\1\72\7\66\1\72\37\0\1\105\24\0"+ - "\2\40\37\0\1\40\4\0\1\40\14\0\2\42\17\0"+ - "\21\42\1\0\1\42\1\0\2\42\64\0\1\106\33\0"+ - "\20\56\2\0\1\56\40\0\20\57\2\0\1\57\22\0"+ - "\1\107\27\0\1\110\16\0\2\111\1\112\1\113\1\114"+ - "\1\115\1\116\2\0\2\67\37\0\1\67\22\0\1\117"+ - "\37\0\1\117\20\0\63\120\1\121\2\122\20\121\2\122"+ - "\2\121\3\122\3\121\1\122\1\121\1\122\2\121\1\122"+ - "\20\121\1\123\2\124\20\123\2\124\2\123\3\124\3\123"+ - "\1\124\1\123\1\124\2\123\1\124\20\123\55\0\1\125"+ - "\1\0\1\126\60\0\1\127\1\130\4\0\5\131\1\0"+ - "\55\131\2\0\1\132\37\0\1\132\20\0\64\133\2\134"+ - "\20\133\2\134\2\133\3\134\3\133\1\134\1\133\1\134"+ - "\2\133\1\134\20\133\64\135\2\136\20\135\2\136\2\135"+ - "\3\136\3\135\1\136\1\135\1\136\2\135\1\136\20\135"+ - "\5\131\1\137\55\131\2\0\1\140\37\0\1\140\20\0"+ - "\64\141\2\142\20\141\2\142\2\141\3\142\3\141\1\142"+ - "\1\141\1\142\2\141\1\142\20\141\64\143\2\144\20\143"+ - "\2\144\2\143\3\144\3\143\1\144\1\143\1\144\2\143"+ - "\1\144\20\143"; + "\3\16\1\17\1\20\1\21\1\22\1\16\1\23\1\16"+ + "\1\24\1\25\1\26\1\27\1\30\1\31\1\32\1\33"+ + "\21\16\1\34\1\16\1\35\4\16\1\25\5\16\1\36"+ + "\1\16\1\25\12\16\1\37\1\0\47\16\1\40\2\41"+ + "\4\40\1\42\12\40\20\43\1\41\1\40\1\43\2\40"+ + "\1\41\1\44\12\40\11\45\1\46\1\45\1\0\47\45"+ + "\6\16\1\22\1\16\1\23\1\47\1\24\1\50\1\26"+ + "\26\16\1\34\5\16\1\51\1\50\7\16\1\50\6\16"+ + "\1\22\1\16\1\52\1\47\1\53\1\50\1\26\26\16"+ + "\1\34\6\16\1\50\7\16\1\50\6\54\1\55\1\54"+ + "\1\56\1\54\1\24\50\54\5\57\1\60\14\57\20\61"+ + "\1\57\1\62\1\61\6\57\1\63\7\57\13\11\1\64"+ + "\46\11\1\64\22\57\20\43\2\57\1\43\7\57\1\65"+ + "\30\57\20\43\2\57\1\43\14\57\1\66\6\57\1\60"+ + "\14\57\20\43\2\57\1\43\17\57\2\41\2\57\1\60"+ + "\14\57\20\43\1\41\1\57\1\43\2\57\1\41\13\57"+ + "\101\0\1\67\55\0\1\70\51\0\1\71\1\72\1\73"+ + "\4\74\1\71\1\74\1\71\1\74\1\75\6\74\2\76"+ + "\2\77\2\100\1\101\1\102\1\101\2\103\1\104\1\105"+ + "\1\104\1\106\1\107\1\72\1\74\1\104\1\75\4\71"+ + "\1\75\7\71\1\75\37\0\1\110\24\0\2\41\37\0"+ + "\1\41\4\0\1\41\14\0\2\43\17\0\21\43\1\0"+ + "\1\43\1\0\2\43\64\0\1\111\11\0\1\71\1\72"+ + "\1\73\4\74\1\71\1\74\1\16\1\74\1\75\6\74"+ + "\2\76\2\77\2\100\1\101\1\102\1\101\2\103\1\104"+ + "\1\105\1\104\1\106\1\107\1\72\1\74\1\104\1\75"+ + "\4\71\1\75\7\71\1\75\22\0\20\61\2\0\1\61"+ + "\40\0\20\62\2\0\1\62\22\0\1\112\27\0\1\113"+ + "\16\0\2\114\1\115\1\116\1\117\1\120\1\121\2\0"+ + "\2\72\37\0\1\72\22\0\1\122\37\0\1\122\20\0"+ + "\63\123\1\124\2\125\20\124\2\125\2\124\3\125\3\124"+ + "\1\125\1\124\1\125\2\124\1\125\20\124\1\126\2\127"+ + "\20\126\2\127\2\126\3\127\3\126\1\127\1\126\1\127"+ + "\2\126\1\127\20\126\55\0\1\130\1\0\1\131\60\0"+ + "\1\132\1\133\4\0\5\134\1\0\55\134\2\0\1\135"+ + "\37\0\1\135\20\0\64\136\2\137\20\136\2\137\2\136"+ + "\3\137\3\136\1\137\1\136\1\137\2\136\1\137\20\136"+ + "\64\140\2\141\20\140\2\141\2\140\3\141\3\140\1\141"+ + "\1\140\1\141\2\140\1\141\20\140\5\134\1\142\55\134"+ + "\2\0\1\143\37\0\1\143\20\0\64\144\2\145\20\144"+ + "\2\145\2\144\3\145\3\144\1\145\1\144\1\145\2\144"+ + "\1\145\20\144\64\146\2\147\20\146\2\147\2\146\3\147"+ + "\3\146\1\147\1\146\1\147\2\146\1\147\20\146"; private static int [] zzUnpackTrans() { - int [] result = new int[2142]; + int [] result = new int[2244]; int offset = 0; offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); return result; @@ -287,15 +292,15 @@ class _RegExLexer implements FlexLexer { private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); private static final String ZZ_ATTRIBUTE_PACKED_0 = - "\6\0\2\1\4\0\2\11\1\1\2\11\2\1\12\11"+ - "\1\1\1\11\1\1\1\11\1\1\5\11\1\1\2\11"+ + "\7\0\2\1\4\0\2\11\1\1\2\11\2\1\12\11"+ + "\1\1\1\11\1\1\1\11\1\1\5\11\3\1\2\11"+ "\1\1\2\11\2\1\4\11\1\1\2\11\2\1\6\11"+ "\1\1\3\11\2\1\3\11\1\0\3\11\1\1\1\0"+ "\1\11\1\1\1\11\4\1\4\11\1\0\1\1\2\11"+ "\2\1\2\11\2\1\2\11"; private static int [] zzUnpackAttribute() { - int [] result = new int[100]; + int [] result = new int[103]; int offset = 0; offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); return result; @@ -362,11 +367,13 @@ class _RegExLexer implements FlexLexer { private boolean xmlSchemaMode; private boolean allowDanglingMetacharacters; + private boolean allowRBracketInCharacterClass; - _RegExLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters) { + _RegExLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters, boolean allowRBracketInCharacterClass) { this((java.io.Reader)null); this.xmlSchemaMode = xmlSchemaMode; this.allowDanglingMetacharacters = allowDanglingMetacharacters; + this.allowRBracketInCharacterClass = allowRBracketInCharacterClass; } private void yypushstate(int state) { @@ -644,19 +651,25 @@ class _RegExLexer implements FlexLexer { { return RegExpTT.GROUP_END; } case 70: break; - case 38: - // lookahead expression with fixed base length - zzMarkedPos = zzStartRead + 1; - { yypushstate(CLASS1); return RegExpTT.CLASS_BEGIN; - } - case 71: break; case 14: { return RegExpTT.STAR; } - case 72: break; + case 71: break; case 42: { return RegExpTT.ESC_CHARACTER; } + case 72: break; + case 38: + // lookahead expression with fixed base length + zzMarkedPos = zzStartRead + 1; + { if (allowRBracketInCharacterClass) { + yypushstate(CLASS1); + } + else { + yypushstate(CLASS2PY); + } + return RegExpTT.CLASS_BEGIN; + } case 73: break; case 28: { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.ESC_CHARACTER; @@ -666,209 +679,215 @@ class _RegExLexer implements FlexLexer { { return commentMode ? RegExpTT.CHARACTER : RegExpTT.REDUNDANT_ESCAPE; } case 75: break; + case 8: + { if (allowRBracketInCharacterClass) { + yypushstate(CLASS2); + } + else { + yypushstate(CLASS2PY); + } + return RegExpTT.CLASS_BEGIN; + } + case 76: break; case 39: { return RegExpTT.REDUNDANT_ESCAPE; } - case 76: break; + case 77: break; case 24: { return RegExpTT.COMMA; } - case 77: break; + case 78: break; case 58: { yybegin(NAMED_GROUP); return RegExpTT.RUBY_NAMED_GROUP; } - case 78: break; + case 79: break; case 64: { return RegExpTT.POS_LOOKBEHIND; } - case 79: break; + case 80: break; case 41: { return RegExpTT.BAD_OCT_VALUE; } - case 80: break; + case 81: break; case 10: { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.CTRL_CHARACTER; } - case 81: break; + case 82: break; case 30: { yypopstate(); yypushstate(EMBRACED); return RegExpTT.LBRACE; } - case 82: break; + case 83: break; case 51: { return StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN; } - case 83: break; + case 84: break; case 65: { return RegExpTT.NEG_LOOKBEHIND; } - case 84: break; + case 85: break; case 68: { return RegExpTT.UNICODE_CHAR; } - case 85: break; + case 86: break; case 61: { if (xmlSchemaMode) { yypushback(1); return RegExpTT.CHAR_CLASS; } else return RegExpTT.CTRL; } - case 86: break; + case 87: break; case 37: { yybegin(OPTIONS); return RegExpTT.SET_OPTIONS; } - case 87: break; + case 88: break; case 12: { return RegExpTT.DOLLAR; } - case 88: break; + case 89: break; case 52: { yypopstate(); return RegExpTT.QUOTE_END; } - case 89: break; + case 90: break; case 56: { return RegExpTT.POS_LOOKAHEAD; } - case 90: break; + case 91: break; case 22: { yypopstate(); return RegExpTT.RBRACE; } - case 91: break; + case 92: break; case 3: { return RegExpTT.CHARACTER; } - case 92: break; + case 93: break; case 57: { return RegExpTT.NEG_LOOKAHEAD; } - case 93: break; + case 94: break; case 44: { return RegExpTT.ESC_CTRL_CHARACTER; } - case 94: break; + case 95: break; case 23: { return RegExpTT.NAME; } - case 95: break; + case 96: break; case 53: { return RegExpTT.ANDAND; } - case 96: break; + case 97: break; case 13: { return RegExpTT.QUEST; } - case 97: break; + case 98: break; case 46: { return RegExpTT.CHAR_CLASS; } - case 98: break; + case 99: break; case 17: { return RegExpTT.MINUS; } - case 99: break; + case 100: break; case 67: { return RegExpTT.COMMENT; } - case 100: break; + case 101: break; case 40: { return yystate() != CLASS2 ? RegExpTT.BACKREF : RegExpTT.ESC_CHARACTER; } - case 101: break; + case 102: break; case 16: { return RegExpTT.UNION; } - case 102: break; + case 103: break; case 47: { if (xmlSchemaMode) return RegExpTT.CHAR_CLASS; else return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN; } - case 103: break; + case 104: break; case 60: { return RegExpTT.OCT_CHAR; } - case 104: break; + case 105: break; case 4: { return RegExpTT.DOT; } - case 105: break; + case 106: break; case 32: { yybegin(YYINITIAL); return RegExpTT.GROUP_END; } - case 106: break; + case 107: break; case 21: { return RegExpTT.NUMBER; } - case 107: break; + case 108: break; case 35: { yybegin(YYINITIAL); return RegExpTT.GT; } - case 108: break; + case 109: break; case 59: { yybegin(QUOTED_NAMED_GROUP); return RegExpTT.RUBY_QUOTED_NAMED_GROUP; } - case 109: break; + case 110: break; case 54: { yybegin(PY_COND_REF); return RegExpTT.PYTHON_COND_REF; } - case 110: break; + case 111: break; case 48: { yypushstate(PROP); return RegExpTT.PROPERTY; } - case 111: break; + case 112: break; case 18: { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.CHARACTER; } - case 112: break; + case 113: break; case 33: { handleOptions(); return RegExpTT.OPTIONS_OFF; } - case 113: break; + case 114: break; case 34: { yybegin(YYINITIAL); return RegExpTT.COLON; } - case 114: break; + case 115: break; case 25: { assert false : yytext(); } - case 115: break; + case 116: break; case 62: { yybegin(PY_NAMED_GROUP_REF); return RegExpTT.PYTHON_NAMED_GROUP_REF; } - case 116: break; + case 117: break; case 27: { yypopstate(); return RegExpTT.CLASS_END; } - case 117: break; + case 118: break; case 11: { return RegExpTT.CARET; } - case 118: break; + case 119: break; case 1: { handleOptions(); return RegExpTT.OPTIONS_ON; } - case 119: break; + case 120: break; case 29: { yypopstate(); yypushback(1); } - case 120: break; + case 121: break; case 45: { return yystate() != CLASS2 ? RegExpTT.BOUNDARY : RegExpTT.ESC_CHARACTER; } - case 121: break; + case 122: break; case 63: { yybegin(NAMED_GROUP); return RegExpTT.PYTHON_NAMED_GROUP; } - case 122: break; + case 123: break; case 19: { if (commentMode) { yypushstate(COMMENT); return RegExpTT.COMMENT; } else return RegExpTT.CHARACTER; } - case 123: break; + case 124: break; case 66: { return RegExpTT.HEX_CHAR; } - case 124: break; + case 125: break; case 5: { return RegExpTT.GROUP_BEGIN; } - case 125: break; - case 8: - { yypushstate(CLASS2); return RegExpTT.CLASS_BEGIN; - } case 126: break; case 55: { return RegExpTT.NON_CAPT_GROUP; @@ -882,26 +901,6 @@ class _RegExLexer implements FlexLexer { { yybegin(YYINITIAL); return RegExpTT.QUOTE; } case 129: break; - case 50: - { return RegExpTT.BAD_HEX_VALUE; - } - case 130: break; - case 2: - { yypopstate(); return RegExpTT.COMMENT; - } - case 131: break; - case 49: - { yypushstate(QUOTED); return RegExpTT.QUOTE_BEGIN; - } - case 132: break; - case 26: - { yybegin(CLASS2); return RegExpTT.CHARACTER; - } - case 133: break; - case 15: - { return RegExpTT.PLUS; - } - case 134: break; case 20: { if (allowDanglingMetacharacters) { yypopstate(); yypushback(1); @@ -909,6 +908,26 @@ class _RegExLexer implements FlexLexer { return RegExpTT.BAD_CHARACTER; } } + case 130: break; + case 50: + { return RegExpTT.BAD_HEX_VALUE; + } + case 131: break; + case 2: + { yypopstate(); return RegExpTT.COMMENT; + } + case 132: break; + case 49: + { yypushstate(QUOTED); return RegExpTT.QUOTE_BEGIN; + } + case 133: break; + case 26: + { yybegin(CLASS2); return RegExpTT.CHARACTER; + } + case 134: break; + case 15: + { return RegExpTT.PLUS; + } case 135: break; case 31: { yybegin(YYINITIAL); return RegExpTT.BAD_CHARACTER; diff --git a/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex b/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex index 5269feebd791..c11e0679ca77 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex +++ b/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex @@ -27,11 +27,13 @@ import com.intellij.psi.StringEscapesTokenTypes; private boolean xmlSchemaMode; private boolean allowDanglingMetacharacters; + private boolean allowRBracketInCharacterClass; - _RegExLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters) { + _RegExLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters, boolean allowRBracketInCharacterClass) { this((java.io.Reader)null); this.xmlSchemaMode = xmlSchemaMode; this.allowDanglingMetacharacters = allowDanglingMetacharacters; + this.allowRBracketInCharacterClass = allowRBracketInCharacterClass; } private void yypushstate(int state) { @@ -59,6 +61,7 @@ import com.intellij.psi.StringEscapesTokenTypes; %xstate EMBRACED %xstate CLASS1 %state CLASS2 +%state CLASS2PY %state PROP %xstate OPTIONS %xstate COMMENT @@ -146,7 +149,14 @@ HEX_CHAR=[0-9a-fA-F] {ESCAPE} [:letter:] { return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN; } {ESCAPE} [\n\b\t\r\f ] { return commentMode ? RegExpTT.CHARACTER : RegExpTT.REDUNDANT_ESCAPE; } + + { + {ESCAPE} {RBRACKET} { return RegExpTT.CHARACTER; } +} + {ESCAPE} {ANY} { return RegExpTT.REDUNDANT_ESCAPE; } + + {ESCAPE} { return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN; } { @@ -175,8 +185,25 @@ HEX_CHAR=[0-9a-fA-F] "-" { return RegExpTT.MINUS; } "^" { return RegExpTT.CARET; } -{LBRACKET} / {RBRACKET} { yypushstate(CLASS1); return RegExpTT.CLASS_BEGIN; } -{LBRACKET} { yypushstate(CLASS2); return RegExpTT.CLASS_BEGIN; } + { + {LBRACKET} { return RegExpTT.CHARACTER; } +} + +{LBRACKET} / {RBRACKET} { if (allowRBracketInCharacterClass) { + yypushstate(CLASS1); + } + else { + yypushstate(CLASS2PY); + } + return RegExpTT.CLASS_BEGIN; } + +{LBRACKET} { if (allowRBracketInCharacterClass) { + yypushstate(CLASS2); + } + else { + yypushstate(CLASS2PY); + } + return RegExpTT.CLASS_BEGIN; } /* []abc] is legal. The first ] is treated as literal character */ { @@ -192,6 +219,15 @@ HEX_CHAR=[0-9a-fA-F] {ANY} { return RegExpTT.CHARACTER; } } +/* see rules for matching LBRACKET and escaped RBRACKET in CLASS2PY above */ + { + {RBRACKET} { yypopstate(); return RegExpTT.CLASS_END; } + + [\n\b\t\r\f] { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.ESC_CHARACTER; } + {ANY} { return RegExpTT.CHARACTER; } +} + + { {LPAREN} { return RegExpTT.GROUP_BEGIN; } {RPAREN} { return RegExpTT.GROUP_END; } From 18bca98e5f9263d79780b1086071a7a2073128fe Mon Sep 17 00:00:00 2001 From: andrey zaytsev Date: Mon, 21 Feb 2011 16:13:31 +0300 Subject: [PATCH 042/169] search and replace: navigation through occurrences --- .../com/intellij/find/EditorSearchComponent.java | 9 +++++++-- .../find/impl/livePreview/SearchResults.java | 15 +++++++++++++-- .../editor/actions/IncrementalFindAction.java | 8 ++++++-- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java index bfd283667e94..516bdaac1f41 100644 --- a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java +++ b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java @@ -166,8 +166,6 @@ public class EditorSearchComponent extends JPanel implements DataProvider, Selec myEditor.getCaretModel().moveToOffset(range.getEndOffset()); myEditor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); - myEditor.getCaretModel().moveToOffset(range.getStartOffset()); - myEditor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); } myToChangeSelection = false; } @@ -528,6 +526,13 @@ public class EditorSearchComponent extends JPanel implements DataProvider, Selec } } + public void replaceCurrent() { + if (mySearchResults.getCursor() != null) { + String replacement = myLivePreviewController.getReplacementPreviewText(myEditor, mySearchResults.getCursor()); + myLivePreviewController.performReplace(mySearchResults.getCursor(), replacement, myEditor); + } + } + private static void setSmallerFontAndOpaque(final JComponent component) { setSmallerFont(component); component.setOpaque(false); diff --git a/platform/lang-impl/src/com/intellij/find/impl/livePreview/SearchResults.java b/platform/lang-impl/src/com/intellij/find/impl/livePreview/SearchResults.java index d6925ef5d915..2381f31aaa3e 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/livePreview/SearchResults.java +++ b/platform/lang-impl/src/com/intellij/find/impl/livePreview/SearchResults.java @@ -237,6 +237,17 @@ public class SearchResults { return firstVisibleOccurrence != null ? firstVisibleOccurrence : firstOccurrence; } + @Nullable + private LiveOccurrence firstOccurrenceBeforeCaret() { + int offset = getEditor().getCaretModel().getOffset(); + for (int i = getOccurrences().size()-1; i >= 0; --i) { + if (getOccurrences().get(i).getPrimaryRange().getEndOffset() < offset) { + return getOccurrences().get(i); + } + } + return null; + } + @Nullable private LiveOccurrence firstOccurrenceAfterCaret() { LiveOccurrence afterCaret = null; @@ -294,7 +305,7 @@ public class SearchResults { } public void prevOccurrence() { - LiveOccurrence prev = prevOccurrence(myCursor); + LiveOccurrence prev = firstOccurrenceBeforeCaret(); if (prev == null && !getOccurrences().isEmpty()) { prev = getOccurrences().get(getOccurrences().size() - 1); } @@ -302,7 +313,7 @@ public class SearchResults { } public void nextOccurrence() { - LiveOccurrence next = nextOccurrence(myCursor); + LiveOccurrence next = firstOccurrenceAfterCaret(); if (next == null && !getOccurrences().isEmpty()) { next = getOccurrences().get(0); } diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/actions/IncrementalFindAction.java b/platform/lang-impl/src/com/intellij/openapi/editor/actions/IncrementalFindAction.java index a8d73ba7d634..2f2535ff5e9f 100644 --- a/platform/lang-impl/src/com/intellij/openapi/editor/actions/IncrementalFindAction.java +++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/IncrementalFindAction.java @@ -42,8 +42,12 @@ public class IncrementalFindAction extends EditorAction { if (!editor.isOneLineMode()) { final JComponent headerComponent = editor.getHeaderComponent(); if (headerComponent instanceof EditorSearchComponent) { - ((EditorSearchComponent) headerComponent).setInitialText(editor.getSelectionModel().getSelectedText()); - headerComponent.requestFocus(); + if (myReplace) { + ((EditorSearchComponent)headerComponent).replaceCurrent(); + } else { + ((EditorSearchComponent) headerComponent).setInitialText(editor.getSelectionModel().getSelectedText()); + headerComponent.requestFocus(); + } } else { final EditorSearchComponent header = new EditorSearchComponent(editor, project, myReplace); From 110d2906da3b2dfa5456ac4d9a6fc61f8bfea696 Mon Sep 17 00:00:00 2001 From: andrey zaytsev Date: Mon, 21 Feb 2011 20:22:15 +0300 Subject: [PATCH 043/169] search/replace: replace-all in selection is fixed. occurrences navigation and selection --- .../intellij/find/EditorSearchComponent.java | 12 +++++- .../LivePreviewControllerBase.java | 27 ++++++++++++-- .../find/impl/livePreview/SearchResults.java | 37 +++++++++++++++---- 3 files changed, 64 insertions(+), 12 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java index 516bdaac1f41..d0e18e187ce3 100644 --- a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java +++ b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java @@ -194,7 +194,15 @@ public class EditorSearchComponent extends JPanel implements DataProvider, Selec public void getFocusBack() { mySearchField.requestFocus(); } + + @Override + public TextRange performReplace(LiveOccurrence occurrence, String replacement, Editor editor) { + myToChangeSelection = true; + return super + .performReplace(occurrence, replacement, editor); //To change body of overridden methods use File | Settings | File Templates. + } }; + mySearchResults.addListener(this); setMatchesLimit(MATCHES_LIMIT); @@ -640,7 +648,9 @@ public class EditorSearchComponent extends JPanel implements DataProvider, Selec model.setGlobal(!mySelectionOnly.isSelected()); model.setPreserveCase(myPreserveCase.isEnabled() && myPreserveCase.isSelected()); } - myToChangeSelection = allowedToChangedEditorSelection; + if (!myToChangeSelection) { + myToChangeSelection = allowedToChangedEditorSelection; + } myLivePreviewController.updateInBackground(model); } diff --git a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java index a94ec03b51a1..c78fd723f35e 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java +++ b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java @@ -26,6 +26,21 @@ public class LivePreviewControllerBase implements LivePreview.Delegate, FindUtil private SearchResults mySearchResults; private LivePreview myLivePreview; + public interface ReplaceListener { + void replacePerformed(LiveOccurrence occurrence, final String replacement, final Editor editor); + void replaceAllPerformed(Editor e); + } + + private ReplaceListener myReplaceListener; + + public ReplaceListener getReplaceListener() { + return myReplaceListener; + } + + public void setReplaceListener(ReplaceListener replaceListener) { + myReplaceListener = replaceListener; + } + public LivePreviewControllerBase(SearchResults searchResults, LivePreview livePreview) { mySearchResults = searchResults; myLivePreview = livePreview; @@ -86,21 +101,27 @@ public class LivePreviewControllerBase implements LivePreview.Delegate, FindUtil public TextRange performReplace(final LiveOccurrence occurrence, final String replacement, final Editor editor) { TextRange range = occurrence.getPrimaryRange(); FindModel findModel = mySearchResults.getFindModel(); + TextRange result = null; try { - return FindUtil.doReplace(editor.getProject(), editor.getDocument(), findModel, new FindResultImpl(range.getStartOffset(), range.getEndOffset()), + result = FindUtil.doReplace(editor.getProject(), editor.getDocument(), findModel, new FindResultImpl(range.getStartOffset(), range.getEndOffset()), FindManager.getInstance(editor.getProject()).getStringToReplace(editor.getDocument().getText(range), findModel), true, new ArrayList>()); } catch (FindManager.MalformedReplacementStringException e) { /**/ } + if (myReplaceListener != null) { + myReplaceListener.replacePerformed(occurrence, replacement, editor); + } mySearchResults.updateThreadSafe(findModel); - return null; + return result; } @Override public void performReplaceAll(Editor e) { - FindUtil.replace(e.getProject(), e, 0, mySearchResults.getFindModel(), this); + FindUtil.replace(e.getProject(), e, + mySearchResults.getFindModel().isGlobal() ? 0 : mySearchResults.getEditor().getSelectionModel().getSelectionStart(), + mySearchResults.getFindModel(), this); } @Override diff --git a/platform/lang-impl/src/com/intellij/find/impl/livePreview/SearchResults.java b/platform/lang-impl/src/com/intellij/find/impl/livePreview/SearchResults.java index 2381f31aaa3e..1fb568ed4c51 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/livePreview/SearchResults.java +++ b/platform/lang-impl/src/com/intellij/find/impl/livePreview/SearchResults.java @@ -4,10 +4,12 @@ package com.intellij.find.impl.livePreview; import com.intellij.find.FindManager; import com.intellij.find.FindModel; import com.intellij.find.FindResult; +import com.intellij.find.FindUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.Nullable; @@ -32,6 +34,7 @@ public class SearchResults { private FindModel myFindModel; private int myMatchesLimit = 100; + private boolean myNotFound = false; public SearchResults(Editor editor) { myEditor = editor; @@ -131,10 +134,16 @@ public class SearchResults { final ArrayList results = new ArrayList(); if (findModel != null) { - + final Ref selectionRef = new Ref(); + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + selectionRef.set(new TextRange(editor.getSelectionModel().getSelectionStart(), + editor.getSelectionModel().getSelectionEnd())); + } + }); TextRange r = findModel.isGlobal() ? new TextRange(0, Integer.MAX_VALUE) : - new TextRange(editor.getSelectionModel().getSelectionStart(), - editor.getSelectionModel().getSelectionEnd()); + selectionRef.get(); if (r.getLength() == 0) { r = new TextRange(0, Integer.MAX_VALUE); } @@ -305,18 +314,30 @@ public class SearchResults { } public void prevOccurrence() { - LiveOccurrence prev = firstOccurrenceBeforeCaret(); - if (prev == null && !getOccurrences().isEmpty()) { - prev = getOccurrences().get(getOccurrences().size() - 1); + LiveOccurrence next = null; + if (!myFindModel.isGlobal()) { + next = prevOccurrence(myCursor); + } else { + next = firstOccurrenceBeforeCaret(); } - moveCursorTo(prev); + if (next == null && !getOccurrences().isEmpty()) { + next = getOccurrences().get(getOccurrences().size()-1); + } + + moveCursorTo(next); } public void nextOccurrence() { - LiveOccurrence next = firstOccurrenceAfterCaret(); + LiveOccurrence next = null; + if (!myFindModel.isGlobal()) { + next = nextOccurrence(myCursor); + } else { + next = firstOccurrenceAfterCaret(); + } if (next == null && !getOccurrences().isEmpty()) { next = getOccurrences().get(0); } + moveCursorTo(next); } From de3f634507019690db341556fc676d4bae9f83c2 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 21 Feb 2011 18:33:00 +0100 Subject: [PATCH 044/169] fix parsing of octal characters in Python regexps (PY-2906) --- .../org/intellij/lang/regexp/RegExpLexer.java | 5 +- .../lang/regexp/RegExpParserDefinition.java | 2 +- .../org/intellij/lang/regexp/_RegExLexer.java | 227 +++++++++--------- .../intellij/lang/regexp/regexp-lexer.flex | 9 +- 4 files changed, 130 insertions(+), 113 deletions(-) diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java index 806b9393ef6a..097b3cb631e2 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java @@ -21,8 +21,9 @@ public class RegExpLexer extends FlexAdapter { private static final int COMMENT_MODE = 1 << 14; - public RegExpLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters, boolean allowRBracketInCharacterClass) { - super(new _RegExLexer(xmlSchemaMode, allowDanglingMetacharacters, allowRBracketInCharacterClass)); + public RegExpLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters, boolean allowRBracketInCharacterClass, + boolean allowOctalNoLeadingZero) { + super(new _RegExLexer(xmlSchemaMode, allowDanglingMetacharacters, allowRBracketInCharacterClass, allowOctalNoLeadingZero)); } public void start(CharSequence buffer, int startOffset, int endOffset, int initialState) { diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpParserDefinition.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpParserDefinition.java index 1788d325e090..c247579512b1 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/RegExpParserDefinition.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/RegExpParserDefinition.java @@ -36,7 +36,7 @@ public class RegExpParserDefinition implements ParserDefinition { @NotNull public Lexer createLexer(Project project) { - return new RegExpLexer(false, false, true); + return new RegExpLexer(false, false, true, false); } public PsiParser createParser(Project project) { diff --git a/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java b/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java index 492a35a3215c..21ad5ba124f0 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java @@ -1,4 +1,4 @@ -/* The following code was generated by JFlex 1.4.3 on 21.02.11 18:10 */ +/* The following code was generated by JFlex 1.4.3 on 21.02.11 18:30 */ /* It's an automatically generated code. Do not modify it. */ package org.intellij.lang.regexp; @@ -14,7 +14,7 @@ import com.intellij.psi.StringEscapesTokenTypes; /** * This class is a scanner generated by * JFlex 1.4.3 - * on 21.02.11 18:10 from the specification file + * on 21.02.11 18:30 from the specification file * C:/JetBrains/IDEA/tools/lexer/../../community/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex */ class _RegExLexer implements FlexLexer { @@ -137,13 +137,14 @@ class _RegExLexer implements FlexLexer { "\1\11\1\35\1\36\1\35\1\37\1\40\1\1\1\41"+ "\1\42\1\2\1\43\1\44\1\45\1\46\1\47\1\50"+ "\1\51\1\52\1\53\1\54\1\55\1\56\2\57\1\60"+ - "\1\11\1\61\1\62\1\63\1\64\1\65\1\66\1\0"+ - "\1\67\1\70\1\71\1\72\1\0\1\73\1\74\1\75"+ - "\2\62\2\63\1\76\1\77\1\100\1\101\1\0\1\74"+ - "\1\62\1\102\2\63\1\103\1\74\3\63\1\104"; + "\1\11\1\61\1\62\1\63\1\50\1\64\1\65\1\66"+ + "\1\0\1\67\1\70\1\71\1\72\1\0\1\73\1\74"+ + "\1\75\2\62\2\63\1\50\1\76\1\77\1\100\1\101"+ + "\1\0\1\74\1\62\1\102\2\63\1\103\1\104\1\74"+ + "\3\63\1\105"; private static int [] zzUnpackAction() { - int [] result = new int[103]; + int [] result = new int[106]; int offset = 0; offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); return result; @@ -176,14 +177,15 @@ class _RegExLexer implements FlexLexer { "\0\u03fc\0\u02fd\0\u042f\0\u0297\0\u0297\0\u02fd\0\u0297\0\u0297"+ "\0\u0462\0\u0495\0\u0297\0\u0297\0\u0297\0\u0297\0\u04c8\0\u0297"+ "\0\u0297\0\u04fb\0\u052e\0\u0297\0\u0297\0\u0297\0\u0297\0\u0297"+ - "\0\u0297\0\u0561\0\u0297\0\u0297\0\u0297\0\u0594\0\u05c7\0\u0297"+ - "\0\u0297\0\u0297\0\u05fa\0\u0297\0\u0297\0\u0297\0\u062d\0\u0660"+ - "\0\u0297\0\u0693\0\u0297\0\u06c6\0\u06f9\0\u072c\0\u075f\0\u0297"+ - "\0\u0297\0\u0297\0\u0297\0\u0792\0\u07c5\0\u0297\0\u0297\0\u07f8"+ - "\0\u082b\0\u0297\0\u0297\0\u085e\0\u0891\0\u0297\0\u0297"; + "\0\u0297\0\u0561\0\u0297\0\u0297\0\u0297\0\u0594\0\u05c7\0\u05fa"+ + "\0\u0297\0\u0297\0\u0297\0\u062d\0\u0297\0\u0297\0\u0297\0\u0660"+ + "\0\u0693\0\u0297\0\u06c6\0\u0297\0\u06f9\0\u072c\0\u075f\0\u0792"+ + "\0\u07c5\0\u0297\0\u0297\0\u0297\0\u0297\0\u07f8\0\u082b\0\u0297"+ + "\0\u0297\0\u085e\0\u0891\0\u04fb\0\u0297\0\u0297\0\u08c4\0\u08f7"+ + "\0\u0297\0\u0297"; private static int [] zzUnpackRowMap() { - int [] result = new int[103]; + int [] result = new int[106]; int offset = 0; offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); return result; @@ -225,33 +227,35 @@ class _RegExLexer implements FlexLexer { "\101\0\1\67\55\0\1\70\51\0\1\71\1\72\1\73"+ "\4\74\1\71\1\74\1\71\1\74\1\75\6\74\2\76"+ "\2\77\2\100\1\101\1\102\1\101\2\103\1\104\1\105"+ - "\1\104\1\106\1\107\1\72\1\74\1\104\1\75\4\71"+ - "\1\75\7\71\1\75\37\0\1\110\24\0\2\41\37\0"+ + "\1\104\1\106\1\107\1\110\1\74\1\104\1\75\4\71"+ + "\1\75\7\71\1\75\37\0\1\111\24\0\2\41\37\0"+ "\1\41\4\0\1\41\14\0\2\43\17\0\21\43\1\0"+ - "\1\43\1\0\2\43\64\0\1\111\11\0\1\71\1\72"+ + "\1\43\1\0\2\43\64\0\1\112\11\0\1\71\1\72"+ "\1\73\4\74\1\71\1\74\1\16\1\74\1\75\6\74"+ "\2\76\2\77\2\100\1\101\1\102\1\101\2\103\1\104"+ - "\1\105\1\104\1\106\1\107\1\72\1\74\1\104\1\75"+ + "\1\105\1\104\1\106\1\107\1\110\1\74\1\104\1\75"+ "\4\71\1\75\7\71\1\75\22\0\20\61\2\0\1\61"+ - "\40\0\20\62\2\0\1\62\22\0\1\112\27\0\1\113"+ - "\16\0\2\114\1\115\1\116\1\117\1\120\1\121\2\0"+ - "\2\72\37\0\1\72\22\0\1\122\37\0\1\122\20\0"+ - "\63\123\1\124\2\125\20\124\2\125\2\124\3\125\3\124"+ - "\1\125\1\124\1\125\2\124\1\125\20\124\1\126\2\127"+ - "\20\126\2\127\2\126\3\127\3\126\1\127\1\126\1\127"+ - "\2\126\1\127\20\126\55\0\1\130\1\0\1\131\60\0"+ - "\1\132\1\133\4\0\5\134\1\0\55\134\2\0\1\135"+ - "\37\0\1\135\20\0\64\136\2\137\20\136\2\137\2\136"+ - "\3\137\3\136\1\137\1\136\1\137\2\136\1\137\20\136"+ + "\40\0\20\62\2\0\1\62\22\0\1\113\27\0\1\114"+ + "\16\0\2\115\1\116\1\117\1\120\1\121\1\122\2\0"+ + "\2\72\37\0\1\72\22\0\1\123\37\0\1\123\20\0"+ + "\63\124\1\125\2\126\20\125\2\126\2\125\3\126\3\125"+ + "\1\126\1\125\1\126\2\125\1\126\20\125\1\127\2\130"+ + "\20\127\2\130\2\127\3\130\3\127\1\130\1\127\1\130"+ + "\2\127\1\130\20\127\1\0\1\72\1\131\37\0\1\131"+ + "\75\0\1\132\1\0\1\133\60\0\1\134\1\135\4\0"+ + "\5\136\1\0\55\136\2\0\1\137\37\0\1\137\20\0"+ "\64\140\2\141\20\140\2\141\2\140\3\141\3\140\1\141"+ - "\1\140\1\141\2\140\1\141\20\140\5\134\1\142\55\134"+ - "\2\0\1\143\37\0\1\143\20\0\64\144\2\145\20\144"+ - "\2\145\2\144\3\145\3\144\1\145\1\144\1\145\2\144"+ - "\1\145\20\144\64\146\2\147\20\146\2\147\2\146\3\147"+ - "\3\146\1\147\1\146\1\147\2\146\1\147\20\146"; + "\1\140\1\141\2\140\1\141\20\140\64\142\2\143\20\142"+ + "\2\143\2\142\3\143\3\142\1\143\1\142\1\143\2\142"+ + "\1\143\20\142\1\0\1\72\1\144\37\0\1\144\20\0"+ + "\5\136\1\145\55\136\2\0\1\146\37\0\1\146\20\0"+ + "\64\147\2\150\20\147\2\150\2\147\3\150\3\147\1\150"+ + "\1\147\1\150\2\147\1\150\20\147\64\151\2\152\20\151"+ + "\2\152\2\151\3\152\3\151\1\152\1\151\1\152\2\151"+ + "\1\152\20\151"; private static int [] zzUnpackTrans() { - int [] result = new int[2244]; + int [] result = new int[2346]; int offset = 0; offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); return result; @@ -295,12 +299,12 @@ class _RegExLexer implements FlexLexer { "\7\0\2\1\4\0\2\11\1\1\2\11\2\1\12\11"+ "\1\1\1\11\1\1\1\11\1\1\5\11\3\1\2\11"+ "\1\1\2\11\2\1\4\11\1\1\2\11\2\1\6\11"+ - "\1\1\3\11\2\1\3\11\1\0\3\11\1\1\1\0"+ - "\1\11\1\1\1\11\4\1\4\11\1\0\1\1\2\11"+ - "\2\1\2\11\2\1\2\11"; + "\1\1\3\11\3\1\3\11\1\0\3\11\1\1\1\0"+ + "\1\11\1\1\1\11\5\1\4\11\1\0\1\1\2\11"+ + "\3\1\2\11\2\1\2\11"; private static int [] zzUnpackAttribute() { - int [] result = new int[103]; + int [] result = new int[106]; int offset = 0; offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); return result; @@ -368,12 +372,14 @@ class _RegExLexer implements FlexLexer { private boolean allowDanglingMetacharacters; private boolean allowRBracketInCharacterClass; + private boolean allowOctalNoLeadingZero; - _RegExLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters, boolean allowRBracketInCharacterClass) { + _RegExLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters, boolean allowRBracketInCharacterClass, boolean allowOctalNoLeadingZero) { this((java.io.Reader)null); this.xmlSchemaMode = xmlSchemaMode; this.allowDanglingMetacharacters = allowDanglingMetacharacters; this.allowRBracketInCharacterClass = allowRBracketInCharacterClass; + this.allowOctalNoLeadingZero = allowOctalNoLeadingZero; } private void yypushstate(int state) { @@ -646,19 +652,19 @@ class _RegExLexer implements FlexLexer { case 7: { if (yystate() != CLASS2) yypushstate(EMBRACED); return RegExpTT.LBRACE; } - case 69: break; + case 70: break; case 6: { return RegExpTT.GROUP_END; } - case 70: break; + case 71: break; case 14: { return RegExpTT.STAR; } - case 71: break; + case 72: break; case 42: { return RegExpTT.ESC_CHARACTER; } - case 72: break; + case 73: break; case 38: // lookahead expression with fixed base length zzMarkedPos = zzStartRead + 1; @@ -670,15 +676,15 @@ class _RegExLexer implements FlexLexer { } return RegExpTT.CLASS_BEGIN; } - case 73: break; + case 74: break; case 28: { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.ESC_CHARACTER; } - case 74: break; + case 75: break; case 43: { return commentMode ? RegExpTT.CHARACTER : RegExpTT.REDUNDANT_ESCAPE; } - case 75: break; + case 76: break; case 8: { if (allowRBracketInCharacterClass) { yypushstate(CLASS2); @@ -688,219 +694,224 @@ class _RegExLexer implements FlexLexer { } return RegExpTT.CLASS_BEGIN; } - case 76: break; + case 77: break; case 39: { return RegExpTT.REDUNDANT_ESCAPE; } - case 77: break; + case 78: break; case 24: { return RegExpTT.COMMA; } - case 78: break; + case 79: break; case 58: { yybegin(NAMED_GROUP); return RegExpTT.RUBY_NAMED_GROUP; } - case 79: break; + case 80: break; case 64: { return RegExpTT.POS_LOOKBEHIND; } - case 80: break; + case 81: break; case 41: { return RegExpTT.BAD_OCT_VALUE; } - case 81: break; + case 82: break; case 10: { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.CTRL_CHARACTER; } - case 82: break; + case 83: break; case 30: { yypopstate(); yypushstate(EMBRACED); return RegExpTT.LBRACE; } - case 83: break; + case 84: break; case 51: { return StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN; } - case 84: break; + case 85: break; case 65: { return RegExpTT.NEG_LOOKBEHIND; } - case 85: break; - case 68: + case 86: break; + case 69: { return RegExpTT.UNICODE_CHAR; } - case 86: break; + case 87: break; case 61: { if (xmlSchemaMode) { yypushback(1); return RegExpTT.CHAR_CLASS; } else return RegExpTT.CTRL; } - case 87: break; + case 88: break; case 37: { yybegin(OPTIONS); return RegExpTT.SET_OPTIONS; } - case 88: break; + case 89: break; case 12: { return RegExpTT.DOLLAR; } - case 89: break; + case 90: break; case 52: { yypopstate(); return RegExpTT.QUOTE_END; } - case 90: break; + case 91: break; case 56: { return RegExpTT.POS_LOOKAHEAD; } - case 91: break; + case 92: break; case 22: { yypopstate(); return RegExpTT.RBRACE; } - case 92: break; + case 93: break; case 3: { return RegExpTT.CHARACTER; } - case 93: break; + case 94: break; case 57: { return RegExpTT.NEG_LOOKAHEAD; } - case 94: break; + case 95: break; + case 67: + { if (allowOctalNoLeadingZero) return RegExpTT.OCT_CHAR; + return yystate() != CLASS2 ? RegExpTT.BACKREF : RegExpTT.ESC_CHARACTER; + } + case 96: break; case 44: { return RegExpTT.ESC_CTRL_CHARACTER; } - case 95: break; + case 97: break; case 23: { return RegExpTT.NAME; } - case 96: break; + case 98: break; case 53: { return RegExpTT.ANDAND; } - case 97: break; + case 99: break; case 13: { return RegExpTT.QUEST; } - case 98: break; + case 100: break; case 46: { return RegExpTT.CHAR_CLASS; } - case 99: break; + case 101: break; case 17: { return RegExpTT.MINUS; } - case 100: break; - case 67: + case 102: break; + case 68: { return RegExpTT.COMMENT; } - case 101: break; + case 103: break; case 40: { return yystate() != CLASS2 ? RegExpTT.BACKREF : RegExpTT.ESC_CHARACTER; } - case 102: break; + case 104: break; case 16: { return RegExpTT.UNION; } - case 103: break; + case 105: break; case 47: { if (xmlSchemaMode) return RegExpTT.CHAR_CLASS; else return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN; } - case 104: break; + case 106: break; case 60: { return RegExpTT.OCT_CHAR; } - case 105: break; + case 107: break; case 4: { return RegExpTT.DOT; } - case 106: break; + case 108: break; case 32: { yybegin(YYINITIAL); return RegExpTT.GROUP_END; } - case 107: break; + case 109: break; case 21: { return RegExpTT.NUMBER; } - case 108: break; + case 110: break; case 35: { yybegin(YYINITIAL); return RegExpTT.GT; } - case 109: break; + case 111: break; case 59: { yybegin(QUOTED_NAMED_GROUP); return RegExpTT.RUBY_QUOTED_NAMED_GROUP; } - case 110: break; + case 112: break; case 54: { yybegin(PY_COND_REF); return RegExpTT.PYTHON_COND_REF; } - case 111: break; + case 113: break; case 48: { yypushstate(PROP); return RegExpTT.PROPERTY; } - case 112: break; + case 114: break; case 18: { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.CHARACTER; } - case 113: break; + case 115: break; case 33: { handleOptions(); return RegExpTT.OPTIONS_OFF; } - case 114: break; + case 116: break; case 34: { yybegin(YYINITIAL); return RegExpTT.COLON; } - case 115: break; + case 117: break; case 25: { assert false : yytext(); } - case 116: break; + case 118: break; case 62: { yybegin(PY_NAMED_GROUP_REF); return RegExpTT.PYTHON_NAMED_GROUP_REF; } - case 117: break; + case 119: break; case 27: { yypopstate(); return RegExpTT.CLASS_END; } - case 118: break; + case 120: break; case 11: { return RegExpTT.CARET; } - case 119: break; + case 121: break; case 1: { handleOptions(); return RegExpTT.OPTIONS_ON; } - case 120: break; + case 122: break; case 29: { yypopstate(); yypushback(1); } - case 121: break; + case 123: break; case 45: { return yystate() != CLASS2 ? RegExpTT.BOUNDARY : RegExpTT.ESC_CHARACTER; } - case 122: break; + case 124: break; case 63: { yybegin(NAMED_GROUP); return RegExpTT.PYTHON_NAMED_GROUP; } - case 123: break; + case 125: break; case 19: { if (commentMode) { yypushstate(COMMENT); return RegExpTT.COMMENT; } else return RegExpTT.CHARACTER; } - case 124: break; + case 126: break; case 66: { return RegExpTT.HEX_CHAR; } - case 125: break; + case 127: break; case 5: { return RegExpTT.GROUP_BEGIN; } - case 126: break; + case 128: break; case 55: { return RegExpTT.NON_CAPT_GROUP; } - case 127: break; + case 129: break; case 9: { return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN; } - case 128: break; + case 130: break; case 36: { yybegin(YYINITIAL); return RegExpTT.QUOTE; } - case 129: break; + case 131: break; case 20: { if (allowDanglingMetacharacters) { yypopstate(); yypushback(1); @@ -908,31 +919,31 @@ class _RegExLexer implements FlexLexer { return RegExpTT.BAD_CHARACTER; } } - case 130: break; + case 132: break; case 50: { return RegExpTT.BAD_HEX_VALUE; } - case 131: break; + case 133: break; case 2: { yypopstate(); return RegExpTT.COMMENT; } - case 132: break; + case 134: break; case 49: { yypushstate(QUOTED); return RegExpTT.QUOTE_BEGIN; } - case 133: break; + case 135: break; case 26: { yybegin(CLASS2); return RegExpTT.CHARACTER; } - case 134: break; + case 136: break; case 15: { return RegExpTT.PLUS; } - case 135: break; + case 137: break; case 31: { yybegin(YYINITIAL); return RegExpTT.BAD_CHARACTER; } - case 136: break; + case 138: break; default: if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { zzAtEOF = true; diff --git a/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex b/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex index c11e0679ca77..eaae7a5060f0 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex +++ b/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex @@ -28,12 +28,14 @@ import com.intellij.psi.StringEscapesTokenTypes; private boolean allowDanglingMetacharacters; private boolean allowRBracketInCharacterClass; + private boolean allowOctalNoLeadingZero; - _RegExLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters, boolean allowRBracketInCharacterClass) { + _RegExLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters, boolean allowRBracketInCharacterClass, boolean allowOctalNoLeadingZero) { this((java.io.Reader)null); this.xmlSchemaMode = xmlSchemaMode; this.allowDanglingMetacharacters = allowDanglingMetacharacters; this.allowRBracketInCharacterClass = allowRBracketInCharacterClass; + this.allowOctalNoLeadingZero = allowOctalNoLeadingZero; } private void yypushstate(int state) { @@ -136,7 +138,10 @@ HEX_CHAR=[0-9a-fA-F] So, for 100% compatibility, backrefs > 9 should be resolved by the parser, but I'm not sure if it's worth the effort - at least not atm. */ - +{ESCAPE} [0-7]{3} { if (allowOctalNoLeadingZero) return RegExpTT.OCT_CHAR; + return yystate() != CLASS2 ? RegExpTT.BACKREF : RegExpTT.ESC_CHARACTER; + } + {ESCAPE} {DIGITS} { return yystate() != CLASS2 ? RegExpTT.BACKREF : RegExpTT.ESC_CHARACTER; } {ESCAPE} "-" { return RegExpTT.ESC_CHARACTER; } From 2c2795823865610a3d0fa1d88844ab64a24fe1a0 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 21 Feb 2011 16:43:00 +0100 Subject: [PATCH 045/169] smart completion: insert diamond iff no arg constructor is present or all constructors are generic free and no diamond inference errors occur --- .../completion/JavaInheritorsGetter.java | 7 ++- .../smartType/DiamondNotCollapsed-out.java | 24 +++++++++++ .../smartType/DiamondNotCollapsed.java | 24 +++++++++++ .../completion/SmartType17CompletionTest.java | 4 ++ .../src/com/intellij/psi/PsiDiamondType.java | 43 +++++++++++++++++++ 5 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/DiamondNotCollapsed-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/DiamondNotCollapsed.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java index baa48c694966..89a928ecb034 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java @@ -135,8 +135,11 @@ public class JavaInheritorsGetter extends CompletionProvider()", parameters.getOriginalFile()); final PsiVariable declaredVar = (PsiVariable)((PsiDeclarationStatement)statement).getDeclaredElements()[0]; - final PsiExpression initializer = declaredVar.getInitializer(); - psiType = initializer.getType(); + final PsiNewExpression initializer = (PsiNewExpression)declaredVar.getInitializer(); + final boolean hasDefaultConstructorOrNoGenericsOne = PsiDiamondType.hasDefaultConstructor(psiClass) || !PsiDiamondType.haveConstructorsGenericsParameters(psiClass); + if (hasDefaultConstructorOrNoGenericsOne && PsiDiamondType.resolveInferredTypes(initializer).getErrorMessage() == null) { + psiType = initializer.getType(); + } } } final LookupItem item = PsiTypeLookupItem.createLookupItem(psiType, parameters.getPosition()); diff --git a/java/java-tests/testData/codeInsight/completion/smartType/DiamondNotCollapsed-out.java b/java/java-tests/testData/codeInsight/completion/smartType/DiamondNotCollapsed-out.java new file mode 100644 index 000000000000..f9430cdb29a0 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/DiamondNotCollapsed-out.java @@ -0,0 +1,24 @@ +/* + * Copyright 2000-2011 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. + */ +class MyClass { + public void foo() { + MyDD d = new MyDD() + } +} + +class MyDD { + MyDD(T t){} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/DiamondNotCollapsed.java b/java/java-tests/testData/codeInsight/completion/smartType/DiamondNotCollapsed.java new file mode 100644 index 000000000000..69a12ec44ec7 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/DiamondNotCollapsed.java @@ -0,0 +1,24 @@ +/* + * Copyright 2000-2011 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. + */ +class MyClass { + public void foo() { + MyDD d = new MyD + } +} + +class MyDD { + MyDD(T t){} +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType17CompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType17CompletionTest.java index bd05bbca53c3..7ee850dac128 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType17CompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType17CompletionTest.java @@ -49,6 +49,10 @@ public class SmartType17CompletionTest extends LightFixtureCompletionTestCase { doTest(); } + public void testDiamondNotCollapsed() throws Exception { + doTest(); + } + private void doTest() throws Exception { configureByFile("/" + getTestName(false) + ".java"); diff --git a/java/openapi/src/com/intellij/psi/PsiDiamondType.java b/java/openapi/src/com/intellij/psi/PsiDiamondType.java index 084e408129e0..5b1488918a12 100644 --- a/java/openapi/src/com/intellij/psi/PsiDiamondType.java +++ b/java/openapi/src/com/intellij/psi/PsiDiamondType.java @@ -22,6 +22,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; import com.intellij.util.Function; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -300,4 +301,46 @@ public class PsiDiamondType extends PsiType { }); } } + + public static boolean hasDefaultConstructor(@NotNull final PsiClass psiClass) { + final PsiMethod[] constructors = psiClass.getConstructors(); + for (PsiMethod method : constructors) { + if (method.getParameterList().getParametersCount() == 0) return true; + } + return constructors.length == 0; + } + + public static boolean haveConstructorsGenericsParameters(@NotNull final PsiClass psiClass) { + for (PsiMethod method : psiClass.getConstructors()) { + for (PsiParameter parameter : method.getParameterList().getParameters()) { + final PsiType type = parameter.getType(); + final Boolean accept = type.accept(new PsiTypeVisitor() { + @Override + public Boolean visitArrayType(PsiArrayType arrayType) { + return arrayType.getComponentType().accept(this); + } + + @Override + public Boolean visitClassType(PsiClassType classType) { + for (PsiType psiType : classType.getParameters()) { + if (psiType != null) { + final Boolean typaParamFound = psiType.accept(this); + if (typaParamFound != null && typaParamFound) return true; + } + } + return PsiUtil.resolveClassInType(classType) instanceof PsiTypeParameter; + } + + @Override + public Boolean visitWildcardType(PsiWildcardType wildcardType) { + final PsiType bound = wildcardType.getBound(); + if (bound == null) return false; + return bound.accept(this); + } + }); + if (accept != null && accept.booleanValue()) return true; + } + } + return false; + } } From 67c44e47df1d068e923b821029418f3eaf5dc617 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 21 Feb 2011 16:59:18 +0100 Subject: [PATCH 046/169] forbid diamonds on non-parameterized types (javac should be fixed accordingly) --- .../daemon/impl/analysis/GenericsHighlightUtil.java | 3 +++ .../daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index 519151b2189f..2d272ee14ae3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -112,6 +112,9 @@ public class GenericsHighlightUtil { if (referenceParameterList != null) { referenceElements = referenceParameterList.getTypeParameterElements(); if (referenceElements.length == 1 && referenceElements[0].getType() instanceof PsiDiamondType) { + if (!typeParameterListOwner.hasTypeParameters()) { + return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, referenceElements[0], "Diamond operator is not applicable for non-parameterized types"); + } inferenceResult = ((PsiDiamondType)referenceElements[0].getType()).resolveInferredTypes(); final String errorMessage = inferenceResult.getErrorMessage(); if (errorMessage != null) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java index d802f473b299..1258a5350bf8 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java @@ -67,3 +67,9 @@ class MyTest { } } } + +class NonParameterized { + void foo() { + new NonParameterized<>(); + } +} From 79e3df1fff15f972fbaf84d6656080f00dac2396 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 21 Feb 2011 17:56:38 +0100 Subject: [PATCH 047/169] intention to delete not applicable annotation --- .../analysis/AnnotationsHighlightUtil.java | 47 ++++++++++++++++++- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java index 43a6890bfb3b..1890c7098760 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java @@ -19,13 +19,19 @@ import com.intellij.codeInsight.AnnotationUtil; import com.intellij.codeInsight.daemon.JavaErrorMessages; import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInsight.daemon.impl.HighlightInfoType; +import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction; +import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.psi.*; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.HashSet; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -221,7 +227,7 @@ public class AnnotationsHighlightUtil { return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, typeElement, JavaErrorMessages.message("annotation.invalid.annotation.member.type")); } - public static HighlightInfo checkApplicability(PsiAnnotation annotation) { + public static HighlightInfo checkApplicability(final PsiAnnotation annotation) { PsiAnnotationOwner owner = annotation.getOwner(); if (!(owner instanceof PsiModifierList || owner instanceof PsiTypeElement || owner instanceof PsiMethodReceiver || owner instanceof PsiTypeParameter)) return null; PsiElement member = ((PsiElement)owner).getParent(); @@ -231,7 +237,9 @@ public class AnnotationsHighlightUtil { String description = JavaErrorMessages.message("annotation.not.applicable", nameRef.getText(), JavaErrorMessages.message("annotation.target." + elementTypeFields[0])); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, nameRef, description); + final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, nameRef, description); + QuickFixAction.registerQuickFixAction(highlightInfo, new DeleteNotApplicableAnnotationAction(annotation)); + return highlightInfo; } public static boolean isAnnotationApplicableTo(PsiAnnotation annotation, boolean strict, String... elementTypeFields) { @@ -445,4 +453,39 @@ public class AnnotationsHighlightUtil { return classType.equalsToText("java.lang.Class") || classType.equalsToText("java.lang.String") ? Boolean.TRUE : Boolean.FALSE; } } + + private static class DeleteNotApplicableAnnotationAction implements IntentionAction { + private final PsiAnnotation myAnnotation; + + public DeleteNotApplicableAnnotationAction(PsiAnnotation annotation) { + myAnnotation = annotation; + } + + @NotNull + @Override + public String getText() { + return "Remove"; + } + + @NotNull + @Override + public String getFamilyName() { + return getText(); + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + return true; + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + myAnnotation.delete(); + } + + @Override + public boolean startInWriteAction() { + return true; + } + } } From 55151743c5ac9ce3ead5c147d91b3773803857d2 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 21 Feb 2011 18:07:58 +0100 Subject: [PATCH 048/169] testng: open diff from tests tree (IDEA-65634) --- .../states/TestComparisionFailedState.java | 2 +- .../testframework/AbstractTestProxy.java | 2 +- .../junit2/states/ComparisonFailureState.java | 2 +- .../testng/model/TestProxy.java | 27 +++++++++++++++++++ 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestComparisionFailedState.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestComparisionFailedState.java index 79cf7e93881c..eb49e38fe8b6 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestComparisionFailedState.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestComparisionFailedState.java @@ -74,7 +74,7 @@ public class TestComparisionFailedState extends TestFailedState implements Abstr } @Override - public String getExpecteed() { + public String getExpected() { return myHyperlink.getLeft(); } diff --git a/platform/testRunner/src/com/intellij/execution/testframework/AbstractTestProxy.java b/platform/testRunner/src/com/intellij/execution/testframework/AbstractTestProxy.java index 3ddc3f1d9821..433f7fda572c 100644 --- a/platform/testRunner/src/com/intellij/execution/testframework/AbstractTestProxy.java +++ b/platform/testRunner/src/com/intellij/execution/testframework/AbstractTestProxy.java @@ -131,7 +131,7 @@ public abstract class AbstractTestProxy extends CompositePrintable { public interface AssertEqualsDiffViewerProvider { void openDiff(final Project project); - String getExpecteed(); + String getExpected(); String getActual(); } } diff --git a/plugins/junit/src/com/intellij/execution/junit2/states/ComparisonFailureState.java b/plugins/junit/src/com/intellij/execution/junit2/states/ComparisonFailureState.java index e41bbcabb9cb..d4ef1319d866 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/states/ComparisonFailureState.java +++ b/plugins/junit/src/com/intellij/execution/junit2/states/ComparisonFailureState.java @@ -48,7 +48,7 @@ public class ComparisonFailureState extends FaultyState implements AbstractTestP myHyperlink.printOn(printer); } - public String getExpecteed() { + public String getExpected() { return myHyperlink.getLeft(); } diff --git a/plugins/testng/src/com/theoryinpractice/testng/model/TestProxy.java b/plugins/testng/src/com/theoryinpractice/testng/model/TestProxy.java index cc70adfe8e0a..267766b6d1c5 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/model/TestProxy.java +++ b/plugins/testng/src/com/theoryinpractice/testng/model/TestProxy.java @@ -56,6 +56,7 @@ public class TestProxy extends AbstractTestProxy { private SmartPsiElementPointer psiElement; private boolean inProgress; private boolean myTearDownFailure; + private DiffHyperlink myHyperlink; public TestProxy() {} @@ -247,6 +248,9 @@ public class TestProxy extends AbstractTestProxy { if (stackTrace != null) { final List printables = getPrintables(result); for (Printable printable : printables) { + if (myHyperlink == null && printable instanceof DiffHyperlink) { + myHyperlink = (DiffHyperlink)printable; + } addLast(printable); } } @@ -273,6 +277,29 @@ public class TestProxy extends AbstractTestProxy { return true; } + @Override + public AssertEqualsDiffViewerProvider getDiffViewerProvider() { + if (myHyperlink == null) { + return null; + } + return new AssertEqualsDiffViewerProvider() { + @Override + public void openDiff(Project project) { + myHyperlink.openDiff(project); + } + + @Override + public String getExpected() { + return myHyperlink.getLeft(); + } + + @Override + public String getActual() { + return myHyperlink.getRight(); + } + }; + } + private static String trimStackTrace(String stackTrace) { String[] lines = stackTrace.split("\n"); StringBuilder builder = new StringBuilder(); From 4b57ede2e1a3b2e826db732e45f625ec5a47b8cd Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 21 Feb 2011 19:09:48 +0100 Subject: [PATCH 049/169] fix parsing of character classes so that it's actually correct (PY-1929) --- .../org/intellij/lang/regexp/RegExpLexer.java | 4 +- .../org/intellij/lang/regexp/_RegExLexer.java | 704 +++++++++--------- .../intellij/lang/regexp/regexp-lexer.flex | 52 +- 3 files changed, 382 insertions(+), 378 deletions(-) diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java index 097b3cb631e2..25d3c1e44769 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java @@ -21,9 +21,9 @@ public class RegExpLexer extends FlexAdapter { private static final int COMMENT_MODE = 1 << 14; - public RegExpLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters, boolean allowRBracketInCharacterClass, + public RegExpLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters, boolean allowNestedCharacterClasses, boolean allowOctalNoLeadingZero) { - super(new _RegExLexer(xmlSchemaMode, allowDanglingMetacharacters, allowRBracketInCharacterClass, allowOctalNoLeadingZero)); + super(new _RegExLexer(xmlSchemaMode, allowDanglingMetacharacters, allowNestedCharacterClasses, allowOctalNoLeadingZero)); } public void start(CharSequence buffer, int startOffset, int endOffset, int initialState) { diff --git a/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java b/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java index 21ad5ba124f0..d6ffe065d269 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java @@ -1,4 +1,4 @@ -/* The following code was generated by JFlex 1.4.3 on 21.02.11 18:30 */ +/* The following code was generated by JFlex 1.4.3 on 21.02.11 19:08 */ /* It's an automatically generated code. Do not modify it. */ package org.intellij.lang.regexp; @@ -14,7 +14,7 @@ import com.intellij.psi.StringEscapesTokenTypes; /** * This class is a scanner generated by * JFlex 1.4.3 - * on 21.02.11 18:30 from the specification file + * on 21.02.11 19:08 from the specification file * C:/JetBrains/IDEA/tools/lexer/../../community/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex */ class _RegExLexer implements FlexLexer { @@ -23,18 +23,17 @@ class _RegExLexer implements FlexLexer { /** lexical states */ public static final int EMBRACED = 4; - public static final int PY_NAMED_GROUP_REF = 22; + public static final int PY_NAMED_GROUP_REF = 20; public static final int QUOTED = 2; - public static final int CLASS2PY = 10; - public static final int OPTIONS = 14; - public static final int PY_COND_REF = 24; + public static final int OPTIONS = 12; + public static final int PY_COND_REF = 22; public static final int YYINITIAL = 0; - public static final int NAMED_GROUP = 18; + public static final int NAMED_GROUP = 16; public static final int CLASS2 = 8; public static final int CLASS1 = 6; - public static final int COMMENT = 16; - public static final int QUOTED_NAMED_GROUP = 20; - public static final int PROP = 12; + public static final int COMMENT = 14; + public static final int QUOTED_NAMED_GROUP = 18; + public static final int PROP = 10; /** * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l @@ -44,7 +43,7 @@ class _RegExLexer implements FlexLexer { */ private static final int ZZ_LEXSTATE[] = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, - 8, 8, 9, 9, 10, 10, 11, 11, 12, 12 + 8, 8, 9, 9, 10, 10, 11, 11 }; /** @@ -130,21 +129,21 @@ class _RegExLexer implements FlexLexer { private static final int [] ZZ_ACTION = zzUnpackAction(); private static final String ZZ_ACTION_PACKED_0 = - "\7\0\1\1\1\2\4\0\1\3\1\4\1\5\1\6"+ + "\6\0\1\1\1\2\4\0\1\3\1\4\1\5\1\6"+ "\1\7\1\10\1\11\1\12\1\13\1\14\1\15\1\16"+ "\1\17\1\20\1\21\1\22\1\23\1\3\1\24\1\25"+ - "\1\26\1\27\1\30\1\31\1\32\1\33\1\34\2\3"+ - "\1\11\1\35\1\36\1\35\1\37\1\40\1\1\1\41"+ - "\1\42\1\2\1\43\1\44\1\45\1\46\1\47\1\50"+ - "\1\51\1\52\1\53\1\54\1\55\1\56\2\57\1\60"+ - "\1\11\1\61\1\62\1\63\1\50\1\64\1\65\1\66"+ - "\1\0\1\67\1\70\1\71\1\72\1\0\1\73\1\74"+ - "\1\75\2\62\2\63\1\50\1\76\1\77\1\100\1\101"+ - "\1\0\1\74\1\62\1\102\2\63\1\103\1\104\1\74"+ - "\3\63\1\105"; + "\1\26\1\27\1\30\1\31\1\32\1\33\1\34\1\11"+ + "\1\35\1\3\1\36\1\37\1\36\1\40\1\41\1\1"+ + "\1\42\1\43\1\2\1\44\1\45\1\46\1\47\1\50"+ + "\1\51\1\52\1\53\1\54\1\55\1\56\1\57\2\60"+ + "\1\61\1\11\1\62\1\63\1\64\1\51\1\65\1\66"+ + "\1\67\1\70\1\71\1\0\1\72\1\73\1\74\1\75"+ + "\1\0\1\76\1\77\1\100\2\63\2\64\1\51\1\101"+ + "\1\102\1\103\1\104\1\0\1\77\1\63\1\105\2\64"+ + "\1\106\1\107\1\77\3\64\1\110"; private static int [] zzUnpackAction() { - int [] result = new int[106]; + int [] result = new int[107]; int offset = 0; offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); return result; @@ -170,22 +169,22 @@ class _RegExLexer implements FlexLexer { private static final String ZZ_ROWMAP_PACKED_0 = "\0\0\0\63\0\146\0\231\0\314\0\377\0\u0132\0\u0165"+ - "\0\u0198\0\u01cb\0\u01fe\0\u0231\0\u0264\0\u0297\0\u0297\0\u02ca"+ - "\0\u0297\0\u0297\0\u02fd\0\u0330\0\u0297\0\u0297\0\u0297\0\u0297"+ - "\0\u0297\0\u0297\0\u0297\0\u0297\0\u0297\0\u0297\0\u0363\0\u0297"+ - "\0\u0396\0\u0297\0\u03c9\0\u0297\0\u0297\0\u0297\0\u0297\0\u0297"+ - "\0\u03fc\0\u02fd\0\u042f\0\u0297\0\u0297\0\u02fd\0\u0297\0\u0297"+ - "\0\u0462\0\u0495\0\u0297\0\u0297\0\u0297\0\u0297\0\u04c8\0\u0297"+ - "\0\u0297\0\u04fb\0\u052e\0\u0297\0\u0297\0\u0297\0\u0297\0\u0297"+ - "\0\u0297\0\u0561\0\u0297\0\u0297\0\u0297\0\u0594\0\u05c7\0\u05fa"+ - "\0\u0297\0\u0297\0\u0297\0\u062d\0\u0297\0\u0297\0\u0297\0\u0660"+ - "\0\u0693\0\u0297\0\u06c6\0\u0297\0\u06f9\0\u072c\0\u075f\0\u0792"+ - "\0\u07c5\0\u0297\0\u0297\0\u0297\0\u0297\0\u07f8\0\u082b\0\u0297"+ - "\0\u0297\0\u085e\0\u0891\0\u04fb\0\u0297\0\u0297\0\u08c4\0\u08f7"+ - "\0\u0297\0\u0297"; + "\0\u0198\0\u01cb\0\u01fe\0\u0231\0\u0264\0\u0264\0\u0297\0\u0264"+ + "\0\u0264\0\u02ca\0\u02fd\0\u0264\0\u0264\0\u0264\0\u0264\0\u0264"+ + "\0\u0264\0\u0264\0\u0264\0\u0264\0\u0264\0\u0330\0\u0264\0\u0363"+ + "\0\u0264\0\u0396\0\u0264\0\u0264\0\u0264\0\u03c9\0\u0264\0\u03fc"+ + "\0\u0264\0\u042f\0\u0264\0\u0264\0\u02ca\0\u0264\0\u0264\0\u0462"+ + "\0\u0495\0\u0264\0\u0264\0\u0264\0\u0264\0\u04c8\0\u0264\0\u0264"+ + "\0\u04fb\0\u052e\0\u0264\0\u0264\0\u0264\0\u0264\0\u0264\0\u0264"+ + "\0\u0561\0\u0264\0\u0264\0\u0264\0\u0594\0\u05c7\0\u05fa\0\u0264"+ + "\0\u0264\0\u0264\0\u0264\0\u0264\0\u062d\0\u0264\0\u0264\0\u0264"+ + "\0\u0660\0\u0693\0\u0264\0\u06c6\0\u0264\0\u06f9\0\u072c\0\u075f"+ + "\0\u0792\0\u07c5\0\u0264\0\u0264\0\u0264\0\u0264\0\u07f8\0\u082b"+ + "\0\u0264\0\u0264\0\u085e\0\u0891\0\u04fb\0\u0264\0\u0264\0\u08c4"+ + "\0\u08f7\0\u0264\0\u0264"; private static int [] zzUnpackRowMap() { - int [] result = new int[106]; + int [] result = new int[107]; int offset = 0; offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); return result; @@ -208,51 +207,49 @@ class _RegExLexer implements FlexLexer { private static final int [] ZZ_TRANS = zzUnpackTrans(); private static final String ZZ_TRANS_PACKED_0 = - "\3\16\1\17\1\20\1\21\1\22\1\16\1\23\1\16"+ - "\1\24\1\25\1\26\1\27\1\30\1\31\1\32\1\33"+ - "\21\16\1\34\1\16\1\35\4\16\1\25\5\16\1\36"+ - "\1\16\1\25\12\16\1\37\1\0\47\16\1\40\2\41"+ - "\4\40\1\42\12\40\20\43\1\41\1\40\1\43\2\40"+ - "\1\41\1\44\12\40\11\45\1\46\1\45\1\0\47\45"+ - "\6\16\1\22\1\16\1\23\1\47\1\24\1\50\1\26"+ - "\26\16\1\34\5\16\1\51\1\50\7\16\1\50\6\16"+ - "\1\22\1\16\1\52\1\47\1\53\1\50\1\26\26\16"+ - "\1\34\6\16\1\50\7\16\1\50\6\54\1\55\1\54"+ - "\1\56\1\54\1\24\50\54\5\57\1\60\14\57\20\61"+ - "\1\57\1\62\1\61\6\57\1\63\7\57\13\11\1\64"+ - "\46\11\1\64\22\57\20\43\2\57\1\43\7\57\1\65"+ - "\30\57\20\43\2\57\1\43\14\57\1\66\6\57\1\60"+ - "\14\57\20\43\2\57\1\43\17\57\2\41\2\57\1\60"+ - "\14\57\20\43\1\41\1\57\1\43\2\57\1\41\13\57"+ - "\101\0\1\67\55\0\1\70\51\0\1\71\1\72\1\73"+ - "\4\74\1\71\1\74\1\71\1\74\1\75\6\74\2\76"+ - "\2\77\2\100\1\101\1\102\1\101\2\103\1\104\1\105"+ - "\1\104\1\106\1\107\1\110\1\74\1\104\1\75\4\71"+ - "\1\75\7\71\1\75\37\0\1\111\24\0\2\41\37\0"+ - "\1\41\4\0\1\41\14\0\2\43\17\0\21\43\1\0"+ - "\1\43\1\0\2\43\64\0\1\112\11\0\1\71\1\72"+ - "\1\73\4\74\1\71\1\74\1\16\1\74\1\75\6\74"+ - "\2\76\2\77\2\100\1\101\1\102\1\101\2\103\1\104"+ - "\1\105\1\104\1\106\1\107\1\110\1\74\1\104\1\75"+ - "\4\71\1\75\7\71\1\75\22\0\20\61\2\0\1\61"+ - "\40\0\20\62\2\0\1\62\22\0\1\113\27\0\1\114"+ - "\16\0\2\115\1\116\1\117\1\120\1\121\1\122\2\0"+ - "\2\72\37\0\1\72\22\0\1\123\37\0\1\123\20\0"+ - "\63\124\1\125\2\126\20\125\2\126\2\125\3\126\3\125"+ - "\1\126\1\125\1\126\2\125\1\126\20\125\1\127\2\130"+ - "\20\127\2\130\2\127\3\130\3\127\1\130\1\127\1\130"+ - "\2\127\1\130\20\127\1\0\1\72\1\131\37\0\1\131"+ - "\75\0\1\132\1\0\1\133\60\0\1\134\1\135\4\0"+ - "\5\136\1\0\55\136\2\0\1\137\37\0\1\137\20\0"+ - "\64\140\2\141\20\140\2\141\2\140\3\141\3\140\1\141"+ - "\1\140\1\141\2\140\1\141\20\140\64\142\2\143\20\142"+ - "\2\143\2\142\3\143\3\142\1\143\1\142\1\143\2\142"+ - "\1\143\20\142\1\0\1\72\1\144\37\0\1\144\20\0"+ - "\5\136\1\145\55\136\2\0\1\146\37\0\1\146\20\0"+ - "\64\147\2\150\20\147\2\150\2\147\3\150\3\147\1\150"+ - "\1\147\1\150\2\147\1\150\20\147\64\151\2\152\20\151"+ - "\2\152\2\151\3\152\3\151\1\152\1\151\1\152\2\151"+ - "\1\152\20\151"; + "\3\15\1\16\1\17\1\20\1\21\1\15\1\22\1\15"+ + "\1\23\1\24\1\25\1\26\1\27\1\30\1\31\1\32"+ + "\21\15\1\33\1\15\1\34\4\15\1\24\5\15\1\35"+ + "\1\15\1\24\12\15\1\36\1\0\47\15\1\37\2\40"+ + "\4\37\1\41\12\37\20\42\1\40\1\37\1\42\2\37"+ + "\1\40\1\43\12\37\11\44\1\45\1\44\1\0\47\44"+ + "\6\15\1\21\1\15\1\46\1\47\1\50\1\51\1\25"+ + "\26\15\1\33\5\15\1\52\1\51\7\15\1\51\6\53"+ + "\1\54\1\53\1\55\1\53\1\23\50\53\5\56\1\57"+ + "\14\56\20\60\1\56\1\61\1\60\6\56\1\62\7\56"+ + "\13\10\1\63\46\10\1\63\22\56\20\42\2\56\1\42"+ + "\7\56\1\64\30\56\20\42\2\56\1\42\14\56\1\65"+ + "\6\56\1\57\14\56\20\42\2\56\1\42\17\56\2\40"+ + "\2\56\1\57\14\56\20\42\1\40\1\56\1\42\2\56"+ + "\1\40\13\56\101\0\1\66\55\0\1\67\51\0\1\70"+ + "\1\71\1\72\4\73\1\70\1\73\1\70\1\73\1\74"+ + "\6\73\2\75\2\76\2\77\1\100\1\101\1\100\2\102"+ + "\1\103\1\104\1\103\1\105\1\106\1\107\1\73\1\103"+ + "\1\74\4\70\1\74\7\70\1\74\37\0\1\110\24\0"+ + "\2\40\37\0\1\40\4\0\1\40\14\0\2\42\17\0"+ + "\21\42\1\0\1\42\1\0\2\42\24\0\1\111\51\0"+ + "\1\70\1\71\1\72\4\73\1\70\1\73\1\112\1\73"+ + "\1\74\6\73\2\75\2\76\2\77\1\100\1\101\1\100"+ + "\2\102\1\103\1\104\1\103\1\105\1\106\1\107\1\73"+ + "\1\103\1\74\4\70\1\74\7\70\1\74\51\0\1\113"+ + "\33\0\20\60\2\0\1\60\40\0\20\61\2\0\1\61"+ + "\22\0\1\114\27\0\1\115\16\0\2\116\1\117\1\120"+ + "\1\121\1\122\1\123\2\0\2\71\37\0\1\71\22\0"+ + "\1\124\37\0\1\124\20\0\63\125\1\126\2\127\20\126"+ + "\2\127\2\126\3\127\3\126\1\127\1\126\1\127\2\126"+ + "\1\127\20\126\1\130\2\131\20\130\2\131\2\130\3\131"+ + "\3\130\1\131\1\130\1\131\2\130\1\131\20\130\1\0"+ + "\1\71\1\132\37\0\1\132\75\0\1\133\1\0\1\134"+ + "\60\0\1\135\1\136\4\0\5\137\1\0\55\137\2\0"+ + "\1\140\37\0\1\140\20\0\64\141\2\142\20\141\2\142"+ + "\2\141\3\142\3\141\1\142\1\141\1\142\2\141\1\142"+ + "\20\141\64\143\2\144\20\143\2\144\2\143\3\144\3\143"+ + "\1\144\1\143\1\144\2\143\1\144\20\143\1\0\1\71"+ + "\1\145\37\0\1\145\20\0\5\137\1\146\55\137\2\0"+ + "\1\147\37\0\1\147\20\0\64\150\2\151\20\150\2\151"+ + "\2\150\3\151\3\150\1\151\1\150\1\151\2\150\1\151"+ + "\20\150\64\152\2\153\20\152\2\153\2\152\3\153\3\152"+ + "\1\153\1\152\1\153\2\152\1\153\20\152"; private static int [] zzUnpackTrans() { int [] result = new int[2346]; @@ -296,15 +293,15 @@ class _RegExLexer implements FlexLexer { private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); private static final String ZZ_ATTRIBUTE_PACKED_0 = - "\7\0\2\1\4\0\2\11\1\1\2\11\2\1\12\11"+ - "\1\1\1\11\1\1\1\11\1\1\5\11\3\1\2\11"+ - "\1\1\2\11\2\1\4\11\1\1\2\11\2\1\6\11"+ - "\1\1\3\11\3\1\3\11\1\0\3\11\1\1\1\0"+ - "\1\11\1\1\1\11\5\1\4\11\1\0\1\1\2\11"+ - "\3\1\2\11\2\1\2\11"; + "\6\0\2\1\4\0\2\11\1\1\2\11\2\1\12\11"+ + "\1\1\1\11\1\1\1\11\1\1\3\11\1\1\1\11"+ + "\1\1\1\11\1\1\2\11\1\1\2\11\2\1\4\11"+ + "\1\1\2\11\2\1\6\11\1\1\3\11\3\1\5\11"+ + "\1\0\3\11\1\1\1\0\1\11\1\1\1\11\5\1"+ + "\4\11\1\0\1\1\2\11\3\1\2\11\2\1\2\11"; private static int [] zzUnpackAttribute() { - int [] result = new int[106]; + int [] result = new int[107]; int offset = 0; offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); return result; @@ -371,14 +368,14 @@ class _RegExLexer implements FlexLexer { private boolean xmlSchemaMode; private boolean allowDanglingMetacharacters; - private boolean allowRBracketInCharacterClass; + private boolean allowNestedCharacterClasses; private boolean allowOctalNoLeadingZero; - _RegExLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters, boolean allowRBracketInCharacterClass, boolean allowOctalNoLeadingZero) { + _RegExLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters, boolean allowNestedCharacterClasses, boolean allowOctalNoLeadingZero) { this((java.io.Reader)null); this.xmlSchemaMode = xmlSchemaMode; this.allowDanglingMetacharacters = allowDanglingMetacharacters; - this.allowRBracketInCharacterClass = allowRBracketInCharacterClass; + this.allowNestedCharacterClasses = allowNestedCharacterClasses; this.allowOctalNoLeadingZero = allowOctalNoLeadingZero; } @@ -649,269 +646,207 @@ class _RegExLexer implements FlexLexer { zzMarkedPos = zzMarkedPosL; switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { + case 72: + { return RegExpTT.UNICODE_CHAR; + } + case 73: break; case 7: { if (yystate() != CLASS2) yypushstate(EMBRACED); return RegExpTT.LBRACE; } - case 70: break; - case 6: - { return RegExpTT.GROUP_END; - } - case 71: break; - case 14: - { return RegExpTT.STAR; - } - case 72: break; - case 42: - { return RegExpTT.ESC_CHARACTER; - } - case 73: break; - case 38: - // lookahead expression with fixed base length - zzMarkedPos = zzStartRead + 1; - { if (allowRBracketInCharacterClass) { - yypushstate(CLASS1); - } - else { - yypushstate(CLASS2PY); - } - return RegExpTT.CLASS_BEGIN; - } case 74: break; - case 28: - { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.ESC_CHARACTER; - } - case 75: break; - case 43: - { return commentMode ? RegExpTT.CHARACTER : RegExpTT.REDUNDANT_ESCAPE; - } - case 76: break; - case 8: - { if (allowRBracketInCharacterClass) { - yypushstate(CLASS2); - } - else { - yypushstate(CLASS2PY); - } - return RegExpTT.CLASS_BEGIN; - } - case 77: break; - case 39: - { return RegExpTT.REDUNDANT_ESCAPE; - } - case 78: break; case 24: { return RegExpTT.COMMA; } - case 79: break; - case 58: - { yybegin(NAMED_GROUP); return RegExpTT.RUBY_NAMED_GROUP; - } - case 80: break; - case 64: - { return RegExpTT.POS_LOOKBEHIND; - } - case 81: break; - case 41: - { return RegExpTT.BAD_OCT_VALUE; - } - case 82: break; - case 10: - { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.CTRL_CHARACTER; - } - case 83: break; - case 30: - { yypopstate(); yypushstate(EMBRACED); return RegExpTT.LBRACE; - } - case 84: break; - case 51: - { return StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN; - } - case 85: break; - case 65: - { return RegExpTT.NEG_LOOKBEHIND; - } - case 86: break; - case 69: - { return RegExpTT.UNICODE_CHAR; - } - case 87: break; - case 61: - { if (xmlSchemaMode) { yypushback(1); return RegExpTT.CHAR_CLASS; } else return RegExpTT.CTRL; - } - case 88: break; - case 37: - { yybegin(OPTIONS); return RegExpTT.SET_OPTIONS; - } - case 89: break; - case 12: - { return RegExpTT.DOLLAR; - } - case 90: break; - case 52: - { yypopstate(); return RegExpTT.QUOTE_END; - } - case 91: break; - case 56: + case 75: break; + case 59: { return RegExpTT.POS_LOOKAHEAD; } - case 92: break; - case 22: - { yypopstate(); return RegExpTT.RBRACE; - } - case 93: break; - case 3: - { return RegExpTT.CHARACTER; - } - case 94: break; - case 57: - { return RegExpTT.NEG_LOOKAHEAD; - } - case 95: break; - case 67: - { if (allowOctalNoLeadingZero) return RegExpTT.OCT_CHAR; - return yystate() != CLASS2 ? RegExpTT.BACKREF : RegExpTT.ESC_CHARACTER; - } - case 96: break; - case 44: - { return RegExpTT.ESC_CTRL_CHARACTER; - } - case 97: break; - case 23: - { return RegExpTT.NAME; - } - case 98: break; - case 53: - { return RegExpTT.ANDAND; - } - case 99: break; - case 13: - { return RegExpTT.QUEST; - } - case 100: break; - case 46: - { return RegExpTT.CHAR_CLASS; - } - case 101: break; - case 17: - { return RegExpTT.MINUS; - } - case 102: break; - case 68: - { return RegExpTT.COMMENT; - } - case 103: break; - case 40: - { return yystate() != CLASS2 ? RegExpTT.BACKREF : RegExpTT.ESC_CHARACTER; - } - case 104: break; - case 16: - { return RegExpTT.UNION; - } - case 105: break; - case 47: - { if (xmlSchemaMode) return RegExpTT.CHAR_CLASS; else return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN; - } - case 106: break; - case 60: - { return RegExpTT.OCT_CHAR; - } - case 107: break; - case 4: - { return RegExpTT.DOT; - } - case 108: break; - case 32: - { yybegin(YYINITIAL); return RegExpTT.GROUP_END; - } - case 109: break; - case 21: - { return RegExpTT.NUMBER; - } - case 110: break; - case 35: - { yybegin(YYINITIAL); return RegExpTT.GT; - } - case 111: break; - case 59: - { yybegin(QUOTED_NAMED_GROUP); return RegExpTT.RUBY_QUOTED_NAMED_GROUP; - } - case 112: break; - case 54: - { yybegin(PY_COND_REF); return RegExpTT.PYTHON_COND_REF; - } - case 113: break; - case 48: - { yypushstate(PROP); return RegExpTT.PROPERTY; - } - case 114: break; - case 18: - { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.CHARACTER; - } - case 115: break; - case 33: - { handleOptions(); return RegExpTT.OPTIONS_OFF; - } - case 116: break; - case 34: - { yybegin(YYINITIAL); return RegExpTT.COLON; - } - case 117: break; - case 25: - { assert false : yytext(); - } - case 118: break; - case 62: - { yybegin(PY_NAMED_GROUP_REF); return RegExpTT.PYTHON_NAMED_GROUP_REF; - } - case 119: break; - case 27: - { yypopstate(); return RegExpTT.CLASS_END; - } - case 120: break; - case 11: - { return RegExpTT.CARET; - } - case 121: break; - case 1: - { handleOptions(); return RegExpTT.OPTIONS_ON; - } - case 122: break; - case 29: - { yypopstate(); yypushback(1); - } - case 123: break; - case 45: - { return yystate() != CLASS2 ? RegExpTT.BOUNDARY : RegExpTT.ESC_CHARACTER; - } - case 124: break; - case 63: + case 76: break; + case 66: { yybegin(NAMED_GROUP); return RegExpTT.PYTHON_NAMED_GROUP; } - case 125: break; - case 19: - { if (commentMode) { yypushstate(COMMENT); return RegExpTT.COMMENT; } else return RegExpTT.CHARACTER; + case 77: break; + case 71: + { return RegExpTT.COMMENT; } - case 126: break; - case 66: - { return RegExpTT.HEX_CHAR; + case 78: break; + case 14: + { return RegExpTT.STAR; } - case 127: break; + case 79: break; + case 57: + { yybegin(PY_COND_REF); return RegExpTT.PYTHON_COND_REF; + } + case 80: break; + case 47: + { return RegExpTT.CHAR_CLASS; + } + case 81: break; + case 34: + { handleOptions(); return RegExpTT.OPTIONS_OFF; + } + case 82: break; + case 53: + { yypopstate(); return RegExpTT.QUOTE_END; + } + case 83: break; + case 33: + { yybegin(YYINITIAL); return RegExpTT.GROUP_END; + } + case 84: break; case 5: { return RegExpTT.GROUP_BEGIN; } - case 128: break; - case 55: + case 85: break; + case 35: + { yybegin(YYINITIAL); return RegExpTT.COLON; + } + case 86: break; + case 6: + { return RegExpTT.GROUP_END; + } + case 87: break; + case 25: + { assert false : yytext(); + } + case 88: break; + case 18: + { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.CHARACTER; + } + case 89: break; + case 44: + { return commentMode ? RegExpTT.CHARACTER : RegExpTT.REDUNDANT_ESCAPE; + } + case 90: break; + case 23: + { return RegExpTT.NAME; + } + case 91: break; + case 70: + { if (allowOctalNoLeadingZero) return RegExpTT.OCT_CHAR; + return yystate() != CLASS2 ? RegExpTT.BACKREF : RegExpTT.ESC_CHARACTER; + } + case 92: break; + case 28: + { yypopstate(); return RegExpTT.CLASS_END; + } + case 93: break; + case 32: + { yybegin(YYINITIAL); return RegExpTT.BAD_CHARACTER; + } + case 94: break; + case 50: + { yypushstate(QUOTED); return RegExpTT.QUOTE_BEGIN; + } + case 95: break; + case 21: + { return RegExpTT.NUMBER; + } + case 96: break; + case 4: + { return RegExpTT.DOT; + } + case 97: break; + case 68: + { return RegExpTT.NEG_LOOKBEHIND; + } + case 98: break; + case 39: + // lookahead expression with fixed base length + zzMarkedPos = zzStartRead + 1; + { yypushstate(CLASS1); + return RegExpTT.CLASS_BEGIN; + } + case 99: break; + case 60: + { return RegExpTT.NEG_LOOKAHEAD; + } + case 100: break; + case 10: + { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.CTRL_CHARACTER; + } + case 101: break; + case 58: { return RegExpTT.NON_CAPT_GROUP; } - case 129: break; - case 9: - { return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN; + case 102: break; + case 62: + { yybegin(QUOTED_NAMED_GROUP); return RegExpTT.RUBY_QUOTED_NAMED_GROUP; } - case 130: break; - case 36: + case 103: break; + case 27: + { if (allowNestedCharacterClasses) { + yypushstate(CLASS2); + return RegExpTT.CLASS_BEGIN; + } + return RegExpTT.CHARACTER; + } + case 104: break; + case 19: + { if (commentMode) { yypushstate(COMMENT); return RegExpTT.COMMENT; } else return RegExpTT.CHARACTER; + } + case 105: break; + case 49: + { yypushstate(PROP); return RegExpTT.PROPERTY; + } + case 106: break; + case 8: + { yypushstate(CLASS2); + return RegExpTT.CLASS_BEGIN; + } + case 107: break; + case 67: + { return RegExpTT.POS_LOOKBEHIND; + } + case 108: break; + case 41: + { return yystate() != CLASS2 ? RegExpTT.BACKREF : RegExpTT.ESC_CHARACTER; + } + case 109: break; + case 69: + { return RegExpTT.HEX_CHAR; + } + case 110: break; + case 1: + { handleOptions(); return RegExpTT.OPTIONS_ON; + } + case 111: break; + case 56: + { return allowNestedCharacterClasses ? RegExpTT.ANDAND : RegExpTT.CHARACTER; + } + case 112: break; + case 2: + { yypopstate(); return RegExpTT.COMMENT; + } + case 113: break; + case 17: + { return RegExpTT.MINUS; + } + case 114: break; + case 45: + { return RegExpTT.ESC_CTRL_CHARACTER; + } + case 115: break; + case 31: + { yypopstate(); yypushstate(EMBRACED); return RegExpTT.LBRACE; + } + case 116: break; + case 13: + { return RegExpTT.QUEST; + } + case 117: break; + case 15: + { return RegExpTT.PLUS; + } + case 118: break; + case 63: + { return RegExpTT.OCT_CHAR; + } + case 119: break; + case 37: { yybegin(YYINITIAL); return RegExpTT.QUOTE; } - case 131: break; + case 120: break; case 20: { if (allowDanglingMetacharacters) { yypopstate(); yypushback(1); @@ -919,31 +854,106 @@ class _RegExLexer implements FlexLexer { return RegExpTT.BAD_CHARACTER; } } - case 132: break; - case 50: - { return RegExpTT.BAD_HEX_VALUE; + case 121: break; + case 30: + { yypopstate(); yypushback(1); } - case 133: break; - case 2: - { yypopstate(); return RegExpTT.COMMENT; + case 122: break; + case 54: + // lookahead expression with fixed base length + zzMarkedPos = zzStartRead + 1; + { if (allowNestedCharacterClasses) { + yypushstate(CLASS1); + return RegExpTT.CLASS_BEGIN; + } + return RegExpTT.CHARACTER; } - case 134: break; - case 49: - { yypushstate(QUOTED); return RegExpTT.QUOTE_BEGIN; + case 123: break; + case 55: + { if (!allowNestedCharacterClasses) return RegExpTT.CHARACTER; + return RegExpTT.REDUNDANT_ESCAPE; } - case 135: break; + case 124: break; + case 36: + { yybegin(YYINITIAL); return RegExpTT.GT; + } + case 125: break; + case 65: + { yybegin(PY_NAMED_GROUP_REF); return RegExpTT.PYTHON_NAMED_GROUP_REF; + } + case 126: break; + case 16: + { return RegExpTT.UNION; + } + case 127: break; + case 3: + { return RegExpTT.CHARACTER; + } + case 128: break; + case 61: + { yybegin(NAMED_GROUP); return RegExpTT.RUBY_NAMED_GROUP; + } + case 129: break; + case 38: + { yybegin(OPTIONS); return RegExpTT.SET_OPTIONS; + } + case 130: break; case 26: { yybegin(CLASS2); return RegExpTT.CHARACTER; } + case 131: break; + case 64: + { if (xmlSchemaMode) { yypushback(1); return RegExpTT.CHAR_CLASS; } else return RegExpTT.CTRL; + } + case 132: break; + case 29: + { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.ESC_CHARACTER; + } + case 133: break; + case 12: + { return RegExpTT.DOLLAR; + } + case 134: break; + case 48: + { if (xmlSchemaMode) return RegExpTT.CHAR_CLASS; else return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN; + } + case 135: break; + case 40: + { return RegExpTT.REDUNDANT_ESCAPE; + } case 136: break; - case 15: - { return RegExpTT.PLUS; + case 46: + { return yystate() != CLASS2 ? RegExpTT.BOUNDARY : RegExpTT.ESC_CHARACTER; } case 137: break; - case 31: - { yybegin(YYINITIAL); return RegExpTT.BAD_CHARACTER; + case 22: + { yypopstate(); return RegExpTT.RBRACE; } case 138: break; + case 52: + { return StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN; + } + case 139: break; + case 42: + { return RegExpTT.BAD_OCT_VALUE; + } + case 140: break; + case 51: + { return RegExpTT.BAD_HEX_VALUE; + } + case 141: break; + case 9: + { return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN; + } + case 142: break; + case 11: + { return RegExpTT.CARET; + } + case 143: break; + case 43: + { return RegExpTT.ESC_CHARACTER; + } + case 144: break; default: if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { zzAtEOF = true; diff --git a/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex b/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex index eaae7a5060f0..b895b9c17066 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex +++ b/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex @@ -27,14 +27,14 @@ import com.intellij.psi.StringEscapesTokenTypes; private boolean xmlSchemaMode; private boolean allowDanglingMetacharacters; - private boolean allowRBracketInCharacterClass; + private boolean allowNestedCharacterClasses; private boolean allowOctalNoLeadingZero; - _RegExLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters, boolean allowRBracketInCharacterClass, boolean allowOctalNoLeadingZero) { + _RegExLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters, boolean allowNestedCharacterClasses, boolean allowOctalNoLeadingZero) { this((java.io.Reader)null); this.xmlSchemaMode = xmlSchemaMode; this.allowDanglingMetacharacters = allowDanglingMetacharacters; - this.allowRBracketInCharacterClass = allowRBracketInCharacterClass; + this.allowNestedCharacterClasses = allowNestedCharacterClasses; this.allowOctalNoLeadingZero = allowOctalNoLeadingZero; } @@ -63,7 +63,6 @@ import com.intellij.psi.StringEscapesTokenTypes; %xstate EMBRACED %xstate CLASS1 %state CLASS2 -%state CLASS2PY %state PROP %xstate OPTIONS %xstate COMMENT @@ -155,8 +154,9 @@ HEX_CHAR=[0-9a-fA-F] {ESCAPE} [:letter:] { return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN; } {ESCAPE} [\n\b\t\r\f ] { return commentMode ? RegExpTT.CHARACTER : RegExpTT.REDUNDANT_ESCAPE; } - { - {ESCAPE} {RBRACKET} { return RegExpTT.CHARACTER; } + { + {ESCAPE} {RBRACKET} { if (!allowNestedCharacterClasses) return RegExpTT.CHARACTER; + return RegExpTT.REDUNDANT_ESCAPE; } } {ESCAPE} {ANY} { return RegExpTT.REDUNDANT_ESCAPE; } @@ -190,24 +190,26 @@ HEX_CHAR=[0-9a-fA-F] "-" { return RegExpTT.MINUS; } "^" { return RegExpTT.CARET; } - { - {LBRACKET} { return RegExpTT.CHARACTER; } + { + {LBRACKET} { if (allowNestedCharacterClasses) { + yypushstate(CLASS2); + return RegExpTT.CLASS_BEGIN; + } + return RegExpTT.CHARACTER; + } + + {LBRACKET} / {RBRACKET} { if (allowNestedCharacterClasses) { + yypushstate(CLASS1); + return RegExpTT.CLASS_BEGIN; + } + return RegExpTT.CHARACTER; + } } -{LBRACKET} / {RBRACKET} { if (allowRBracketInCharacterClass) { - yypushstate(CLASS1); - } - else { - yypushstate(CLASS2PY); - } +{LBRACKET} / {RBRACKET} { yypushstate(CLASS1); return RegExpTT.CLASS_BEGIN; } -{LBRACKET} { if (allowRBracketInCharacterClass) { - yypushstate(CLASS2); - } - else { - yypushstate(CLASS2PY); - } +{LBRACKET} { yypushstate(CLASS2); return RegExpTT.CLASS_BEGIN; } /* []abc] is legal. The first ] is treated as literal character */ @@ -219,15 +221,7 @@ HEX_CHAR=[0-9a-fA-F] { {RBRACKET} { yypopstate(); return RegExpTT.CLASS_END; } - "&&" { return RegExpTT.ANDAND; } - [\n\b\t\r\f] { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.ESC_CHARACTER; } - {ANY} { return RegExpTT.CHARACTER; } -} - -/* see rules for matching LBRACKET and escaped RBRACKET in CLASS2PY above */ - { - {RBRACKET} { yypopstate(); return RegExpTT.CLASS_END; } - + "&&" { return allowNestedCharacterClasses ? RegExpTT.ANDAND : RegExpTT.CHARACTER; } [\n\b\t\r\f] { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.ESC_CHARACTER; } {ANY} { return RegExpTT.CHARACTER; } } From 39fa7fb7c346a5b4d90a375b4955da218fa73f9d Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 21 Feb 2011 19:23:09 +0100 Subject: [PATCH 050/169] rbracket after caret at the beginning of character class doesn't close it (PY-1929 part 2) --- .../org/intellij/lang/regexp/_RegExLexer.java | 451 +++++++++--------- .../intellij/lang/regexp/regexp-lexer.flex | 16 + 2 files changed, 251 insertions(+), 216 deletions(-) diff --git a/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java b/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java index d6ffe065d269..ad78d535bdc6 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java @@ -1,4 +1,4 @@ -/* The following code was generated by JFlex 1.4.3 on 21.02.11 19:08 */ +/* The following code was generated by JFlex 1.4.3 on 21.02.11 19:21 */ /* It's an automatically generated code. Do not modify it. */ package org.intellij.lang.regexp; @@ -14,7 +14,7 @@ import com.intellij.psi.StringEscapesTokenTypes; /** * This class is a scanner generated by * JFlex 1.4.3 - * on 21.02.11 19:08 from the specification file + * on 21.02.11 19:21 from the specification file * C:/JetBrains/IDEA/tools/lexer/../../community/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex */ class _RegExLexer implements FlexLexer { @@ -23,17 +23,18 @@ class _RegExLexer implements FlexLexer { /** lexical states */ public static final int EMBRACED = 4; - public static final int PY_NAMED_GROUP_REF = 20; + public static final int CLASS1PY = 8; + public static final int PY_NAMED_GROUP_REF = 22; public static final int QUOTED = 2; - public static final int OPTIONS = 12; - public static final int PY_COND_REF = 22; + public static final int OPTIONS = 14; + public static final int PY_COND_REF = 24; public static final int YYINITIAL = 0; - public static final int NAMED_GROUP = 16; - public static final int CLASS2 = 8; + public static final int NAMED_GROUP = 18; + public static final int CLASS2 = 10; public static final int CLASS1 = 6; - public static final int COMMENT = 14; - public static final int QUOTED_NAMED_GROUP = 18; - public static final int PROP = 10; + public static final int COMMENT = 16; + public static final int QUOTED_NAMED_GROUP = 20; + public static final int PROP = 12; /** * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l @@ -43,7 +44,7 @@ class _RegExLexer implements FlexLexer { */ private static final int ZZ_LEXSTATE[] = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, - 8, 8, 9, 9, 10, 10, 11, 11 + 8, 8, 9, 9, 10, 10, 11, 11, 12, 12 }; /** @@ -129,21 +130,21 @@ class _RegExLexer implements FlexLexer { private static final int [] ZZ_ACTION = zzUnpackAction(); private static final String ZZ_ACTION_PACKED_0 = - "\6\0\1\1\1\2\4\0\1\3\1\4\1\5\1\6"+ + "\7\0\1\1\1\2\4\0\1\3\1\4\1\5\1\6"+ "\1\7\1\10\1\11\1\12\1\13\1\14\1\15\1\16"+ "\1\17\1\20\1\21\1\22\1\23\1\3\1\24\1\25"+ - "\1\26\1\27\1\30\1\31\1\32\1\33\1\34\1\11"+ - "\1\35\1\3\1\36\1\37\1\36\1\40\1\41\1\1"+ - "\1\42\1\43\1\2\1\44\1\45\1\46\1\47\1\50"+ - "\1\51\1\52\1\53\1\54\1\55\1\56\1\57\2\60"+ - "\1\61\1\11\1\62\1\63\1\64\1\51\1\65\1\66"+ - "\1\67\1\70\1\71\1\0\1\72\1\73\1\74\1\75"+ - "\1\0\1\76\1\77\1\100\2\63\2\64\1\51\1\101"+ - "\1\102\1\103\1\104\1\0\1\77\1\63\1\105\2\64"+ - "\1\106\1\107\1\77\3\64\1\110"; + "\1\26\1\27\1\30\1\31\1\32\1\33\1\34\1\35"+ + "\1\11\1\36\1\3\1\37\1\40\1\37\1\41\1\42"+ + "\1\1\1\43\1\44\1\2\1\45\1\46\1\47\1\50"+ + "\1\0\1\51\1\52\1\53\1\54\1\55\1\56\1\57"+ + "\1\60\2\61\1\62\1\11\1\63\1\64\1\65\1\52"+ + "\1\66\1\67\1\70\1\71\1\72\1\0\1\73\1\74"+ + "\1\75\1\76\1\0\1\77\1\100\1\101\1\102\2\64"+ + "\2\65\1\52\1\103\1\104\1\105\1\106\1\0\1\101"+ + "\1\64\1\107\2\65\1\110\1\111\1\101\3\65\1\112"; private static int [] zzUnpackAction() { - int [] result = new int[107]; + int [] result = new int[111]; int offset = 0; offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); return result; @@ -169,22 +170,22 @@ class _RegExLexer implements FlexLexer { private static final String ZZ_ROWMAP_PACKED_0 = "\0\0\0\63\0\146\0\231\0\314\0\377\0\u0132\0\u0165"+ - "\0\u0198\0\u01cb\0\u01fe\0\u0231\0\u0264\0\u0264\0\u0297\0\u0264"+ - "\0\u0264\0\u02ca\0\u02fd\0\u0264\0\u0264\0\u0264\0\u0264\0\u0264"+ - "\0\u0264\0\u0264\0\u0264\0\u0264\0\u0264\0\u0330\0\u0264\0\u0363"+ - "\0\u0264\0\u0396\0\u0264\0\u0264\0\u0264\0\u03c9\0\u0264\0\u03fc"+ - "\0\u0264\0\u042f\0\u0264\0\u0264\0\u02ca\0\u0264\0\u0264\0\u0462"+ - "\0\u0495\0\u0264\0\u0264\0\u0264\0\u0264\0\u04c8\0\u0264\0\u0264"+ - "\0\u04fb\0\u052e\0\u0264\0\u0264\0\u0264\0\u0264\0\u0264\0\u0264"+ - "\0\u0561\0\u0264\0\u0264\0\u0264\0\u0594\0\u05c7\0\u05fa\0\u0264"+ - "\0\u0264\0\u0264\0\u0264\0\u0264\0\u062d\0\u0264\0\u0264\0\u0264"+ - "\0\u0660\0\u0693\0\u0264\0\u06c6\0\u0264\0\u06f9\0\u072c\0\u075f"+ - "\0\u0792\0\u07c5\0\u0264\0\u0264\0\u0264\0\u0264\0\u07f8\0\u082b"+ - "\0\u0264\0\u0264\0\u085e\0\u0891\0\u04fb\0\u0264\0\u0264\0\u08c4"+ - "\0\u08f7\0\u0264\0\u0264"; + "\0\u0198\0\u01cb\0\u01fe\0\u0231\0\u0264\0\u0297\0\u0297\0\u02ca"+ + "\0\u0297\0\u0297\0\u02fd\0\u0330\0\u0297\0\u0297\0\u0297\0\u0297"+ + "\0\u0297\0\u0297\0\u0297\0\u0297\0\u0297\0\u0297\0\u0363\0\u0297"+ + "\0\u0396\0\u0297\0\u03c9\0\u0297\0\u0297\0\u0297\0\u0297\0\u03fc"+ + "\0\u0297\0\u042f\0\u0297\0\u0462\0\u0297\0\u0297\0\u02fd\0\u0297"+ + "\0\u0297\0\u0495\0\u04c8\0\u0297\0\u0297\0\u0297\0\u0297\0\u04fb"+ + "\0\u0297\0\u052e\0\u0297\0\u0561\0\u0594\0\u0297\0\u0297\0\u0297"+ + "\0\u0297\0\u0297\0\u0297\0\u05c7\0\u0297\0\u0297\0\u0297\0\u05fa"+ + "\0\u062d\0\u0660\0\u0297\0\u0297\0\u0297\0\u0297\0\u0297\0\u0693"+ + "\0\u0297\0\u0297\0\u0297\0\u06c6\0\u06f9\0\u0297\0\u0297\0\u072c"+ + "\0\u0297\0\u075f\0\u0792\0\u07c5\0\u07f8\0\u082b\0\u0297\0\u0297"+ + "\0\u0297\0\u0297\0\u085e\0\u0891\0\u0297\0\u0297\0\u08c4\0\u08f7"+ + "\0\u0561\0\u0297\0\u0297\0\u092a\0\u095d\0\u0297\0\u0297"; private static int [] zzUnpackRowMap() { - int [] result = new int[107]; + int [] result = new int[111]; int offset = 0; offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); return result; @@ -207,52 +208,53 @@ class _RegExLexer implements FlexLexer { private static final int [] ZZ_TRANS = zzUnpackTrans(); private static final String ZZ_TRANS_PACKED_0 = - "\3\15\1\16\1\17\1\20\1\21\1\15\1\22\1\15"+ - "\1\23\1\24\1\25\1\26\1\27\1\30\1\31\1\32"+ - "\21\15\1\33\1\15\1\34\4\15\1\24\5\15\1\35"+ - "\1\15\1\24\12\15\1\36\1\0\47\15\1\37\2\40"+ - "\4\37\1\41\12\37\20\42\1\40\1\37\1\42\2\37"+ - "\1\40\1\43\12\37\11\44\1\45\1\44\1\0\47\44"+ - "\6\15\1\21\1\15\1\46\1\47\1\50\1\51\1\25"+ - "\26\15\1\33\5\15\1\52\1\51\7\15\1\51\6\53"+ - "\1\54\1\53\1\55\1\53\1\23\50\53\5\56\1\57"+ - "\14\56\20\60\1\56\1\61\1\60\6\56\1\62\7\56"+ - "\13\10\1\63\46\10\1\63\22\56\20\42\2\56\1\42"+ - "\7\56\1\64\30\56\20\42\2\56\1\42\14\56\1\65"+ - "\6\56\1\57\14\56\20\42\2\56\1\42\17\56\2\40"+ - "\2\56\1\57\14\56\20\42\1\40\1\56\1\42\2\56"+ - "\1\40\13\56\101\0\1\66\55\0\1\67\51\0\1\70"+ - "\1\71\1\72\4\73\1\70\1\73\1\70\1\73\1\74"+ - "\6\73\2\75\2\76\2\77\1\100\1\101\1\100\2\102"+ - "\1\103\1\104\1\103\1\105\1\106\1\107\1\73\1\103"+ - "\1\74\4\70\1\74\7\70\1\74\37\0\1\110\24\0"+ - "\2\40\37\0\1\40\4\0\1\40\14\0\2\42\17\0"+ - "\21\42\1\0\1\42\1\0\2\42\24\0\1\111\51\0"+ - "\1\70\1\71\1\72\4\73\1\70\1\73\1\112\1\73"+ - "\1\74\6\73\2\75\2\76\2\77\1\100\1\101\1\100"+ - "\2\102\1\103\1\104\1\103\1\105\1\106\1\107\1\73"+ - "\1\103\1\74\4\70\1\74\7\70\1\74\51\0\1\113"+ - "\33\0\20\60\2\0\1\60\40\0\20\61\2\0\1\61"+ - "\22\0\1\114\27\0\1\115\16\0\2\116\1\117\1\120"+ - "\1\121\1\122\1\123\2\0\2\71\37\0\1\71\22\0"+ - "\1\124\37\0\1\124\20\0\63\125\1\126\2\127\20\126"+ - "\2\127\2\126\3\127\3\126\1\127\1\126\1\127\2\126"+ - "\1\127\20\126\1\130\2\131\20\130\2\131\2\130\3\131"+ - "\3\130\1\131\1\130\1\131\2\130\1\131\20\130\1\0"+ - "\1\71\1\132\37\0\1\132\75\0\1\133\1\0\1\134"+ - "\60\0\1\135\1\136\4\0\5\137\1\0\55\137\2\0"+ - "\1\140\37\0\1\140\20\0\64\141\2\142\20\141\2\142"+ - "\2\141\3\142\3\141\1\142\1\141\1\142\2\141\1\142"+ - "\20\141\64\143\2\144\20\143\2\144\2\143\3\144\3\143"+ - "\1\144\1\143\1\144\2\143\1\144\20\143\1\0\1\71"+ - "\1\145\37\0\1\145\20\0\5\137\1\146\55\137\2\0"+ - "\1\147\37\0\1\147\20\0\64\150\2\151\20\150\2\151"+ - "\2\150\3\151\3\150\1\151\1\150\1\151\2\150\1\151"+ - "\20\150\64\152\2\153\20\152\2\153\2\152\3\153\3\152"+ - "\1\153\1\152\1\153\2\152\1\153\20\152"; + "\3\16\1\17\1\20\1\21\1\22\1\16\1\23\1\16"+ + "\1\24\1\25\1\26\1\27\1\30\1\31\1\32\1\33"+ + "\21\16\1\34\1\16\1\35\4\16\1\25\5\16\1\36"+ + "\1\16\1\25\12\16\1\37\1\0\47\16\1\40\2\41"+ + "\4\40\1\42\12\40\20\43\1\41\1\40\1\43\2\40"+ + "\1\41\1\44\12\40\11\45\1\46\1\45\1\0\62\45"+ + "\1\0\1\47\46\45\6\16\1\22\1\16\1\50\1\51"+ + "\1\52\1\53\1\26\26\16\1\34\5\16\1\54\1\53"+ + "\7\16\1\53\6\55\1\56\1\55\1\57\1\55\1\24"+ + "\50\55\5\60\1\61\14\60\20\62\1\60\1\63\1\62"+ + "\6\60\1\64\7\60\13\11\1\65\46\11\1\65\22\60"+ + "\20\43\2\60\1\43\7\60\1\66\30\60\20\43\2\60"+ + "\1\43\14\60\1\67\6\60\1\61\14\60\20\43\2\60"+ + "\1\43\17\60\2\41\2\60\1\61\14\60\20\43\1\41"+ + "\1\60\1\43\2\60\1\41\13\60\101\0\1\70\55\0"+ + "\1\71\2\0\1\72\46\0\1\73\1\74\1\75\4\76"+ + "\1\73\1\76\1\73\1\76\1\77\6\76\2\100\2\101"+ + "\2\102\1\103\1\104\1\103\2\105\1\106\1\107\1\106"+ + "\1\110\1\111\1\112\1\76\1\106\1\77\4\73\1\77"+ + "\7\73\1\77\37\0\1\113\24\0\2\41\37\0\1\41"+ + "\4\0\1\41\14\0\2\43\17\0\21\43\1\0\1\43"+ + "\1\0\2\43\24\0\1\114\2\0\1\72\46\0\1\73"+ + "\1\74\1\75\4\76\1\73\1\76\1\115\1\76\1\77"+ + "\6\76\2\100\2\101\2\102\1\103\1\104\1\103\2\105"+ + "\1\106\1\107\1\106\1\110\1\111\1\112\1\76\1\106"+ + "\1\77\4\73\1\77\7\73\1\77\51\0\1\116\33\0"+ + "\20\62\2\0\1\62\40\0\20\63\2\0\1\63\22\0"+ + "\1\117\27\0\1\120\16\0\2\121\1\122\1\123\1\124"+ + "\1\125\1\126\12\0\1\127\52\0\2\74\37\0\1\74"+ + "\22\0\1\130\37\0\1\130\20\0\63\131\1\132\2\133"+ + "\20\132\2\133\2\132\3\133\3\132\1\133\1\132\1\133"+ + "\2\132\1\133\20\132\1\134\2\135\20\134\2\135\2\134"+ + "\3\135\3\134\1\135\1\134\1\135\2\134\1\135\20\134"+ + "\1\0\1\74\1\136\37\0\1\136\75\0\1\137\1\0"+ + "\1\140\60\0\1\141\1\142\4\0\5\143\1\0\55\143"+ + "\2\0\1\144\37\0\1\144\20\0\64\145\2\146\20\145"+ + "\2\146\2\145\3\146\3\145\1\146\1\145\1\146\2\145"+ + "\1\146\20\145\64\147\2\150\20\147\2\150\2\147\3\150"+ + "\3\147\1\150\1\147\1\150\2\147\1\150\20\147\1\0"+ + "\1\74\1\151\37\0\1\151\20\0\5\143\1\152\55\143"+ + "\2\0\1\153\37\0\1\153\20\0\64\154\2\155\20\154"+ + "\2\155\2\154\3\155\3\154\1\155\1\154\1\155\2\154"+ + "\1\155\20\154\64\156\2\157\20\156\2\157\2\156\3\157"+ + "\3\156\1\157\1\156\1\157\2\156\1\157\20\156"; private static int [] zzUnpackTrans() { - int [] result = new int[2346]; + int [] result = new int[2448]; int offset = 0; offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); return result; @@ -293,15 +295,16 @@ class _RegExLexer implements FlexLexer { private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); private static final String ZZ_ATTRIBUTE_PACKED_0 = - "\6\0\2\1\4\0\2\11\1\1\2\11\2\1\12\11"+ - "\1\1\1\11\1\1\1\11\1\1\3\11\1\1\1\11"+ + "\7\0\2\1\4\0\2\11\1\1\2\11\2\1\12\11"+ + "\1\1\1\11\1\1\1\11\1\1\4\11\1\1\1\11"+ "\1\1\1\11\1\1\2\11\1\1\2\11\2\1\4\11"+ - "\1\1\2\11\2\1\6\11\1\1\3\11\3\1\5\11"+ - "\1\0\3\11\1\1\1\0\1\11\1\1\1\11\5\1"+ - "\4\11\1\0\1\1\2\11\3\1\2\11\2\1\2\11"; + "\1\1\1\11\1\0\1\11\2\1\6\11\1\1\3\11"+ + "\3\1\5\11\1\0\3\11\1\1\1\0\2\11\1\1"+ + "\1\11\5\1\4\11\1\0\1\1\2\11\3\1\2\11"+ + "\2\1\2\11"; private static int [] zzUnpackAttribute() { - int [] result = new int[107]; + int [] result = new int[111]; int offset = 0; offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); return result; @@ -646,207 +649,219 @@ class _RegExLexer implements FlexLexer { zzMarkedPos = zzMarkedPosL; switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { - case 72: + case 74: { return RegExpTT.UNICODE_CHAR; } - case 73: break; + case 75: break; case 7: { if (yystate() != CLASS2) yypushstate(EMBRACED); return RegExpTT.LBRACE; } - case 74: break; + case 76: break; case 24: { return RegExpTT.COMMA; } - case 75: break; - case 59: + case 77: break; + case 60: { return RegExpTT.POS_LOOKAHEAD; } - case 76: break; - case 66: - { yybegin(NAMED_GROUP); return RegExpTT.PYTHON_NAMED_GROUP; - } - case 77: break; - case 71: + case 78: break; + case 73: { return RegExpTT.COMMENT; } - case 78: break; + case 79: break; + case 68: + { yybegin(NAMED_GROUP); return RegExpTT.PYTHON_NAMED_GROUP; + } + case 80: break; case 14: { return RegExpTT.STAR; } - case 79: break; - case 57: + case 81: break; + case 58: { yybegin(PY_COND_REF); return RegExpTT.PYTHON_COND_REF; } - case 80: break; - case 47: + case 82: break; + case 48: { return RegExpTT.CHAR_CLASS; } - case 81: break; - case 34: + case 83: break; + case 35: { handleOptions(); return RegExpTT.OPTIONS_OFF; } - case 82: break; - case 53: + case 84: break; + case 54: { yypopstate(); return RegExpTT.QUOTE_END; } - case 83: break; - case 33: + case 85: break; + case 34: { yybegin(YYINITIAL); return RegExpTT.GROUP_END; } - case 84: break; + case 86: break; case 5: { return RegExpTT.GROUP_BEGIN; } - case 85: break; - case 35: + case 87: break; + case 36: { yybegin(YYINITIAL); return RegExpTT.COLON; } - case 86: break; + case 88: break; case 6: { return RegExpTT.GROUP_END; } - case 87: break; + case 89: break; case 25: { assert false : yytext(); } - case 88: break; + case 90: break; case 18: { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.CHARACTER; } - case 89: break; - case 44: + case 91: break; + case 45: { return commentMode ? RegExpTT.CHARACTER : RegExpTT.REDUNDANT_ESCAPE; } - case 90: break; + case 92: break; case 23: { return RegExpTT.NAME; } - case 91: break; - case 70: + case 93: break; + case 72: { if (allowOctalNoLeadingZero) return RegExpTT.OCT_CHAR; return yystate() != CLASS2 ? RegExpTT.BACKREF : RegExpTT.ESC_CHARACTER; } - case 92: break; - case 28: + case 94: break; + case 29: { yypopstate(); return RegExpTT.CLASS_END; } - case 93: break; - case 32: + case 95: break; + case 33: { yybegin(YYINITIAL); return RegExpTT.BAD_CHARACTER; } - case 94: break; - case 50: + case 96: break; + case 51: { yypushstate(QUOTED); return RegExpTT.QUOTE_BEGIN; } - case 95: break; + case 97: break; case 21: { return RegExpTT.NUMBER; } - case 96: break; + case 98: break; case 4: { return RegExpTT.DOT; } - case 97: break; - case 68: + case 99: break; + case 70: { return RegExpTT.NEG_LOOKBEHIND; } - case 98: break; - case 39: + case 100: break; + case 40: // lookahead expression with fixed base length zzMarkedPos = zzStartRead + 1; { yypushstate(CLASS1); return RegExpTT.CLASS_BEGIN; } - case 99: break; - case 60: + case 101: break; + case 61: { return RegExpTT.NEG_LOOKAHEAD; } - case 100: break; + case 102: break; case 10: { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.CTRL_CHARACTER; } - case 101: break; - case 58: + case 103: break; + case 59: { return RegExpTT.NON_CAPT_GROUP; } - case 102: break; - case 62: + case 104: break; + case 63: { yybegin(QUOTED_NAMED_GROUP); return RegExpTT.RUBY_QUOTED_NAMED_GROUP; } - case 103: break; - case 27: + case 105: break; + case 28: { if (allowNestedCharacterClasses) { yypushstate(CLASS2); return RegExpTT.CLASS_BEGIN; } return RegExpTT.CHARACTER; } - case 104: break; + case 106: break; case 19: { if (commentMode) { yypushstate(COMMENT); return RegExpTT.COMMENT; } else return RegExpTT.CHARACTER; } - case 105: break; - case 49: + case 107: break; + case 50: { yypushstate(PROP); return RegExpTT.PROPERTY; } - case 106: break; + case 108: break; case 8: { yypushstate(CLASS2); return RegExpTT.CLASS_BEGIN; } - case 107: break; - case 67: - { return RegExpTT.POS_LOOKBEHIND; - } - case 108: break; - case 41: - { return yystate() != CLASS2 ? RegExpTT.BACKREF : RegExpTT.ESC_CHARACTER; - } case 109: break; case 69: - { return RegExpTT.HEX_CHAR; + { return RegExpTT.POS_LOOKBEHIND; } case 110: break; + case 42: + { return yystate() != CLASS2 ? RegExpTT.BACKREF : RegExpTT.ESC_CHARACTER; + } + case 111: break; + case 71: + { return RegExpTT.HEX_CHAR; + } + case 112: break; case 1: { handleOptions(); return RegExpTT.OPTIONS_ON; } - case 111: break; - case 56: + case 113: break; + case 57: { return allowNestedCharacterClasses ? RegExpTT.ANDAND : RegExpTT.CHARACTER; } - case 112: break; + case 114: break; case 2: { yypopstate(); return RegExpTT.COMMENT; } - case 113: break; + case 115: break; case 17: { return RegExpTT.MINUS; } - case 114: break; - case 45: + case 116: break; + case 46: { return RegExpTT.ESC_CTRL_CHARACTER; } - case 115: break; - case 31: + case 117: break; + case 32: { yypopstate(); yypushstate(EMBRACED); return RegExpTT.LBRACE; } - case 116: break; + case 118: break; case 13: { return RegExpTT.QUEST; } - case 117: break; + case 119: break; case 15: { return RegExpTT.PLUS; } - case 118: break; - case 63: + case 120: break; + case 65: { return RegExpTT.OCT_CHAR; } - case 119: break; - case 37: + case 121: break; + case 38: { yybegin(YYINITIAL); return RegExpTT.QUOTE; } - case 120: break; + case 122: break; + case 64: + // lookahead expression with fixed base length + zzMarkedPos = zzStartRead + 1; + { if (!allowNestedCharacterClasses) { + yypushstate(CLASS1PY); + } + else { + yypushstate(CLASS2); + } + return RegExpTT.CLASS_BEGIN; + } + case 123: break; case 20: { if (allowDanglingMetacharacters) { yypopstate(); yypushback(1); @@ -854,12 +869,16 @@ class _RegExLexer implements FlexLexer { return RegExpTT.BAD_CHARACTER; } } - case 121: break; - case 30: + case 124: break; + case 31: { yypopstate(); yypushback(1); } - case 122: break; - case 54: + case 125: break; + case 27: + { yybegin(CLASS1); return RegExpTT.CARET; + } + case 126: break; + case 55: // lookahead expression with fixed base length zzMarkedPos = zzStartRead + 1; { if (allowNestedCharacterClasses) { @@ -868,92 +887,92 @@ class _RegExLexer implements FlexLexer { } return RegExpTT.CHARACTER; } - case 123: break; - case 55: + case 127: break; + case 56: { if (!allowNestedCharacterClasses) return RegExpTT.CHARACTER; return RegExpTT.REDUNDANT_ESCAPE; } - case 124: break; - case 36: + case 128: break; + case 37: { yybegin(YYINITIAL); return RegExpTT.GT; } - case 125: break; - case 65: + case 129: break; + case 67: { yybegin(PY_NAMED_GROUP_REF); return RegExpTT.PYTHON_NAMED_GROUP_REF; } - case 126: break; + case 130: break; case 16: { return RegExpTT.UNION; } - case 127: break; + case 131: break; case 3: { return RegExpTT.CHARACTER; } - case 128: break; - case 61: + case 132: break; + case 62: { yybegin(NAMED_GROUP); return RegExpTT.RUBY_NAMED_GROUP; } - case 129: break; - case 38: + case 133: break; + case 39: { yybegin(OPTIONS); return RegExpTT.SET_OPTIONS; } - case 130: break; + case 134: break; case 26: { yybegin(CLASS2); return RegExpTT.CHARACTER; } - case 131: break; - case 64: + case 135: break; + case 66: { if (xmlSchemaMode) { yypushback(1); return RegExpTT.CHAR_CLASS; } else return RegExpTT.CTRL; } - case 132: break; - case 29: + case 136: break; + case 30: { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.ESC_CHARACTER; } - case 133: break; + case 137: break; case 12: { return RegExpTT.DOLLAR; } - case 134: break; - case 48: + case 138: break; + case 49: { if (xmlSchemaMode) return RegExpTT.CHAR_CLASS; else return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN; } - case 135: break; - case 40: + case 139: break; + case 41: { return RegExpTT.REDUNDANT_ESCAPE; } - case 136: break; - case 46: + case 140: break; + case 47: { return yystate() != CLASS2 ? RegExpTT.BOUNDARY : RegExpTT.ESC_CHARACTER; } - case 137: break; + case 141: break; case 22: { yypopstate(); return RegExpTT.RBRACE; } - case 138: break; - case 52: - { return StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN; - } - case 139: break; - case 42: - { return RegExpTT.BAD_OCT_VALUE; - } - case 140: break; - case 51: - { return RegExpTT.BAD_HEX_VALUE; - } - case 141: break; - case 9: - { return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN; - } case 142: break; - case 11: - { return RegExpTT.CARET; + case 53: + { return StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN; } case 143: break; case 43: - { return RegExpTT.ESC_CHARACTER; + { return RegExpTT.BAD_OCT_VALUE; } case 144: break; + case 52: + { return RegExpTT.BAD_HEX_VALUE; + } + case 145: break; + case 9: + { return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN; + } + case 146: break; + case 11: + { return RegExpTT.CARET; + } + case 147: break; + case 44: + { return RegExpTT.ESC_CHARACTER; + } + case 148: break; default: if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { zzAtEOF = true; diff --git a/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex b/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex index b895b9c17066..ac4b4d340838 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex +++ b/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex @@ -62,6 +62,7 @@ import com.intellij.psi.StringEscapesTokenTypes; %xstate QUOTED %xstate EMBRACED %xstate CLASS1 +%xstate CLASS1PY %state CLASS2 %state PROP %xstate OPTIONS @@ -209,6 +210,16 @@ HEX_CHAR=[0-9a-fA-F] {LBRACKET} / {RBRACKET} { yypushstate(CLASS1); return RegExpTT.CLASS_BEGIN; } +/* Python understands that, Java doesn't */ +{LBRACKET} / "^" {RBRACKET} { if (!allowNestedCharacterClasses) { + yypushstate(CLASS1PY); + } + else { + yypushstate(CLASS2); + } + return RegExpTT.CLASS_BEGIN; + } + {LBRACKET} { yypushstate(CLASS2); return RegExpTT.CLASS_BEGIN; } @@ -218,6 +229,11 @@ HEX_CHAR=[0-9a-fA-F] . { assert false : yytext(); } } + { + "^" { yybegin(CLASS1); return RegExpTT.CARET; } + . { assert false : yytext(); } +} + { {RBRACKET} { yypopstate(); return RegExpTT.CLASS_END; } From e84bc3af06a93c4a860eb9c280eeaab9c807acd1 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 21 Feb 2011 17:48:10 +0100 Subject: [PATCH 051/169] Project Coin try-with-resource support, take 2 --- .../intellij/codeInsight/ExceptionUtil.java | 55 ++++++-- .../daemon/impl/analysis/HighlightUtil.java | 33 +++-- .../impl/analysis/HighlightVisitorImpl.java | 10 +- .../lang/java/parser/DeclarationParser.java | 120 ++++++++++-------- .../lang/java/parser/StatementParser.java | 4 +- .../psi/controlFlow/ControlFlowAnalyzer.java | 9 +- .../com/intellij/psi/impl/PsiImplUtil.java | 25 ++-- .../psi/impl/PsiJavaParserFacadeImpl.java | 14 +- .../psi/impl/source/tree/JavaElementType.java | 3 +- .../tree/java/PsiLocalVariableImpl.java | 13 +- .../source/tree/java/PsiResourceListImpl.java | 58 +++++++++ .../source/tree/java/PsiTryStatementImpl.java | 4 +- .../advHighlighting7/TryWithResources.java | 58 +++++---- .../statements/TryIncomplete10.txt | 2 +- .../statements/TryIncomplete11.txt | 2 +- .../statements/TryIncomplete12.txt | 2 +- .../statements/TryIncomplete13.txt | 10 +- .../statements/TryIncomplete14.txt | 15 +-- .../statements/TryIncomplete15.txt | 4 +- .../statements/TryIncomplete16.txt | 4 +- .../statements/TryIncomplete17.txt | 4 +- .../parser-partial/statements/TryNormal4.txt | 4 +- .../parser-partial/statements/TryNormal5.txt | 6 +- .../parser-partial/statements/TryNormal6.txt | 13 ++ .../parser-partial/statements/TryNormal7.txt | 17 +++ .../parser/partial/StatementParserTest.java | 4 +- .../com/intellij/psi/JavaElementVisitor.java | 6 +- .../src/com/intellij/psi/PsiResourceList.java | 44 +++++++ .../src/com/intellij/psi/PsiTryStatement.java | 2 +- .../src/com/intellij/psi/util/PsiUtil.java | 17 ++- .../com/intellij/psi/util/PsiTreeUtil.java | 16 +++ 31 files changed, 404 insertions(+), 174 deletions(-) create mode 100644 java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java create mode 100644 java/java-tests/testData/psi/parser-partial/statements/TryNormal6.txt create mode 100644 java/java-tests/testData/psi/parser-partial/statements/TryNormal7.txt create mode 100644 java/openapi/src/com/intellij/psi/PsiResourceList.java diff --git a/java/java-impl/src/com/intellij/codeInsight/ExceptionUtil.java b/java/java-impl/src/com/intellij/codeInsight/ExceptionUtil.java index c7f3c32476d5..a8a6f914ada4 100644 --- a/java/java-impl/src/com/intellij/codeInsight/ExceptionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/ExceptionUtil.java @@ -22,6 +22,7 @@ import com.intellij.psi.*; import com.intellij.psi.controlFlow.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.InheritanceUtil; +import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; @@ -206,10 +207,10 @@ public class ExceptionUtil { PsiClassType exception = getUnhandledException(statement, topElement); unhandledExceptions = exception == null ? Collections.emptyList() : Collections.singletonList(exception); } - else if (element instanceof PsiCodeBlock - && element.getParent() instanceof PsiMethod - && ((PsiMethod)element.getParent()).isConstructor() - && !firstStatementIsConstructorCall((PsiCodeBlock)element)) { + else if (element instanceof PsiCodeBlock && + element.getParent() instanceof PsiMethod && + ((PsiMethod)element.getParent()).isConstructor() && + !firstStatementIsConstructorCall((PsiCodeBlock)element)) { // there is implicit parent constructor call final PsiMethod constructor = (PsiMethod)element.getParent(); final PsiClass aClass = constructor.getContainingClass(); @@ -246,6 +247,22 @@ public class ExceptionUtil { unhandledExceptions = unhandled; } + if (PsiUtil.isResourceInTryStatement(element)) { + final PsiType resourceType = PsiUtil.getResourceType(element); + if (resourceType instanceof PsiClassType) { + final PsiClass resourceClass = ((PsiClassType)resourceType).resolve(); + if (resourceClass != null) { + final List unhandled = getUnhandledCloserExceptions(element, resourceClass, topElement); + if (unhandledExceptions == null) { + unhandledExceptions = unhandled; + } + else { + unhandledExceptions.addAll(unhandled); + } + } + } + } + if (unhandledExceptions != null) { if (foundExceptions == null) { foundExceptions = new THashSet(); @@ -309,15 +326,28 @@ public class ExceptionUtil { } @NotNull - public static List getUnhandledExceptions(PsiCallExpression methodCall, PsiElement topElement) { + public static List getUnhandledExceptions(final PsiCallExpression methodCall, final PsiElement topElement) { final JavaResolveResult result = methodCall.resolveMethodGenerics(); - PsiMethod method = (PsiMethod)result.getElement(); - return getUnhandledExceptions(method, methodCall, topElement, - ApplicationManager.getApplication().runReadAction(new Computable() { - public PsiSubstitutor compute() { - return result.getSubstitutor(); - } - })); + final PsiMethod method = (PsiMethod)result.getElement(); + final PsiSubstitutor substitutor = ApplicationManager.getApplication().runReadAction(new Computable() { + public PsiSubstitutor compute() { + return result.getSubstitutor(); + } + }); + return getUnhandledExceptions(method, methodCall, topElement, substitutor); + } + + @NotNull + public static List getUnhandledCloserExceptions(final PsiElement resource, + final PsiClass resourceClass, + final PsiElement topElement) { + final PsiMethod[] closers = resourceClass.findMethodsByName("close", false); + for (final PsiMethod method : closers) { + if (method.getParameterList().getParametersCount() == 0) { + return getUnhandledExceptions(method, resource, topElement, PsiSubstitutor.EMPTY); + } + } + return Collections.emptyList(); } @Nullable @@ -335,7 +365,6 @@ public class ExceptionUtil { return null; } - @NotNull private static List getUnhandledExceptions(PsiMethod method, PsiElement element, diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index ec903511c0e1..8368aec10784 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -553,18 +553,19 @@ public class HighlightUtil { return JavaErrorMessages.message("unhandled.exceptions", exceptionsText.toString(), unhandledExceptions.size()); } - @Nullable static HighlightInfo checkVariableAlreadyDefined(PsiVariable variable) { if (variable instanceof ExternallyDefinedPsiElement) return null; boolean isIncorrect = false; PsiIdentifier identifier = variable.getNameIdentifier(); + assert identifier != null : variable; String name = variable.getName(); if (variable instanceof PsiLocalVariable || variable instanceof PsiParameter && ((PsiParameter)variable).getDeclarationScope() instanceof PsiCatchSection || - variable instanceof PsiParameter && ((PsiParameter)variable).getDeclarationScope() instanceof PsiForeachStatement) { + variable instanceof PsiParameter && ((PsiParameter)variable).getDeclarationScope() instanceof PsiForeachStatement || + PsiUtil.isResourceInTryStatement(variable)) { PsiElement scope = PsiTreeUtil.getParentOfType(variable, PsiFile.class, PsiMethod.class, PsiClassInitializer.class); - VariablesNotProcessor proc = new VariablesNotProcessor(variable, false){ + VariablesNotProcessor proc = new VariablesNotProcessor(variable, false) { protected boolean check(final PsiVariable var, final ResolveState state) { return (var instanceof PsiLocalVariable || var instanceof PsiParameter) && super.check(var, state); } @@ -864,13 +865,11 @@ public class HighlightUtil { assert tryBlock != null : statement; thrownTypes.addAll(ExceptionUtil.collectUnhandledExceptions(tryBlock, tryBlock)); - final PsiParameterList resources = statement.getResourceList(); + final PsiResourceList resources = statement.getResourceList(); if (resources != null) { thrownTypes.addAll(ExceptionUtil.collectUnhandledExceptions(resources, resources)); } - // todo: add exceptions from resource's close() method - final PsiType caughtType = parameter.getType(); if (caughtType instanceof PsiClassType) { return checkSimpleCatchParameter(parameter, thrownTypes, (PsiClassType)caughtType); @@ -1110,14 +1109,32 @@ public class HighlightUtil { @Nullable - public static HighlightInfo checkCatchParameterIsThrowable(PsiParameter parameter) { + public static HighlightInfo checkCatchParameterIsThrowable(final PsiParameter parameter) { if (parameter.getDeclarationScope() instanceof PsiCatchSection) { - PsiType type = parameter.getType(); + final PsiType type = parameter.getType(); return checkMustBeThrowable(type, parameter, true); } return null; } + @Nullable + public static HighlightInfo checkTryResourceIsAutoCloseable(@NotNull final PsiElement resource) { + final PsiType type = PsiUtil.getResourceType(resource); + if (type == null) return null; + + final PsiElementFactory factory = JavaPsiFacade.getInstance(resource.getProject()).getElementFactory(); + final PsiClassType autoCloseable = factory.createTypeByFQClassName("java.lang.AutoCloseable", resource.getResolveScope()); + if (TypeConversionUtil.isAssignable(autoCloseable, type)) return null; + + final HighlightInfo highlightInfo = createIncompatibleTypeHighlightInfo(autoCloseable, type, resource.getTextRange()); + //if (addCastIntention && TypeConversionUtil.areTypesConvertible(type, autoCloseable)) { + // if (parameter instanceof PsiExpression) { + // QuickFixAction.registerQuickFixAction(highlightInfo, new AddTypeCastFix(autoCloseable, (PsiExpression)parameter)); + // } + //} + return highlightInfo; + } + public static void checkArrayInitalizer(final PsiExpression initializer, final HighlightInfoHolder holder) { if (! (initializer instanceof PsiArrayInitializerExpression)) return; diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index 9d963c68c0d2..003e0d8e01a0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -897,12 +897,18 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh @Override public void visitTryStatement(PsiTryStatement statement) { super.visitTryStatement(statement); if (!myHolder.hasErrorResults()) { - PsiParameter[] parameters = statement.getCatchBlockParameters(); - for (PsiParameter parameter : parameters) { + for (PsiParameter parameter : statement.getCatchBlockParameters()) { myHolder.addAll(HighlightUtil.checkExceptionThrownInTry(parameter)); myHolder.add(HighlightUtil.checkCatchParameterIsThrowable(parameter)); myHolder.add(GenericsHighlightUtil.checkCatchParameterIsClass(parameter)); } + + PsiResourceList resources = statement.getResourceList(); + if (resources != null) { + for (PsiElement resource : resources.getResources()) { + myHolder.add(HighlightUtil.checkTryResourceIsAutoCloseable(resource)); + } + } } } diff --git a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java index 23a23791a1aa..018bbbc3c875 100644 --- a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java +++ b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java @@ -35,7 +35,7 @@ import static com.intellij.lang.java.parser.JavaParserUtil.*; public class DeclarationParser { public enum Context { - FILE, CLASS, CODE_BLOCK, ANNOTATION_INTERFACE + FILE, CLASS, CODE_BLOCK, ANNOTATION_INTERFACE, RESOURCE_LIST } private static final TokenSet AFTER_END_DECLARATION_SET = TokenSet.create(JavaElementType.FIELD, JavaElementType.METHOD); @@ -222,7 +222,7 @@ public class DeclarationParser { if (tokenType == null) return null; if (tokenType == JavaTokenType.LBRACE) { - if (context == Context.FILE || context == Context.CODE_BLOCK) return null; + if (context == Context.FILE || context == Context.CODE_BLOCK || context == Context.RESOURCE_LIST) return null; } else if (tokenType == JavaTokenType.IDENTIFIER || ElementType.PRIMITIVE_TYPE_BIT_SET.contains(tokenType)) { if (context == Context.FILE) return null; @@ -234,7 +234,7 @@ public class DeclarationParser { else if (!ElementType.MODIFIER_BIT_SET.contains(tokenType) && !ElementType.CLASS_KEYWORD_BIT_SET.contains(tokenType) && tokenType != JavaTokenType.AT && - (context == Context.CODE_BLOCK || tokenType != JavaTokenType.LT)) { + (context == Context.CODE_BLOCK || context == Context.RESOURCE_LIST || tokenType != JavaTokenType.LT)) { return null; } @@ -278,7 +278,7 @@ public class DeclarationParser { final PsiBuilder.Marker idPos = builder.mark(); type = parseTypeNotNull(builder); if (builder.getTokenType() == JavaTokenType.LPARENTH) { // constructor - if (context == Context.CODE_BLOCK) { + if (context == Context.CODE_BLOCK || context == Context.RESOURCE_LIST) { declaration.rollbackTo(); return null; } @@ -301,6 +301,10 @@ public class DeclarationParser { declaration.drop(); return modList; } + else if (context == Context.RESOURCE_LIST) { + declaration.rollbackTo(); + return null; + } final PsiBuilder.Marker codeBlock = StatementParser.parseCodeBlock(builder); assert codeBlock != null : builder.getOriginalText(); @@ -326,7 +330,7 @@ public class DeclarationParser { } if (!expect(builder, JavaTokenType.IDENTIFIER)) { - if (context == Context.CODE_BLOCK && modListInfo.second) { + if ((context == Context.CODE_BLOCK || context == Context.RESOURCE_LIST) && modListInfo.second) { declaration.rollbackTo(); return null; } @@ -447,33 +451,33 @@ public class DeclarationParser { @NotNull public static PsiBuilder.Marker parseParameterList(final PsiBuilder builder) { - return parseParameterList(builder, false); + return parseElementList(builder, false); } @NotNull public static PsiBuilder.Marker parseResourceList(final PsiBuilder builder) { - return parseParameterList(builder, true); + return parseElementList(builder, true); } @NotNull - private static PsiBuilder.Marker parseParameterList(final PsiBuilder builder, final boolean resources) { + private static PsiBuilder.Marker parseElementList(final PsiBuilder builder, final boolean resources) { assert builder.getTokenType() == JavaTokenType.LPARENTH : builder.getTokenType(); - final PsiBuilder.Marker paramList = builder.mark(); + final PsiBuilder.Marker elementList = builder.mark(); builder.advanceLexer(); final IElementType delimiter = resources ? JavaTokenType.SEMICOLON : JavaTokenType.COMMA; final String noDelimiterMsg = JavaErrorMessages.message(resources ? "expected.semicolon" : "expected.comma"); - final String noParameterMsg = JavaErrorMessages.message(resources ? "expected.resource" : "expected.parameter"); + final String noElementMsg = JavaErrorMessages.message(resources ? "expected.resource" : "expected.parameter"); PsiBuilder.Marker invalidElements = null; String errorMessage = null; boolean delimiterExpected = false; - int paramCount = 0; + int elementCount = 0; while (true) { final IElementType tokenType = builder.getTokenType(); if (tokenType == null || tokenType == JavaTokenType.RPARENTH || tokenType == JavaTokenType.LBRACE) { - boolean noLastParam = !delimiterExpected && paramCount > 0; - if (noLastParam) { + boolean noLastElement = !delimiterExpected && elementCount > 0; + if (noLastElement) { error(builder, JavaErrorMessages.message("expected.identifier.or.type")); } if (tokenType == JavaTokenType.RPARENTH) { @@ -481,13 +485,13 @@ public class DeclarationParser { invalidElements.error(errorMessage); invalidElements = null; } - else if (resources && paramCount == 0) { + else if (resources && elementCount == 0) { error(builder, JavaErrorMessages.message("expected.resource")); } builder.advanceLexer(); } else { - if (!noLastParam) { + if (!noLastElement) { if (invalidElements != null) { invalidElements.error(errorMessage); } @@ -510,27 +514,27 @@ public class DeclarationParser { } } else { - final PsiBuilder.Marker param = parseParameter(builder, true, false, resources); - if (param != null) { + final PsiBuilder.Marker listElement = resources ? parseResource(builder) : parseParameter(builder, true, false); + if (listElement != null) { delimiterExpected = true; if (invalidElements != null) { - invalidElements.errorBefore(errorMessage, param); + invalidElements.errorBefore(errorMessage, listElement); invalidElements = null; } - paramCount++; + elementCount++; continue; } } if (invalidElements == null) { if (builder.getTokenType() == delimiter) { - error(builder, noParameterMsg); + error(builder, noElementMsg); builder.advanceLexer(); continue; } else { invalidElements = builder.mark(); - errorMessage = delimiterExpected ? noDelimiterMsg : noParameterMsg; + errorMessage = delimiterExpected ? noDelimiterMsg : noElementMsg; } } @@ -545,19 +549,19 @@ public class DeclarationParser { invalidElements.error(errorMessage); } - done(paramList, JavaElementType.PARAMETER_LIST); - return paramList; + done(elementList, resources ? JavaElementType.RESOURCE_LIST : JavaElementType.PARAMETER_LIST); + return elementList; } @Nullable - public static PsiBuilder.Marker parseParameter(final PsiBuilder builder, final boolean ellipsis, final boolean disjunction, final boolean value) { + public static PsiBuilder.Marker parseParameter(final PsiBuilder builder, final boolean ellipsis, final boolean disjunctiveType) { final PsiBuilder.Marker param = builder.mark(); final Pair modListInfo = parseModifierList(builder); int flags = ReferenceParser.EAT_LAST_DOT | ReferenceParser.WILDCARD; if (ellipsis) flags |= ReferenceParser.ELLIPSIS; - if (disjunction) flags |= ReferenceParser.DISJUNCTIONS; + if (disjunctiveType) flags |= ReferenceParser.DISJUNCTIONS; final ReferenceParser.TypeInfo typeInfo = ReferenceParser.parseTypeInfo(builder, flags); if (typeInfo == null) { @@ -572,23 +576,24 @@ public class DeclarationParser { } if (expect(builder, JavaTokenType.IDENTIFIER)) { - eatBrackets(builder, typeInfo != null && typeInfo.isVarArg || value, JavaErrorMessages.message("expected.rparen")); - if (value) { - if (expectOrError(builder, JavaTokenType.EQ, JavaErrorMessages.message("expected.eq"))) { - if (ExpressionParser.parse(builder) == null) { - error(builder, JavaErrorMessages.message("expected.expression")); - } - } - } + eatBrackets(builder, typeInfo != null && typeInfo.isVarArg, JavaErrorMessages.message("expected.rparen")); + done(param, JavaElementType.PARAMETER); + return param; } else { error(builder, JavaErrorMessages.message("expected.identifier")); param.drop(); return modListInfo.first; } + } - done(param, JavaElementType.PARAMETER); - return param; + @Nullable + private static PsiBuilder.Marker parseResource(final PsiBuilder builder) { + PsiBuilder.Marker resource = parse(builder, Context.RESOURCE_LIST); + if (resource == null) { + resource = ExpressionParser.parse(builder); + } + return resource; } @Nullable @@ -598,7 +603,7 @@ public class DeclarationParser { if (context == Context.CLASS || context == Context.ANNOTATION_INTERFACE) { varType = JavaElementType.FIELD; } - else if (context == Context.CODE_BLOCK) { + else if (context == Context.CODE_BLOCK || context == Context.RESOURCE_LIST) { varType = JavaElementType.LOCAL_VARIABLE; } else { @@ -629,6 +634,11 @@ public class DeclarationParser { unclosed = true; break; } + if (context == Context.RESOURCE_LIST) break; + } + else if (context == Context.RESOURCE_LIST) { + error(builder, JavaErrorMessages.message("expected.eq")); + break; } if (builder.getTokenType() != JavaTokenType.COMMA) break; @@ -647,26 +657,28 @@ public class DeclarationParser { builder.advanceLexer(); } - if (builder.getTokenType() == JavaTokenType.SEMICOLON && eatSemicolon) { - builder.advanceLexer(); - } - else { - // special treatment (see DeclarationParserTest.testMultiLineUnclosed()) - if (!builder.eof() && shouldRollback) { - final CharSequence text = builder.getOriginalText(); - final int spaceEnd = builder.getCurrentOffset(); - final int spaceStart = CharArrayUtil.shiftBackward(text, spaceEnd-1, WHITESPACES); - final int lineStart = CharArrayUtil.shiftBackwardUntil(text, spaceEnd, LINE_ENDS); - - if (declarationStart < lineStart && lineStart < spaceStart) { - final int newBufferEnd = CharArrayUtil.shiftForward(text, lineStart, WHITESPACES); - declaration.rollbackTo(); - return parse(stoppingBuilder(builder, newBufferEnd), context); - } + if (context != Context.RESOURCE_LIST) { + if (builder.getTokenType() == JavaTokenType.SEMICOLON && eatSemicolon) { + builder.advanceLexer(); } + else { + // special treatment (see DeclarationParserTest.testMultiLineUnclosed()) + if (!builder.eof() && shouldRollback) { + final CharSequence text = builder.getOriginalText(); + final int spaceEnd = builder.getCurrentOffset(); + final int spaceStart = CharArrayUtil.shiftBackward(text, spaceEnd-1, WHITESPACES); + final int lineStart = CharArrayUtil.shiftBackwardUntil(text, spaceEnd, LINE_ENDS); - if (!unclosed) { - error(builder, JavaErrorMessages.message("expected.semicolon")); + if (declarationStart < lineStart && lineStart < spaceStart) { + final int newBufferEnd = CharArrayUtil.shiftForward(text, lineStart, WHITESPACES); + declaration.rollbackTo(); + return parse(stoppingBuilder(builder, newBufferEnd), context); + } + } + + if (!unclosed) { + error(builder, JavaErrorMessages.message("expected.semicolon")); + } } } diff --git a/java/java-impl/src/com/intellij/lang/java/parser/StatementParser.java b/java/java-impl/src/com/intellij/lang/java/parser/StatementParser.java index eb10691aca69..2f4061c26114 100644 --- a/java/java-impl/src/com/intellij/lang/java/parser/StatementParser.java +++ b/java/java-impl/src/com/intellij/lang/java/parser/StatementParser.java @@ -375,7 +375,7 @@ public class StatementParser { } final PsiBuilder.Marker afterParenth = builder.mark(); - final PsiBuilder.Marker param = DeclarationParser.parseParameter(builder, false, false, false); + final PsiBuilder.Marker param = DeclarationParser.parseParameter(builder, false, false); if (param == null || JavaParserUtil.exprType(param) != JavaElementType.PARAMETER || builder.getTokenType() != JavaTokenType.COLON) { afterParenth.rollbackTo(); return parseForLoopFromInitialization(builder, statement); @@ -657,7 +657,7 @@ public class StatementParser { return false; } - final PsiBuilder.Marker param = DeclarationParser.parseParameter(builder, false, areMultiCatchSupported(builder), false); + final PsiBuilder.Marker param = DeclarationParser.parseParameter(builder, false, areMultiCatchSupported(builder)); if (param == null) { error(builder, JavaErrorMessages.message("expected.parameter")); } diff --git a/java/java-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java b/java/java-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java index 59c3cf484641..add49f2a4f7a 100644 --- a/java/java-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java +++ b/java/java-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java @@ -268,7 +268,6 @@ class ControlFlowAnalyzer extends JavaJspElementVisitor { } } - // generate jump to the top finally block if (!myFinallyBlocks.isEmpty()) { final PsiElement finallyBlock = myFinallyBlocks.peek(); @@ -278,13 +277,10 @@ class ControlFlowAnalyzer extends JavaJspElementVisitor { addElementOffsetLater(finallyBlock, true); } } - } private void generateCheckedExceptionJumps(PsiElement element) { //generate jumps to all handled exception handlers - //if (myCatchBlocks.size() != 0) { - //} Collection unhandledExceptions = ExceptionUtil.collectUnhandledExceptions(element, element.getParent()); for (PsiClassType unhandledException : unhandledExceptions) { ProgressManager.checkCanceled(); @@ -1040,6 +1036,11 @@ class ControlFlowAnalyzer extends JavaJspElementVisitor { generateCheckedExceptionJumps(tryBlock); tryBlock.accept(this); } + PsiResourceList resourceList = statement.getResourceList(); + if (resourceList != null) { + generateCheckedExceptionJumps(resourceList); + resourceList.accept(this); + } //noinspection StatementWithEmptyBody while (myUnhandledExceptionCatchBlocks.pop() != null) ; diff --git a/java/java-impl/src/com/intellij/psi/impl/PsiImplUtil.java b/java/java-impl/src/com/intellij/psi/impl/PsiImplUtil.java index aaa1450e159d..2fa673130c31 100644 --- a/java/java-impl/src/com/intellij/psi/impl/PsiImplUtil.java +++ b/java/java-impl/src/com/intellij/psi/impl/PsiImplUtil.java @@ -185,8 +185,10 @@ public class PsiImplUtil { if (list != null && !list.processDeclarations(processor, state, null, place)) return false; } if (lastParent instanceof PsiCodeBlock) { - final PsiParameterList parameterList = method.getParameterList(); - if (processDeclarationsInParameterList(parameterList, processor, state)) return false; + final PsiParameter[] parameters = method.getParameterList().getParameters(); + for (PsiParameter parameter : parameters) { + if (!processor.execute(parameter, state)) return false; + } } return true; @@ -196,24 +198,17 @@ public class PsiImplUtil { @NotNull final PsiScopeProcessor processor, @NotNull final ResolveState state, final PsiElement lastParent) { - if (lastParent instanceof PsiCodeBlock) { - final PsiParameterList parameterList = statement.getResourceList(); - if (parameterList != null && processDeclarationsInParameterList(parameterList, processor, state)) return false; + final PsiResourceList resourceList = statement.getResourceList(); + if (resourceList != null && lastParent instanceof PsiCodeBlock && lastParent == statement.getTryBlock()) { + final List resources = resourceList.getNamedResources(); + for (PsiLocalVariable resource : resources) { + if (!processor.execute(resource, state)) return false; + } } return true; } - private static boolean processDeclarationsInParameterList(@NotNull final PsiParameterList parameterList, - @NotNull final PsiScopeProcessor processor, - @NotNull final ResolveState state) { - final PsiParameter[] parameters = parameterList.getParameters(); - for (PsiParameter parameter : parameters) { - if (!processor.execute(parameter, state)) return true; - } - return false; - } - public static boolean hasTypeParameters(@NotNull PsiTypeParameterListOwner owner) { final PsiTypeParameterList typeParameterList = owner.getTypeParameterList(); return typeParameterList != null && typeParameterList.getTypeParameters().length != 0; diff --git a/java/java-impl/src/com/intellij/psi/impl/PsiJavaParserFacadeImpl.java b/java/java-impl/src/com/intellij/psi/impl/PsiJavaParserFacadeImpl.java index 083602d0e83f..52d766646901 100644 --- a/java/java-impl/src/com/intellij/psi/impl/PsiJavaParserFacadeImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/PsiJavaParserFacadeImpl.java @@ -60,14 +60,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ private static final JavaParserUtil.ParserWrapper PARAMETER = new JavaParserUtil.ParserWrapper() { @Override public void parse(final PsiBuilder builder) { - DeclarationParser.parseParameter(builder, true, false, false); - } - }; - - private static final JavaParserUtil.ParserWrapper RESOURCE = new JavaParserUtil.ParserWrapper() { - @Override - public void parse(final PsiBuilder builder) { - DeclarationParser.parseParameter(builder, true, false, true); + DeclarationParser.parseParameter(builder, true, false); } }; @@ -239,10 +232,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ @NotNull public PsiParameter createParameterFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { - final boolean resource = context instanceof PsiParameterList && - context.getParent() instanceof PsiTryStatement; - final JavaParserUtil.ParserWrapper wrapper = resource ? RESOURCE : PARAMETER; - final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, wrapper, false), context); + final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, PARAMETER, false), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); if (!(element instanceof PsiParameter)) { throw new IncorrectOperationException("Incorrect parameter \"" + text + "\"."); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java index 4270606ec5e1..7d31f4b1ff3a 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java @@ -127,9 +127,10 @@ public interface JavaElementType { IElementType THROW_STATEMENT = new JavaCompositeElementType("THROW_STATEMENT", PsiThrowStatementImpl.class); IElementType SYNCHRONIZED_STATEMENT = new JavaCompositeElementType("SYNCHRONIZED_STATEMENT", PsiSynchronizedStatementImpl.class); IElementType TRY_STATEMENT = new JavaCompositeElementType("TRY_STATEMENT", PsiTryStatementImpl.class); + IElementType RESOURCE_LIST = new JavaCompositeElementType("RESOURCE_LIST", PsiResourceListImpl.class); + IElementType CATCH_SECTION = new JavaCompositeElementType("CATCH_SECTION", PsiCatchSectionImpl.class); IElementType LABELED_STATEMENT = new JavaCompositeElementType("LABELED_STATEMENT", PsiLabeledStatementImpl.class); IElementType ASSERT_STATEMENT = new JavaCompositeElementType("ASSERT_STATEMENT", PsiAssertStatementImpl.class); - IElementType CATCH_SECTION = new JavaCompositeElementType("CATCH_SECTION", PsiCatchSectionImpl.class); IElementType ANNOTATION_ARRAY_INITIALIZER = new JavaCompositeElementType("ANNOTATION_ARRAY_INITIALIZER", PsiArrayInitializerMemberValueImpl.class); IElementType NAME_VALUE_PAIR = new JavaCompositeElementType("NAME_VALUE_PAIR", PsiNameValuePairImpl.class, true); IElementType ANNOTATION_PARAMETER_LIST = new JavaCompositeElementType("ANNOTATION_PARAMETER_LIST", PsiAnnotationParameterListImpl.class, true); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiLocalVariableImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiLocalVariableImpl.java index 61872ff2f4c2..910c1f171773 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiLocalVariableImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiLocalVariableImpl.java @@ -94,7 +94,7 @@ public class PsiLocalVariableImpl extends CompositePsiElement implements PsiLoca @NotNull public PsiTypeElement getTypeElement() { ASTNode first = getTreeParent().findChildByType(LOCAL_VARIABLE); - return (PsiTypeElement)SourceTreeToPsiMap.treeElementToPsi(first.findChildByType(TYPE)); + return SourceTreeToPsiMap.treeToPsiNotNull(first.findChildByType(TYPE)); } public PsiModifierList getModifierList() { @@ -105,7 +105,8 @@ public class PsiLocalVariableImpl extends CompositePsiElement implements PsiLoca } public boolean hasModifierProperty(@NotNull String name) { - return getModifierList().hasModifierProperty(name); + final PsiModifierList modifierList = getModifierList(); + return modifierList != null && modifierList.hasModifierProperty(name); } public PsiExpression getInitializer() { @@ -304,10 +305,15 @@ public class PsiLocalVariableImpl extends CompositePsiElement implements PsiLoca } } - PsiElement parentElement = getParent(); + final PsiElement parentElement = getParent(); if (parentElement instanceof PsiDeclarationStatement) { return new LocalSearchScope(parentElement.getParent()); } + else if (parentElement instanceof PsiResourceList) { + final PsiElement tryStatement = parentElement.getParent(); + final PsiCodeBlock tryBlock = ((PsiTryStatement)tryStatement).getTryBlock(); + return new LocalSearchScope(tryBlock != null ? tryBlock : tryStatement); + } else { return getManager().getFileManager().getUseScope(this); } @@ -317,6 +323,7 @@ public class PsiLocalVariableImpl extends CompositePsiElement implements PsiLoca final RowIcon baseIcon = createLayeredIcon(Icons.VARIABLE_ICON, ElementPresentationUtil.getFlags(this, false)); return ElementPresentationUtil.addVisibilityIcon(this, flags, baseIcon); } + public PsiType getTypeNoResolve() { return getType(); } diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java new file mode 100644 index 000000000000..f078c02d9514 --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java @@ -0,0 +1,58 @@ +/* + * Copyright 2000-2011 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 com.intellij.psi.impl.source.tree.java; + +import com.intellij.psi.*; +import com.intellij.psi.impl.source.tree.CompositePsiElement; +import com.intellij.psi.impl.source.tree.JavaElementType; +import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class PsiResourceListImpl extends CompositePsiElement implements PsiResourceList { + public PsiResourceListImpl() { + super(JavaElementType.RESOURCE_LIST); + } + + @NotNull + @Override + public List getResources() { + //noinspection unchecked + return PsiTreeUtil.getChildrenOfAnyType(this, PsiExpression.class, PsiLocalVariable.class); + } + + @NotNull + @Override + public List getNamedResources() { + return PsiTreeUtil.getChildrenOfTypeAsList(this, PsiLocalVariable.class); + } + + @Override + public void accept(@NotNull final PsiElementVisitor visitor) { + if (visitor instanceof JavaElementVisitor) { + ((JavaElementVisitor)visitor).visitResourceList(this); + } + else { + visitor.visitElement(this); + } + } + + @Override + public String toString() { + return "PsiResourceList:" + getText(); + } +} diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiTryStatementImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiTryStatementImpl.java index dc23a38cd074..b8bd9a9e373d 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiTryStatementImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiTryStatementImpl.java @@ -93,8 +93,8 @@ public class PsiTryStatementImpl extends CompositePsiElement implements PsiTrySt } @Override - public PsiParameterList getResourceList() { - return PsiTreeUtil.findChildOfType(this, PsiParameterList.class); + public PsiResourceList getResourceList() { + return PsiTreeUtil.findChildOfType(this, PsiResourceList.class); } public ASTNode findChildByRole(int role) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResources.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResources.java index 750e9bc5cb0e..36187d86a680 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResources.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResources.java @@ -1,31 +1,45 @@ -import java.io.*; -import java.lang.Exception; - class C { - void m0() throws Exception { - try (FileReader reader = new FileReader(new File("input.txt"))) { - reader.read(); - } catch (Exception e) { - reader = null; - } - reader = null; + static class E extends Exception { } + static class E1 extends E { } + static class E2 extends E { } + static class E3 extends E { } + + static class MyResource implements AutoCloseable { + public MyResource() throws E1 { } + public void doSomething() throws E2 { } + @Override public void close() throws E3 { } } void m1() { - try (final FileReader reader = new FileReader(new File("input.txt"))) { - reader.read(); - } - catch (IOException ignore) { } + try (MyResource r = new MyResource()) { r.doSomething(); } + catch (E1 | E2 | E3 ignore) { } - try (final FileReader reader = new FileReader(new File("input.txt"))) { - System.out.println("Try."); - } - catch (IOException ignore) { } + try (new MyResource()) { } + catch (E1 | E3 ignore) { } } - /*void m2() throws IOException { - try (final FileReader reader = new FileReader(new File("input.txt"))) { - reader.read(); + void m2() throws Exception { + try (Object r = new MyResource()) { } + + try ("resource") { } + } + + void m3() throws Exception { + try (MyResource r = new MyResource()) { + r.doSomething(); } - }*/ + catch (E e) { + r = null; + } + finally { + r = null; + } + r = null; + + MyResource r = null; + + try (MyResource r = new MyResource()) { } + + try (r = new MyResource()) { } + } } \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete10.txt b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete10.txt index c9b9aaf68b6e..2e113f719226 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete10.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete10.txt @@ -1,7 +1,7 @@ PsiJavaFile:TryIncomplete10.java PsiTryStatement PsiKeyword:try('try') - PsiParameterList:( + PsiResourceList:( PsiJavaToken:LPARENTH('(') PsiErrorElement:')' expected diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete11.txt b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete11.txt index 05e296fcc190..11b2811b4174 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete11.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete11.txt @@ -1,7 +1,7 @@ PsiJavaFile:TryIncomplete11.java PsiTryStatement PsiKeyword:try('try') - PsiParameterList:() + PsiResourceList:() PsiJavaToken:LPARENTH('(') PsiErrorElement:Resource definition expected diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete12.txt b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete12.txt index 829a9a293c17..78a125c530b4 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete12.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete12.txt @@ -1,7 +1,7 @@ PsiJavaFile:TryIncomplete12.java PsiTryStatement PsiKeyword:try('try') - PsiParameterList:(;) + PsiResourceList:(;) PsiJavaToken:LPARENTH('(') PsiErrorElement:Resource definition expected diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete13.txt b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete13.txt index 5883e80baf09..598f1ac3e5c0 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete13.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete13.txt @@ -1,18 +1,14 @@ PsiJavaFile:TryIncomplete13.java PsiTryStatement PsiKeyword:try('try') - PsiParameterList:(final ) + PsiResourceList:(final ) PsiJavaToken:LPARENTH('(') PsiModifierList:final PsiKeyword:final('final') - PsiErrorElement:Type expected + PsiErrorElement:Identifier or type expected PsiWhiteSpace(' ') - PsiTypeElement: - - PsiErrorElement:Identifier expected - PsiJavaToken:RPARENTH(')') PsiCodeBlock PsiJavaToken:LBRACE('{') - PsiJavaToken:RBRACE('}') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete14.txt b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete14.txt index 36386acc63b2..88a8aca925b2 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete14.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete14.txt @@ -1,18 +1,11 @@ PsiJavaFile:TryIncomplete14.java PsiTryStatement PsiKeyword:try('try') - PsiParameterList:(R) + PsiResourceList:(int) PsiJavaToken:LPARENTH('(') - PsiModifierList: - - PsiTypeElement:R - PsiJavaCodeReferenceElement:R - PsiIdentifier:R('R') - PsiReferenceParameterList - - PsiErrorElement:Identifier expected - + PsiErrorElement:Resource definition expected + PsiKeyword:int('int') PsiJavaToken:RPARENTH(')') PsiCodeBlock PsiJavaToken:LBRACE('{') - PsiJavaToken:RBRACE('}') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete15.txt b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete15.txt index f38fe8b04bc7..297e7e00cfaf 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete15.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete15.txt @@ -1,9 +1,9 @@ PsiJavaFile:TryIncomplete15.java PsiTryStatement PsiKeyword:try('try') - PsiParameterList:(R r) + PsiResourceList:(R r) PsiJavaToken:LPARENTH('(') - PsiParameter:r + PsiLocalVariable:r PsiModifierList: PsiTypeElement:R diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete16.txt b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete16.txt index d18696953396..4ed639c77577 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete16.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete16.txt @@ -1,9 +1,9 @@ PsiJavaFile:TryIncomplete16.java PsiTryStatement PsiKeyword:try('try') - PsiParameterList:(R r =) + PsiResourceList:(R r =) PsiJavaToken:LPARENTH('(') - PsiParameter:r + PsiLocalVariable:r PsiModifierList: PsiTypeElement:R diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete17.txt b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete17.txt index 4f8626c450a0..4a4aa969fceb 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete17.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete17.txt @@ -1,9 +1,9 @@ PsiJavaFile:TryIncomplete17.java PsiTryStatement PsiKeyword:try('try') - PsiParameterList:(R r = 0;) + PsiResourceList:(R r = 0;) PsiJavaToken:LPARENTH('(') - PsiParameter:r + PsiLocalVariable:r PsiModifierList: PsiTypeElement:R diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryNormal4.txt b/java/java-tests/testData/psi/parser-partial/statements/TryNormal4.txt index 29b541335e1f..0cf390a0fcbd 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryNormal4.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryNormal4.txt @@ -1,9 +1,9 @@ PsiJavaFile:TryNormal4.java PsiTryStatement PsiKeyword:try('try') - PsiParameterList:(R r = 0) + PsiResourceList:(R r = 0) PsiJavaToken:LPARENTH('(') - PsiParameter:r + PsiLocalVariable:r PsiModifierList: PsiTypeElement:R diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryNormal5.txt b/java/java-tests/testData/psi/parser-partial/statements/TryNormal5.txt index 78c53a180d3c..8c11fdeff9ca 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryNormal5.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryNormal5.txt @@ -1,9 +1,9 @@ PsiJavaFile:TryNormal5.java PsiTryStatement PsiKeyword:try('try') - PsiParameterList:(R1 r1 = 1; R2 r2 = 2) + PsiResourceList:(R1 r1 = 1; R2 r2 = 2) PsiJavaToken:LPARENTH('(') - PsiParameter:r1 + PsiLocalVariable:r1 PsiModifierList: PsiTypeElement:R1 @@ -20,7 +20,7 @@ PsiJavaFile:TryNormal5.java PsiJavaToken:INTEGER_LITERAL('1') PsiJavaToken:SEMICOLON(';') PsiWhiteSpace(' ') - PsiParameter:r2 + PsiLocalVariable:r2 PsiModifierList: PsiTypeElement:R2 diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryNormal6.txt b/java/java-tests/testData/psi/parser-partial/statements/TryNormal6.txt new file mode 100644 index 000000000000..c82b04a42e85 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/statements/TryNormal6.txt @@ -0,0 +1,13 @@ +PsiJavaFile:TryNormal6.java + PsiTryStatement + PsiKeyword:try('try') + PsiResourceList:(r) + PsiJavaToken:LPARENTH('(') + PsiReferenceExpression:r + PsiReferenceParameterList + + PsiIdentifier:r('r') + PsiJavaToken:RPARENTH(')') + PsiCodeBlock + PsiJavaToken:LBRACE('{') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryNormal7.txt b/java/java-tests/testData/psi/parser-partial/statements/TryNormal7.txt new file mode 100644 index 000000000000..746ded3b71bb --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/statements/TryNormal7.txt @@ -0,0 +1,17 @@ +PsiJavaFile:TryNormal7.java + PsiTryStatement + PsiKeyword:try('try') + PsiResourceList:(r; null) + PsiJavaToken:LPARENTH('(') + PsiReferenceExpression:r + PsiReferenceParameterList + + PsiIdentifier:r('r') + PsiJavaToken:SEMICOLON(';') + PsiWhiteSpace(' ') + PsiLiteralExpression:null + PsiJavaToken:NULL_KEYWORD('null') + PsiJavaToken:RPARENTH(')') + PsiCodeBlock + PsiJavaToken:LBRACE('{') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/StatementParserTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/StatementParserTest.java index 7cf68cf63d66..df12da3f6c62 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/StatementParserTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/StatementParserTest.java @@ -122,6 +122,8 @@ public class StatementParserTest extends JavaParsingTestCase { public void testTryNormal3() { doParserTestJDK7("try{}catch(A|B e){}"); } public void testTryNormal4() { doParserTestJDK7("try(R r = 0){}"); } public void testTryNormal5() { doParserTestJDK7("try(R1 r1 = 1; R2 r2 = 2){}"); } + public void testTryNormal6() { doParserTestJDK7("try(r){}"); } + public void testTryNormal7() { doParserTestJDK7("try(r; null){}"); } public void testTryIncomplete0() { doParserTest("try"); } public void testTryIncomplete1() { doParserTest("try{}"); } public void testTryIncomplete2() { doParserTest("try{}catch"); } @@ -136,7 +138,7 @@ public class StatementParserTest extends JavaParsingTestCase { public void testTryIncomplete11() { doParserTestJDK7("try(){}"); } public void testTryIncomplete12() { doParserTestJDK7("try(;){}"); } public void testTryIncomplete13() { doParserTestJDK7("try(final ){}"); } - public void testTryIncomplete14() { doParserTestJDK7("try(R){}"); } + public void testTryIncomplete14() { doParserTestJDK7("try(int){}"); } public void testTryIncomplete15() { doParserTestJDK7("try(R r){}"); } public void testTryIncomplete16() { doParserTestJDK7("try(R r =){}"); } public void testTryIncomplete17() { doParserTestJDK7("try(R r = 0;){}"); } diff --git a/java/openapi/src/com/intellij/psi/JavaElementVisitor.java b/java/openapi/src/com/intellij/psi/JavaElementVisitor.java index 810755020371..6325cc5fcd59 100644 --- a/java/openapi/src/com/intellij/psi/JavaElementVisitor.java +++ b/java/openapi/src/com/intellij/psi/JavaElementVisitor.java @@ -238,7 +238,7 @@ public abstract class JavaElementVisitor extends PsiElementVisitor { * of this method we can easily stuck with exponential algorithm if the derived visitor * extends visitElement() and accepts children there. * PsiRecursiveElement visitor works that around and implements this method accordingly. - * All other visitor must decide themselves what implementation (visitReferenceElement() or visitExpreission() or none or LOG.error()) + * All other visitor must decide themselves what implementation (visitReferenceElement() or visitExpression() or none or LOG.error()) * is appropriate for them. * @param expression */ @@ -296,6 +296,10 @@ public abstract class JavaElementVisitor extends PsiElementVisitor { visitElement(section); } + public void visitResourceList(PsiResourceList resourceList) { + visitElement(resourceList); + } + public void visitTypeElement(PsiTypeElement type) { visitElement(type); } diff --git a/java/openapi/src/com/intellij/psi/PsiResourceList.java b/java/openapi/src/com/intellij/psi/PsiResourceList.java new file mode 100644 index 000000000000..55b5cb12b863 --- /dev/null +++ b/java/openapi/src/com/intellij/psi/PsiResourceList.java @@ -0,0 +1,44 @@ +/* + * Copyright 2000-2011 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 com.intellij.psi; + +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * Represents a resource list of try-with-resources statement (automatic resource management) introduced in JDK 7. + * + * @see PsiTryStatement#getResourceList() + * @since 10.5. + */ +public interface PsiResourceList extends PsiElement { + /** + * Returns list of resource elements. Each element is either {@link PsiLocalVariable} or {@link PsiExpression}. + * + * @return list of resource elements. + */ + @NotNull + List getResources(); + + /** + * Returns list of named resource elements only. + * + * @return list of named resource elements. + */ + @NotNull + List getNamedResources(); +} diff --git a/java/openapi/src/com/intellij/psi/PsiTryStatement.java b/java/openapi/src/com/intellij/psi/PsiTryStatement.java index 91375d343340..dd5574b5d322 100644 --- a/java/openapi/src/com/intellij/psi/PsiTryStatement.java +++ b/java/openapi/src/com/intellij/psi/PsiTryStatement.java @@ -71,5 +71,5 @@ public interface PsiTryStatement extends PsiStatement { * @return resource list, or null if the statement doesn't have it. */ @Nullable - PsiParameterList getResourceList(); + PsiResourceList getResourceList(); } diff --git a/java/openapi/src/com/intellij/psi/util/PsiUtil.java b/java/openapi/src/com/intellij/psi/util/PsiUtil.java index f34dfee9b11d..de515c55ca48 100644 --- a/java/openapi/src/com/intellij/psi/util/PsiUtil.java +++ b/java/openapi/src/com/intellij/psi/util/PsiUtil.java @@ -15,6 +15,7 @@ */ package com.intellij.psi.util; +import com.intellij.openapi.diagnostic.LogUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.openapi.util.Comparing; @@ -635,6 +636,19 @@ public final class PsiUtil extends PsiUtilBase { return PsiTreeUtil.getParentOfType(element, PsiDocComment.class, true) != null; } + public static boolean isResourceInTryStatement(final PsiElement element) { + return (element instanceof PsiLocalVariable || element instanceof PsiExpression) && + element.getParent() instanceof PsiResourceList; + } + + @Nullable + public static PsiType getResourceType(final PsiElement element) { + if (element == null || !(element.getParent() instanceof PsiResourceList)) return null; + if (element instanceof PsiLocalVariable) return ((PsiLocalVariable)element).getType(); + if (element instanceof PsiExpression) return ((PsiExpression)element).getType(); + LOG.error("Unexpected resource type: " + LogUtil.objectAndClass(element)); + return null; + } private static class ParamWriteProcessor implements Processor { private volatile boolean myIsWriteRefFound = false; @@ -651,6 +665,7 @@ public final class PsiUtil extends PsiUtilBase { return myIsWriteRefFound; } } + public static boolean isAssigned(final PsiParameter parameter) { ParamWriteProcessor processor = new ParamWriteProcessor(); ReferencesSearch.search(parameter, new LocalSearchScope(parameter.getDeclarationScope()), true).forEach(processor); @@ -717,7 +732,7 @@ public final class PsiUtil extends PsiUtilBase { } } - /** + /* * Returns iterator of type parameters visible in owner. Type parameters are iterated in * inner-to-outer, right-to-left order. */ diff --git a/platform/lang-api/src/com/intellij/psi/util/PsiTreeUtil.java b/platform/lang-api/src/com/intellij/psi/util/PsiTreeUtil.java index 92a835d850a4..91063c18bf59 100644 --- a/platform/lang-api/src/com/intellij/psi/util/PsiTreeUtil.java +++ b/platform/lang-api/src/com/intellij/psi/util/PsiTreeUtil.java @@ -312,6 +312,22 @@ public class PsiTreeUtil { return null; } + @NotNull + public static List getChildrenOfAnyType(@Nullable final PsiElement element, + @Nullable final Class... classes) { + if (element == null || classes == null || classes.length == 0) return Collections.emptyList(); + + final List result = new SmartList(); + for (PsiElement child = element.getFirstChild(); child != null; child = child.getNextSibling()) { + for (Class aClass : classes) { + if (aClass.isInstance(child)) { + result.add(child); + } + } + } + return result; + } + @Nullable public static T getNextSiblingOfType(@Nullable PsiElement sibling, @NotNull Class aClass) { if (sibling == null) return null; From 991df2761b644883210383fc5dac8f04c235a808 Mon Sep 17 00:00:00 2001 From: Roman Chernyatchik Date: Mon, 21 Feb 2011 21:10:10 +0300 Subject: [PATCH 052/169] cmdline launcher should use "open -a" cmd on MacOS, otherwise at least 32/64 bit mode setting wont be correct. --- .../ide/actions/CreateLauncherScriptAction.java | 3 ++- platform/platform-resources/src/launcher.py | 13 ++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java b/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java index c4091286e937..223f1a11a8ef 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java @@ -137,7 +137,8 @@ public class CreateLauncherScriptAction extends AnAction { String homePath = PathManager.getHomePath(); String productName = ApplicationNamesInfo.getInstance().getProductName().toLowerCase(); if (SystemInfo.isMac) { - launcherContents = launcherContents.replace("$RUN_PATH$", homePath + "/Contents/MacOS/" + productName); + // Just use "*.app" + launcherContents = launcherContents.replace("$RUN_PATH$", homePath); } else { launcherContents = launcherContents.replace("$RUN_PATH$", homePath + "/bin/" + productName + ".sh"); diff --git a/platform/platform-resources/src/launcher.py b/platform/platform-resources/src/launcher.py index 0bcc36326934..79183be49cef 100644 --- a/platform/platform-resources/src/launcher.py +++ b/platform/platform-resources/src/launcher.py @@ -69,6 +69,13 @@ if port == -1: else: if launch_with_port(port): exit() -bin_dir, bin_file = os.path.split(RUN_PATH) -os.chdir(bin_dir) -os.execv(bin_file, [bin_file] + args) +if sys.platform == "darwin": + # Mac OS: RUN_PATH is *.app path + if len(args): + args.insert(0, "--args") + os.execvp("open", ["-a", RUN_PATH] + args) +else: + # unix common + bin_dir, bin_file = os.path.split(RUN_PATH) + os.chdir(bin_dir) + os.execv(bin_file, [bin_file] + args) From 4a16b2899e78ca1c5f17113fde73225169709d8b Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 21 Feb 2011 20:23:52 +0100 Subject: [PATCH 053/169] refactoring: enum set of regexp capabilities instead of a bunch of boolean flags --- .../lang/regexp/RegExpCapability.java | 27 +++++++++++++++++++ .../org/intellij/lang/regexp/RegExpLexer.java | 7 ++--- .../intellij/lang/regexp/RegExpParser.java | 19 ++++++------- .../lang/regexp/RegExpParserDefinition.java | 4 ++- .../org/intellij/lang/regexp/_RegExLexer.java | 18 +++++++------ .../intellij/lang/regexp/regexp-lexer.flex | 14 +++++----- 6 files changed, 62 insertions(+), 27 deletions(-) create mode 100644 RegExpSupport/src/org/intellij/lang/regexp/RegExpCapability.java diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpCapability.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpCapability.java new file mode 100644 index 000000000000..26c1ccf41c69 --- /dev/null +++ b/RegExpSupport/src/org/intellij/lang/regexp/RegExpCapability.java @@ -0,0 +1,27 @@ +/* + * Copyright 2000-2011 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.intellij.lang.regexp; + +/** + * @author yole + */ +public enum RegExpCapability { + XML_SCHEMA_MODE, + DANGLING_METACHARACTERS, + NESTED_CHARACTER_CLASSES, + OCTAL_NO_LEADING_ZERO, + OMIT_NUMBERS_IN_QUANTIFIERS +} diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java index 25d3c1e44769..b31c686402f6 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java @@ -17,13 +17,14 @@ package org.intellij.lang.regexp; import com.intellij.lexer.FlexAdapter; +import java.util.EnumSet; + public class RegExpLexer extends FlexAdapter { private static final int COMMENT_MODE = 1 << 14; - public RegExpLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters, boolean allowNestedCharacterClasses, - boolean allowOctalNoLeadingZero) { - super(new _RegExLexer(xmlSchemaMode, allowDanglingMetacharacters, allowNestedCharacterClasses, allowOctalNoLeadingZero)); + public RegExpLexer(EnumSet capabilities) { + super(new _RegExLexer(capabilities)); } public void start(CharSequence buffer, int startOffset, int endOffset, int initialState) { diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpParser.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpParser.java index d5d576b36df1..e0e06d940d10 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/RegExpParser.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/RegExpParser.java @@ -23,17 +23,18 @@ import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.EnumSet; + @SuppressWarnings({"RedundantIfStatement"}) public class RegExpParser implements PsiParser { - private boolean myAllowDanglingMetacharacters; - private boolean myAllowOmitNumbersInQuantifiers; + private final EnumSet myCapabilities; - public void setAllowDanglingMetacharacters(boolean allowDanglingMetacharacters) { - myAllowDanglingMetacharacters = allowDanglingMetacharacters; + public RegExpParser() { + myCapabilities = EnumSet.noneOf(RegExpCapability.class); } - public void setAllowOmitNumbersInQuantifiers(boolean allowOmitNumbersInQuantifiers) { - myAllowOmitNumbersInQuantifiers = allowOmitNumbersInQuantifiers; + public RegExpParser(EnumSet capabilities) { + myCapabilities = capabilities; } @NotNull @@ -136,11 +137,11 @@ public class RegExpParser implements PsiParser { if (builder.getTokenType() == RegExpTT.LBRACE) { builder.advanceLexer(); boolean minOmitted = false; - if (builder.getTokenType() == RegExpTT.COMMA && myAllowOmitNumbersInQuantifiers) { + if (builder.getTokenType() == RegExpTT.COMMA && myCapabilities.contains(RegExpCapability.OMIT_NUMBERS_IN_QUANTIFIERS)) { minOmitted = true; builder.advanceLexer(); } - else if (builder.getTokenType() != RegExpTT.NUMBER && myAllowDanglingMetacharacters) { + else if (builder.getTokenType() != RegExpTT.NUMBER && myCapabilities.contains(RegExpCapability.DANGLING_METACHARACTERS)) { marker.done(RegExpTT.CHARACTER); return true; } @@ -432,7 +433,7 @@ public class RegExpParser implements PsiParser { marker.drop(); return parseClass(builder); } - else if (type == RegExpTT.LBRACE && myAllowDanglingMetacharacters) { + else if (type == RegExpTT.LBRACE && myCapabilities.contains(RegExpCapability.DANGLING_METACHARACTERS)) { builder.advanceLexer(); marker.done(RegExpElementTypes.CHAR); } diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpParserDefinition.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpParserDefinition.java index c247579512b1..2148acb3bb13 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/RegExpParserDefinition.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/RegExpParserDefinition.java @@ -31,12 +31,14 @@ import com.intellij.psi.tree.TokenSet; import org.intellij.lang.regexp.psi.impl.*; import org.jetbrains.annotations.NotNull; +import java.util.EnumSet; + public class RegExpParserDefinition implements ParserDefinition { private static final TokenSet COMMENT_TOKENS = TokenSet.create(RegExpTT.COMMENT); @NotNull public Lexer createLexer(Project project) { - return new RegExpLexer(false, false, true, false); + return new RegExpLexer(EnumSet.of(RegExpCapability.NESTED_CHARACTER_CLASSES)); } public PsiParser createParser(Project project) { diff --git a/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java b/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java index ad78d535bdc6..ad58411c892c 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java @@ -1,4 +1,4 @@ -/* The following code was generated by JFlex 1.4.3 on 21.02.11 19:21 */ +/* The following code was generated by JFlex 1.4.3 on 21.02.11 20:18 */ /* It's an automatically generated code. Do not modify it. */ package org.intellij.lang.regexp; @@ -6,6 +6,7 @@ package org.intellij.lang.regexp; import com.intellij.lexer.FlexLexer; import com.intellij.psi.tree.IElementType; import java.util.LinkedList; +import java.util.EnumSet; import com.intellij.psi.StringEscapesTokenTypes; // IDEADEV-11055 @@ -14,7 +15,7 @@ import com.intellij.psi.StringEscapesTokenTypes; /** * This class is a scanner generated by * JFlex 1.4.3 - * on 21.02.11 19:21 from the specification file + * on 21.02.11 20:18 from the specification file * C:/JetBrains/IDEA/tools/lexer/../../community/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex */ class _RegExLexer implements FlexLexer { @@ -367,19 +368,20 @@ class _RegExLexer implements FlexLexer { private final LinkedList states = new LinkedList(); // This was an idea to use the regex implementation for XML schema regexes (which use a slightly different syntax) - // as well, but is currently unfinished as it requires to tweak more places than just the lexer. + // as well, but is currently unfinished as it requires to tweak more places than just the lexer. private boolean xmlSchemaMode; + private boolean allowDanglingMetacharacters; private boolean allowNestedCharacterClasses; private boolean allowOctalNoLeadingZero; - _RegExLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters, boolean allowNestedCharacterClasses, boolean allowOctalNoLeadingZero) { + _RegExLexer(EnumSet capabilities) { this((java.io.Reader)null); - this.xmlSchemaMode = xmlSchemaMode; - this.allowDanglingMetacharacters = allowDanglingMetacharacters; - this.allowNestedCharacterClasses = allowNestedCharacterClasses; - this.allowOctalNoLeadingZero = allowOctalNoLeadingZero; + this.xmlSchemaMode = capabilities.contains(RegExpCapability.XML_SCHEMA_MODE); + this.allowDanglingMetacharacters = capabilities.contains(RegExpCapability.DANGLING_METACHARACTERS); + this.allowNestedCharacterClasses = capabilities.contains(RegExpCapability.NESTED_CHARACTER_CLASSES); + this.allowOctalNoLeadingZero = capabilities.contains(RegExpCapability.OCTAL_NO_LEADING_ZERO); } private void yypushstate(int state) { diff --git a/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex b/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex index ac4b4d340838..ac1c0ad48d41 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex +++ b/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex @@ -4,6 +4,7 @@ package org.intellij.lang.regexp; import com.intellij.lexer.FlexLexer; import com.intellij.psi.tree.IElementType; import java.util.LinkedList; +import java.util.EnumSet; import com.intellij.psi.StringEscapesTokenTypes; // IDEADEV-11055 @@ -23,19 +24,20 @@ import com.intellij.psi.StringEscapesTokenTypes; private final LinkedList states = new LinkedList(); // This was an idea to use the regex implementation for XML schema regexes (which use a slightly different syntax) - // as well, but is currently unfinished as it requires to tweak more places than just the lexer. + // as well, but is currently unfinished as it requires to tweak more places than just the lexer. private boolean xmlSchemaMode; + private boolean allowDanglingMetacharacters; private boolean allowNestedCharacterClasses; private boolean allowOctalNoLeadingZero; - _RegExLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters, boolean allowNestedCharacterClasses, boolean allowOctalNoLeadingZero) { + _RegExLexer(EnumSet capabilities) { this((java.io.Reader)null); - this.xmlSchemaMode = xmlSchemaMode; - this.allowDanglingMetacharacters = allowDanglingMetacharacters; - this.allowNestedCharacterClasses = allowNestedCharacterClasses; - this.allowOctalNoLeadingZero = allowOctalNoLeadingZero; + this.xmlSchemaMode = capabilities.contains(RegExpCapability.XML_SCHEMA_MODE); + this.allowDanglingMetacharacters = capabilities.contains(RegExpCapability.DANGLING_METACHARACTERS); + this.allowNestedCharacterClasses = capabilities.contains(RegExpCapability.NESTED_CHARACTER_CLASSES); + this.allowOctalNoLeadingZero = capabilities.contains(RegExpCapability.OCTAL_NO_LEADING_ZERO); } private void yypushstate(int state) { From 7ec009641e41c1aa5b094a53d9e34e4cef8a918a Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 21 Feb 2011 19:10:10 +0100 Subject: [PATCH 054/169] read access (IDEA-65715) --- .../intellij/refactoring/BaseRefactoringProcessor.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java b/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java index 666c20317590..c44e92b0c712 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java +++ b/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java @@ -33,6 +33,7 @@ import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.EmptyRunnable; import com.intellij.openapi.util.Factory; import com.intellij.openapi.util.Ref; @@ -224,7 +225,12 @@ public abstract class BaseRefactoringProcessor { refUsages.set(findUsages()); } }); - final Usage[] usages = UsageInfo2UsageAdapter.convert(refUsages.get()); + final Usage[] usages = ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public Usage[] compute() { + return UsageInfo2UsageAdapter.convert(refUsages.get()); + } + }); for (Usage usage : usages) { processor.process(usage); From 1758aa4e20c3e5addb3f8463576a061822e23165 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 21 Feb 2011 19:26:32 +0100 Subject: [PATCH 055/169] run configurations: do not force user to choose configuration type if plus from conf. type node was pressed (IDEA-65236 ) --- .../execution/impl/RunConfigurable.java | 19 +++++++++++++++++-- .../src/messages/ExecutionBundle.properties | 2 +- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java index c7a4b291ee56..c44d17fc9471 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java @@ -21,6 +21,7 @@ import com.intellij.execution.configuration.ConfigurationFactoryEx; import com.intellij.execution.configurations.*; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.options.*; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; @@ -332,12 +333,26 @@ class RunConfigurable extends BaseConfigurable { ? configurationType.getConfigurationTypeDescription() : ExecutionBundle.message("run.configuration.default.type.description"); browser.setText(ExecutionBundle.message("empty.run.configuration.panel.text.label", font.getFontName(), addUrl, defaultsURL, - configurationTypeDescription)); + configurationTypeDescription, configurationType != null ? configurationType.getId() : "")); browser.setPreferredSize(new Dimension(200, 50)); browser.addHyperlinkListener(new HyperlinkListener() { public void hyperlinkUpdate(final HyperlinkEvent e) { if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - if (Comparing.strEqual(e.getDescription(), "add")) { + final String description = e.getDescription(); + final String addPrefix = "add"; + if (description.startsWith(addPrefix)) { + final String typeId = description.substring(addPrefix.length()); + if (!typeId.isEmpty()) { + for (ConfigurationType type : Extensions.getExtensions(ConfigurationType.CONFIGURATION_TYPE_EP)) { + if (Comparing.strEqual(type.getId(), typeId)) { + final ConfigurationFactory[] factories = type.getConfigurationFactories(); + if (factories.length > 0) { + createNewConfiguration(factories[0]); + } + return; + } + } + } new MyToolbarAddAction().actionPerformed(null); } } diff --git a/platform/platform-resources-en/src/messages/ExecutionBundle.properties b/platform/platform-resources-en/src/messages/ExecutionBundle.properties index 66abc2caa26d..325b17dd811f 100644 --- a/platform/platform-resources-en/src/messages/ExecutionBundle.properties +++ b/platform/platform-resources-en/src/messages/ExecutionBundle.properties @@ -222,7 +222,7 @@ no.applet.class.specified.error.message=No applet class specified no.main.class.specified.error.text=No main class specified action.name.save.configuration=Save Configuration #2 - configuration type description -empty.run.configuration.panel.text.label=

Press the \\  button \ +empty.run.configuration.panel.text.label=

Press the \\  button \ to create a new {3} based on default settings. default.package.presentable.name= default.package.configuration.name=default package From 8f6e4a270c0bfa63a589624d2c8ec47234ae5dfd Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 21 Feb 2011 20:26:01 +0100 Subject: [PATCH 056/169] revert (WI-4622) --- .../intellij/codeInspection/ex/ProblemDescriptorImpl.java | 7 +++++++ .../intellij/codeInspection/ui/InspectionResultsView.java | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/ProblemDescriptorImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/ProblemDescriptorImpl.java index ab434c9165c7..2ae97b01bbbe 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/ProblemDescriptorImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/ProblemDescriptorImpl.java @@ -160,6 +160,13 @@ public class ProblemDescriptorImpl extends CommonProblemDescriptorImpl implement return myEnforcedTextAttributes; } + public TextRange getTextRangeForNavigation() { + TextRange textRange = getTextRange(); + if (textRange == null) return null; + PsiElement element = getPsiElement(); + return InjectedLanguageManager.getInstance(element.getProject()).injectedToHost(element, element.getTextRange()); + } + public TextRange getTextRange() { PsiElement startElement = getStartElement(); PsiElement endElement = myEndSmartPointer == null ? startElement : getEndElement(); diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java index c0008e364fb1..dafc108e254f 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java @@ -645,7 +645,7 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren if (virtualFile != null) { int startOffset = psiElement.getTextOffset(); if (descriptor instanceof ProblemDescriptorImpl) { - final TextRange textRange = ((ProblemDescriptorImpl)descriptor).getTextRange(); + final TextRange textRange = ((ProblemDescriptorImpl)descriptor).getTextRangeForNavigation(); if (textRange != null) { if (virtualFile instanceof VirtualFileWindow) { virtualFile = ((VirtualFileWindow)virtualFile).getDelegate(); From c884d5eca6d2c981994c541f316f26c155022a8b Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 21 Feb 2011 21:03:54 +0100 Subject: [PATCH 057/169] separate language for python regexps with verbose flag set, set commentMode to true by default (PY-2941) --- .../src/org/intellij/lang/regexp/RegExpCapability.java | 3 ++- .../src/org/intellij/lang/regexp/RegExpHighlighter.java | 2 +- RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java | 6 ++++-- RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java | 5 +++-- .../src/org/intellij/lang/regexp/regexp-lexer.flex | 1 + 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpCapability.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpCapability.java index 26c1ccf41c69..2a10039ba12b 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/RegExpCapability.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/RegExpCapability.java @@ -23,5 +23,6 @@ public enum RegExpCapability { DANGLING_METACHARACTERS, NESTED_CHARACTER_CLASSES, OCTAL_NO_LEADING_ZERO, - OMIT_NUMBERS_IN_QUANTIFIERS + OMIT_NUMBERS_IN_QUANTIFIERS, + COMMENT_MODE } diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpHighlighter.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpHighlighter.java index 17da2ae193b4..16ae1f322d28 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/RegExpHighlighter.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/RegExpHighlighter.java @@ -30,7 +30,7 @@ import org.jetbrains.annotations.NotNull; import java.util.HashMap; import java.util.Map; -class RegExpHighlighter extends SyntaxHighlighterBase { +public class RegExpHighlighter extends SyntaxHighlighterBase { private static final Map keys1; private static final Map keys2; diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java index b31c686402f6..c37f576a885b 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/RegExpLexer.java @@ -22,13 +22,15 @@ import java.util.EnumSet; public class RegExpLexer extends FlexAdapter { private static final int COMMENT_MODE = 1 << 14; + private final EnumSet myCapabilities; public RegExpLexer(EnumSet capabilities) { super(new _RegExLexer(capabilities)); - } + myCapabilities = capabilities; + } public void start(CharSequence buffer, int startOffset, int endOffset, int initialState) { - getFlex().commentMode = (initialState & COMMENT_MODE) != 0; + getFlex().commentMode = (initialState & COMMENT_MODE) != 0 || myCapabilities.contains(RegExpCapability.COMMENT_MODE); super.start(buffer, startOffset, endOffset, initialState & ~COMMENT_MODE); } diff --git a/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java b/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java index ad58411c892c..4381a383a338 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/_RegExLexer.java @@ -1,4 +1,4 @@ -/* The following code was generated by JFlex 1.4.3 on 21.02.11 20:18 */ +/* The following code was generated by JFlex 1.4.3 on 21.02.11 20:37 */ /* It's an automatically generated code. Do not modify it. */ package org.intellij.lang.regexp; @@ -15,7 +15,7 @@ import com.intellij.psi.StringEscapesTokenTypes; /** * This class is a scanner generated by * JFlex 1.4.3 - * on 21.02.11 20:18 from the specification file + * on 21.02.11 20:37 from the specification file * C:/JetBrains/IDEA/tools/lexer/../../community/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex */ class _RegExLexer implements FlexLexer { @@ -382,6 +382,7 @@ class _RegExLexer implements FlexLexer { this.allowDanglingMetacharacters = capabilities.contains(RegExpCapability.DANGLING_METACHARACTERS); this.allowNestedCharacterClasses = capabilities.contains(RegExpCapability.NESTED_CHARACTER_CLASSES); this.allowOctalNoLeadingZero = capabilities.contains(RegExpCapability.OCTAL_NO_LEADING_ZERO); + this.commentMode = capabilities.contains(RegExpCapability.COMMENT_MODE); } private void yypushstate(int state) { diff --git a/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex b/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex index ac1c0ad48d41..e42ae56cdef0 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex +++ b/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex @@ -38,6 +38,7 @@ import com.intellij.psi.StringEscapesTokenTypes; this.allowDanglingMetacharacters = capabilities.contains(RegExpCapability.DANGLING_METACHARACTERS); this.allowNestedCharacterClasses = capabilities.contains(RegExpCapability.NESTED_CHARACTER_CLASSES); this.allowOctalNoLeadingZero = capabilities.contains(RegExpCapability.OCTAL_NO_LEADING_ZERO); + this.commentMode = capabilities.contains(RegExpCapability.COMMENT_MODE); } private void yypushstate(int state) { From 80e2631a1870e7c5daebe41bbbae3717588fcebc Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 21 Feb 2011 16:38:26 +0100 Subject: [PATCH 058/169] diagnostics --- .../codeInsight/completion/CompletionProgressIndicator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java index 9336b40c3c3b..ab766b30cb10 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java @@ -392,10 +392,10 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement public void closeAndFinish(boolean hideLookup) { final CompletionProgressIndicator current = CompletionServiceImpl.getCompletionService().getCurrentCompletion(); - LOG.assertTrue(this == current, current); + LOG.assertTrue(this == current, current + "!=" + this); Lookup lookup = LookupManager.getActiveLookup(myEditor); - LOG.assertTrue(lookup == myLookup, lookup); + LOG.assertTrue(lookup == myLookup, lookup + "; " + this); myLookup.removeLookupListener(myLookupListener); finishCompletionProcess(); CompletionServiceImpl.assertPhase(CompletionPhase.NoCompletion.getClass()); From 07fb0d8b67eb4a1989348b2e40796825267f2f44 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 21 Feb 2011 17:04:37 +0100 Subject: [PATCH 059/169] EA-25606 diagnostics for invalid PSI in dom highlighting --- .../highlighting/DomElementProblemDescriptorImpl.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/xml/dom-impl/src/com/intellij/util/xml/highlighting/DomElementProblemDescriptorImpl.java b/xml/dom-impl/src/com/intellij/util/xml/highlighting/DomElementProblemDescriptorImpl.java index 7e6fd84aeefe..479ccd79ef66 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/highlighting/DomElementProblemDescriptorImpl.java +++ b/xml/dom-impl/src/com/intellij/util/xml/highlighting/DomElementProblemDescriptorImpl.java @@ -26,10 +26,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; -import com.intellij.psi.xml.XmlAttributeValue; -import com.intellij.psi.xml.XmlElement; -import com.intellij.psi.xml.XmlTag; -import com.intellij.psi.xml.XmlText; +import com.intellij.psi.xml.*; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.xml.DomElement; import com.intellij.util.xml.GenericAttributeValue; @@ -88,6 +85,7 @@ public class DomElementProblemDescriptorImpl implements DomElementProblemDescrip if (textRange != null) { final PsiElement psiElement = getPsiElement(); LOG.assertTrue(psiElement != null, "Problems with explicit text range can't be created for DOM elements without underlying XML element"); + assert psiElement.isValid(); myPair = new Pair(textRange, psiElement); } myHighlightType = highlightType; @@ -124,10 +122,12 @@ public class DomElementProblemDescriptorImpl implements DomElementProblemDescrip public void highlightWholeElement() { final PsiElement psiElement = getPsiElement(); if (psiElement instanceof XmlAttributeValue) { + assert psiElement.isValid() : psiElement; final PsiElement attr = psiElement.getParent(); myPair = Pair.create(new TextRange(0, attr.getTextLength()), attr); } else if (psiElement != null) { + assert psiElement.isValid() : psiElement; final XmlTag tag = (XmlTag)(psiElement instanceof XmlTag ? psiElement : psiElement.getParent()); myPair = new Pair(new TextRange(0, tag.getTextLength()), tag); } @@ -137,6 +137,7 @@ public class DomElementProblemDescriptorImpl implements DomElementProblemDescrip if (myPair == null) { myPair = computeProblemRange(); } + assert myPair.second.isValid(); return myPair; } @@ -145,6 +146,7 @@ public class DomElementProblemDescriptorImpl implements DomElementProblemDescrip final PsiElement element = getPsiElement(); if (element != null) { + assert element.isValid() : element; if (element instanceof XmlTag) { return createTagNameRange((XmlTag)element); } From ca8aaed24f2023bd2c2cad388ed2bbac028d269b Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 21 Feb 2011 18:01:47 +0100 Subject: [PATCH 060/169] remove non-meaningful hint requirements --- .../src/com/intellij/codeInsight/lookup/impl/LookupImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java index ca3956129aee..b3f576c62ef8 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java @@ -1149,7 +1149,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { editor.getContentComponent() ); - final HintHint hintHint = new HintHint(editor, editorPoint).setHighlighterType(true).setContentActive(true); + final HintHint hintHint = new HintHint(editor, editorPoint); final HintManagerImpl hintManager = HintManagerImpl.getInstanceImpl(); if (myAutopopupHint == null) { From d91749f4c387e2cac96b3836f4146cf76ba6a982 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 21 Feb 2011 20:23:10 +0100 Subject: [PATCH 061/169] IDEA-65234 Smart Completion: suggest most-probable method for delegation --- .../completion/RecursionWeigher.java | 8 ++--- .../normalSorting/PreferSameNamedMethods.java | 15 ++++++++++ .../PreferSameNamedMethods.java | 30 +++++++++++++++++++ .../NormalCompletionOrderingTest.java | 4 +++ .../SmartTypeCompletionOrderingTest.java | 4 +++ 5 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/normalSorting/PreferSameNamedMethods.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferSameNamedMethods.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/RecursionWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/RecursionWeigher.java index 4eb4fc592ad4..c481bd86145b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/RecursionWeigher.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/RecursionWeigher.java @@ -79,11 +79,11 @@ public class RecursionWeigher extends CompletionWeigher { if (object instanceof PsiMethod && positionMethod != null) { final PsiMethod method = (PsiMethod)object; if (PsiTreeUtil.isAncestor(reference, position, false) && - Comparing.equal(method.getName(), positionMethod.getName()) && - method.getParameterList().getParametersCount() == positionMethod.getParameterList().getParametersCount()) { - if (findDeepestSuper(method).equals(findDeepestSuper(positionMethod))) { - return isDelegate ? Result.delegation : Result.recursive; + Comparing.equal(method.getName(), positionMethod.getName())) { + if (!isDelegate && findDeepestSuper(method).equals(findDeepestSuper(positionMethod))) { + return Result.recursive; } + return RecursionWeigher.Result.delegation; } } diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/PreferSameNamedMethods.java b/java/java-tests/testData/codeInsight/completion/normalSorting/PreferSameNamedMethods.java new file mode 100644 index 000000000000..03d1003a0b7f --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normalSorting/PreferSameNamedMethods.java @@ -0,0 +1,15 @@ +class Goo { + int boo() {} + int doo() {} + int foo() {} +} + +class Foooo { + Goo g; + + int foo() { + return g. + } + +} + diff --git a/java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferSameNamedMethods.java b/java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferSameNamedMethods.java new file mode 100644 index 000000000000..fff5241c35a8 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferSameNamedMethods.java @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2011 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. + */ +class Goo { + int boo() {} + int doo() {} + int foo() {} +} + +class Foooo { + Goo g; + + int foo() { + return g. + } + +} + diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.java index e3b88bd2b5e5..7da3343c047e 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.java @@ -201,4 +201,8 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase { assertFalse(getLookup().getItems().get(0).getObject() instanceof PsiClass); } + public void testPreferSameNamedMethods() { + checkPreferredItems(0, "foo", "boo", "doo", "hashCode"); + } + } \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.java index 319811803680..963a4bebb9b2 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.java @@ -235,6 +235,10 @@ public class SmartTypeCompletionOrderingTest extends CompletionSortingTestCase { assertPreferredItems(0, "myFoo", "myBar"); } + public void testPreferSameNamedMethods() { + checkPreferredItems(0, "foo", "boo", "doo", "hashCode"); + } + @Override protected String getBasePath() { return JavaTestUtil.getRelativeJavaTestDataPath() + BASE_PATH; From ab4660c7acaa380ed11f4b297c66811a1ca7ffe4 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 21 Feb 2011 20:36:57 +0100 Subject: [PATCH 062/169] IDEA-46653 Completion in parameter list should not insert a trailing comma if the following parameter is varargs --- .../com/intellij/codeInsight/ExpectedTypesProvider.java | 2 +- .../completion/smartType/NoCommaBeforeVarargs-out.java | 8 ++++++++ .../completion/smartType/NoCommaBeforeVarargs.java | 8 ++++++++ .../codeInsight/completion/SmartTypeCompletionTest.java | 2 ++ 4 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/NoCommaBeforeVarargs-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/NoCommaBeforeVarargs.java diff --git a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java index beaa799fa0fb..3f818584c3d4 100644 --- a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java @@ -953,7 +953,7 @@ public class ExpectedTypesProvider { if (index >= params.length) { return TailType.NONE; } - if (index == params.length - 1) { + if (index == params.length - 1 || index == params.length - 2 && params[index + 1].isVarArgs()) { //myTailType = CompletionUtil.NONE_TAIL; final PsiElement call = argument.getParent().getParent(); if (call instanceof JspMethodCall) return TailType.NONE; diff --git a/java/java-tests/testData/codeInsight/completion/smartType/NoCommaBeforeVarargs-out.java b/java/java-tests/testData/codeInsight/completion/smartType/NoCommaBeforeVarargs-out.java new file mode 100644 index 000000000000..3d0404d5ba78 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/NoCommaBeforeVarargs-out.java @@ -0,0 +1,8 @@ +class Foooo { + int bar(int a, Object... varargs) {} + + int foo() { + bar(hashCode()); + } + +} diff --git a/java/java-tests/testData/codeInsight/completion/smartType/NoCommaBeforeVarargs.java b/java/java-tests/testData/codeInsight/completion/smartType/NoCommaBeforeVarargs.java new file mode 100644 index 000000000000..2d588132a9bf --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/NoCommaBeforeVarargs.java @@ -0,0 +1,8 @@ +class Foooo { + int bar(int a, Object... varargs) {} + + int foo() { + bar(ha); + } + +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java index 61086af10243..ad197fd77080 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java @@ -875,6 +875,8 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase { doTest(); } + public void testNoCommaBeforeVarargs() throws Throwable { doTest(); } + public void testEnumField() throws Throwable { doItemTest(); } From 0955db3442c092b528652cccd7fe11e4da154c36 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 21 Feb 2011 20:44:03 +0100 Subject: [PATCH 063/169] restore field negation by ! --- .../completion/DefaultInsertHandler.java | 16 ------------- .../lookup/VariableLookupItem.java | 23 ++++++++++++++----- .../completion/normal/FieldNegation.java | 7 ++++++ .../normal/FieldNegation_after.java | 7 ++++++ .../completion/NormalCompletionTest.groovy | 2 ++ 5 files changed, 33 insertions(+), 22 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/normal/FieldNegation.java create mode 100644 java/java-tests/testData/codeInsight/completion/normal/FieldNegation_after.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/DefaultInsertHandler.java b/java/java-impl/src/com/intellij/codeInsight/completion/DefaultInsertHandler.java index 1688020af584..6949e1cc1bb1 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/DefaultInsertHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/DefaultInsertHandler.java @@ -21,7 +21,6 @@ import com.intellij.codeInsight.TailType; import com.intellij.codeInsight.TailTypes; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupItem; -import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -31,7 +30,6 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; -import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; @@ -73,20 +71,6 @@ public class DefaultInsertHandler extends TemplateInsertHandler implements Clone handleParentheses(false, false, tailType, context, state); handleBrackets(item, document, state); - if (item.getObject() instanceof PsiVariable) { - if (completionChar == '!' && PsiType.BOOLEAN.isAssignableFrom(((PsiVariable) item.getObject()).getType())) { - PsiDocumentManager.getInstance(project).commitDocument(document); - final PsiReferenceExpression ref = - PsiTreeUtil.findElementOfClassAtOffset(file, state.tailOffset - 1, PsiReferenceExpression.class, false); - if (ref != null) { - FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.EXCLAMATION_FINISH); - document.insertString(ref.getTextRange().getStartOffset(), "!"); - state.caretOffset++; - state.tailOffset++; - } - } - } - context.setTailOffset(state.tailOffset); state.caretOffset = processTail(tailType, state.caretOffset, state.tailOffset, editor); editor.getSelectionModel().removeSelection(); diff --git a/java/java-impl/src/com/intellij/codeInsight/lookup/VariableLookupItem.java b/java/java-impl/src/com/intellij/codeInsight/lookup/VariableLookupItem.java index 2bf42fcb0e3d..ff9c2f13df50 100644 --- a/java/java-impl/src/com/intellij/codeInsight/lookup/VariableLookupItem.java +++ b/java/java-impl/src/com/intellij/codeInsight/lookup/VariableLookupItem.java @@ -2,10 +2,11 @@ package com.intellij.codeInsight.lookup; import com.intellij.codeInsight.AutoPopupController; import com.intellij.codeInsight.TailType; +import com.intellij.codeInsight.completion.CodeCompletionFeatures; import com.intellij.codeInsight.completion.InsertionContext; -import com.intellij.psi.PsiSubstitutor; -import com.intellij.psi.PsiType; -import com.intellij.psi.PsiVariable; +import com.intellij.featureStatistics.FeatureUsageTracker; +import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; /** @@ -34,17 +35,27 @@ public class VariableLookupItem extends LookupItem implements Typed public void handleInsert(InsertionContext context) { super.handleInsert(context); - if (context.getCompletionChar() == '=') { + final char completionChar = context.getCompletionChar(); + if (completionChar == '=') { context.setAddCompletionChar(false); TailType.EQ.processTail(context.getEditor(), context.getTailOffset()); } - else if (context.getCompletionChar() == ',' && getAttribute(LookupItem.TAIL_TYPE_ATTR) != TailType.UNKNOWN) { + else if (completionChar == ',' && getAttribute(LookupItem.TAIL_TYPE_ATTR) != TailType.UNKNOWN) { context.setAddCompletionChar(false); TailType.COMMA.processTail(context.getEditor(), context.getTailOffset()); } - else if (context.getCompletionChar() == '.') { + else if (completionChar == '.') { AutoPopupController.getInstance(context.getProject()).autoPopupMemberLookup(context.getEditor(), null); } + else if (completionChar == '!' && PsiType.BOOLEAN.isAssignableFrom(getObject().getType())) { + context.setAddCompletionChar(false); + final PsiReferenceExpression ref = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getTailOffset() - 1, PsiReferenceExpression.class, false); + if (ref != null) { + FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.EXCLAMATION_FINISH); + context.getDocument().insertString(ref.getTextRange().getStartOffset(), "!"); + } + } + } } diff --git a/java/java-tests/testData/codeInsight/completion/normal/FieldNegation.java b/java/java-tests/testData/codeInsight/completion/normal/FieldNegation.java new file mode 100644 index 000000000000..7379f0135de7 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/FieldNegation.java @@ -0,0 +1,7 @@ +public class ConstConfig { + public static boolean testMode = false; + + { + if (testx) + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/FieldNegation_after.java b/java/java-tests/testData/codeInsight/completion/normal/FieldNegation_after.java new file mode 100644 index 000000000000..39e4af0ac513 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/FieldNegation_after.java @@ -0,0 +1,7 @@ +public class ConstConfig { + public static boolean testMode = false; + + { + if (!testModex) + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index b32981e99d55..bce6bff004d8 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -582,6 +582,8 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase { checkResult() } + public void testFieldNegation() throws Throwable { doTest('!');} + public void testSuperInConstructor() throws Throwable { doTest(); } From df58d454e5036999de808f05de31b5be5e55e680 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 21 Feb 2011 20:52:17 +0100 Subject: [PATCH 064/169] IDEA-62188 Java: Basic completion doesn't suggest "default" keyword in switch construction --- .../codeInsight/completion/JavaCompletionData.java | 5 +++-- .../codeInsight/completion/normal/DefaultInSwitch.java | 9 +++++++++ .../completion/normal/DefaultInSwitch_after.java | 9 +++++++++ .../codeInsight/completion/NormalCompletionTest.groovy | 1 + 4 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/normal/DefaultInSwitch.java create mode 100644 java/java-tests/testData/codeInsight/completion/normal/DefaultInSwitch_after.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java index faf84cdf482c..bd4597559c47 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java @@ -503,8 +503,9 @@ public class JavaCompletionData extends JavaAwareCompletionData{ new ParentElementFilter(new ClassFilter(PsiSwitchLabelStatement.class)), new LeftNeighbour(new OrFilter( new ParentElementFilter(new ClassFilter(PsiSwitchStatement.class), 2), - new AndFilter(new TextFilter(";", "}", ":"),new ParentElementFilter(new ClassFilter(PsiSwitchStatement.class), 3) - )))))); + new AndFilter(new TextFilter(";", ":"),new ParentElementFilter(new ClassFilter(PsiSwitchStatement.class), 3)), + new AndFilter(new TextFilter("}"), new ParentElementFilter(new ClassFilter(PsiSwitchStatement.class), 4)) + ))))); variant.includeScopeClass(PsiElement.class, false); variant.addCompletion(PsiKeyword.CASE, TailType.SPACE); variant.addCompletion(PsiKeyword.DEFAULT, TailType.CASE_COLON); diff --git a/java/java-tests/testData/codeInsight/completion/normal/DefaultInSwitch.java b/java/java-tests/testData/codeInsight/completion/normal/DefaultInSwitch.java new file mode 100644 index 000000000000..8bfb38e08d3a --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/DefaultInSwitch.java @@ -0,0 +1,9 @@ +public class ConstConfig { + { + switch (a) { + case Foooo: {} + def + + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/DefaultInSwitch_after.java b/java/java-tests/testData/codeInsight/completion/normal/DefaultInSwitch_after.java new file mode 100644 index 000000000000..bbd0330ecd94 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/DefaultInSwitch_after.java @@ -0,0 +1,9 @@ +public class ConstConfig { + { + switch (a) { + case Foooo: {} + default: + + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index bce6bff004d8..488562c7249a 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -583,6 +583,7 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase { } public void testFieldNegation() throws Throwable { doTest('!');} + public void testDefaultInSwitch() throws Throwable { doTest()} public void testSuperInConstructor() throws Throwable { doTest(); From 5d2c3908682fdb9704409317be1dca2aab04b296 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 21 Feb 2011 21:08:53 +0100 Subject: [PATCH 065/169] ignore compilation output --- native/restarter/.gitignore | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 native/restarter/.gitignore diff --git a/native/restarter/.gitignore b/native/restarter/.gitignore new file mode 100644 index 000000000000..5f88d71148d0 --- /dev/null +++ b/native/restarter/.gitignore @@ -0,0 +1,8 @@ +Debug +Release +_UpgradeReport_Files +*.suo +*.vcxproj.user +UpgradeLog.xml +ipch +*.sdf From f61be4d32997ad5555b6138fb6e5eddc5b8a5b59 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Mon, 21 Feb 2011 22:31:47 +0100 Subject: [PATCH 066/169] text formatting --- .../siyeh/InspectionGadgetsBundle.properties | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties index 8cad05468417..ff04edd0437a 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties @@ -387,15 +387,15 @@ anonymous.class.parameter.hides.containing.method.variable.problem.descriptor=An anonymous.class.field.hides.containing.method.variable.problem.descriptor=Anonymous class field #ref hides variable in containing method #loc anonymous.class.variable.hides.containing.method.variable.problem.descriptor=Anonymous class local variable #ref hides variable in containing method #loc channel.opened.not.closed.display.name=Channel opened but not safely closed -channel.opened.not.closed.problem.descriptor=''{0}'' should be opened in front of a try block and closed in the corresponding finally block #loc +channel.opened.not.closed.problem.descriptor=''{0}'' should be opened in front of a ''try'' block and closed in the corresponding ''finally'' block #loc drivermanager.call.display.name=Use of DriverManager to get JDBC connection drivermanager.call.problem.descriptor=Call to DriverManager.#ref() #loc hibernate.resource.opened.not.closed.display.name=Hibernate resource opened but not safely closed -hibernate.resource.opened.not.closed.problem.descriptor=''{0}'' should be opened in front of a try block and closed in the corresponding finally block #loc +hibernate.resource.opened.not.closed.problem.descriptor=''{0}'' should be opened in front of a ''try'' block and closed in the corresponding ''finally'' block #loc i.o.resource.opened.not.closed.display.name=I/O resource opened but not safely closed -resource.opened.not.closed.problem.descriptor=''{0}'' should be opened in front of a try block and closed in the corresponding finally block #loc +resource.opened.not.closed.problem.descriptor=''{0}'' should be opened in front of a ''try'' block and closed in the corresponding ''finally'' block #loc jdbc.resource.opened.not.closed.display.name=JDBC resource opened but not safely closed -jdbc.resource.opened.not.closed.problem.descriptor=JDBC ''{0}'' should be opened in front of a try block and closed in the corresponding finally block #loc +jdbc.resource.opened.not.closed.problem.descriptor=JDBC ''{0}'' should be opened in front of a ''try'' block and closed in the corresponding ''finally'' block #loc jndi.resource.opened.not.closed.display.name=JNDI resource opened but not safely closed socket.opened.not.closed.display.name=Socket opened but not safely closed annotation.class.display.name=Annotation class @@ -674,7 +674,7 @@ c.style.array.declaration.display.name=C-style array declaration final.method.in.final.class.display.name='final' method in 'final' class extends.annotation.display.name=Class extends annotation interface naked.notify.display.name='notify()' or 'notifyAll()' without corresponding state change -constant.if.statement.display.name=Constant if statement +constant.if.statement.display.name=Constant 'if' statement switch.statement.density.display.name='switch' statement with too low of a branch density switch.statement.with.too.few.branches.display.name='switch' statement with too few branches upper.case.field.name.not.constant.display.name=Non-constant field with upper-case name @@ -691,7 +691,7 @@ system.set.security.manager.problem.descriptor=Call to System.#ref()#ref() can b floating.point.equality.problem.descriptor=#ref: floating point values compared for exact equality #loc fallthru.in.switch.statement.problem.descriptor=#ref fallthrough in 'switch' statement #loc switch.statements.without.default.problem.descriptor=#ref statement without 'default' branch #loc -default.not.last.case.in.switch.problem.descriptor=#ref branch not last case in 'switch' #loc +default.not.last.case.in.switch.problem.descriptor=#ref branch not last case in 'switch' statement #loc loop.statements.that.dont.loop.problem.descriptor=#ref statement does not loop #loc conditional.expression.with.identical.branches.problem.descriptor=Conditional expression #ref with identical branches #loc if.statement.with.identical.branches.problem.descriptor=#ref statement with identical branches #loc @@ -890,7 +890,7 @@ implicit.call.to.super.problem.descriptor=Implicit call to super() #ref#ref statement with negated condition #loc negated.conditional.problem.descriptor=Conditional expression with negated condition #loc confusing.else.problem.descriptor=#ref branch may be unwrapped, as the if branch never completes #loc -switch.statement.with.confusing.declaration.problem.descriptor=Local variable #ref declared in one switch branch and used in another #loc +switch.statement.with.confusing.declaration.problem.descriptor=Local variable #ref declared in one 'switch' branch and used in another #loc raw.use.of.parameterized.type.problem.descriptor=Raw use of parameterized class #ref #loc final.class.problem.descriptor=Class declared #ref #loc empty.class.problem.descriptor=Class #ref is empty #loc @@ -932,10 +932,10 @@ interface.never.implemented.problem.descriptor=Interface #ref has n missing.deprecated.annotation.problem.descriptor=Missing '@Deprecated' annotation on #ref() #loc missing.override.annotation.problem.descriptor=Missing '@Override' annotation on #ref() #loc non.thread.safe.lazy.initialization.problem.descriptor=Lazy initialization of static field #ref is not thread-safe #loc -catch.generic.class.problem.descriptor=catch of generic #ref class should be replaced with more precise exception #loc +catch.generic.class.problem.descriptor='catch' of generic #ref class should be replaced with more precise exception #loc empty.catch.block.problem.descriptor=Empty #ref block #loc -unused.catch.parameter.problem.descriptor=Unused catch parameter #ref #loc -used.catch.parameter.named.ignore.problem.descriptor=Catch parameter named #ref is used #loc +unused.catch.parameter.problem.descriptor=Unused 'catch' parameter #ref #loc +used.catch.parameter.named.ignore.problem.descriptor='catch' parameter named #ref is used #loc empty.finally.block.problem.descriptor=Empty #ref block #loc finally.block.cannot.complete.normally.problem.descriptor=#ref block can not complete normally #loc empty.try.block.problem.descriptor=Empty #ref block #loc @@ -1142,7 +1142,7 @@ local.variable.naming.convention.problem.descriptor.short=Local variable name #ref is too long #loc local.variable.naming.convention.problem.descriptor.regex.mismatch=Local variable name #ref doesn''t match regex ''{0}'' #loc local.variable.naming.convention.ignore.option=Ignore for-loop parameters -local.variable.naming.convention.ignore.catch.option=Ignore catch block parameters +local.variable.naming.convention.ignore.catch.option=Ignore 'catch' block parameters method.names.differ.only.by.case.problem.descriptor=Method names #ref and ''{0}'' differ only by case #loc parameter.name.differs.from.overridden.parameter.ignore.character.option=Ignore if overridden parameter contains only one character parameter.name.differs.from.overridden.parameter.ignore.library.option=Ignore if overridden parameter is from a library @@ -1204,7 +1204,7 @@ transient.field.in.non.serializable.class.problem.descriptor=Field ''{0}'' is ma transient.field.in.non.serializable.class.remove.quickfix=Remove 'transient' condition.signal.replace.quickfix=Replace with 'signalAll()' object.notify.replace.quickfix=Replace with 'notifyAll()' -safe.lock.problem.descriptor=''{0}'' should be locked in front of a try block and unlocked in the corresponding finally block #loc +safe.lock.problem.descriptor=''{0}'' should be locked in front of a ''try'' block and unlocked in the corresponding ''finally'' block #loc synchronized.method.problem.descriptor=Method ''{0}()'' declared #ref #loc synchronized.method.include.option=Include native methods synchronized.method.move.quickfix=Move synchronization into method @@ -1213,12 +1213,12 @@ volatile.field.problem.descriptor=Volatile field #ref of type ''{0} exception.class.column.name=Exception class bad.exception.thrown.problem.descriptor=Prohibited exception ''{0}'' thrown #loc empty.catch.block.comments.option=Comments count as content -empty.catch.block.ignore.option=Ignore empty catch blocks in tests -empty.catch.block.ignore.ignore.option=Ignore for catch parameters named 'ignore' or 'ignored' -too.broad.catch.problem.descriptor=Catch of #ref is too broad, masking exception ''{0}'' #loc -too.broad.catch.problem.descriptor1=Catch of #ref is too broad, masking exceptions ''{0}'' and ''{1}'' #loc -unused.catch.parameter.ignore.catch.option=Ignore for catch blocks containing comments -unused.catch.parameter.ignore.empty.option=Ignore unused catch parameters in tests +empty.catch.block.ignore.option=Ignore empty 'catch' blocks in tests +empty.catch.block.ignore.ignore.option=Ignore for 'catch' parameters named 'ignore' or 'ignored' +too.broad.catch.problem.descriptor=''catch'' of #ref is too broad, masking exception ''{0}'' #loc +too.broad.catch.problem.descriptor1=''catch'' of #ref is too broad, masking exceptions ''{0}'' and ''{1}'' #loc +unused.catch.parameter.ignore.catch.option=Ignore for 'catch' blocks containing comments +unused.catch.parameter.ignore.empty.option=Ignore unused 'catch' parameters in tests add.serialversionuidfield.quickfix=Add 'serialVersionUID' field delete.import.quickfix=Delete unnecessary import encapsulate.variable.quickfix=Encapsulate variable @@ -1382,7 +1382,7 @@ create.documentation.couldnt.cast.class=Couldn''t cast {0} create.documentation.inspections.enabled.by.default.message=Inspections enabled by default: create.documentation.couldnt.find.documentation.file.error.message=Couldn''t find documentation file: {0} create.documentation.unused.documentation.file.error.message=Unused documentation file: {0} -assignment.to.catch.block.parameter.problem.descriptor=Assignment to catch block parameter #ref #loc +assignment.to.catch.block.parameter.problem.descriptor=Assignment to 'catch' block parameter #ref #loc assignment.to.method.parameter.problem.descriptor=Assignment to method parameter #ref #loc value.of.post.increment.problem.descriptor=Value of post-increment expression #ref is used #loc value.of.post.decrement.problem.descriptor=Value of post-decrement expression #ref is used #loc @@ -1647,14 +1647,14 @@ ignore.guard.clauses=Ignore &guard clauses ignore.for.equals.methods=Ignore for &equals() methods caught.exception.immediately.rethrown.display.name=Caught exception is immediately rethrown caught.exception.immediately.rethrown.problem.descriptor=Caught exception #ref is immediately rethrown #loc -delete.catch.section.quickfix=Delete catch section -remove.try.catch.quickfix=Remove try-catch statement +delete.catch.section.quickfix=Delete 'catch' section +remove.try.catch.quickfix=Remove 'try catch' statement loop.with.implicit.termination.condition.display.name=Loop with implicit termination condition loop.with.implicit.termination.condition.dowhile.problem.descriptor=#ref-while loop with implicit termination condition #loc loop.with.implicit.termination.condition.problem.descriptor=#ref loop with implicit termination condition #loc loop.with.implicit.termination.condition.quickfix=Make condition explicit ignore.iterator.loop.variables=Ignore java.util.Iterator loop variables -rename.catch.parameter.to.ignored=Rename catch parameter to 'ignored' +rename.catch.parameter.to.ignored=Rename 'catch' parameter to 'ignored' unnecessary.super.qualifier.display.name=Unnecessary 'super' qualifier unnecessary.super.qualifier.problem.descriptor=Qualifier #ref is unnecessary in this context #loc unnecessary.super.qualifier.quickfix=Remove unnecessary 'super.' @@ -1664,7 +1664,7 @@ collections.field.access.replaceable.by.method.call.quickfix=Replace with ''{0}' synchronization.on.local.variable.or.method.parameter.display.name=Synchronization on local variable or method parameter synchronization.on.local.variable.problem.descriptor=Synchronization on local variable #ref #loc synchronization.on.method.parameter.problem.descriptor=Synchronization on method parameter #ref #loc -too.broad.catch.quickfix=Add catch clause for ''{0}'' +too.broad.catch.quickfix=Add ''catch'' clause for ''{0}'' too.broad.catch.option=&Only warn on RuntimeException, Exception, Error or Throwable unnecessary.call.to.string.valueof.display.name=Unnecessary call to 'String.valueOf()' unnecessary.call.to.string.valueof.problem.descriptor=#ref can be simplified to ''{0}'' #loc @@ -1710,9 +1710,9 @@ unnecessary.parentheses.conditional.option=Ignore parentheses around the conditi field.may.be.final.display.name=Field may be final field.may.be.final.problem.descriptor=Field #ref may be 'final' #loc cast.that.loses.precision.option=Ignore casts from int to char -variable.not.used.inside.if.display.name=Reference checked for null is not used inside if +variable.not.used.inside.if.display.name=Reference checked for 'null' is not used inside 'if' variable.not.used.inside.if.problem.descriptor=#ref is not used inside if #loc -if.may.be.conditional.display.name=If statement could be replaced with simple conditional expression +if.may.be.conditional.display.name='if' statement could be replaced with simple conditional expression if.may.be.conditional.problem.descriptor=#ref could be replaced with simple conditional expression #loc if.may.be.conditional.quickfix=Replace with conditional expression redundant.string.format.call.display.name=Redundant call to 'String.format()' @@ -1759,8 +1759,8 @@ unnecessary.javadoc.link.this.class.problem.descriptor=#ref pointin unnecessary.javadoc.link.quickfix=Remove unnecessary '{0}' thread.local.not.static.final.display.name=ThreadLocal field not declared static final thread.local.not.static.final.problem.descriptor=ThreadLocal #ref is not declared 'static final' #loc -remove.try.finally.block.quickfix=Remove try-finally block -remove.finally.block.quickfix=Remove finally block +remove.try.finally.block.quickfix=Remove 'try-finally' block +remove.finally.block.quickfix=Remove 'finally' block remove.leading.zero.to.make.decimal.quickfix=Remove leading zero to make decimal convert.octal.literal.to.decimal.literal.quickfix=Convert octal literal to decimal literal ignore.single.field.static.imports.option=Ignore single &field static imports @@ -1772,7 +1772,7 @@ ignored.io.resource.types=Ignored I/O resource types choose.io.resource.type.to.ignore=Choose I/O resource type to ignore ignore.accesses.from.the.same.class=Ignore accesses from the same class ignore.accesses.from.equals.method=Ignore accesses from 'equals()' method -ignore.branches.of.switch.statements=Ignore branches of switch statements +ignore.branches.of.switch.statements=Ignore branches of 'switch' statements ignore.equals.hashcode.and.tostring=Ignore equals, hashCode and toString methods class.name=Class name method.name.pattern=Method name pattern @@ -1811,14 +1811,14 @@ unnecessarily.qualified.statically.imported.element.problem.descriptor=Staticall unnecessarily.qualified.statically.imported.element.quickfix=Remove unnecessary qualifier ignore.instanceof.on.library.classes=Ignore instanceof on library classes assertequals.may.be.assertsame.quickfix=Replace with 'assertSame()' -for.can.be.foreach.option=Report indexed java.util.List loops +for.can.be.foreach.option=Report indexed 'java.util.List' loops cast.conflicts.with.instanceof.quickfix1=Replace cast to ''{0}'' with ''{1}'' cast.conflicts.with.instanceof.quickfix2=Replace instanceof ''{0}'' with ''{1}'' double.checked.locking.quickfix=Make ''{0}'' 'volatile' double.literal.may.be.float.literal.display.name='double' literal cast to 'float' could be 'float' literal double.literal.may.be.float.literal.problem.descriptor=#ref could be replaced with ''{0}'' #loc double.literal.may.be.float.literal.quickfix=Replace with ''{0}'' -multiple.declaration.option=Ignore for loop declarations +multiple.declaration.option=Ignore 'for' loop declarations simplifiable.annotation.display.name=Simplifiable annotation simplifiable.annotation.problem.descriptor=Annotation #ref may be replaced with ''{0}'' simplifiable.annotation.quickfix=Simplify annotation From e4f24b084df4fd943d01b6e92ea6229a105d5c25 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 22 Feb 2011 00:35:23 +0100 Subject: [PATCH 067/169] Project Coin try-with-resource support, take 3 --- .../intellij/codeInsight/ExceptionUtil.java | 5 +- .../analysis/HighlightControlFlowUtil.java | 43 ++++++----- .../daemon/impl/analysis/HighlightUtil.java | 6 +- .../impl/analysis/HighlightVisitorImpl.java | 4 +- .../lang/java/parser/DeclarationParser.java | 21 ++++-- .../com/intellij/psi/impl/PsiImplUtil.java | 7 +- .../psi/impl/source/tree/JavaElementType.java | 1 + .../tree/java/PsiLocalVariableImpl.java | 26 +++++-- .../source/tree/java/PsiResourceImpl.java | 74 +++++++++++++++++++ .../source/tree/java/PsiResourceListImpl.java | 16 ++-- .../statements/TryIncomplete15.txt | 25 ++++--- .../statements/TryIncomplete16.txt | 29 ++++---- .../statements/TryIncomplete17.txt | 31 ++++---- .../parser-partial/statements/TryNormal4.txt | 31 ++++---- .../parser-partial/statements/TryNormal5.txt | 62 ++++++++-------- .../parser-partial/statements/TryNormal6.txt | 9 ++- .../parser-partial/statements/TryNormal7.txt | 14 ++-- .../com/intellij/psi/JavaElementVisitor.java | 4 + .../src/com/intellij/psi/PsiResource.java | 39 ++++++++++ .../src/com/intellij/psi/PsiResourceList.java | 15 +--- .../intellij/psi/PsiScopedLocalVariable.java | 28 +++++++ .../src/com/intellij/psi/util/PsiUtil.java | 15 ---- .../com/intellij/psi/util/PsiTreeUtil.java | 16 ---- 23 files changed, 327 insertions(+), 194 deletions(-) create mode 100644 java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceImpl.java create mode 100644 java/openapi/src/com/intellij/psi/PsiResource.java create mode 100644 java/openapi/src/com/intellij/psi/PsiScopedLocalVariable.java diff --git a/java/java-impl/src/com/intellij/codeInsight/ExceptionUtil.java b/java/java-impl/src/com/intellij/codeInsight/ExceptionUtil.java index a8a6f914ada4..ea1008c5fb32 100644 --- a/java/java-impl/src/com/intellij/codeInsight/ExceptionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/ExceptionUtil.java @@ -22,7 +22,6 @@ import com.intellij.psi.*; import com.intellij.psi.controlFlow.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.InheritanceUtil; -import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; @@ -247,8 +246,8 @@ public class ExceptionUtil { unhandledExceptions = unhandled; } - if (PsiUtil.isResourceInTryStatement(element)) { - final PsiType resourceType = PsiUtil.getResourceType(element); + if (element instanceof PsiResource) { + final PsiType resourceType = ((PsiResource)element).getType(); if (resourceType instanceof PsiClassType) { final PsiClass resourceClass = ((PsiClassType)resourceType).resolve(); if (resourceClass != null) { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java index 9afe6a9b3815..2288f318bdfc 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java @@ -13,15 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -/* - * Created by IntelliJ IDEA. - * User: cdr - * Date: Aug 8, 2002 - * Time: 5:55:01 PM - * To change template for new class use - * Code Style | Class Templates options (Tools | IDE Options). - */ package com.intellij.codeInsight.daemon.impl.analysis; import com.intellij.codeInsight.daemon.JavaErrorMessages; @@ -43,9 +34,14 @@ import org.jetbrains.annotations.Nullable; import java.util.*; +/** + * @author cdr + * Date: Aug 8, 2002 + */ public class HighlightControlFlowUtil { private static final QuickFixFactory QUICK_FIX_FACTORY = QuickFixFactory.getInstance(); + private HighlightControlFlowUtil() { } @Nullable public static HighlightInfo checkMissingReturnStatement(PsiMethod method) { @@ -297,7 +293,7 @@ public class HighlightControlFlowUtil { topBlock = JspPsiUtil.isInJspFile(scope) && scope instanceof PsiFile ? scope : PsiUtil.getTopLevelEnclosingCodeBlock(expression, scope); if (variable instanceof PsiField) { - // non final field already initalized with default value + // non final field already initialized with default value if (!variable.hasModifierProperty(PsiModifier.FINAL)) return null; // final field may be initialized in ctor or class initializer only // if we're inside non-ctr method, skip it @@ -314,9 +310,9 @@ public class HighlightControlFlowUtil { if (parent instanceof PsiMethod) { PsiMethod constructor = (PsiMethod)parent; if (!parent.getManager().areElementsEquivalent(constructor.getContainingClass(), ((PsiField)variable).getContainingClass())) return null; - // static variables already initalized in class initalizers + // static variables already initialized in class initializers if (variable.hasModifierProperty(PsiModifier.STATIC)) return null; - // as a last chance, field may be initalized in this() call + // as a last chance, field may be initialized in this() call final List redirectedConstructors = getChainedConstructors(constructor); for (int j = 0; redirectedConstructors != null && j < redirectedConstructors.size(); j++) { PsiMethod redirectedConstructor = redirectedConstructors.get(j); @@ -338,7 +334,7 @@ public class HighlightControlFlowUtil { aClass = classInitializer.getContainingClass(); } else { - // field reference outside codeblock + // field reference outside code block // check variable initialized before its usage final PsiField field = (PsiField)variable; @@ -356,7 +352,7 @@ public class HighlightControlFlowUtil { && variableDefinitelyAssignedIn(variable, constructor.getBody())) { return null; } - // as a last chance, field may be initalized in this() call + // as a last chance, field may be initialized in this() call final List redirectedConstructors = getChainedConstructors(constructor); for (int j = 0; redirectedConstructors != null && j < redirectedConstructors.size(); j++) { PsiMethod redirectedConstructor = redirectedConstructors.get(j); @@ -371,13 +367,13 @@ public class HighlightControlFlowUtil { } if (aClass != null) { - // field may be initialized in class initalizer + // field may be initialized in class initializer final PsiClassInitializer[] initializers = aClass.getInitializers(); for (PsiClassInitializer initializer : initializers) { PsiCodeBlock body = initializer.getBody(); if (body == block) break; // variable referenced in initializer must be initialized in initializer preceding assignment - // varaibel refernced in field initializer or in class initializier + // variable referenced in field initializer or in class initializer boolean shouldCheckInitializerOrder = block == null || block.getParent() instanceof PsiClassInitializer; if (shouldCheckInitializerOrder && startOffset < initializer.getTextRange().getStartOffset()) continue; if (initializer.hasModifierProperty(PsiModifier.STATIC) @@ -449,6 +445,7 @@ public class HighlightControlFlowUtil { } + @Nullable public static HighlightInfo checkFinalVariableMightAlreadyHaveBeenAssignedTo(PsiVariable variable, PsiReferenceExpression expression, Map> finalVarProblems) { @@ -473,7 +470,7 @@ public class HighlightControlFlowUtil { final PsiField field = (PsiField)variable; final PsiClass aClass = field.getContainingClass(); if (aClass == null) return null; - // field can get assigned in other field inititializers + // field can get assigned in other field initializers final PsiField[] fields = aClass.getFields(); boolean isFieldStatic = field.hasModifierProperty(PsiModifier.STATIC); for (PsiField psiField : fields) { @@ -565,7 +562,8 @@ public class HighlightControlFlowUtil { } - public static HighlightInfo checkFinalVariableInitalizedInLoop(PsiReferenceExpression expression, PsiElement resolved) { + @Nullable + public static HighlightInfo checkFinalVariableInitializedInLoop(PsiReferenceExpression expression, PsiElement resolved) { if (ControlFlowUtil.isVariableAssignedInLoop(expression, resolved)) { String description = JavaErrorMessages.message("variable.assigned.in.loop", ((PsiVariable)resolved).getName()); final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo( @@ -580,6 +578,7 @@ public class HighlightControlFlowUtil { } + @Nullable public static HighlightInfo checkCannotWriteToFinal(PsiExpression expression) { PsiReferenceExpression reference = null; if (expression instanceof PsiAssignmentExpression) { @@ -659,6 +658,7 @@ public class HighlightControlFlowUtil { } + @Nullable static HighlightInfo checkVariableMustBeFinal(PsiVariable variable, PsiJavaCodeReferenceElement context) { if (variable.hasModifierProperty(PsiModifier.FINAL)) return null; final PsiClass innerClass = getInnerClassVariableReferencedFrom(variable, context); @@ -672,9 +672,13 @@ public class HighlightControlFlowUtil { return null; } + @Nullable public static PsiClass getInnerClassVariableReferencedFrom(PsiVariable variable, PsiElement context) { PsiElement scope; - if (variable instanceof PsiLocalVariable) { + if (variable instanceof PsiScopedLocalVariable) { + scope = ((PsiScopedLocalVariable)variable).getDeclarationScope(); + } + else if (variable instanceof PsiLocalVariable) { scope = variable.getParent().getParent(); // code block or for statement } else if (variable instanceof PsiParameter) { @@ -699,6 +703,7 @@ public class HighlightControlFlowUtil { } + @Nullable public static HighlightInfo checkInitializerCompleteNormally(PsiClassInitializer initializer) { final PsiCodeBlock body = initializer.getBody(); // unhandled exceptions already reported diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index 8368aec10784..8a02cbf32e83 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -563,7 +563,7 @@ public class HighlightUtil { if (variable instanceof PsiLocalVariable || variable instanceof PsiParameter && ((PsiParameter)variable).getDeclarationScope() instanceof PsiCatchSection || variable instanceof PsiParameter && ((PsiParameter)variable).getDeclarationScope() instanceof PsiForeachStatement || - PsiUtil.isResourceInTryStatement(variable)) { + variable instanceof PsiResource && ((PsiResource)variable).getResourceElement() instanceof PsiLocalVariable) { PsiElement scope = PsiTreeUtil.getParentOfType(variable, PsiFile.class, PsiMethod.class, PsiClassInitializer.class); VariablesNotProcessor proc = new VariablesNotProcessor(variable, false) { protected boolean check(final PsiVariable var, final ResolveState state) { @@ -1118,8 +1118,8 @@ public class HighlightUtil { } @Nullable - public static HighlightInfo checkTryResourceIsAutoCloseable(@NotNull final PsiElement resource) { - final PsiType type = PsiUtil.getResourceType(resource); + public static HighlightInfo checkTryResourceIsAutoCloseable(@NotNull final PsiResource resource) { + final PsiType type = resource.getType(); if (type == null) return null; final PsiElementFactory factory = JavaPsiFacade.getInstance(resource.getProject()).getElementFactory(); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index 003e0d8e01a0..dfc4475f17e5 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -820,7 +820,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh if (!myHolder.hasErrorResults()) { myHolder.add(HighlightControlFlowUtil.checkFinalVariableMightAlreadyHaveBeenAssignedTo(variable, expression, myFinalVarProblems)); } - if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkFinalVariableInitalizedInLoop(expression, resolved)); + if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkFinalVariableInitializedInLoop(expression, resolved)); } } @@ -905,7 +905,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh PsiResourceList resources = statement.getResourceList(); if (resources != null) { - for (PsiElement resource : resources.getResources()) { + for (PsiResource resource : resources.getResources()) { myHolder.add(HighlightUtil.checkTryResourceIsAutoCloseable(resource)); } } diff --git a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java index 018bbbc3c875..b162024dcd20 100644 --- a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java +++ b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java @@ -31,6 +31,7 @@ import org.jetbrains.annotations.Nullable; import static com.intellij.lang.PsiBuilderUtil.expect; import static com.intellij.lang.PsiBuilderUtil.nextTokenType; import static com.intellij.lang.java.parser.JavaParserUtil.*; +import static com.intellij.lang.java.parser.JavaParserUtil.exprType; public class DeclarationParser { @@ -588,12 +589,22 @@ public class DeclarationParser { } @Nullable - private static PsiBuilder.Marker parseResource(final PsiBuilder builder) { - PsiBuilder.Marker resource = parse(builder, Context.RESOURCE_LIST); - if (resource == null) { - resource = ExpressionParser.parse(builder); + public static PsiBuilder.Marker parseResource(final PsiBuilder builder) { + PsiBuilder.Marker element = parse(builder, Context.RESOURCE_LIST); + if (exprType(element) == JavaElementType.MODIFIER_LIST) { + return element; } - return resource; + else if (element == null) { + element = ExpressionParser.parse(builder); + } + + if (element != null) { + final PsiBuilder.Marker resource = element.precede(); + done(resource, JavaElementType.RESOURCE); + return resource; + } + + return null; } @Nullable diff --git a/java/java-impl/src/com/intellij/psi/impl/PsiImplUtil.java b/java/java-impl/src/com/intellij/psi/impl/PsiImplUtil.java index 2fa673130c31..0a863ea0d9a3 100644 --- a/java/java-impl/src/com/intellij/psi/impl/PsiImplUtil.java +++ b/java/java-impl/src/com/intellij/psi/impl/PsiImplUtil.java @@ -200,9 +200,10 @@ public class PsiImplUtil { final PsiElement lastParent) { final PsiResourceList resourceList = statement.getResourceList(); if (resourceList != null && lastParent instanceof PsiCodeBlock && lastParent == statement.getTryBlock()) { - final List resources = resourceList.getNamedResources(); - for (PsiLocalVariable resource : resources) { - if (!processor.execute(resource, state)) return false; + final List resources = resourceList.getResources(); + for (PsiResource resource : resources) { + final PsiElement resourceElement = resource.getResourceElement(); + if (resourceElement instanceof PsiLocalVariable && !processor.execute(resourceElement, state)) return false; } } diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java index 7d31f4b1ff3a..593bb11d77c3 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java @@ -128,6 +128,7 @@ public interface JavaElementType { IElementType SYNCHRONIZED_STATEMENT = new JavaCompositeElementType("SYNCHRONIZED_STATEMENT", PsiSynchronizedStatementImpl.class); IElementType TRY_STATEMENT = new JavaCompositeElementType("TRY_STATEMENT", PsiTryStatementImpl.class); IElementType RESOURCE_LIST = new JavaCompositeElementType("RESOURCE_LIST", PsiResourceListImpl.class); + IElementType RESOURCE = new JavaCompositeElementType("RESOURCE", PsiResourceImpl.class); IElementType CATCH_SECTION = new JavaCompositeElementType("CATCH_SECTION", PsiCatchSectionImpl.class); IElementType LABELED_STATEMENT = new JavaCompositeElementType("LABELED_STATEMENT", PsiLabeledStatementImpl.class); IElementType ASSERT_STATEMENT = new JavaCompositeElementType("ASSERT_STATEMENT", PsiAssertStatementImpl.class); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiLocalVariableImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiLocalVariableImpl.java index 910c1f171773..af9a91209384 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiLocalVariableImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiLocalVariableImpl.java @@ -49,7 +49,7 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.util.Set; -public class PsiLocalVariableImpl extends CompositePsiElement implements PsiLocalVariable, PsiVariableEx, Constants { +public class PsiLocalVariableImpl extends CompositePsiElement implements PsiScopedLocalVariable, PsiVariableEx, Constants { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiLocalVariableImpl"); private volatile String myCachedName = null; @@ -279,6 +279,21 @@ public class PsiLocalVariableImpl extends CompositePsiElement implements PsiLoca return "PsiLocalVariable:" + getName(); } + @NotNull + public PsiElement getDeclarationScope() { + final PsiElement parentElement = getParent(); + if (parentElement instanceof PsiDeclarationStatement) { + return parentElement.getParent(); + } + else if (parentElement instanceof PsiResource) { + final PsiResourceList resourceList = (PsiResourceList)parentElement.getParent(); + final PsiTryStatement tryStatement = (PsiTryStatement)resourceList.getParent(); + final PsiCodeBlock tryBlock = tryStatement.getTryBlock(); + return tryBlock != null ? tryBlock : resourceList; + } + return parentElement.getParent(); + } + @NotNull public SearchScope getUseScope() { if (JspPsiUtil.isInJspFile(this)) { @@ -306,13 +321,8 @@ public class PsiLocalVariableImpl extends CompositePsiElement implements PsiLoca } final PsiElement parentElement = getParent(); - if (parentElement instanceof PsiDeclarationStatement) { - return new LocalSearchScope(parentElement.getParent()); - } - else if (parentElement instanceof PsiResourceList) { - final PsiElement tryStatement = parentElement.getParent(); - final PsiCodeBlock tryBlock = ((PsiTryStatement)tryStatement).getTryBlock(); - return new LocalSearchScope(tryBlock != null ? tryBlock : tryStatement); + if (parentElement instanceof PsiDeclarationStatement || parentElement instanceof PsiResource) { + return new LocalSearchScope(getDeclarationScope()); } else { return getManager().getFileManager().getUseScope(this); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceImpl.java new file mode 100644 index 000000000000..35faa6a76cea --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceImpl.java @@ -0,0 +1,74 @@ +/* + * Copyright 2000-2011 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 com.intellij.psi.impl.source.tree.java; + +import com.intellij.openapi.diagnostic.LogUtil; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.psi.*; +import com.intellij.psi.impl.source.tree.CompositePsiElement; +import com.intellij.psi.impl.source.tree.JavaElementType; +import org.jetbrains.annotations.NotNull; + +public class PsiResourceImpl extends CompositePsiElement implements PsiResource { + private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiResourceImpl"); + + public PsiResourceImpl() { + super(JavaElementType.RESOURCE); + } + + @NotNull + @Override + public PsiElement getResourceElement() { + final PsiElement element = getFirstChild(); + assert element != null : this; + return element; + } + + @Override + public PsiType getType() { + final PsiElement element = getResourceElement(); + if (element instanceof PsiLocalVariable) { + return ((PsiLocalVariable)element).getType(); + } + else if (element instanceof PsiExpression) { + return ((PsiExpression)element).getType(); + } + LOG.error("Unexpected resource type: " + LogUtil.objectAndClass(element)); + return null; + } + + @Override + public void accept(@NotNull final PsiElementVisitor visitor) { + if (visitor instanceof JavaElementVisitor) { + ((JavaElementVisitor)visitor).visitResource(this); + } + else { + visitor.visitElement(this); + } + } + + public String getName() { + final PsiElement element = getResourceElement(); + if (element instanceof PsiLocalVariable) return ((PsiLocalVariable)element).getName(); + if (element instanceof PsiAssignmentExpression) return ((PsiAssignmentExpression)element).getLExpression().toString(); + return ""; + } + + @Override + public String toString() { + return "PsiResource:" + getName(); + } +} diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java index f078c02d9514..f69d21569307 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java @@ -15,7 +15,10 @@ */ package com.intellij.psi.impl.source.tree.java; -import com.intellij.psi.*; +import com.intellij.psi.JavaElementVisitor; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.PsiResource; +import com.intellij.psi.PsiResourceList; import com.intellij.psi.impl.source.tree.CompositePsiElement; import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.util.PsiTreeUtil; @@ -30,15 +33,8 @@ public class PsiResourceListImpl extends CompositePsiElement implements PsiResou @NotNull @Override - public List getResources() { - //noinspection unchecked - return PsiTreeUtil.getChildrenOfAnyType(this, PsiExpression.class, PsiLocalVariable.class); - } - - @NotNull - @Override - public List getNamedResources() { - return PsiTreeUtil.getChildrenOfTypeAsList(this, PsiLocalVariable.class); + public List getResources() { + return PsiTreeUtil.getChildrenOfTypeAsList(this, PsiResource.class); } @Override diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete15.txt b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete15.txt index 297e7e00cfaf..5748458436f0 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete15.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete15.txt @@ -3,18 +3,19 @@ PsiJavaFile:TryIncomplete15.java PsiKeyword:try('try') PsiResourceList:(R r) PsiJavaToken:LPARENTH('(') - PsiLocalVariable:r - PsiModifierList: - - PsiTypeElement:R - PsiJavaCodeReferenceElement:R - PsiIdentifier:R('R') - PsiReferenceParameterList - - PsiWhiteSpace(' ') - PsiIdentifier:r('r') - PsiErrorElement:'=' expected - + PsiResource:r + PsiLocalVariable:r + PsiModifierList: + + PsiTypeElement:R + PsiJavaCodeReferenceElement:R + PsiIdentifier:R('R') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiIdentifier:r('r') + PsiErrorElement:'=' expected + PsiJavaToken:RPARENTH(')') PsiCodeBlock PsiJavaToken:LBRACE('{') diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete16.txt b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete16.txt index 4ed639c77577..e04ca47331f8 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete16.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete16.txt @@ -3,20 +3,21 @@ PsiJavaFile:TryIncomplete16.java PsiKeyword:try('try') PsiResourceList:(R r =) PsiJavaToken:LPARENTH('(') - PsiLocalVariable:r - PsiModifierList: - - PsiTypeElement:R - PsiJavaCodeReferenceElement:R - PsiIdentifier:R('R') - PsiReferenceParameterList - - PsiWhiteSpace(' ') - PsiIdentifier:r('r') - PsiWhiteSpace(' ') - PsiJavaToken:EQ('=') - PsiErrorElement:Expression expected - + PsiResource:r + PsiLocalVariable:r + PsiModifierList: + + PsiTypeElement:R + PsiJavaCodeReferenceElement:R + PsiIdentifier:R('R') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiIdentifier:r('r') + PsiWhiteSpace(' ') + PsiJavaToken:EQ('=') + PsiErrorElement:Expression expected + PsiJavaToken:RPARENTH(')') PsiCodeBlock PsiJavaToken:LBRACE('{') diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete17.txt b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete17.txt index 4a4aa969fceb..e4f111fb50c8 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete17.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete17.txt @@ -3,21 +3,22 @@ PsiJavaFile:TryIncomplete17.java PsiKeyword:try('try') PsiResourceList:(R r = 0;) PsiJavaToken:LPARENTH('(') - PsiLocalVariable:r - PsiModifierList: - - PsiTypeElement:R - PsiJavaCodeReferenceElement:R - PsiIdentifier:R('R') - PsiReferenceParameterList - - PsiWhiteSpace(' ') - PsiIdentifier:r('r') - PsiWhiteSpace(' ') - PsiJavaToken:EQ('=') - PsiWhiteSpace(' ') - PsiLiteralExpression:0 - PsiJavaToken:INTEGER_LITERAL('0') + PsiResource:r + PsiLocalVariable:r + PsiModifierList: + + PsiTypeElement:R + PsiJavaCodeReferenceElement:R + PsiIdentifier:R('R') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiIdentifier:r('r') + PsiWhiteSpace(' ') + PsiJavaToken:EQ('=') + PsiWhiteSpace(' ') + PsiLiteralExpression:0 + PsiJavaToken:INTEGER_LITERAL('0') PsiJavaToken:SEMICOLON(';') PsiErrorElement:Identifier or type expected diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryNormal4.txt b/java/java-tests/testData/psi/parser-partial/statements/TryNormal4.txt index 0cf390a0fcbd..c3bec38b2bf4 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryNormal4.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryNormal4.txt @@ -3,21 +3,22 @@ PsiJavaFile:TryNormal4.java PsiKeyword:try('try') PsiResourceList:(R r = 0) PsiJavaToken:LPARENTH('(') - PsiLocalVariable:r - PsiModifierList: - - PsiTypeElement:R - PsiJavaCodeReferenceElement:R - PsiIdentifier:R('R') - PsiReferenceParameterList - - PsiWhiteSpace(' ') - PsiIdentifier:r('r') - PsiWhiteSpace(' ') - PsiJavaToken:EQ('=') - PsiWhiteSpace(' ') - PsiLiteralExpression:0 - PsiJavaToken:INTEGER_LITERAL('0') + PsiResource:r + PsiLocalVariable:r + PsiModifierList: + + PsiTypeElement:R + PsiJavaCodeReferenceElement:R + PsiIdentifier:R('R') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiIdentifier:r('r') + PsiWhiteSpace(' ') + PsiJavaToken:EQ('=') + PsiWhiteSpace(' ') + PsiLiteralExpression:0 + PsiJavaToken:INTEGER_LITERAL('0') PsiJavaToken:RPARENTH(')') PsiCodeBlock PsiJavaToken:LBRACE('{') diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryNormal5.txt b/java/java-tests/testData/psi/parser-partial/statements/TryNormal5.txt index 8c11fdeff9ca..b69bed12f700 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryNormal5.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryNormal5.txt @@ -3,38 +3,40 @@ PsiJavaFile:TryNormal5.java PsiKeyword:try('try') PsiResourceList:(R1 r1 = 1; R2 r2 = 2) PsiJavaToken:LPARENTH('(') - PsiLocalVariable:r1 - PsiModifierList: - - PsiTypeElement:R1 - PsiJavaCodeReferenceElement:R1 - PsiIdentifier:R1('R1') - PsiReferenceParameterList - - PsiWhiteSpace(' ') - PsiIdentifier:r1('r1') - PsiWhiteSpace(' ') - PsiJavaToken:EQ('=') - PsiWhiteSpace(' ') - PsiLiteralExpression:1 - PsiJavaToken:INTEGER_LITERAL('1') + PsiResource:r1 + PsiLocalVariable:r1 + PsiModifierList: + + PsiTypeElement:R1 + PsiJavaCodeReferenceElement:R1 + PsiIdentifier:R1('R1') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiIdentifier:r1('r1') + PsiWhiteSpace(' ') + PsiJavaToken:EQ('=') + PsiWhiteSpace(' ') + PsiLiteralExpression:1 + PsiJavaToken:INTEGER_LITERAL('1') PsiJavaToken:SEMICOLON(';') PsiWhiteSpace(' ') - PsiLocalVariable:r2 - PsiModifierList: - - PsiTypeElement:R2 - PsiJavaCodeReferenceElement:R2 - PsiIdentifier:R2('R2') - PsiReferenceParameterList - - PsiWhiteSpace(' ') - PsiIdentifier:r2('r2') - PsiWhiteSpace(' ') - PsiJavaToken:EQ('=') - PsiWhiteSpace(' ') - PsiLiteralExpression:2 - PsiJavaToken:INTEGER_LITERAL('2') + PsiResource:r2 + PsiLocalVariable:r2 + PsiModifierList: + + PsiTypeElement:R2 + PsiJavaCodeReferenceElement:R2 + PsiIdentifier:R2('R2') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiIdentifier:r2('r2') + PsiWhiteSpace(' ') + PsiJavaToken:EQ('=') + PsiWhiteSpace(' ') + PsiLiteralExpression:2 + PsiJavaToken:INTEGER_LITERAL('2') PsiJavaToken:RPARENTH(')') PsiCodeBlock PsiJavaToken:LBRACE('{') diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryNormal6.txt b/java/java-tests/testData/psi/parser-partial/statements/TryNormal6.txt index c82b04a42e85..bf1b0ed88fd3 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryNormal6.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryNormal6.txt @@ -3,10 +3,11 @@ PsiJavaFile:TryNormal6.java PsiKeyword:try('try') PsiResourceList:(r) PsiJavaToken:LPARENTH('(') - PsiReferenceExpression:r - PsiReferenceParameterList - - PsiIdentifier:r('r') + PsiResource: + PsiReferenceExpression:r + PsiReferenceParameterList + + PsiIdentifier:r('r') PsiJavaToken:RPARENTH(')') PsiCodeBlock PsiJavaToken:LBRACE('{') diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryNormal7.txt b/java/java-tests/testData/psi/parser-partial/statements/TryNormal7.txt index 746ded3b71bb..1299595c7a9b 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryNormal7.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryNormal7.txt @@ -3,14 +3,16 @@ PsiJavaFile:TryNormal7.java PsiKeyword:try('try') PsiResourceList:(r; null) PsiJavaToken:LPARENTH('(') - PsiReferenceExpression:r - PsiReferenceParameterList - - PsiIdentifier:r('r') + PsiResource: + PsiReferenceExpression:r + PsiReferenceParameterList + + PsiIdentifier:r('r') PsiJavaToken:SEMICOLON(';') PsiWhiteSpace(' ') - PsiLiteralExpression:null - PsiJavaToken:NULL_KEYWORD('null') + PsiResource: + PsiLiteralExpression:null + PsiJavaToken:NULL_KEYWORD('null') PsiJavaToken:RPARENTH(')') PsiCodeBlock PsiJavaToken:LBRACE('{') diff --git a/java/openapi/src/com/intellij/psi/JavaElementVisitor.java b/java/openapi/src/com/intellij/psi/JavaElementVisitor.java index 6325cc5fcd59..c8162c6004b3 100644 --- a/java/openapi/src/com/intellij/psi/JavaElementVisitor.java +++ b/java/openapi/src/com/intellij/psi/JavaElementVisitor.java @@ -300,6 +300,10 @@ public abstract class JavaElementVisitor extends PsiElementVisitor { visitElement(resourceList); } + public void visitResource(PsiResource resource) { + visitElement(resource); + } + public void visitTypeElement(PsiTypeElement type) { visitElement(type); } diff --git a/java/openapi/src/com/intellij/psi/PsiResource.java b/java/openapi/src/com/intellij/psi/PsiResource.java new file mode 100644 index 000000000000..e53289079c86 --- /dev/null +++ b/java/openapi/src/com/intellij/psi/PsiResource.java @@ -0,0 +1,39 @@ +/* + * Copyright 2000-2011 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 com.intellij.psi; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Represents a resource list of try-with-resources statement (automatic resource management) introduced in JDK 7. + * + * @see PsiResourceList#getResources() + * @since 10.5. + */ +public interface PsiResource extends PsiElement { + /** + * Returns main element of the resource. + * It may be PsiLocalVariable, PsiAssignmentExpression, or other instance of PsiExpression. + * + * @return resource element. + */ + @NotNull + PsiElement getResourceElement(); + + @Nullable + PsiType getType(); +} diff --git a/java/openapi/src/com/intellij/psi/PsiResourceList.java b/java/openapi/src/com/intellij/psi/PsiResourceList.java index 55b5cb12b863..c954ae7e79bd 100644 --- a/java/openapi/src/com/intellij/psi/PsiResourceList.java +++ b/java/openapi/src/com/intellij/psi/PsiResourceList.java @@ -26,19 +26,6 @@ import java.util.List; * @since 10.5. */ public interface PsiResourceList extends PsiElement { - /** - * Returns list of resource elements. Each element is either {@link PsiLocalVariable} or {@link PsiExpression}. - * - * @return list of resource elements. - */ @NotNull - List getResources(); - - /** - * Returns list of named resource elements only. - * - * @return list of named resource elements. - */ - @NotNull - List getNamedResources(); + List getResources(); } diff --git a/java/openapi/src/com/intellij/psi/PsiScopedLocalVariable.java b/java/openapi/src/com/intellij/psi/PsiScopedLocalVariable.java new file mode 100644 index 000000000000..a3e629e79f49 --- /dev/null +++ b/java/openapi/src/com/intellij/psi/PsiScopedLocalVariable.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2011 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 com.intellij.psi; + +import org.jetbrains.annotations.NotNull; + +public interface PsiScopedLocalVariable extends PsiLocalVariable { + /** + * Returns the element (method, "for" statement or try block) in which the variable is declared. + * + * @return the declaration scope for the variable. + */ + @NotNull + PsiElement getDeclarationScope(); +} diff --git a/java/openapi/src/com/intellij/psi/util/PsiUtil.java b/java/openapi/src/com/intellij/psi/util/PsiUtil.java index de515c55ca48..12f0b759f1f8 100644 --- a/java/openapi/src/com/intellij/psi/util/PsiUtil.java +++ b/java/openapi/src/com/intellij/psi/util/PsiUtil.java @@ -15,7 +15,6 @@ */ package com.intellij.psi.util; -import com.intellij.openapi.diagnostic.LogUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.openapi.util.Comparing; @@ -636,20 +635,6 @@ public final class PsiUtil extends PsiUtilBase { return PsiTreeUtil.getParentOfType(element, PsiDocComment.class, true) != null; } - public static boolean isResourceInTryStatement(final PsiElement element) { - return (element instanceof PsiLocalVariable || element instanceof PsiExpression) && - element.getParent() instanceof PsiResourceList; - } - - @Nullable - public static PsiType getResourceType(final PsiElement element) { - if (element == null || !(element.getParent() instanceof PsiResourceList)) return null; - if (element instanceof PsiLocalVariable) return ((PsiLocalVariable)element).getType(); - if (element instanceof PsiExpression) return ((PsiExpression)element).getType(); - LOG.error("Unexpected resource type: " + LogUtil.objectAndClass(element)); - return null; - } - private static class ParamWriteProcessor implements Processor { private volatile boolean myIsWriteRefFound = false; public boolean process(PsiReference reference) { diff --git a/platform/lang-api/src/com/intellij/psi/util/PsiTreeUtil.java b/platform/lang-api/src/com/intellij/psi/util/PsiTreeUtil.java index 91063c18bf59..92a835d850a4 100644 --- a/platform/lang-api/src/com/intellij/psi/util/PsiTreeUtil.java +++ b/platform/lang-api/src/com/intellij/psi/util/PsiTreeUtil.java @@ -312,22 +312,6 @@ public class PsiTreeUtil { return null; } - @NotNull - public static List getChildrenOfAnyType(@Nullable final PsiElement element, - @Nullable final Class... classes) { - if (element == null || classes == null || classes.length == 0) return Collections.emptyList(); - - final List result = new SmartList(); - for (PsiElement child = element.getFirstChild(); child != null; child = child.getNextSibling()) { - for (Class aClass : classes) { - if (aClass.isInstance(child)) { - result.add(child); - } - } - } - return result; - } - @Nullable public static T getNextSiblingOfType(@Nullable PsiElement sibling, @NotNull Class aClass) { if (sibling == null) return null; From c7b7f41b99fbccf2699d4baa52efdc800c4763f7 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Mon, 21 Feb 2011 17:45:29 +0300 Subject: [PATCH 068/169] IDEA-57891 Reformat file: run under modal progress Don't perform 'sequential formatting' during 'optimize imports' phase --- .../psi/codeStyle/CodeStyleManager.java | 16 +++++ .../ReformatAndOptimizeImportsProcessor.java | 10 ++- .../source/codeStyle/CodeFormatterFacade.java | 5 +- .../codeStyle/CodeStyleManagerImpl.java | 65 +++++++++++++++++++ 4 files changed, 94 insertions(+), 2 deletions(-) diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleManager.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleManager.java index 4c0055ceb905..e79ff8eedfc3 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleManager.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleManager.java @@ -216,4 +216,20 @@ public abstract class CodeStyleManager { * the file is read-only). */ public abstract void reformatNewlyAddedElement(@NotNull final ASTNode block, @NotNull final ASTNode addedElement) throws IncorrectOperationException; + + /** + * Formatting may be executed sequentially, i.e. the whole (re)formatting task is split into a number of smaller sub-tasks + * that are executed sequentially. That is done primarily for ability to show progress dialog during formatting (formatting + * is always performed from EDT, hence, the GUI freezes if we perform formatting as a single big iteration). + *

+ * However, there are situation when we don't want to use such an approach - for example, IntelliJ IDEA sometimes inserts dummy + * text into file in order to calculate formatting-specific data and removes it after that. We don't want to allow Swing events + * dispatching during that in order to not show that dummy text to the end-user. + *

+ * It's possible to configure that (implementation details are insignificant here) and current method serves as a read-only + * facade for obtaining information if 'sequential' processing is allowed at the moment. + * + * @return true if 'sequential' formatting is allowed now; false otherwise + */ + public abstract boolean isSequentialProcessingAllowed(); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatAndOptimizeImportsProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatAndOptimizeImportsProcessor.java index 8d82a14c80be..f5ed69680a5f 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatAndOptimizeImportsProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatAndOptimizeImportsProcessor.java @@ -21,6 +21,8 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.psi.impl.source.codeStyle.CodeStyleManagerImpl; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; @@ -71,7 +73,13 @@ public class ReformatAndOptimizeImportsProcessor extends AbstractLayoutCodeProce return new Runnable() { public void run() { r1.run(); - r2.run(); + CodeStyleManagerImpl.setSequentialProcessingAllowed(false); + try { + r2.run(); + } + finally { + CodeStyleManagerImpl.setSequentialProcessingAllowed(true); + } } }; } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java index 4708ab4c5307..b765cb3f1a90 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java @@ -36,6 +36,7 @@ import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.formatter.DocumentBasedFormattingModel; import com.intellij.psi.impl.source.PostprocessReformattingAspect; @@ -188,7 +189,9 @@ public class CodeFormatterFacade { project, mySettings, file.getFileType(), file); FormatterEx formatter = FormatterEx.getInstanceEx(); - formatter.setProgressIndicator(new FormattingProgressIndicatorImpl(project, file, document)); + if (CodeStyleManager.getInstance(project).isSequentialProcessingAllowed()) { + formatter.setProgressIndicator(new FormattingProgressIndicatorImpl(project, file, document)); + } formatter.format(model, mySettings, mySettings.getIndentOptions(file.getFileType()), ranges); for (FormatTextRanges.FormatTextRange range : textRanges) { TextRange textRange = range.getTextRange(); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java index a8ab933f8d24..a6049ecbb69b 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java @@ -48,8 +48,20 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.concurrent.TimeUnit; + public class CodeStyleManagerImpl extends CodeStyleManager { + private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.codeStyle.CodeStyleManagerImpl"); + private static final ThreadLocal SEQUENTIAL_PROCESSING_ALLOWED + = new ThreadLocal() + { + @Override + protected ProcessingUnderProgressInfo initialValue() { + return new ProcessingUnderProgressInfo(); + } + }; + private final Project myProject; @NonNls private static final String DUMMY_IDENTIFIER = "xxx"; @@ -478,6 +490,7 @@ public class CodeStyleManagerImpl extends CodeStyleManager { document.deleteString(start, end); document.insertString(start, buffer); + setSequentialProcessingAllowed(false); document.insertString(offset, DUMMY_IDENTIFIER); return new TextRange(offset, offset + DUMMY_IDENTIFIER.length()); } @@ -506,6 +519,7 @@ public class CodeStyleManagerImpl extends CodeStyleManager { ASTNode space1 = splitSpaceElement((TreeElement)element, offset - elementStart, charTable); ASTNode marker = Factory.createSingleLeafElement(TokenType.NEW_LINE_INDENT, DUMMY_IDENTIFIER, charTable, file.getManager()); + setSequentialProcessingAllowed(false); parent.addChild(marker, space1.getTreeNext()); PsiElement psiElement = SourceTreeToPsiMap.treeElementToPsi(marker); return psiElement == null ? null : psiElement.getTextRange(); @@ -561,4 +575,55 @@ public class CodeStyleManagerImpl extends CodeStyleManager { private CodeStyleSettings getSettings() { return CodeStyleSettingsManager.getSettings(myProject); } + + @Override + public boolean isSequentialProcessingAllowed() { + return SEQUENTIAL_PROCESSING_ALLOWED.get().isAllowed(); + } + + /** + * Allows to define if {@link #isSequentialProcessingAllowed() sequential processing} should be allowed. + *

+ * Current approach is not allow to stop sequential processing for more than predefine amount of time (couple of seconds). + * That means that call to this method with 'true' argument is not mandatory for successful processing even + * if this method is called with 'false' argument before. + * + * @param allowed flag that defines if {@link #isSequentialProcessingAllowed() sequential processing} should be allowed + */ + public static void setSequentialProcessingAllowed(boolean allowed) { + ProcessingUnderProgressInfo info = SEQUENTIAL_PROCESSING_ALLOWED.get(); + if (allowed) { + info.decrement(); + } + else { + info.increment(); + } + } + + private static class ProcessingUnderProgressInfo { + + private static final long DURATION_TIME = TimeUnit.MILLISECONDS.convert(5, TimeUnit.SECONDS); + + private int myCount; + private long myEndTime; + + public void increment() { + if (myCount > 0 && System.currentTimeMillis() > myEndTime) { + myCount = 0; + } + myCount++; + myEndTime = System.currentTimeMillis() + DURATION_TIME; + } + + public void decrement() { + if (myCount <= 0) { + return; + } + myCount--; + } + + public boolean isAllowed() { + return myCount <= 0 || System.currentTimeMillis() >= myEndTime; + } + } } From 2601a251aeff9c567b2e7aea3d2ff87a10550325 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Mon, 21 Feb 2011 18:00:57 +0300 Subject: [PATCH 069/169] IDEA-64975 Possibility of keeping multiple expressions on one line Reverted inadvertent 'keep simple methods in one line' option removal --- .../application/options/codeStyle/WrappingAndBracesPanel.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/WrappingAndBracesPanel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/WrappingAndBracesPanel.java index f71cb326b960..33e071a46f4c 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/WrappingAndBracesPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/WrappingAndBracesPanel.java @@ -36,6 +36,7 @@ public class WrappingAndBracesPanel extends OptionTableWithPreviewPanel { addOption("KEEP_CONTROL_STATEMENT_IN_ONE_LINE", ApplicationBundle.message("checkbox.keep.when.reformatting.control.statement.in.one.line"), WRAPPING_KEEP); addOption("KEEP_SIMPLE_BLOCKS_IN_ONE_LINE", ApplicationBundle.message("wrapping.keep.simple.blocks.in.one.line"), WRAPPING_KEEP); + addOption("KEEP_SIMPLE_METHODS_IN_ONE_LINE", ApplicationBundle.message("wrapping.keep.simple.methods.in.one.line"), WRAPPING_KEEP); addOption("KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE", ApplicationBundle.message("wrapping.keep.multiple.expressions.in.one.line"), WRAPPING_KEEP); addOption("CLASS_BRACE_STYLE", ApplicationBundle.message("wrapping.brace.placement.class.declaration"), WRAPPING_BRACES, BRACE_PLACEMENT_OPTIONS, BRACE_PLACEMENT_VALUES); From 711d884ceb9c74b3c4192b7778e4ff3e7c0ffcce Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Tue, 22 Feb 2011 11:13:04 +0300 Subject: [PATCH 070/169] IDEA-65433 Code style feature: simple classes and interfaces in one line 1. Added new code style setting - 'keep simple classes and interfaces in one line'; 2. Corresponding tests are added; --- ...JavaLanguageCodeStyleSettingsProvider.java | 3 +++ .../java/JavaSpacePropertyProcessor.java | 4 ++++ .../java/JavaFormatterBracesTest.java | 19 +++++++++++++++++++ .../codeStyle/CommonCodeStyleSettings.java | 1 + .../codeStyle/WrappingAndBracesPanel.java | 3 ++- .../src/messages/ApplicationBundle.properties | 1 + 6 files changed, 30 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.java b/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.java index 3b4d6ecd6955..3f2dde01087f 100644 --- a/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.java +++ b/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.java @@ -220,7 +220,10 @@ public class JavaLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSett " throws Exception { \n" + " foo.foo().bar(\"arg1\", \n" + " \"arg2\"); \n" + + " new Object() {};" + " } \n" + + " class TestInnerClass {}\n" + + " interface TestInnerInterface {}\n" + "}\n" + "\n" + "enum Breed {\n" + diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java index 5ab5d59e7187..2e1bad933cc9 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java @@ -213,6 +213,10 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { if (aClass.isEnum()) { createParenSpace(true, false); } + else if (myRole2 == ChildRole.RBRACE && mySettings.KEEP_SIMPLE_CLASSES_IN_ONE_LINE) { + int spaces = mySettings.SPACE_WITHIN_BRACES ? 1 : 0; + myResult = Spacing.createSpacing(spaces, spaces, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_DECLARATIONS); + } else if (aClass instanceof PsiAnonymousClass) { if (myRole2 == ChildRole.CLASS_INITIALIZER && isTheOnlyClassMember(myChild2)) { myResult = Spacing.createSpacing(0, 0, 0, diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterBracesTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterBracesTest.java index 823218a86e1c..a1ba7ff3bd7a 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterBracesTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterBracesTest.java @@ -113,4 +113,23 @@ public class JavaFormatterBracesTest extends AbstractJavaFormatterTest { "}" ); } + + public void testKeepSimpleClassesAndInterfacesInOneLine() { + // Inspired by IDEA-65433 + getSettings().KEEP_SIMPLE_CLASSES_IN_ONE_LINE = true; + + String[] tests = { + "class Test {}", + "interface Test {}", + "class Test {\n" + + " void test() {\n" + + " new Object() {};\n" + + " }\n" + + "}" + }; + + for (String test : tests) { + doTextTest(test, test); + } + } } diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java index 5ac8f5bd2a22..5bd8c3d1854a 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java @@ -654,6 +654,7 @@ public class CommonCodeStyleSettings { public boolean KEEP_SIMPLE_BLOCKS_IN_ONE_LINE = false; public boolean KEEP_SIMPLE_METHODS_IN_ONE_LINE = false; + public boolean KEEP_SIMPLE_CLASSES_IN_ONE_LINE = false; public boolean KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE = false; public int FOR_STATEMENT_WRAP = DO_NOT_WRAP; diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/WrappingAndBracesPanel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/WrappingAndBracesPanel.java index 33e071a46f4c..9cbf44d54ae7 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/WrappingAndBracesPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/WrappingAndBracesPanel.java @@ -35,9 +35,10 @@ public class WrappingAndBracesPanel extends OptionTableWithPreviewPanel { addOption("KEEP_FIRST_COLUMN_COMMENT", ApplicationBundle.message("wrapping.keep.comment.at.first.column"), WRAPPING_KEEP); addOption("KEEP_CONTROL_STATEMENT_IN_ONE_LINE", ApplicationBundle.message("checkbox.keep.when.reformatting.control.statement.in.one.line"), WRAPPING_KEEP); + addOption("KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE", ApplicationBundle.message("wrapping.keep.multiple.expressions.in.one.line"), WRAPPING_KEEP); addOption("KEEP_SIMPLE_BLOCKS_IN_ONE_LINE", ApplicationBundle.message("wrapping.keep.simple.blocks.in.one.line"), WRAPPING_KEEP); addOption("KEEP_SIMPLE_METHODS_IN_ONE_LINE", ApplicationBundle.message("wrapping.keep.simple.methods.in.one.line"), WRAPPING_KEEP); - addOption("KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE", ApplicationBundle.message("wrapping.keep.multiple.expressions.in.one.line"), WRAPPING_KEEP); + addOption("KEEP_SIMPLE_CLASSES_IN_ONE_LINE", ApplicationBundle.message("wrapping.keep.simple.classes.in.one.line"), WRAPPING_KEEP); addOption("CLASS_BRACE_STYLE", ApplicationBundle.message("wrapping.brace.placement.class.declaration"), WRAPPING_BRACES, BRACE_PLACEMENT_OPTIONS, BRACE_PLACEMENT_VALUES); addOption("METHOD_BRACE_STYLE", ApplicationBundle.message("wrapping.brace.placement.method.declaration"), WRAPPING_BRACES, BRACE_PLACEMENT_OPTIONS, BRACE_PLACEMENT_VALUES); diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties index d6e18c427278..ffaf57f2093f 100644 --- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties +++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties @@ -131,6 +131,7 @@ wrapping.and.braces=Wrapping and Braces wrapping.keep.when.reformatting=Keep when reformatting wrapping.keep.line.breaks=Line breaks wrapping.keep.comment.at.first.column=Comment at first column +wrapping.keep.simple.classes.in.one.line=Simple classes in one line wrapping.keep.simple.methods.in.one.line=Simple methods in one line wrapping.keep.multiple.expressions.in.one.line=Multiple expressions in one line wrapping.keep.simple.blocks.in.one.line=Simple blocks in one line From 8a2e4c12418c9189bba3e1dfeb5baadece11f8a1 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Mon, 21 Feb 2011 20:01:32 +0300 Subject: [PATCH 071/169] Console init moved out of the event dispatch thread. --- .../console/LanguageConsoleImpl.java | 20 +++++++++---- .../AbstractConsoleRunnerWithHistory.java | 29 ++++++++++++++----- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java index af25959298ce..bc703320ecca 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java @@ -21,6 +21,7 @@ import com.intellij.ide.impl.TypeSafeDataProviderAdapter; import com.intellij.lang.Language; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.editor.*; @@ -373,7 +374,7 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider { HighlighterTargetArea.EXACT_RANGE); final String text = consoleEditor.getDocument().getText(textRange); - //offset can be changed after text trimming after insert due to buffer constraints + //offset can be changed after text trimming after insert due to buffer constraints appendToHistoryDocument(history, text); int offset = history.getTextLength() - text.length(); final int localStartOffset = textRange.getStartOffset(); @@ -617,10 +618,17 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider { attributes = additionalType.getAttributes().clone(); attributes.setBackgroundColor(mainAttributes.getBackgroundColor()); } - ApplicationManager.getApplication().invokeLater(new Runnable() { - public void run() { - console.printToHistory(string, attributes); - } - }, ModalityState.stateForComponent(console.getComponent())); + + Application application = ApplicationManager.getApplication(); + if (application.isDispatchThread()) { + console.printToHistory(string, attributes); + } + else { + application.invokeLater(new Runnable() { + public void run() { + console.printToHistory(string, attributes); + } + }, ModalityState.stateForComponent(console.getComponent())); + } } } diff --git a/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java b/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java index ef936fc4706b..f1f6b203f471 100644 --- a/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java +++ b/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java @@ -30,18 +30,14 @@ import com.intellij.execution.ui.RunContentDescriptor; import com.intellij.execution.ui.actions.CloseAction; import com.intellij.ide.CommonActionsManager; import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.Result; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.editor.CaretModel; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.actions.ScrollToTheEndToolbarAction; -import com.intellij.openapi.editor.actions.ToggleUseSoftWrapsToolbarAction; import com.intellij.openapi.editor.ex.EditorEx; -import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; -import com.intellij.openapi.editor.ex.util.EditorUtil; -import com.intellij.openapi.editor.impl.softwrap.SoftWrapAppliancePlaces; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; @@ -60,8 +56,8 @@ import java.util.List; /** * @author oleg - * This class provides basic functionality for running consoles. - * It launches external process and handles line input with history + * This class provides basic functionality for running consoles. + * It launches external process and handles line input with history */ public abstract class AbstractConsoleRunnerWithHistory { private final Project myProject; @@ -96,6 +92,23 @@ public abstract class AbstractConsoleRunnerWithHistory { // Create Server process final Process process = createProcess(myProvider); + Application application = ApplicationManager.getApplication(); + + if (application.isDispatchThread()) { + initConsoleUI(process); + } + else { + application.invokeLater(new Runnable() { + @Override + public void run() { + initConsoleUI(process); + } + }); + } + } + + + private void initConsoleUI(Process process) { // Init console view myConsoleView = createConsoleView(); @@ -257,7 +270,7 @@ public abstract class AbstractConsoleRunnerWithHistory { // Check if we have active lookup or if we can move in editor return LookupManager.getActiveLookup(consoleEditor) != null || document.getLineNumber(caretModel.getOffset()) < document.getLineCount() - 1 && - !StringUtil.isEmptyOrSpaces(document.getText().substring(caretModel.getOffset())); + !StringUtil.isEmptyOrSpaces(document.getText().substring(caretModel.getOffset())); } }; } From 9e9584b4a5993335f62c052a99d102f23d7f37ff Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Tue, 22 Feb 2011 11:38:47 +0300 Subject: [PATCH 072/169] IDEA-65422 Editor: Add support for 'Scroll to Top' and 'Scroll to Bottom' actions 'Scroll to Top' and 'Scroll to Bottom' actions are added --- .../editor/actions/ScrollToBottomAction.java | 45 +++++++++++++++++++ .../editor/actions/ScrollToTopAction.java | 43 ++++++++++++++++++ .../src/messages/ActionsBundle.properties | 2 + .../src/idea/PlatformActions.xml | 2 + 4 files changed, 92 insertions(+) create mode 100644 platform/platform-impl/src/com/intellij/openapi/editor/actions/ScrollToBottomAction.java create mode 100644 platform/platform-impl/src/com/intellij/openapi/editor/actions/ScrollToTopAction.java diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/ScrollToBottomAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/ScrollToBottomAction.java new file mode 100644 index 000000000000..b971dce1cf45 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/ScrollToBottomAction.java @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2011 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 com.intellij.openapi.editor.actions; + +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.ScrollType; +import com.intellij.openapi.editor.actionSystem.EditorActionHandler; +import com.intellij.openapi.editor.ex.EditorEx; + +/** + * Scrolls to the top of the target editor without changing its caret position. + * + * @author Denis Zhdanov + * @since 2/22/11 11:17 AM + */ +public class ScrollToBottomAction extends InactiveEditorAction { + + public ScrollToBottomAction() { + super(new MyHandler()); + } + + private static class MyHandler extends EditorActionHandler { + @Override + public void execute(Editor editor, DataContext dataContext) { + if (editor == null) { + return; + } + editor.getScrollingModel().scrollTo(editor.offsetToLogicalPosition(editor.getDocument().getTextLength()), ScrollType.CENTER); + } + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/ScrollToTopAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/ScrollToTopAction.java new file mode 100644 index 000000000000..a3771a173725 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/ScrollToTopAction.java @@ -0,0 +1,43 @@ +/* + * Copyright 2000-2011 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 com.intellij.openapi.editor.actions; + +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.actionSystem.EditorActionHandler; + +/** + * Scrolls to the top of the target editor without changing its caret position. + * + * @author Denis Zhdanov + * @since 2/22/11 11:17 AM + */ +public class ScrollToTopAction extends InactiveEditorAction { + + public ScrollToTopAction() { + super(new MyHandler()); + } + + private static class MyHandler extends EditorActionHandler { + @Override + public void execute(Editor editor, DataContext dataContext) { + if (editor == null) { + return; + } + editor.getScrollingModel().scrollVertically(0); + } + } +} diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index 1f15ebcbf287..cb21d7434c35 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -87,6 +87,8 @@ action.EditorTab.text=Tab action.EmacsStyleIndent.text=Emacs Tab action.EditorScrollUp.text=Scroll Up action.EditorScrollDown.text=Scroll Down +action.EditorScrollTop.text=Scroll to Top +action.EditorScrollBottom.text=Scroll to Bottom action.EditorMoveUpAndScroll.text=Move Up and Scroll action.EditorMoveDownAndScroll.text=Move Down and Scroll action.EditorMoveUpAndScrollWithSelection.text=Move Up and Scroll with Selection diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml index f448f143b688..22b63fd3e470 100644 --- a/platform/platform-resources/src/idea/PlatformActions.xml +++ b/platform/platform-resources/src/idea/PlatformActions.xml @@ -50,6 +50,8 @@ + + From a060107f891f2095908a858d714775251391e1b2 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 22 Feb 2011 10:05:35 +0100 Subject: [PATCH 073/169] Multi-catch type API cleanup --- .../src/com/intellij/psi/impl/PsiSubstitutorImpl.java | 2 +- java/openapi/src/com/intellij/psi/PsiDisjunctionType.java | 8 ++++---- .../src/com/intellij/psi/util/TypeConversionUtil.java | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java b/java/java-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java index 14527352e906..c6c975bb5653 100644 --- a/java/java-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java @@ -177,7 +177,7 @@ public class PsiSubstitutorImpl implements PsiSubstitutor { final List substituted = ContainerUtil.map(disjunctionType.getDisjunctions(), new Function() { @Override public PsiType fun(PsiType psiType) { return psiType.accept(SubstitutionVisitorBase.this); } }); - return new PsiDisjunctionType(substituted, disjunctionType.getManager()); + return disjunctionType.newDisjunctionType(substituted); } } diff --git a/java/openapi/src/com/intellij/psi/PsiDisjunctionType.java b/java/openapi/src/com/intellij/psi/PsiDisjunctionType.java index 0ae89e9850b4..8b4b4bace061 100644 --- a/java/openapi/src/com/intellij/psi/PsiDisjunctionType.java +++ b/java/openapi/src/com/intellij/psi/PsiDisjunctionType.java @@ -30,8 +30,8 @@ import java.util.Collections; import java.util.List; /** - * Composite type resulting from Project Coin's multi-catch statements, * i.e. FileNotFoundException | EOFException. - * In most cases should be threatened via its least upper bound * (IOException in the example above). + * Composite type resulting from Project Coin's multi-catch statements, i.e. FileNotFoundException | EOFException. + * In most cases should be threatened via its least upper bound (IOException in the example above). */ public class PsiDisjunctionType extends PsiType { private final PsiManager myManager; @@ -64,8 +64,8 @@ public class PsiDisjunctionType extends PsiType { return myTypes; } - public PsiManager getManager() { - return myManager; + public PsiDisjunctionType newDisjunctionType(final List types) { + return new PsiDisjunctionType(types, myManager); } @Override diff --git a/java/openapi/src/com/intellij/psi/util/TypeConversionUtil.java b/java/openapi/src/com/intellij/psi/util/TypeConversionUtil.java index bbe345501d62..295a4a03a585 100644 --- a/java/openapi/src/com/intellij/psi/util/TypeConversionUtil.java +++ b/java/openapi/src/com/intellij/psi/util/TypeConversionUtil.java @@ -1170,7 +1170,7 @@ public class TypeConversionUtil { final List erased = ContainerUtil.map(disjunctionType.getDisjunctions(), new Function() { @Override public PsiType fun(PsiType psiType) { return erasure(psiType, beforeSubstitutor); } }); - return new PsiDisjunctionType(erased, disjunctionType.getManager()); + return disjunctionType.newDisjunctionType(erased); } }); } From 005c5e2df2d064b2e99c13b30a7230450dfa9842 Mon Sep 17 00:00:00 2001 From: nik Date: Tue, 22 Feb 2011 12:10:07 +0300 Subject: [PATCH 074/169] fixed NPE --- .../com/intellij/openapi/ui/MasterDetailsStateService.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsStateService.java b/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsStateService.java index 6bd41e819a80..a76d2cf819f2 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsStateService.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsStateService.java @@ -62,7 +62,9 @@ public class MasterDetailsStateService implements PersistentStateComponent stateClass) { ComponentState state = myStates.get(key); - return state != null ? XmlSerializer.deserialize(state.mySettings, stateClass) : null; + if (state == null) return null; + final Element settings = state.mySettings; + return settings != null ? XmlSerializer.deserialize(settings, stateClass) : null; } public void setComponentState(@NotNull @NonNls String key, @NotNull MasterDetailsState state) { From f95d422409de8a852fc9bb75429da9b17c6c9f5f Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Tue, 22 Feb 2011 11:20:16 +0100 Subject: [PATCH 075/169] CIDR: build errors (compiler, linker) --- .../com/intellij/util/ui/ErrorTreeView.java | 29 +++++++++- .../ide/errorTreeView/ErrorViewStructure.java | 24 ++++++--- .../errorTreeView/NewErrorTreeViewPanel.java | 54 ++++++++++++++----- .../openapi/util/text/StringUtil.java | 4 ++ 4 files changed, 89 insertions(+), 22 deletions(-) diff --git a/platform/platform-api/src/com/intellij/util/ui/ErrorTreeView.java b/platform/platform-api/src/com/intellij/util/ui/ErrorTreeView.java index f069ba016658..1870e7b4011b 100644 --- a/platform/platform-api/src/com/intellij/util/ui/ErrorTreeView.java +++ b/platform/platform-api/src/com/intellij/util/ui/ErrorTreeView.java @@ -19,6 +19,8 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.DataKey; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.Navigatable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -29,12 +31,35 @@ public interface ErrorTreeView extends Disposable { /** * If file is not null, allows to navigate to this file, line, column */ - void addMessage(int type, String[] text, VirtualFile file, int line, int column, Object data); + void addMessage(int type, + @NotNull String[] text, + @Nullable VirtualFile file, + int line, + int column, + @Nullable Object data); + + /** + * Allows adding messages related to other files under 'underFileGroup' + */ + void addMessage(int type, + @NotNull String[] text, + @Nullable VirtualFile underFileGroup, + @Nullable VirtualFile file, + int line, + int column, + @Nullable Object data); /** * add message, allowing navigation via custom Navigatable object */ - void addMessage(int type, String[] text, String groupName, Navigatable navigatable, String exportTextPrefix, String rendererTextPrefix, Object data); + void addMessage(int type, + @NotNull String[] text, + @NotNull String groupName, + @NotNull Navigatable navigatable, + @Nullable String exportTextPrefix, + @Nullable String rendererTextPrefix, + @Nullable Object data); + @NotNull JComponent getComponent(); } diff --git a/platform/platform-impl/src/com/intellij/ide/errorTreeView/ErrorViewStructure.java b/platform/platform-impl/src/com/intellij/ide/errorTreeView/ErrorViewStructure.java index 6336e78cd75e..3a2021a2071a 100644 --- a/platform/platform-impl/src/com/intellij/ide/errorTreeView/ErrorViewStructure.java +++ b/platform/platform-impl/src/com/intellij/ide/errorTreeView/ErrorViewStructure.java @@ -28,6 +28,7 @@ import com.intellij.ui.SimpleColoredComponent; import com.intellij.util.ArrayUtil; import com.intellij.util.ui.MutableErrorTreeView; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.*; @@ -142,20 +143,31 @@ public class ErrorViewStructure extends AbstractTreeStructure { return false; } - public void addMessage(ErrorTreeElementKind kind, String[] text, VirtualFile file, int line, int column, Object data) { - if (file != null) { + public void addMessage(ErrorTreeElementKind kind, + @NotNull String[] text, + @Nullable VirtualFile underFileGroup, + @Nullable VirtualFile file, + int line, + int column, + @Nullable Object data) { + if (underFileGroup != null || file != null) { + if (file == null) line = column = -1; + final int guiline = line < 0 ? -1 : line + 1; - final int guicolumn = column < 0 ? -1:column + 1; + final int guicolumn = column < 0 ? -1 : column + 1; + + VirtualFile group = underFileGroup != null ? underFileGroup : file; + VirtualFile nav = file != null ? file : underFileGroup; addNavigatableMessage( - file.getPresentableUrl(), - new OpenFileDescriptor(myProject, file, line, column), + group.getPresentableUrl(), + new OpenFileDescriptor(myProject, nav, line, column), kind, text, data, NewErrorTreeViewPanel.createExportPrefix(guiline), NewErrorTreeViewPanel.createRendererPrefix(guiline, guicolumn), - file + group ); } else { diff --git a/platform/platform-impl/src/com/intellij/ide/errorTreeView/NewErrorTreeViewPanel.java b/platform/platform-impl/src/com/intellij/ide/errorTreeView/NewErrorTreeViewPanel.java index e5f3eb16d4da..d91271637dde 100644 --- a/platform/platform-impl/src/com/intellij/ide/errorTreeView/NewErrorTreeViewPanel.java +++ b/platform/platform-impl/src/com/intellij/ide/errorTreeView/NewErrorTreeViewPanel.java @@ -38,6 +38,7 @@ import com.intellij.util.ui.MutableErrorTreeView; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.tree.TreeUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; @@ -230,6 +231,7 @@ public class NewErrorTreeViewPanel extends JPanel implements DataProvider, Occur protected boolean shouldShowFirstErrorInEditor() { return false; } + public void clearMessages() { myErrorViewStructure.clear(); myBuilder.updateTree(); @@ -238,14 +240,36 @@ public class NewErrorTreeViewPanel extends JPanel implements DataProvider, Occur public void updateTree() { myBuilder.updateTree(); } - public void addMessage(int type, String[] text, VirtualFile file, int line, int column, Object data) { - myErrorViewStructure.addMessage(ErrorTreeElementKind.convertMessageFromCompilerErrorType(type), text, file, line, column, data); + + public void addMessage(int type, @NotNull String[] text, @Nullable VirtualFile file, int line, int column, @Nullable Object data) { + addMessage(type, text, null, file, line, column, data); + } + + @Override + public void addMessage(int type, + @NotNull String[] text, + @Nullable VirtualFile underFileGroup, + @Nullable VirtualFile file, + int line, + int column, + @Nullable Object data) { + myErrorViewStructure + .addMessage(ErrorTreeElementKind.convertMessageFromCompilerErrorType(type), text, underFileGroup, file, line, column, data); myBuilder.updateTree(); } - public void addMessage(int type, String[] text, String groupName, Navigatable navigatable, String exportTextPrefix, String rendererTextPrefix, Object data) { - myErrorViewStructure.addNavigatableMessage(groupName, navigatable, ErrorTreeElementKind.convertMessageFromCompilerErrorType(type), text, data, exportTextPrefix, rendererTextPrefix, - data instanceof VirtualFile ? (VirtualFile) data : null); + public void addMessage(int type, + @NotNull String[] text, + @NotNull String groupName, + @NotNull Navigatable navigatable, + @Nullable String exportTextPrefix, + @Nullable String rendererTextPrefix, + @Nullable Object data) { + myErrorViewStructure.addNavigatableMessage(groupName, navigatable, ErrorTreeElementKind.convertMessageFromCompilerErrorType(type), text, + data, + exportTextPrefix == null ? "" : exportTextPrefix, + rendererTextPrefix == null ? "" : rendererTextPrefix, + data instanceof VirtualFile ? (VirtualFile)data : null); myBuilder.updateTree(); } @@ -254,11 +278,13 @@ public class NewErrorTreeViewPanel extends JPanel implements DataProvider, Occur } public static String createExportPrefix(int line) { - return line < 0? "" : IdeBundle.message("errortree.prefix.line", line); + return line < 0 ? "" : IdeBundle.message("errortree.prefix.line", line); } public static String createRendererPrefix(int line, int column) { - return line < 0? "" : "(" + line + ", " + column + ")"; + if (line < 0) return ""; + if (column < 0) return "(" + line + ")"; + return "(" + line + ", " + column + ")"; } public JComponent getComponent() { @@ -267,7 +293,7 @@ public class NewErrorTreeViewPanel extends JPanel implements DataProvider, Occur private NavigatableMessageElement getSelectedMessageElement() { final ErrorTreeElement selectedElement = getSelectedErrorTreeElement(); - return selectedElement instanceof NavigatableMessageElement? (NavigatableMessageElement)selectedElement : null; + return selectedElement instanceof NavigatableMessageElement ? (NavigatableMessageElement)selectedElement : null; } public ErrorTreeElement getSelectedErrorTreeElement() { @@ -423,7 +449,7 @@ public class NewErrorTreeViewPanel extends JPanel implements DataProvider, Occur if (rerunAction != null) { leftUpdateableActionGroup.add(new RerunAction(rerunAction, closeMessageViewAction)); } - + leftUpdateableActionGroup.add(new StopAction()); if (myCreateExitAction) { leftUpdateableActionGroup.add(closeMessageViewAction); @@ -439,10 +465,10 @@ public class NewErrorTreeViewPanel extends JPanel implements DataProvider, Occur JPanel toolbarPanel = new JPanel(new GridLayout(1, 2)); final ActionManager actionManager = ActionManager.getInstance(); myLeftToolbar = - actionManager.createActionToolbar(ActionPlaces.COMPILER_MESSAGES_TOOLBAR, leftUpdateableActionGroup, false); + actionManager.createActionToolbar(ActionPlaces.COMPILER_MESSAGES_TOOLBAR, leftUpdateableActionGroup, false); toolbarPanel.add(myLeftToolbar.getComponent()); myRightToolbar = - actionManager.createActionToolbar(ActionPlaces.COMPILER_MESSAGES_TOOLBAR, rightUpdateableActionGroup, false); + actionManager.createActionToolbar(ActionPlaces.COMPILER_MESSAGES_TOOLBAR, rightUpdateableActionGroup, false); toolbarPanel.add(myRightToolbar.getComponent()); return toolbarPanel; @@ -521,7 +547,7 @@ public class NewErrorTreeViewPanel extends JPanel implements DataProvider, Occur } } - protected boolean canHideWarnings(){ + protected boolean canHideWarnings() { return true; } @@ -543,11 +569,11 @@ public class NewErrorTreeViewPanel extends JPanel implements DataProvider, Occur } } } - + public boolean isHideWarnings() { return ErrorTreeViewConfiguration.getInstance(myProject).isHideWarnings(); } - + private class MyTreeExpander implements TreeExpander { public void expandAll() { NewErrorTreeViewPanel.this.expandAll(); diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index 078c4ec16588..9836f79cf3c6 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -1313,6 +1313,10 @@ public class StringUtil { return range.replace(string, replacement); } + public static boolean startsWithWhitespace(@NotNull String text) { + return !text.isEmpty() && Character.isWhitespace(text.charAt(0)); + } + public static boolean startsWith(@NotNull CharSequence text, @NotNull CharSequence prefix) { int l1 = text.length(); int l2 = prefix.length(); From 8986280b064a42d73bc1e510a2132a7a732c99ec Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Mon, 21 Feb 2011 18:01:51 +0300 Subject: [PATCH 076/169] deprecation --- .../src/com/intellij/execution/process/ProcessHandler.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/platform/platform-api/src/com/intellij/execution/process/ProcessHandler.java b/platform/platform-api/src/com/intellij/execution/process/ProcessHandler.java index f75ccb40cf4c..d1976a2804bd 100644 --- a/platform/platform-api/src/com/intellij/execution/process/ProcessHandler.java +++ b/platform/platform-api/src/com/intellij/execution/process/ProcessHandler.java @@ -15,10 +15,8 @@ */ package com.intellij.execution.process; -import com.intellij.openapi.Disposable; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; -import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.util.concurrency.Semaphore; @@ -26,7 +24,6 @@ import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.Nullable; import java.io.OutputStream; -import java.lang.ref.WeakReference; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; @@ -36,6 +33,10 @@ import java.util.concurrent.atomic.AtomicInteger; public abstract class ProcessHandler extends UserDataHolderBase { private static final Logger LOG = Logger.getInstance("#com.intellij.execution.process.ProcessHandler"); + /** + * todo: replace with an overridable method [nik] + * @deprecated + */ public static final Key SILENTLY_DESTROY_ON_CLOSE = Key.create("SILENTLY_DESTROY_ON_CLOSE"); private final List myListeners = ContainerUtil.createEmptyCOWList(); From 52d4ff995fa6d8471de3f51669c478aad86f4674 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Mon, 21 Feb 2011 18:44:55 +0300 Subject: [PATCH 077/169] do not copy it to history document --- .../execution/runners/ConsoleExecuteActionHandler.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java b/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java index bbc4c9271ede..3f6f84a9c98d 100644 --- a/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java +++ b/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java @@ -31,6 +31,7 @@ import java.io.OutputStream; public class ConsoleExecuteActionHandler { private final ProcessHandler myProcessHandler; private final boolean myPreserveMarkup; + private boolean myAddCurrentToHistory; public ConsoleExecuteActionHandler(ProcessHandler processHandler, boolean preserveMarkup) { myProcessHandler = processHandler; @@ -47,7 +48,9 @@ public class ConsoleExecuteActionHandler { final TextRange range = new TextRange(0, document.getTextLength()); languageConsole.getCurrentEditor().getSelectionModel().setSelection(range.getStartOffset(), range.getEndOffset()); - languageConsole.addCurrentToHistory(range, false, myPreserveMarkup); + if (myAddCurrentToHistory) { + languageConsole.addCurrentToHistory(range, false, myPreserveMarkup); + } languageConsole.setInputText(""); if (!StringUtil.isEmptyOrSpaces(text)) { consoleHistoryModel.addToHistory(text); @@ -73,4 +76,8 @@ public class ConsoleExecuteActionHandler { // ignore } } + + public void setAddCurrentToHistory(boolean addCurrentToHistory) { + myAddCurrentToHistory = addCurrentToHistory; + } } From 90a4aa153dba5293269611b57c7383bb5f0f751d Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 22 Feb 2011 12:31:43 +0100 Subject: [PATCH 078/169] added option to "to ignore references to inner classes where the removal of the qualification would require the addition of an import" --- .../siyeh/InspectionGadgetsBundle.properties | 3 +- ...lyQualifiedInnerClassAccessInspection.java | 43 +++++++++++++++---- ...nnecessarilyQualifiedInnerClassAccess.html | 6 ++- 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties index ff04edd0437a..ea8e2dfd6977 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties @@ -1558,7 +1558,7 @@ constant.string.intern.quickfix=Remove '.intern()' class.extends.utility.class.display.name=Class extends utility class class.extends.utility.class.problem.descriptor=Class #ref extends utility class ''{0}'' #loc public.constructor.in.non.public.class.quickfix=Make constructor ''{0}'' -assignment.to.method.parameter.ignore.transformation.option=Ignore if assignment is a transformation of the original parameter +assignment.to.method.parameter.ignore.transformation.option=Ignore if assignment is a transformation of the original parameter type.parameter.extends.final.class.display.name=Type parameter extends final class type.parameter.extends.final.class.problem.descriptor1=Type parameter #ref extends final class ''{0}'' #loc type.parameter.extends.final.class.problem.descriptor2=Wildcard type argument #ref extends final class ''{0}'' #loc @@ -1851,3 +1851,4 @@ if.can.be.switch.display.name='if' replaceable with 'switch' if.can.be.switch.problem.descriptor=#ref statement replaceable with 'switch' statement if.can.be.switch.quickfix=Replace with 'switch' if.can.be.switch.minimum.branch.option=Minimum number of branches +unnecessarily.qualified.inner.class.access.option=Ignore references to foreign inner classes diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessarilyQualifiedInnerClassAccessInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessarilyQualifiedInnerClassAccessInspection.java index a38eb211b874..6c3a57d5e184 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessarilyQualifiedInnerClassAccessInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessarilyQualifiedInnerClassAccessInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Bas Leijdekkers + * Copyright 2010-2011 Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,10 @@ package com.siyeh.ig.style; import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; import com.intellij.openapi.project.Project; import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; @@ -27,9 +29,14 @@ import com.siyeh.ig.psiutils.ImportUtils; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; +import javax.swing.*; + public class UnnecessarilyQualifiedInnerClassAccessInspection extends BaseInspection { + @SuppressWarnings({"PublicField"}) + public boolean ignoreReferencesToForeignInnerClasses = false; + @Nls @NotNull @Override @@ -47,6 +54,14 @@ public class UnnecessarilyQualifiedInnerClassAccessInspection aClass.getName()); } + @Override + public JComponent createOptionsPanel() { + return new SingleCheckboxOptionsPanel( + InspectionGadgetsBundle.message( + "unnecessarily.qualified.inner.class.access.option"), + this, "ignoreReferencesToForeignInnerClasses"); + } + @Override protected InspectionGadgetsFix buildFix(Object... infos) { return new UnnecessarilyQualifiedInnerClassAccessFix(); @@ -90,7 +105,7 @@ public class UnnecessarilyQualifiedInnerClassAccessInspection return new UnnecessarilyQualifiedInnerClassAccessVisitor(); } - private static class UnnecessarilyQualifiedInnerClassAccessVisitor + private class UnnecessarilyQualifiedInnerClassAccessVisitor extends BaseInspectionVisitor { @Override @@ -116,6 +131,20 @@ public class UnnecessarilyQualifiedInnerClassAccessInspection if (!(qualifierTarget instanceof PsiClass)) { return; } + final PsiClass referenceClass = + PsiTreeUtil.getParentOfType(reference, PsiClass.class); + if (referenceClass == null) { + return; + } + if (!referenceClass.equals(qualifierTarget)) { + if (PsiTreeUtil.isAncestor(referenceClass, qualifierTarget, + true) || + (ignoreReferencesToForeignInnerClasses && + !PsiTreeUtil.isAncestor(qualifierTarget, + referenceClass, true))) { + return; + } + } final PsiElement target = reference.resolve(); if (!(target instanceof PsiClass)) { return; @@ -141,7 +170,7 @@ public class UnnecessarilyQualifiedInnerClassAccessInspection visitReferenceElement(expression); } - private static boolean isReferenceToTarget( + private boolean isReferenceToTarget( String referenceText, PsiClass target, PsiElement context) { final PsiManager manager = target.getManager(); final JavaPsiFacade facade = @@ -150,13 +179,11 @@ public class UnnecessarilyQualifiedInnerClassAccessInspection final PsiClass referencedClass = resolveHelper.resolveReferencedClass(referenceText, context); - if (referencedClass == null) { - return true; - } - return manager.areElementsEquivalent(target, referencedClass); + return referencedClass == null || + manager.areElementsEquivalent(target, referencedClass); } - private static boolean isInImportOrPackage(PsiElement element) { + private boolean isInImportOrPackage(PsiElement element) { while (element instanceof PsiJavaCodeReferenceElement) { element = element.getParent(); if (element instanceof PsiImportStatementBase || diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/UnnecessarilyQualifiedInnerClassAccess.html b/plugins/InspectionGadgets/src/inspectionDescriptions/UnnecessarilyQualifiedInnerClassAccess.html index 5d94579c09ba..d29db28c7692 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/UnnecessarilyQualifiedInnerClassAccess.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/UnnecessarilyQualifiedInnerClassAccess.html @@ -1,7 +1,11 @@ This inspection reports any references to inner classes which are unnecessarily qualified with the name -of the enclosing class. Such qualification is unnecessary, and may be safely removed. +of the enclosing class. Such qualification is unnecessary, and may be safely removed. This may +require the addition of an import for the inner class. +

+Use the checkbox below to ignore references to inner classes where the removal of the qualification +would require the addition of an import.

New in 10, Powered by InspectionGadgets From 9f0a0d43d1aa8e456480e3c1712485ef9eb1c446 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 22 Feb 2011 12:55:17 +0100 Subject: [PATCH 079/169] added option to ignore references to local inner classes that do not require an import to "unqualified inner class access" inspection --- .../siyeh/InspectionGadgetsBundle.properties | 1 + ...UnqualifiedInnerClassAccessInspection.java | 50 +++++++++++++++---- .../UnqualifiedInnerClassAccess.html | 2 + 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties index ea8e2dfd6977..ec7b8830a4ba 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties @@ -1852,3 +1852,4 @@ if.can.be.switch.problem.descriptor=#ref statement replaceable with if.can.be.switch.quickfix=Replace with 'switch' if.can.be.switch.minimum.branch.option=Minimum number of branches unnecessarily.qualified.inner.class.access.option=Ignore references to foreign inner classes +unqualified.inner.class.access.option=Ignore references to local inner classes diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedInnerClassAccessInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedInnerClassAccessInspection.java index 01262754a49b..6580869f4b53 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedInnerClassAccessInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedInnerClassAccessInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Bas Leijdekkers + * Copyright 2010-2011 Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,9 +16,11 @@ package com.siyeh.ig.style; import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.Project; import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; @@ -29,10 +31,14 @@ import com.siyeh.ig.psiutils.ImportUtils; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; +import javax.swing.*; import java.util.*; public class UnqualifiedInnerClassAccessInspection extends BaseInspection { + @SuppressWarnings({"PublicField"}) + public boolean ignoreReferencesToLocalInnerClasses = false; + @Nls @NotNull @Override @@ -48,6 +54,14 @@ public class UnqualifiedInnerClassAccessInspection extends BaseInspection { "unqualified.inner.class.access.problem.descriptor"); } + @Override + public JComponent createOptionsPanel() { + return new SingleCheckboxOptionsPanel( + InspectionGadgetsBundle.message( + "unqualified.inner.class.access.option"), + this, "ignoreReferencesToLocalInnerClasses"); + } + @Override protected InspectionGadgetsFix buildFix(Object... infos) { return new UnqualifiedInnerClassAccessFix(); @@ -146,7 +160,8 @@ public class UnqualifiedInnerClassAccessInspection extends BaseInspection { ImportUtils.addImportIfNeeded(javaFile, containingClass); final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project); - final Document document = documentManager.getDocument(containingFile); + final Document document = + documentManager.getDocument(containingFile); if (document == null) { return; } @@ -194,13 +209,15 @@ public class UnqualifiedInnerClassAccessInspection extends BaseInspection { } private static boolean isReferenceToTargetClass( - String referenceText, PsiClass targetClass, PsiElement context) { + String referenceText, PsiClass targetClass, + PsiElement context) { final PsiManager manager = targetClass.getManager(); final JavaPsiFacade facade = JavaPsiFacade.getInstance(manager.getProject()); final PsiResolveHelper resolveHelper = facade.getResolveHelper(); final PsiClass referencedClass = - resolveHelper.resolveReferencedClass(referenceText, context); + resolveHelper.resolveReferencedClass(referenceText, + context); if (referencedClass == null) { return true; } @@ -208,7 +225,8 @@ public class UnqualifiedInnerClassAccessInspection extends BaseInspection { } } - private static class ReferenceCollector extends JavaRecursiveElementVisitor { + private static class ReferenceCollector + extends JavaRecursiveElementVisitor { private final String name; private final boolean onDemand; @@ -265,7 +283,7 @@ public class UnqualifiedInnerClassAccessInspection extends BaseInspection { return new UnqualifiedInnerClassAccessVisitor(); } - private static class UnqualifiedInnerClassAccessVisitor + private class UnqualifiedInnerClassAccessVisitor extends BaseInspectionVisitor { @Override @@ -284,12 +302,24 @@ public class UnqualifiedInnerClassAccessInspection extends BaseInspection { if (containingClass == null) { return; } + if (ignoreReferencesToLocalInnerClasses) { + if (PsiTreeUtil.isAncestor(containingClass, reference, true)) { + return; + } + final PsiClass referenceClass = + PsiTreeUtil.getParentOfType(reference, PsiClass.class); + if (PsiTreeUtil.isAncestor(referenceClass, containingClass, + true)) { + return; + } + } registerError(reference, containingClass.getName()); } - @Override - public void visitReferenceExpression(PsiReferenceExpression expression) { - visitReferenceElement(expression); - } + @Override + public void visitReferenceExpression( + PsiReferenceExpression expression) { + visitReferenceElement(expression); + } } } diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/UnqualifiedInnerClassAccess.html b/plugins/InspectionGadgets/src/inspectionDescriptions/UnqualifiedInnerClassAccess.html index 3776625d5513..77f370cfc018 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/UnqualifiedInnerClassAccess.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/UnqualifiedInnerClassAccess.html @@ -3,6 +3,8 @@ This inspection reports any references to inner classes which are not qualified with the name of the enclosing class.

+Use the checkbox below to ignore references to local inner classes that do not require an import. +

New in 10, Powered by InspectionGadgets \ No newline at end of file From 85ffda4545e579d2e253c273232a17d1a922cf9e Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 22 Feb 2011 15:04:59 +0300 Subject: [PATCH 080/169] logging for weird assertion --- .../intellij/psi/stubs/StubUpdatingIndex.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java index d8d71241774e..c2a3e2d99284 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java @@ -78,10 +78,19 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(l); if (parserDefinition == null) return false; - final IFileElementType filetype = parserDefinition.getFileNodeType(); - return filetype instanceof IStubFileElementType && - (((IStubFileElementType)filetype).shouldBuildStubFor(file) || - IndexingStamp.isFileIndexed(file, INDEX_ID, IndexInfrastructure.getIndexCreationStamp(INDEX_ID))); + final IFileElementType elementType = parserDefinition.getFileNodeType(); + boolean b = elementType instanceof IStubFileElementType && + (((IStubFileElementType)elementType).shouldBuildStubFor(file) || + IndexingStamp.isFileIndexed(file, INDEX_ID, IndexInfrastructure.getIndexCreationStamp(INDEX_ID))); + if (b) { + String extension = file.getExtension(); + LOG.assertTrue(!"xml".equalsIgnoreCase(extension) && !"tld".equalsIgnoreCase(extension), "File: " + file + + " language: " + l + + " filetype: " + fileType + + " element type: " + elementType + ); + } + return b; } else if (fileType.isBinary()) { final BinaryFileStubBuilder builder = BinaryFileStubBuilders.INSTANCE.forFileType(fileType); From eda946513b8dd5695ba50c9402b75fe6bbecc4a7 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 22 Feb 2011 14:05:57 +0100 Subject: [PATCH 081/169] rename package jdk15 to migration --- .../src/com/siyeh/ig/BaseInspection.java | 2 +- .../src/com/siyeh/ig/InspectionGadgetsPlugin.java | 8 ++++---- ...tionsFieldAccessReplaceableByMethodCallInspection.java | 2 +- .../EnumerationCanBeIterationInspection.java | 2 +- .../{jdk15 => migration}/ForCanBeForeachInspection.java | 2 +- .../IndexOfReplaceableByContainsInspection.java | 2 +- .../RawUseOfParameterizedTypeInspection.java | 2 +- .../{jdk15 => migration}/UnnecessaryBoxingInspection.java | 2 +- .../UnnecessaryUnboxingInspection.java | 2 +- .../{jdk15 => migration}/WhileCanBeForeachInspection.java | 2 +- .../EnumerationCanBeIterationInspection.java | 2 +- .../{jdk15 => migration}/foreach/ForCanBeForEach.java | 2 +- .../igtest/{jdk15 => migration}/foreach/expected.xml | 0 .../unnecessary_boxing/UnnecessaryBoxing.java | 2 +- .../{jdk15 => migration}/unnecessary_boxing/expected.xml | 0 .../unnecessary_unboxing/UnnecessaryUnboxing.java | 2 +- .../unnecessary_unboxing/expected.xml | 0 .../while_can_be_foreach/WhileCanBeForeachInspection.java | 2 +- .../while_can_be_foreach/expected.xml | 0 .../ForCanBeForeachInspectionTest.java | 4 ++-- .../UnnecessaryBoxingInspectionTest.java | 4 ++-- .../UnnecessaryUnboxingInspectionTest.java | 4 ++-- .../WhileCanBeForeachInspectionTest.java | 4 ++-- 23 files changed, 26 insertions(+), 26 deletions(-) rename plugins/InspectionGadgets/src/com/siyeh/ig/{jdk15 => migration}/CollectionsFieldAccessReplaceableByMethodCallInspection.java (99%) rename plugins/InspectionGadgets/src/com/siyeh/ig/{jdk15 => migration}/EnumerationCanBeIterationInspection.java (99%) rename plugins/InspectionGadgets/src/com/siyeh/ig/{jdk15 => migration}/ForCanBeForeachInspection.java (99%) rename plugins/InspectionGadgets/src/com/siyeh/ig/{jdk15 => migration}/IndexOfReplaceableByContainsInspection.java (99%) rename plugins/InspectionGadgets/src/com/siyeh/ig/{jdk15 => migration}/RawUseOfParameterizedTypeInspection.java (99%) rename plugins/InspectionGadgets/src/com/siyeh/ig/{jdk15 => migration}/UnnecessaryBoxingInspection.java (99%) rename plugins/InspectionGadgets/src/com/siyeh/ig/{jdk15 => migration}/UnnecessaryUnboxingInspection.java (99%) rename plugins/InspectionGadgets/src/com/siyeh/ig/{jdk15 => migration}/WhileCanBeForeachInspection.java (99%) rename plugins/InspectionGadgets/test/com/siyeh/igtest/{jdk15 => migration}/EnumerationCanBeIterationInspection.java (96%) rename plugins/InspectionGadgets/test/com/siyeh/igtest/{jdk15 => migration}/foreach/ForCanBeForEach.java (99%) rename plugins/InspectionGadgets/test/com/siyeh/igtest/{jdk15 => migration}/foreach/expected.xml (100%) rename plugins/InspectionGadgets/test/com/siyeh/igtest/{jdk15 => migration}/unnecessary_boxing/UnnecessaryBoxing.java (96%) rename plugins/InspectionGadgets/test/com/siyeh/igtest/{jdk15 => migration}/unnecessary_boxing/expected.xml (100%) rename plugins/InspectionGadgets/test/com/siyeh/igtest/{jdk15 => migration}/unnecessary_unboxing/UnnecessaryUnboxing.java (94%) rename plugins/InspectionGadgets/test/com/siyeh/igtest/{jdk15 => migration}/unnecessary_unboxing/expected.xml (100%) rename plugins/InspectionGadgets/test/com/siyeh/igtest/{jdk15 => migration}/while_can_be_foreach/WhileCanBeForeachInspection.java (96%) rename plugins/InspectionGadgets/test/com/siyeh/igtest/{jdk15 => migration}/while_can_be_foreach/expected.xml (100%) rename plugins/InspectionGadgets/testsrc/com/siyeh/ig/{jdk15 => migration}/ForCanBeForeachInspectionTest.java (57%) rename plugins/InspectionGadgets/testsrc/com/siyeh/ig/{jdk15 => migration}/UnnecessaryBoxingInspectionTest.java (68%) rename plugins/InspectionGadgets/testsrc/com/siyeh/ig/{jdk15 => migration}/UnnecessaryUnboxingInspectionTest.java (68%) rename plugins/InspectionGadgets/testsrc/com/siyeh/ig/{jdk15 => migration}/WhileCanBeForeachInspectionTest.java (68%) diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/BaseInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/BaseInspection.java index 5deb22cc2a72..1d20d6af62f1 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/BaseInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/BaseInspection.java @@ -74,7 +74,7 @@ public abstract class BaseInspection extends BaseJavaLocalInspectionTool { packageGroupDisplayNameMap.put("javabeans", GroupNames.JAVABEANS_GROUP_NAME); packageGroupDisplayNameMap.put("javadoc", GroupNames.JAVADOC_GROUP_NAME); packageGroupDisplayNameMap.put("jdk", GroupNames.JDK_GROUP_NAME); - packageGroupDisplayNameMap.put("jdk15", GroupNames.LANGUAGE_LEVEL_SPECIFIC_GROUP_NAME); + packageGroupDisplayNameMap.put("migration", GroupNames.LANGUAGE_LEVEL_SPECIFIC_GROUP_NAME); packageGroupDisplayNameMap.put("junit", GroupNames.JUNIT_GROUP_NAME); packageGroupDisplayNameMap.put("logging", GroupNames.LOGGING_GROUP_NAME); packageGroupDisplayNameMap.put("maturity", GroupNames.MATURITY_GROUP_NAME); diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionGadgetsPlugin.java b/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionGadgetsPlugin.java index 5c6a5b9a75b1..c41a237911c1 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionGadgetsPlugin.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionGadgetsPlugin.java @@ -58,7 +58,7 @@ import com.siyeh.ig.javadoc.PackageDotHtmlMayBePackageInfoInspection; import com.siyeh.ig.javadoc.UnnecessaryInheritDocInspection; import com.siyeh.ig.javadoc.UnnecessaryJavaDocLinkInspection; import com.siyeh.ig.jdk.*; -import com.siyeh.ig.jdk15.*; +import com.siyeh.ig.migration.*; import com.siyeh.ig.junit.*; import com.siyeh.ig.logging.*; import com.siyeh.ig.maturity.*; @@ -296,7 +296,7 @@ public class InspectionGadgetsPlugin implements ApplicationComponent, registerJ2MEInspections(); registerJavaBeansInspections(); registerJavadocInspections(); - registerJdk5SpecificInspections(); + registerLanguageLevelMigrationInspections(); registerJdkInspections(); registerJUnitInspections(); registerLoggingInspections(); @@ -481,7 +481,6 @@ public class InspectionGadgetsPlugin implements ApplicationComponent, m_inspectionClasses.add(FallthruInSwitchStatementInspection.class); m_inspectionClasses.add(ForLoopReplaceableByWhileInspection.class); m_inspectionClasses.add(ForLoopWithMissingComponentInspection.class); - m_inspectionClasses.add(IfCanBeSwitchInspection.class); m_inspectionClasses.add(IfMayBeConditionalInspection.class); m_inspectionClasses.add(IfStatementWithIdenticalBranchesInspection.class); m_inspectionClasses.add(IfStatementWithTooManyBranchesInspection.class); @@ -625,10 +624,11 @@ public class InspectionGadgetsPlugin implements ApplicationComponent, m_inspectionClasses.add(ReplaceAssignmentWithOperatorAssignmentInspection.class); } - private void registerJdk5SpecificInspections() { + private void registerLanguageLevelMigrationInspections() { m_inspectionClasses.add(CollectionsFieldAccessReplaceableByMethodCallInspection .class); m_inspectionClasses.add(ForCanBeForeachInspection.class); m_inspectionClasses.add(EnumerationCanBeIterationInspection.class); + m_inspectionClasses.add(IfCanBeSwitchInspection.class); m_inspectionClasses.add(IndexOfReplaceableByContainsInspection.class); m_inspectionClasses.add(RawUseOfParameterizedTypeInspection.class); m_inspectionClasses.add(UnnecessaryBoxingInspection.class); diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/CollectionsFieldAccessReplaceableByMethodCallInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/CollectionsFieldAccessReplaceableByMethodCallInspection.java similarity index 99% rename from plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/CollectionsFieldAccessReplaceableByMethodCallInspection.java rename to plugins/InspectionGadgets/src/com/siyeh/ig/migration/CollectionsFieldAccessReplaceableByMethodCallInspection.java index dda2605db29e..5390fe0d939c 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/CollectionsFieldAccessReplaceableByMethodCallInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/CollectionsFieldAccessReplaceableByMethodCallInspection.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.siyeh.ig.jdk15; +package com.siyeh.ig.migration; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/EnumerationCanBeIterationInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/EnumerationCanBeIterationInspection.java similarity index 99% rename from plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/EnumerationCanBeIterationInspection.java rename to plugins/InspectionGadgets/src/com/siyeh/ig/migration/EnumerationCanBeIterationInspection.java index 7d56268a6a55..4845a85b74a4 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/EnumerationCanBeIterationInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/EnumerationCanBeIterationInspection.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.siyeh.ig.jdk15; +package com.siyeh.ig.migration; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/ForCanBeForeachInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/ForCanBeForeachInspection.java similarity index 99% rename from plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/ForCanBeForeachInspection.java rename to plugins/InspectionGadgets/src/com/siyeh/ig/migration/ForCanBeForeachInspection.java index f8f3b37f7a87..c88e5d45ee81 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/ForCanBeForeachInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/ForCanBeForeachInspection.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.siyeh.ig.jdk15; +package com.siyeh.ig.migration; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/IndexOfReplaceableByContainsInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/IndexOfReplaceableByContainsInspection.java similarity index 99% rename from plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/IndexOfReplaceableByContainsInspection.java rename to plugins/InspectionGadgets/src/com/siyeh/ig/migration/IndexOfReplaceableByContainsInspection.java index f8c46f80a7a3..c656f993a111 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/IndexOfReplaceableByContainsInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/IndexOfReplaceableByContainsInspection.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.siyeh.ig.jdk15; +package com.siyeh.ig.migration; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/RawUseOfParameterizedTypeInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/RawUseOfParameterizedTypeInspection.java similarity index 99% rename from plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/RawUseOfParameterizedTypeInspection.java rename to plugins/InspectionGadgets/src/com/siyeh/ig/migration/RawUseOfParameterizedTypeInspection.java index 029f378ccaa2..ed73360db49c 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/RawUseOfParameterizedTypeInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/RawUseOfParameterizedTypeInspection.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.siyeh.ig.jdk15; +package com.siyeh.ig.migration; import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel; import com.intellij.lang.StdLanguages; diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/UnnecessaryBoxingInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/UnnecessaryBoxingInspection.java similarity index 99% rename from plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/UnnecessaryBoxingInspection.java rename to plugins/InspectionGadgets/src/com/siyeh/ig/migration/UnnecessaryBoxingInspection.java index 46c65ed6d623..932f59af5063 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/UnnecessaryBoxingInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/UnnecessaryBoxingInspection.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.siyeh.ig.jdk15; +package com.siyeh.ig.migration; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/UnnecessaryUnboxingInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/UnnecessaryUnboxingInspection.java similarity index 99% rename from plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/UnnecessaryUnboxingInspection.java rename to plugins/InspectionGadgets/src/com/siyeh/ig/migration/UnnecessaryUnboxingInspection.java index 090092544f3e..0d8c1da0e178 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/UnnecessaryUnboxingInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/UnnecessaryUnboxingInspection.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.siyeh.ig.jdk15; +package com.siyeh.ig.migration; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/WhileCanBeForeachInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/WhileCanBeForeachInspection.java similarity index 99% rename from plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/WhileCanBeForeachInspection.java rename to plugins/InspectionGadgets/src/com/siyeh/ig/migration/WhileCanBeForeachInspection.java index 3472dff50aba..459326faac37 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/jdk15/WhileCanBeForeachInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/WhileCanBeForeachInspection.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.siyeh.ig.jdk15; +package com.siyeh.ig.migration; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk15/EnumerationCanBeIterationInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/EnumerationCanBeIterationInspection.java similarity index 96% rename from plugins/InspectionGadgets/test/com/siyeh/igtest/jdk15/EnumerationCanBeIterationInspection.java rename to plugins/InspectionGadgets/test/com/siyeh/igtest/migration/EnumerationCanBeIterationInspection.java index a56cac6bb65d..d218c3beae74 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk15/EnumerationCanBeIterationInspection.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/EnumerationCanBeIterationInspection.java @@ -1,4 +1,4 @@ -package com.siyeh.igtest.jdk15; +package com.siyeh.igtest.migration; import java.util.Vector; import java.util.Hashtable; diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk15/foreach/ForCanBeForEach.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/foreach/ForCanBeForEach.java similarity index 99% rename from plugins/InspectionGadgets/test/com/siyeh/igtest/jdk15/foreach/ForCanBeForEach.java rename to plugins/InspectionGadgets/test/com/siyeh/igtest/migration/foreach/ForCanBeForEach.java index 8da347ac246b..51d5a37047fb 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk15/foreach/ForCanBeForEach.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/foreach/ForCanBeForEach.java @@ -1,4 +1,4 @@ -package com.siyeh.igtest.jdk15.foreach; +package com.siyeh.igtest.migration.foreach; import com.siyeh.igtest.verbose.OuterClass; diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk15/foreach/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/foreach/expected.xml similarity index 100% rename from plugins/InspectionGadgets/test/com/siyeh/igtest/jdk15/foreach/expected.xml rename to plugins/InspectionGadgets/test/com/siyeh/igtest/migration/foreach/expected.xml diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk15/unnecessary_boxing/UnnecessaryBoxing.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/unnecessary_boxing/UnnecessaryBoxing.java similarity index 96% rename from plugins/InspectionGadgets/test/com/siyeh/igtest/jdk15/unnecessary_boxing/UnnecessaryBoxing.java rename to plugins/InspectionGadgets/test/com/siyeh/igtest/migration/unnecessary_boxing/UnnecessaryBoxing.java index 70e5bf746ca0..a25f0bcdb679 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk15/unnecessary_boxing/UnnecessaryBoxing.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/unnecessary_boxing/UnnecessaryBoxing.java @@ -1,4 +1,4 @@ -package com.siyeh.igtest.jdk15.unnecessary_boxing; +package com.siyeh.igtest.migration.unnecessary_boxing; diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk15/unnecessary_boxing/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/unnecessary_boxing/expected.xml similarity index 100% rename from plugins/InspectionGadgets/test/com/siyeh/igtest/jdk15/unnecessary_boxing/expected.xml rename to plugins/InspectionGadgets/test/com/siyeh/igtest/migration/unnecessary_boxing/expected.xml diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk15/unnecessary_unboxing/UnnecessaryUnboxing.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/unnecessary_unboxing/UnnecessaryUnboxing.java similarity index 94% rename from plugins/InspectionGadgets/test/com/siyeh/igtest/jdk15/unnecessary_unboxing/UnnecessaryUnboxing.java rename to plugins/InspectionGadgets/test/com/siyeh/igtest/migration/unnecessary_unboxing/UnnecessaryUnboxing.java index d772cf1da396..d83a1f862083 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk15/unnecessary_unboxing/UnnecessaryUnboxing.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/unnecessary_unboxing/UnnecessaryUnboxing.java @@ -1,4 +1,4 @@ -package com.siyeh.igtest.jdk15.unnecessary_unboxing; +package com.siyeh.igtest.migration.unnecessary_unboxing; diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk15/unnecessary_unboxing/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/unnecessary_unboxing/expected.xml similarity index 100% rename from plugins/InspectionGadgets/test/com/siyeh/igtest/jdk15/unnecessary_unboxing/expected.xml rename to plugins/InspectionGadgets/test/com/siyeh/igtest/migration/unnecessary_unboxing/expected.xml diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk15/while_can_be_foreach/WhileCanBeForeachInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/while_can_be_foreach/WhileCanBeForeachInspection.java similarity index 96% rename from plugins/InspectionGadgets/test/com/siyeh/igtest/jdk15/while_can_be_foreach/WhileCanBeForeachInspection.java rename to plugins/InspectionGadgets/test/com/siyeh/igtest/migration/while_can_be_foreach/WhileCanBeForeachInspection.java index b6c5d5dbf840..1c7703507fe5 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk15/while_can_be_foreach/WhileCanBeForeachInspection.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/while_can_be_foreach/WhileCanBeForeachInspection.java @@ -1,4 +1,4 @@ -package com.siyeh.igtest.jdk15.while_can_be_foreach; +package com.siyeh.igtest.migration.while_can_be_foreach; import java.util.*; diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk15/while_can_be_foreach/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/while_can_be_foreach/expected.xml similarity index 100% rename from plugins/InspectionGadgets/test/com/siyeh/igtest/jdk15/while_can_be_foreach/expected.xml rename to plugins/InspectionGadgets/test/com/siyeh/igtest/migration/while_can_be_foreach/expected.xml diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/jdk15/ForCanBeForeachInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/ForCanBeForeachInspectionTest.java similarity index 57% rename from plugins/InspectionGadgets/testsrc/com/siyeh/ig/jdk15/ForCanBeForeachInspectionTest.java rename to plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/ForCanBeForeachInspectionTest.java index 7ac680a8c3b6..e68038fbc0a6 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/jdk15/ForCanBeForeachInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/ForCanBeForeachInspectionTest.java @@ -1,4 +1,4 @@ -package com.siyeh.ig.jdk15; +package com.siyeh.ig.migration; import com.IGInspectionTestCase; import com.intellij.codeInspection.ex.LocalInspectionToolWrapper; @@ -6,6 +6,6 @@ import com.intellij.codeInspection.ex.LocalInspectionToolWrapper; public class ForCanBeForeachInspectionTest extends IGInspectionTestCase { public void test() throws Exception { - doTest("com/siyeh/igtest/jdk15/foreach", new LocalInspectionToolWrapper(new ForCanBeForeachInspection()), "java 1.5"); + doTest("com/siyeh/igtest/migration/foreach", new LocalInspectionToolWrapper(new ForCanBeForeachInspection()), "java 1.5"); } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/jdk15/UnnecessaryBoxingInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/UnnecessaryBoxingInspectionTest.java similarity index 68% rename from plugins/InspectionGadgets/testsrc/com/siyeh/ig/jdk15/UnnecessaryBoxingInspectionTest.java rename to plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/UnnecessaryBoxingInspectionTest.java index 06d88ec849d1..e3041773eb5f 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/jdk15/UnnecessaryBoxingInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/UnnecessaryBoxingInspectionTest.java @@ -1,11 +1,11 @@ -package com.siyeh.ig.jdk15; +package com.siyeh.ig.migration; import com.IGInspectionTestCase; public class UnnecessaryBoxingInspectionTest extends IGInspectionTestCase { public void test() throws Exception { - doTest("com/siyeh/igtest/jdk15/unnecessary_boxing", + doTest("com/siyeh/igtest/migration/unnecessary_boxing", new UnnecessaryBoxingInspection()); } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/jdk15/UnnecessaryUnboxingInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/UnnecessaryUnboxingInspectionTest.java similarity index 68% rename from plugins/InspectionGadgets/testsrc/com/siyeh/ig/jdk15/UnnecessaryUnboxingInspectionTest.java rename to plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/UnnecessaryUnboxingInspectionTest.java index 185923eef5e0..7cffee7eec27 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/jdk15/UnnecessaryUnboxingInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/UnnecessaryUnboxingInspectionTest.java @@ -1,11 +1,11 @@ -package com.siyeh.ig.jdk15; +package com.siyeh.ig.migration; import com.IGInspectionTestCase; public class UnnecessaryUnboxingInspectionTest extends IGInspectionTestCase { public void test() throws Exception { - doTest("com/siyeh/igtest/jdk15/unnecessary_unboxing", + doTest("com/siyeh/igtest/migration/unnecessary_unboxing", new UnnecessaryUnboxingInspection()); } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/jdk15/WhileCanBeForeachInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/WhileCanBeForeachInspectionTest.java similarity index 68% rename from plugins/InspectionGadgets/testsrc/com/siyeh/ig/jdk15/WhileCanBeForeachInspectionTest.java rename to plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/WhileCanBeForeachInspectionTest.java index e8c5959b9087..9352af5030ac 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/jdk15/WhileCanBeForeachInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/WhileCanBeForeachInspectionTest.java @@ -1,11 +1,11 @@ -package com.siyeh.ig.jdk15; +package com.siyeh.ig.migration; import com.IGInspectionTestCase; public class WhileCanBeForeachInspectionTest extends IGInspectionTestCase { public void test() throws Exception { - doTest("com/siyeh/igtest/jdk15/while_can_be_foreach", + doTest("com/siyeh/igtest/migration/while_can_be_foreach", new WhileCanBeForeachInspection()); } } From 08d549492c46b438a4bb0301fa32b207e32179dd Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 22 Feb 2011 10:32:49 +0100 Subject: [PATCH 082/169] clean read-only status --- .../daemon/impl/analysis/AnnotationsHighlightUtil.java | 2 ++ .../codeInspection/ExplicitTypeCanBeDiamondInspection.java | 2 ++ 2 files changed, 4 insertions(+) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java index 1890c7098760..233825ad6688 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java @@ -16,6 +16,7 @@ package com.intellij.codeInsight.daemon.impl.analysis; import com.intellij.codeInsight.AnnotationUtil; +import com.intellij.codeInsight.CodeInsightUtilBase; import com.intellij.codeInsight.daemon.JavaErrorMessages; import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInsight.daemon.impl.HighlightInfoType; @@ -480,6 +481,7 @@ public class AnnotationsHighlightUtil { @Override public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + if (!CodeInsightUtilBase.prepareFileForWrite(file)) return; myAnnotation.delete(); } diff --git a/java/java-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java b/java/java-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java index 57c3d2a43852..6cf445dd6a69 100644 --- a/java/java-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInspection; +import com.intellij.codeInsight.CodeInsightUtilBase; import com.intellij.codeInsight.daemon.GroupNames; import com.intellij.codeInsight.intention.HighPriorityAction; import com.intellij.openapi.project.Project; @@ -124,6 +125,7 @@ public class ExplicitTypeCanBeDiamondInspection extends BaseJavaLocalInspectionT public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { final PsiElement psiElement = descriptor.getPsiElement(); if (psiElement instanceof PsiReferenceParameterList) { + if (!CodeInsightUtilBase.prepareFileForWrite(psiElement.getContainingFile())) return; final PsiTypeElement[] parameterElements = ((PsiReferenceParameterList)psiElement).getTypeParameterElements(); psiElement.deleteChildRange(parameterElements[0], parameterElements[parameterElements.length - 1]); } From 5515464ddfb18c0184ab1d96e62c39f686d65350 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 22 Feb 2011 12:38:53 +0100 Subject: [PATCH 083/169] move run configuration refactoring listener to platform --- .../execution/configurations/RefactoringListenerProvider.java | 0 .../RunConfigurationRefactoringElementListenerProvider.java | 0 platform/platform-resources/src/META-INF/LangExtensions.xml | 1 + resources/src/META-INF/IdeaPlugin.xml | 2 -- 4 files changed, 1 insertion(+), 2 deletions(-) rename {java/execution/openapi => platform/lang-api}/src/com/intellij/execution/configurations/RefactoringListenerProvider.java (100%) rename {java/execution/impl => platform/lang-impl}/src/com/intellij/execution/impl/RunConfigurationRefactoringElementListenerProvider.java (100%) diff --git a/java/execution/openapi/src/com/intellij/execution/configurations/RefactoringListenerProvider.java b/platform/lang-api/src/com/intellij/execution/configurations/RefactoringListenerProvider.java similarity index 100% rename from java/execution/openapi/src/com/intellij/execution/configurations/RefactoringListenerProvider.java rename to platform/lang-api/src/com/intellij/execution/configurations/RefactoringListenerProvider.java diff --git a/java/execution/impl/src/com/intellij/execution/impl/RunConfigurationRefactoringElementListenerProvider.java b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationRefactoringElementListenerProvider.java similarity index 100% rename from java/execution/impl/src/com/intellij/execution/impl/RunConfigurationRefactoringElementListenerProvider.java rename to platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationRefactoringElementListenerProvider.java diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index 3cf38093581e..a661a767e16c 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -610,4 +610,5 @@ + diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 9a8aa3592a9e..506ed2dc7daa 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -1160,8 +1160,6 @@ - - From 5e792f7395ec3ac97bb20233048ce411c5bba77b Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 22 Feb 2011 13:20:21 +0100 Subject: [PATCH 084/169] remove code duplication: introduce and use RefactoringElementAdapter --- .../execution/junit/RefactoringListeners.java | 22 +++++------- .../listeners/RefactoringElementAdapter.java | 36 +++++++++++++++++++ ...factoringScopeElementListenerProvider.java | 14 ++------ .../android/run/AndroidRunConfiguration.java | 9 ++--- .../intellij/execution/junit/TestMethod.java | 15 +++----- .../configuration/TestNGConfiguration.java | 15 +++----- .../PaletteRefactoringListenerProvider.java | 9 ++--- 7 files changed, 61 insertions(+), 59 deletions(-) create mode 100644 platform/lang-api/src/com/intellij/refactoring/listeners/RefactoringElementAdapter.java diff --git a/java/execution/impl/src/com/intellij/execution/junit/RefactoringListeners.java b/java/execution/impl/src/com/intellij/execution/junit/RefactoringListeners.java index 7e88f7ea46ea..fd2518cb3a5f 100644 --- a/java/execution/impl/src/com/intellij/execution/junit/RefactoringListeners.java +++ b/java/execution/impl/src/com/intellij/execution/junit/RefactoringListeners.java @@ -22,6 +22,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.refactoring.listeners.RefactoringElementAdapter; import com.intellij.refactoring.listeners.RefactoringElementListener; import org.jetbrains.annotations.NotNull; @@ -85,7 +86,7 @@ public class RefactoringListeners { } } - private static abstract class RenameElement implements RefactoringElementListener { + private static abstract class RenameElement extends RefactoringElementAdapter { private final Accessor myAccessor; private final String myPath; @@ -94,22 +95,15 @@ public class RefactoringListeners { myPath = path; } - public void elementMoved(@NotNull final PsiElement newElement) { - setName((T)newElement); - } - - public void elementRenamed(@NotNull final PsiElement newElement) { - setName((T)newElement); - } - - private void setName(@NotNull T newElement) { - String qualifiedName = getQualifiedName(newElement); + public void elementRenamedOrMoved(@NotNull final PsiElement newElement) { + T newElement1 = (T)newElement; + String qualifiedName = getQualifiedName(newElement1); if (myPath.length() > 0) { qualifiedName = qualifiedName + "." + myPath; - newElement = findNewElement(newElement, qualifiedName); + newElement1 = findNewElement(newElement1, qualifiedName); } - if (newElement != null) { - myAccessor.setPsiElement(newElement); + if (newElement1 != null) { + myAccessor.setPsiElement(newElement1); } else { myAccessor.setName(qualifiedName); diff --git a/platform/lang-api/src/com/intellij/refactoring/listeners/RefactoringElementAdapter.java b/platform/lang-api/src/com/intellij/refactoring/listeners/RefactoringElementAdapter.java new file mode 100644 index 000000000000..11cba838d421 --- /dev/null +++ b/platform/lang-api/src/com/intellij/refactoring/listeners/RefactoringElementAdapter.java @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2011 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 com.intellij.refactoring.listeners; + +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; + +/** + * @author yole + */ +public abstract class RefactoringElementAdapter implements RefactoringElementListener { + @Override + public final void elementMoved(@NotNull PsiElement newElement) { + elementRenamedOrMoved(newElement); + } + + protected abstract void elementRenamedOrMoved(@NotNull PsiElement newElement); + + @Override + public final void elementRenamed(@NotNull PsiElement newElement) { + elementRenamedOrMoved(newElement); + } +} diff --git a/platform/lang-impl/src/com/intellij/packageDependencies/ui/RefactoringScopeElementListenerProvider.java b/platform/lang-impl/src/com/intellij/packageDependencies/ui/RefactoringScopeElementListenerProvider.java index 505ed9dbb175..940cbe6d37c8 100644 --- a/platform/lang-impl/src/com/intellij/packageDependencies/ui/RefactoringScopeElementListenerProvider.java +++ b/platform/lang-impl/src/com/intellij/packageDependencies/ui/RefactoringScopeElementListenerProvider.java @@ -20,6 +20,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiQualifiedNamedElement; import com.intellij.psi.search.scope.packageSet.*; +import com.intellij.refactoring.listeners.RefactoringElementAdapter; import com.intellij.refactoring.listeners.RefactoringElementListener; import com.intellij.refactoring.listeners.RefactoringElementListenerComposite; import com.intellij.refactoring.listeners.RefactoringElementListenerProvider; @@ -80,18 +81,9 @@ public class RefactoringScopeElementListenerProvider implements RefactoringEleme if (composite == null) { composite = new RefactoringElementListenerComposite(); } - composite.addListener(new RefactoringElementListener() { + composite.addListener(new RefactoringElementAdapter() { @Override - public void elementMoved(@NotNull PsiElement newElement) { - setName(newElement); - } - - @Override - public void elementRenamed(@NotNull PsiElement newElement) { - setName(newElement); - } - - private void setName(@NotNull PsiElement newElement) { + public void elementRenamedOrMoved(@NotNull PsiElement newElement) { LOG.assertTrue(newElement instanceof PsiQualifiedNamedElement); try { final String newPattern = text.replace(descriptor.getOldQName(), ((PsiQualifiedNamedElement)newElement).getQualifiedName()); diff --git a/plugins/android/src/org/jetbrains/android/run/AndroidRunConfiguration.java b/plugins/android/src/org/jetbrains/android/run/AndroidRunConfiguration.java index 64dd0fc2cb42..5c8b414c6f0b 100644 --- a/plugins/android/src/org/jetbrains/android/run/AndroidRunConfiguration.java +++ b/plugins/android/src/org/jetbrains/android/run/AndroidRunConfiguration.java @@ -35,6 +35,7 @@ import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.search.ProjectScope; +import com.intellij.refactoring.listeners.RefactoringElementAdapter; import com.intellij.refactoring.listeners.RefactoringElementListener; import org.jetbrains.android.dom.manifest.Manifest; import org.jetbrains.android.facet.AndroidFacet; @@ -115,12 +116,8 @@ public class AndroidRunConfiguration extends AndroidRunConfigurationBase impleme @Nullable public RefactoringElementListener getRefactoringElementListener(PsiElement element) { if (element instanceof PsiClass && Comparing.strEqual(((PsiClass)element).getQualifiedName(), ACTIVITY_CLASS, true)) { - return new RefactoringElementListener() { - public void elementMoved(@NotNull PsiElement newElement) { - ACTIVITY_CLASS = ((PsiClass)newElement).getQualifiedName(); - } - - public void elementRenamed(@NotNull PsiElement newElement) { + return new RefactoringElementAdapter() { + public void elementRenamedOrMoved(@NotNull PsiElement newElement) { ACTIVITY_CLASS = ((PsiClass)newElement).getQualifiedName(); } }; diff --git a/plugins/junit/src/com/intellij/execution/junit/TestMethod.java b/plugins/junit/src/com/intellij/execution/junit/TestMethod.java index 5ad9dbf38108..63a2ec4e13ac 100644 --- a/plugins/junit/src/com/intellij/execution/junit/TestMethod.java +++ b/plugins/junit/src/com/intellij/execution/junit/TestMethod.java @@ -26,6 +26,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiPackage; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.refactoring.listeners.RefactoringElementAdapter; import com.intellij.refactoring.listeners.RefactoringElementListener; import com.intellij.rt.execution.junit.JUnitStarter; import org.jetbrains.annotations.NotNull; @@ -78,18 +79,10 @@ class TestMethod extends TestObject { final PsiMethod method = (PsiMethod)element; if (!method.getName().equals(configuration.getPersistentData().getMethodName())) return null; if (!method.getContainingClass().equals(configuration.myClass.getPsiElement())) return null; - return new RefactoringElementListener() { - public void elementMoved(@NotNull final PsiElement newElement) { - setMethod(configuration, (PsiMethod)newElement); - } - - public void elementRenamed(@NotNull final PsiElement newElement) { - setMethod(configuration, (PsiMethod)newElement); - } - - private void setMethod(final JUnitConfiguration configuration, final PsiMethod psiMethod) { + return new RefactoringElementAdapter() { + public void elementRenamedOrMoved(@NotNull final PsiElement newElement) { final boolean generatedName = configuration.isGeneratedName(); - configuration.getPersistentData().setTestMethod(PsiLocation.fromPsiElement(psiMethod)); + configuration.getPersistentData().setTestMethod(PsiLocation.fromPsiElement((PsiMethod)newElement)); if (generatedName) configuration.setGeneratedName(); } }; diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfiguration.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfiguration.java index a12c01192498..1678e3670bfb 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfiguration.java +++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfiguration.java @@ -39,6 +39,7 @@ import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.WriteExternalException; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.refactoring.listeners.RefactoringElementAdapter; import com.intellij.refactoring.listeners.RefactoringElementListener; import com.theoryinpractice.testng.model.TestData; import com.theoryinpractice.testng.model.TestType; @@ -395,18 +396,10 @@ public class TestNGConfiguration extends ModuleBasedConfiguration Date: Tue, 22 Feb 2011 13:56:45 +0100 Subject: [PATCH 085/169] crash proof --- ...figurationRefactoringElementListenerProvider.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationRefactoringElementListenerProvider.java b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationRefactoringElementListenerProvider.java index 0b3b8f13629a..5940a623731c 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationRefactoringElementListenerProvider.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationRefactoringElementListenerProvider.java @@ -18,6 +18,7 @@ package com.intellij.execution.impl; import com.intellij.execution.RunManager; import com.intellij.execution.configurations.RefactoringListenerProvider; import com.intellij.execution.configurations.RunConfiguration; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.PsiElement; import com.intellij.refactoring.listeners.RefactoringElementListener; import com.intellij.refactoring.listeners.RefactoringElementListenerComposite; @@ -27,13 +28,22 @@ import com.intellij.refactoring.listeners.RefactoringElementListenerProvider; * @author spleaner */ public class RunConfigurationRefactoringElementListenerProvider implements RefactoringElementListenerProvider { + private static final Logger LOG = Logger.getInstance("#com.intellij.execution.impl.RunConfigurationRefactoringElementListenerProvider"); + public RefactoringElementListener getListener(final PsiElement element) { RefactoringElementListenerComposite composite = null; final RunConfiguration[] configurations = RunManager.getInstance(element.getProject()).getAllConfigurations(); for (RunConfiguration configuration : configurations) { if (configuration instanceof RefactoringListenerProvider) { // todo: perhaps better way to handle listeners? - final RefactoringElementListener listener = ((RefactoringListenerProvider)configuration).getRefactoringElementListener(element); + final RefactoringElementListener listener; + try { + listener = ((RefactoringListenerProvider)configuration).getRefactoringElementListener(element); + } + catch (Exception e) { + LOG.error(e); + continue; + } if (listener != null) { if (composite == null) { composite = new RefactoringElementListenerComposite(); From 20812d36f8b3c50fe2806400496963661c5a8a7e Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 22 Feb 2011 16:33:55 +0100 Subject: [PATCH 086/169] move "If replaceable with switch statement" inspection to migration aids group to make it more discoverable added options to (not) report on int and enum switches --- .../siyeh/InspectionGadgetsBundle.properties | 2 + .../IfCanBeSwitchInspection.java | 93 +++++++++++++++++-- .../IfStatementBranch.java | 34 +++---- 3 files changed, 106 insertions(+), 23 deletions(-) rename plugins/InspectionGadgets/src/com/siyeh/ig/{controlflow => migration}/IfCanBeSwitchInspection.java (84%) rename plugins/InspectionGadgets/src/com/siyeh/ig/{controlflow => migration}/IfStatementBranch.java (80%) diff --git a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties index ec7b8830a4ba..bde874a76fa1 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties @@ -1851,5 +1851,7 @@ if.can.be.switch.display.name='if' replaceable with 'switch' if.can.be.switch.problem.descriptor=#ref statement replaceable with 'switch' statement if.can.be.switch.quickfix=Replace with 'switch' if.can.be.switch.minimum.branch.option=Minimum number of branches +if.can.be.switch.int.option=Suggest switch on int +if.can.be.switch.enum.option=Suggest switch on enum unnecessarily.qualified.inner.class.access.option=Ignore references to foreign inner classes unqualified.inner.class.access.option=Ignore references to local inner classes diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/IfCanBeSwitchInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/IfCanBeSwitchInspection.java similarity index 84% rename from plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/IfCanBeSwitchInspection.java rename to plugins/InspectionGadgets/src/com/siyeh/ig/migration/IfCanBeSwitchInspection.java index 1c4a722745c5..5b2c1d0925c6 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/IfCanBeSwitchInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/IfCanBeSwitchInspection.java @@ -13,14 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.siyeh.ig.controlflow; +package com.siyeh.ig.migration; import com.intellij.codeInspection.ProblemDescriptor; -import com.intellij.codeInspection.ui.SingleIntegerFieldOptionsPanel; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.ui.DocumentAdapter; import com.intellij.util.IncorrectOperationException; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; @@ -35,6 +35,13 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.DocumentEvent; +import javax.swing.text.Document; +import java.awt.*; +import java.text.NumberFormat; +import java.text.ParseException; import java.util.ArrayList; import java.util.List; @@ -43,6 +50,12 @@ public class IfCanBeSwitchInspection extends BaseInspection { @SuppressWarnings({"PublicField"}) public int minimumBranches = 3; + @SuppressWarnings({"PublicField"}) + public boolean suggestIntSwitches = false; + + @SuppressWarnings({"PublicField"}) + public boolean suggestEnumSwitches = false; + @Nls @NotNull @Override @@ -64,10 +77,67 @@ public class IfCanBeSwitchInspection extends BaseInspection { @Override public JComponent createOptionsPanel() { - return new SingleIntegerFieldOptionsPanel( - InspectionGadgetsBundle.message( - "if.can.be.switch.minimum.branch.option"), - this, "minimumBranches"); + final JPanel panel = new JPanel(new GridBagLayout()); + final JLabel label = new JLabel(InspectionGadgetsBundle.message( + "if.can.be.switch.minimum.branch.option")); + final NumberFormat formatter = NumberFormat.getIntegerInstance(); + formatter.setParseIntegerOnly(true); + final JFormattedTextField valueField = + new JFormattedTextField(formatter); + valueField.setValue(Integer.valueOf(minimumBranches)); + valueField.setColumns(2); + final Document document = valueField.getDocument(); + document.addDocumentListener(new DocumentAdapter() { + @Override + public void textChanged(DocumentEvent e) { + try { + valueField.commitEdit(); + minimumBranches = + ((Number) valueField.getValue()).intValue(); + } catch (ParseException e1) { + // No luck this time + } + } + }); + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.gridx = 0; + constraints.gridy = 0; + constraints.insets.left = 4; + constraints.insets.top = 4; + constraints.weightx = 0.0; + constraints.anchor = GridBagConstraints.BASELINE_LEADING; + constraints.fill = GridBagConstraints.NONE; + panel.add(label, constraints); + constraints.gridx = 1; + constraints.gridy = 0; + constraints.weightx = 1.0; + panel.add(valueField, constraints); + constraints.gridx = 0; + constraints.gridy = 1; + constraints.gridwidth = 2; + final JCheckBox checkBox1 = new JCheckBox( + InspectionGadgetsBundle.message("if.can.be.switch.int.option"), + suggestIntSwitches); + final ButtonModel model1 = checkBox1.getModel(); + model1.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + suggestIntSwitches = model1.isSelected(); + } + }); + panel.add(checkBox1, constraints); + constraints.gridy = 2; + constraints.weighty = 1.0; + final JCheckBox checkBox2 = new JCheckBox( + InspectionGadgetsBundle.message("if.can.be.switch.enum.option"), + suggestEnumSwitches); + final ButtonModel model2 = checkBox2.getModel(); + model2.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + suggestEnumSwitches = model2.isSelected(); + } + }); + panel.add(checkBox2, constraints); + return panel; } private static class IfCanBeSwitchFix extends InspectionGadgetsFix { @@ -453,6 +523,17 @@ public class IfCanBeSwitchInspection extends BaseInspection { if (switchExpression == null) { return; } + final PsiType type = switchExpression.getType(); + if (!suggestIntSwitches && PsiType.INT.equals(type)) { + return; + } + if (!suggestEnumSwitches && type instanceof PsiClassType) { + final PsiClassType classType = (PsiClassType) type; + final PsiClass aClass = classType.resolve(); + if (aClass == null || aClass.isEnum()) { + return; + } + } registerStatementError(statement, switchExpression); } } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/IfStatementBranch.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/IfStatementBranch.java similarity index 80% rename from plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/IfStatementBranch.java rename to plugins/InspectionGadgets/src/com/siyeh/ig/migration/IfStatementBranch.java index 582ee9b4755e..78a05949d219 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/IfStatementBranch.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/IfStatementBranch.java @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.siyeh.ig.controlflow; +package com.siyeh.ig.migration; import com.intellij.psi.*; import java.util.*; -class IfStatementBranch{ +class IfStatementBranch { private final Set topLevelVariables = new HashSet(3); private final LinkedList comments = new LinkedList(); @@ -34,7 +34,7 @@ class IfStatementBranch{ calculateVariablesDeclared(statement); } - public void addComment(String comment){ + public void addComment(String comment) { comments.addFirst(comment); } @@ -42,32 +42,32 @@ class IfStatementBranch{ statementComments.addFirst(comment); } - public void addCondition(String conditionString){ + public void addCondition(String conditionString) { conditions.add(conditionString); } - public PsiStatement getStatement(){ + public PsiStatement getStatement() { return statement; } - public List getConditions(){ + public List getConditions() { return Collections.unmodifiableList(conditions); } - public boolean isElse(){ + public boolean isElse() { return elseBranch; } public boolean topLevelDeclarationsConflictWith( - IfStatementBranch testBranch){ + IfStatementBranch testBranch) { final Set topLevel = testBranch.topLevelVariables; return intersects(topLevelVariables, topLevel); } private static boolean intersects(Set set1, - Set set2){ - for(final String s : set1){ - if(set2.contains(s)){ + Set set2) { + for (final String s : set1) { + if (set2.contains(s)) { return true; } } @@ -82,25 +82,25 @@ class IfStatementBranch{ return statementComments; } - public void calculateVariablesDeclared(PsiStatement statement){ - if(statement == null){ + public void calculateVariablesDeclared(PsiStatement statement) { + if (statement == null) { return; } - if(statement instanceof PsiDeclarationStatement){ + if (statement instanceof PsiDeclarationStatement) { final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement) statement; final PsiElement[] elements = declarationStatement.getDeclaredElements(); - for(PsiElement element : elements){ + for (PsiElement element : elements) { final PsiVariable variable = (PsiVariable) element; final String varName = variable.getName(); topLevelVariables.add(varName); } - } else if(statement instanceof PsiBlockStatement){ + } else if (statement instanceof PsiBlockStatement) { final PsiBlockStatement block = (PsiBlockStatement) statement; final PsiCodeBlock codeBlock = block.getCodeBlock(); final PsiStatement[] statements = codeBlock.getStatements(); - for(PsiStatement statement1 : statements){ + for (PsiStatement statement1 : statements) { calculateVariablesDeclared(statement1); } } From bbd0b72f3849cc1c08a9fc903f2b4d11a2edd9a2 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 22 Feb 2011 17:08:41 +0100 Subject: [PATCH 087/169] move "Identical 'catch' branches in 'try' statement" inspection to migration aids group --- .../src/com/siyeh/InspectionGadgetsBundle.properties | 1 + .../ig/errorhandling/TryWithIdenticalCatchesInspection.java | 6 +++--- .../src/inspectionDescriptions/TryWithIdenticalCatches.html | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties index bde874a76fa1..452fcd5e459c 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties @@ -1855,3 +1855,4 @@ if.can.be.switch.int.option=Suggest switch on int if.can.be.switch.enum.option=Suggest switch on enum unnecessarily.qualified.inner.class.access.option=Ignore references to foreign inner classes unqualified.inner.class.access.option=Ignore references to local inner classes +try.with.identical.catches.quickfix=Collapse catch blocks into multi-catch diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TryWithIdenticalCatchesInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TryWithIdenticalCatchesInspection.java index bfe4f41616b5..574eb4d1320e 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TryWithIdenticalCatchesInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TryWithIdenticalCatchesInspection.java @@ -30,6 +30,7 @@ import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.InspectionGadgetsFix; import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import java.util.Collections; @@ -123,16 +124,15 @@ public class TryWithIdenticalCatchesInspection extends BaseInspection { if (parameter1 == null || parameter2 == null) { return; } - String text = "try { } catch(" + parameter1.getTypeElement().getText() + " | " + parameter2.getTypeElement().getText() + " e) { }"; + @NonNls String text = "try { } catch(" + parameter1.getTypeElement().getText() + " | " + parameter2.getTypeElement().getText() + " e) { }"; PsiTryStatement newTryCatch = (PsiTryStatement)JavaPsiFacade.getElementFactory(project).createStatementFromText(text, stmt); parameter1.getTypeElement().replace(newTryCatch.getCatchSections() [0].getParameter().getTypeElement()); section.delete(); } @NotNull - @Override public String getName() { - return"Collapse catch blocks into multi-catch"; + return InspectionGadgetsBundle.message("try.with.identical.catches.quickfix"); } } } diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/TryWithIdenticalCatches.html b/plugins/InspectionGadgets/src/inspectionDescriptions/TryWithIdenticalCatches.html index 887abc484396..85514604f59d 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/TryWithIdenticalCatches.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/TryWithIdenticalCatches.html @@ -2,6 +2,6 @@ This inspection reports identical 'catch' sections in 'try' blocks under JDK 7. A quickfix is provided to collapse the sections into a multi-catch section. -Powered by InspectionGadgets +

Powered by InspectionGadgets \ No newline at end of file From d6dc7106ca206f9873044511df397643c6dfac2b Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 22 Feb 2011 17:13:26 +0100 Subject: [PATCH 088/169] preserve editor selection in inline rename; make ctrl-A works inside template bounds (IDEA-60743) --- .../codeInsight/template/Template.java | 3 ++ .../template/impl/TemplateImpl.java | 10 +++++ .../template/impl/TemplateState.java | 8 +++- .../impl/editorActions/SelectAllHandler.java | 45 +++++++++++++++++++ .../inplace/VariableInplaceRenamer.java | 16 +++++++ .../intellij/ide/actions/SelectAllAction.java | 25 ++++++----- .../src/META-INF/LangExtensions.xml | 1 + 7 files changed, 95 insertions(+), 13 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/SelectAllHandler.java diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/Template.java b/platform/lang-impl/src/com/intellij/codeInsight/template/Template.java index 0da41ec1cb35..5fa3924895d0 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/Template.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/Template.java @@ -17,6 +17,7 @@ package com.intellij.codeInsight.template; import com.intellij.codeInsight.template.impl.Variable; +import com.intellij.openapi.editor.RangeMarker; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -65,4 +66,6 @@ public abstract class Template { public abstract boolean isToShortenLongNames(); public abstract void setToShortenLongNames(boolean toShortenLongNames); + + public abstract void setSubSelection(RangeMarker selection); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateImpl.java index a1a9f3bf567c..3d06dcf57232 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateImpl.java @@ -19,6 +19,7 @@ package com.intellij.codeInsight.template.impl; import com.intellij.codeInsight.template.Expression; import com.intellij.codeInsight.template.Template; import com.intellij.codeInsight.template.TemplateContextType; +import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.options.SchemeElement; import com.intellij.openapi.util.text.StringUtil; @@ -41,6 +42,7 @@ public class TemplateImpl extends Template implements SchemeElement { private ArrayList mySegments = null; private String myTemplateText = null; private String myId; + private RangeMarker mySubSelection; public boolean equals(Object o) { if (this == o) return true; @@ -450,6 +452,14 @@ public class TemplateImpl extends Template implements SchemeElement { return myVariables.get(i).skipOnStart(); } + public RangeMarker getSubSelection() { + return mySubSelection; + } + + public void setSubSelection(RangeMarker selection) { + mySubSelection = selection; + } + private static class Segment { public String name; public int offset; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java index 7457d7e91936..50df33f95cc0 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java @@ -459,8 +459,12 @@ public class TemplateState implements Disposable { myEditor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); myEditor.getSelectionModel().removeSelection(); - - myEditor.getSelectionModel().setSelection(start, end); + final RangeMarker selection = myTemplate.getSubSelection(); + if (selection != null && selection.getStartOffset() >= start && selection.getEndOffset() <= end) { + myEditor.getSelectionModel().setSelection(selection.getStartOffset(), selection.getEndOffset()); + } else { + myEditor.getSelectionModel().setSelection(start, end); + } Expression expressionNode = myTemplate.getExpressionAt(myCurrentVariableNumber); final ExpressionContext context = createExpressionContext(start); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/SelectAllHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/SelectAllHandler.java new file mode 100644 index 000000000000..b19d7da4dbbb --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/SelectAllHandler.java @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2011 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 com.intellij.codeInsight.template.impl.editorActions; + +import com.intellij.codeInsight.template.impl.TemplateManagerImpl; +import com.intellij.codeInsight.template.impl.TemplateState; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.actionSystem.EditorActionHandler; +import com.intellij.openapi.util.TextRange; + +public class SelectAllHandler extends EditorActionHandler { + private final EditorActionHandler myOriginalHandler; + + public SelectAllHandler(final EditorActionHandler originalHandler) { + myOriginalHandler = originalHandler; + } + + public void execute(Editor editor, DataContext dataContext) { + final TemplateState templateState = TemplateManagerImpl.getTemplateState(editor); + if (templateState != null && !templateState.isFinished()) { + final TextRange range = templateState.getCurrentVariableRange(); + final int caretOffset = editor.getCaretModel().getOffset(); + if (range != null && range.getStartOffset() <= caretOffset && caretOffset <= range.getEndOffset()) { + editor.getSelectionModel().setSelection(range.getStartOffset(), range.getEndOffset()); + return; + } + } + myOriginalHandler.execute(editor, dataContext); + } +} diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java index cd01409972b3..bdae42635a79 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java @@ -32,6 +32,8 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.RangeMarker; +import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.editor.colors.EditorColors; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.markup.RangeHighlighter; @@ -183,6 +185,13 @@ public class VariableInplaceRenamer { PsiElement selectedElement = getSelectedInEditorElement(nameIdentifier, refs, offset); if (!CommonRefactoringUtil.checkReadOnlyStatus(myProject, myElementToRename)) return true; + final RangeMarker selection; + final SelectionModel selectionModel = myEditor.getSelectionModel(); + if (selectionModel.hasSelection()) { + selection = myEditor.getDocument().createRangeMarker(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()); + } else { + selection = null; + } if (nameIdentifier != null) addVariable(nameIdentifier, selectedElement, builder, nameSuggestions); for (PsiReference ref : refs) { addVariable(ref, selectedElement, builder, offset, nameSuggestions); @@ -198,6 +207,7 @@ public class VariableInplaceRenamer { final int offset = myEditor.getCaretModel().getOffset(); Template template = builder.buildInlineTemplate(); template.setToShortenLongNames(false); + template.setSubSelection(selection); TextRange range = scope1.getTextRange(); assert range != null; myHighlighters = new ArrayList(); @@ -230,11 +240,17 @@ public class VariableInplaceRenamer { performAutomaticRename(myNewName, PsiTreeUtil.getParentOfType(containingFile.findElementAt(renameOffset), PsiNameIdentifierOwner.class)); } moveOffsetAfter(true); + if (selection != null) { + selection.dispose(); + } } public void templateCancelled(Template template) { finish(); moveOffsetAfter(false); + if (selection != null) { + selection.dispose(); + } } }); diff --git a/platform/platform-impl/src/com/intellij/ide/actions/SelectAllAction.java b/platform/platform-impl/src/com/intellij/ide/actions/SelectAllAction.java index c66184fdb8c3..8b2d47a7deb1 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/SelectAllAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/SelectAllAction.java @@ -19,24 +19,27 @@ import com.intellij.ide.IdeBundle; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.actionSystem.EditorAction; +import com.intellij.openapi.editor.actionSystem.EditorActionHandler; import com.intellij.openapi.editor.actions.TextComponentEditorAction; import com.intellij.openapi.project.DumbAware; -public class SelectAllAction extends AnAction implements DumbAware { +public class SelectAllAction extends TextComponentEditorAction implements DumbAware { public SelectAllAction() { + super(new Handler()); setEnabledInModalContext(true); } - public void actionPerformed(AnActionEvent e) { - final DataContext dataContext = e.getDataContext(); - final Editor editor = TextComponentEditorAction.getEditorFromContext(dataContext); - if (editor == null) return; - CommandProcessor processor = CommandProcessor.getInstance(); - processor.executeCommand(PlatformDataKeys.PROJECT.getData(dataContext), new Runnable() { - public void run() { - editor.getSelectionModel().setSelection(0, editor.getDocument().getTextLength()); - } - }, IdeBundle.message("command.select.all"), null); + private static class Handler extends EditorActionHandler { + @Override + public void execute(final Editor editor, DataContext dataContext) { + CommandProcessor processor = CommandProcessor.getInstance(); + processor.executeCommand(PlatformDataKeys.PROJECT.getData(dataContext), new Runnable() { + public void run() { + editor.getSelectionModel().setSelection(0, editor.getDocument().getTextLength()); + } + }, IdeBundle.message("command.select.all"), null); + } } public void update(AnActionEvent event){ diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index a661a767e16c..81efbfedb9da 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -505,6 +505,7 @@ + From c04314608c5fa759ab2188551a5f8730da918178 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 22 Feb 2011 17:31:09 +0100 Subject: [PATCH 089/169] line start/end with selection inside live template --- .../LineEndWithSelectionHandler.java | 28 +++++++++++ .../LineStartEndWithSelectionHandler.java | 49 +++++++++++++++++++ .../LineStartWithSelectionHandler.java | 28 +++++++++++ .../src/META-INF/LangExtensions.xml | 2 + 4 files changed, 107 insertions(+) create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/LineEndWithSelectionHandler.java create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/LineStartEndWithSelectionHandler.java create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/LineStartWithSelectionHandler.java diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/LineEndWithSelectionHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/LineEndWithSelectionHandler.java new file mode 100644 index 000000000000..2c6ae0e7caeb --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/LineEndWithSelectionHandler.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2011 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 com.intellij.codeInsight.template.impl.editorActions; + +import com.intellij.openapi.editor.actionSystem.EditorActionHandler; + +/** + * User: anna + * Date: 2/22/11 + */ +public class LineEndWithSelectionHandler extends LineStartEndWithSelectionHandler { + public LineEndWithSelectionHandler(final EditorActionHandler originalHandler) { + super(originalHandler, false); + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/LineStartEndWithSelectionHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/LineStartEndWithSelectionHandler.java new file mode 100644 index 000000000000..c0b832f9e479 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/LineStartEndWithSelectionHandler.java @@ -0,0 +1,49 @@ +/* + * Copyright 2000-2011 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 com.intellij.codeInsight.template.impl.editorActions; + +import com.intellij.codeInsight.template.impl.TemplateManagerImpl; +import com.intellij.codeInsight.template.impl.TemplateState; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.actionSystem.EditorActionHandler; +import com.intellij.openapi.util.TextRange; + +public abstract class LineStartEndWithSelectionHandler extends EditorActionHandler { + private final EditorActionHandler myOriginalHandler; + boolean myIsHomeHandler; + + public LineStartEndWithSelectionHandler(final EditorActionHandler originalHandler, boolean isHomeHandler) { + myOriginalHandler = originalHandler; + myIsHomeHandler = isHomeHandler; + } + + public void execute(Editor editor, DataContext dataContext) { + final TemplateState templateState = TemplateManagerImpl.getTemplateState(editor); + if (templateState != null && !templateState.isFinished()) { + final TextRange range = templateState.getCurrentVariableRange(); + final int caretOffset = editor.getCaretModel().getOffset(); + if (range != null && range.getStartOffset() <= caretOffset && caretOffset <= range.getEndOffset()) { + int offsetToMove = myIsHomeHandler ? range.getStartOffset() : range.getEndOffset(); + editor.getCaretModel().moveToOffset(offsetToMove); + editor.getSelectionModel().setSelection(myIsHomeHandler ? offsetToMove : caretOffset, myIsHomeHandler ? caretOffset : offsetToMove); + return; + } + } + myOriginalHandler.execute(editor, dataContext); + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/LineStartWithSelectionHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/LineStartWithSelectionHandler.java new file mode 100644 index 000000000000..fe390b8fc842 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/LineStartWithSelectionHandler.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2011 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 com.intellij.codeInsight.template.impl.editorActions; + +import com.intellij.openapi.editor.actionSystem.EditorActionHandler; + +/** + * User: anna + * Date: 2/22/11 + */ +public class LineStartWithSelectionHandler extends LineStartEndWithSelectionHandler { + public LineStartWithSelectionHandler(final EditorActionHandler originalHandler) { + super(originalHandler, true); + } +} diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index 81efbfedb9da..1b99e6df7bad 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -504,7 +504,9 @@ + + From 7b6139a37ffc9c0fbf0aedb3965d6d978561fb05 Mon Sep 17 00:00:00 2001 From: andrey zaytsev Date: Tue, 22 Feb 2011 19:58:08 +0300 Subject: [PATCH 090/169] EA-25516: already disposed --- .../find/impl/livePreview/LivePreview.java | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java index 8deac659bc64..dd3d532331fd 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java +++ b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java @@ -30,6 +30,7 @@ import com.intellij.openapi.editor.markup.CustomHighlighterRenderer; import com.intellij.openapi.editor.markup.EffectType; import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.editor.markup.TextAttributes; +import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.ui.popup.BalloonBuilder; import com.intellij.openapi.ui.popup.JBPopupFactory; @@ -187,12 +188,15 @@ public class LivePreview extends DocumentAdapter implements ReplacementView.Dele editor.getScrollingModel().removeVisibleAreaListener(visibleAreaListener); } myVisibleAreaListenersToRemove.clear(); - for (RangeHighlighter h : myHighlighters) { - HighlightManager.getInstance(mySearchResults.getProject()).removeSegmentHighlighter(editor, h); - } - if (myCursorHighlighter != null) { - HighlightManager.getInstance(mySearchResults.getProject()).removeSegmentHighlighter(editor, myCursorHighlighter); - myCursorHighlighter = null; + Project project = mySearchResults.getProject(); + if (!project.isDisposed()) { + for (RangeHighlighter h : myHighlighters) { + HighlightManager.getInstance(project).removeSegmentHighlighter(editor, h); + } + if (myCursorHighlighter != null) { + HighlightManager.getInstance(project).removeSegmentHighlighter(editor, myCursorHighlighter); + myCursorHighlighter = null; + } } } } @@ -247,11 +251,14 @@ public class LivePreview extends DocumentAdapter implements ReplacementView.Dele } private void highlightRange(TextRange textRange, TextAttributes attributes, Collection highlighters) { - HighlightManager highlightManager = HighlightManager.getInstance(mySearchResults.getProject()); - if (highlightManager != null) { - highlightManager.addRangeHighlight(mySearchResults.getEditor(), - textRange.getStartOffset(), textRange.getEndOffset(), - attributes, false, highlighters); + Project project = mySearchResults.getProject(); + if (!project.isDisposed()) { + HighlightManager highlightManager = HighlightManager.getInstance(project); + if (highlightManager != null) { + highlightManager.addRangeHighlight(mySearchResults.getEditor(), + textRange.getStartOffset(), textRange.getEndOffset(), + attributes, false, highlighters); + } } } @@ -269,7 +276,6 @@ public class LivePreview extends DocumentAdapter implements ReplacementView.Dele drawSegment(editor, new TextRange(offset, newOffset), g); offset = newOffset+1; } - } private static void drawSegment(Editor editor, Segment highlighter, Graphics g) { From a3c863c4889962fb96e57df3a2e6e20466d81a32 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 22 Feb 2011 11:54:24 +0300 Subject: [PATCH 091/169] injected brace highlighters stuck --- .../BraceHighlightingHandler.java | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java index 653c8421ee7b..833b276060b7 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java @@ -28,6 +28,7 @@ import com.intellij.codeInsight.CodeInsightSettings; import com.intellij.codeInsight.hint.EditorFragmentComponent; import com.intellij.concurrency.Job; import com.intellij.concurrency.JobUtil; +import com.intellij.injected.editor.EditorWindow; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.editor.Document; @@ -44,7 +45,7 @@ import com.intellij.openapi.editor.highlighter.HighlighterIterator; import com.intellij.openapi.editor.markup.*; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileTypes.FileType; -import com.intellij.openapi.fileTypes.StdFileTypes; +import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.project.DumbAwareRunnable; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; @@ -291,7 +292,7 @@ public class BraceHighlightingHandler { } private void highlightBraces(final int lBraceOffset, int rBraceOffset, boolean matched, boolean scopeHighlighting) { - if (!matched && myFileType == StdFileTypes.PLAIN_TEXT) { + if (!matched && myFileType == FileTypes.PLAIN_TEXT) { return; } @@ -304,10 +305,8 @@ public class BraceHighlightingHandler { highlightBrace(rBraceOffset, matched); } - if (lBraceOffset >= 0) { - if (!scopeHighlighting) { - highlightBrace(lBraceOffset, matched); - } + if (lBraceOffset >= 0 && !scopeHighlighting) { + highlightBrace(lBraceOffset, matched); } if (!myEditor.equals(FileEditorManager.getInstance(myProject).getSelectedTextEditor())) { @@ -368,13 +367,20 @@ public class BraceHighlightingHandler { } private void registerHighlighter(RangeHighlighter highlighter) { - List highlighters = myEditor.getUserData(BRACE_HIGHLIGHTERS_IN_EDITOR_VIEW_KEY); + List highlighters = getHighlightersList(); + highlighters.add(highlighter); + } + + @NotNull + private List getHighlightersList() { + // braces are highlighted across the whole editor, not in each injected editor separately + Editor editor = myEditor instanceof EditorWindow ? ((EditorWindow)myEditor).getDelegate() : myEditor; + List highlighters = editor.getUserData(BRACE_HIGHLIGHTERS_IN_EDITOR_VIEW_KEY); if (highlighters == null) { highlighters = new ArrayList(); - myEditor.putUserData(BRACE_HIGHLIGHTERS_IN_EDITOR_VIEW_KEY, highlighters); + editor.putUserData(BRACE_HIGHLIGHTERS_IN_EDITOR_VIEW_KEY, highlighters); } - - highlighters.add(highlighter); + return highlighters; } private void showScopeHint(final int lbraceStart, final int lbraceEnd) { @@ -405,12 +411,11 @@ public class BraceHighlightingHandler { } public void clearBraceHighlighters() { - List highlighters = myEditor.getUserData(BRACE_HIGHLIGHTERS_IN_EDITOR_VIEW_KEY); - if (highlighters == null) return; - myEditor.putUserData(BRACE_HIGHLIGHTERS_IN_EDITOR_VIEW_KEY, null); + List highlighters = getHighlightersList(); for (final RangeHighlighter highlighter : highlighters) { highlighter.dispose(); } + highlighters.clear(); } private void lineMarkFragment(int startLine, int endLine, Color color) { From 66526a9970ae433c4852f706db2969e6c169f70a Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 22 Feb 2011 11:58:11 +0300 Subject: [PATCH 092/169] notnull --- .../java/events/PomJavaAspectChangeSet.java | 4 +++- .../com/intellij/pom/event/PomChangeSet.java | 4 +++- .../com/intellij/pom/event/PomModelEvent.java | 6 ++--- .../src/com/intellij/pom/tree/TreeAspect.java | 5 ++-- .../pom/tree/events/TreeChangeEvent.java | 7 ++++-- .../tree/events/impl/TreeChangeEventImpl.java | 23 +++++++++---------- .../pom/xml/impl/XmlAspectChangeSetImpl.java | 3 ++- .../com/intellij/pom/xml/XmlChangeSet.java | 1 + 8 files changed, 30 insertions(+), 23 deletions(-) diff --git a/java/openapi/src/com/intellij/pom/java/events/PomJavaAspectChangeSet.java b/java/openapi/src/com/intellij/pom/java/events/PomJavaAspectChangeSet.java index 2625a48a6144..ebbd94c2d4e2 100644 --- a/java/openapi/src/com/intellij/pom/java/events/PomJavaAspectChangeSet.java +++ b/java/openapi/src/com/intellij/pom/java/events/PomJavaAspectChangeSet.java @@ -20,6 +20,7 @@ import com.intellij.pom.PomModel; import com.intellij.pom.PomModelAspect; import com.intellij.pom.event.PomChangeSet; import com.intellij.pom.java.PomJavaAspect; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; @@ -37,11 +38,12 @@ public class PomJavaAspectChangeSet implements PomChangeSet{ myChanges.add(change); } + @NotNull public PomModelAspect getAspect() { return myModel.getModelAspect(PomJavaAspect.class); } - public void merge(PomChangeSet blocked) { + public void merge(@NotNull PomChangeSet blocked) { if(!(blocked instanceof PomJavaAspectChangeSet)) return; final PomJavaAspectChangeSet blockedJavaChange = (PomJavaAspectChangeSet)blocked; myChanges.addAll(blockedJavaChange.myChanges); diff --git a/platform/lang-api/src/com/intellij/pom/event/PomChangeSet.java b/platform/lang-api/src/com/intellij/pom/event/PomChangeSet.java index 37315a0aed40..c2247b97c9dc 100644 --- a/platform/lang-api/src/com/intellij/pom/event/PomChangeSet.java +++ b/platform/lang-api/src/com/intellij/pom/event/PomChangeSet.java @@ -16,8 +16,10 @@ package com.intellij.pom.event; import com.intellij.pom.PomModelAspect; +import org.jetbrains.annotations.NotNull; public interface PomChangeSet { + @NotNull PomModelAspect getAspect(); - void merge(PomChangeSet blocked); + void merge(@NotNull PomChangeSet blocked); } \ No newline at end of file diff --git a/platform/lang-api/src/com/intellij/pom/event/PomModelEvent.java b/platform/lang-api/src/com/intellij/pom/event/PomModelEvent.java index 2697ed849cd6..e5387834deba 100644 --- a/platform/lang-api/src/com/intellij/pom/event/PomModelEvent.java +++ b/platform/lang-api/src/com/intellij/pom/event/PomModelEvent.java @@ -43,11 +43,11 @@ public class PomModelEvent extends EventObject { if (myChangeSets == null) { myChangeSets = new HashMap(); } - if (set != null) { - myChangeSets.put(aspect, set); + if (set == null) { + myChangeSets.remove(aspect); } else { - myChangeSets.remove(aspect); + myChangeSets.put(aspect, set); } } diff --git a/platform/lang-api/src/com/intellij/pom/tree/TreeAspect.java b/platform/lang-api/src/com/intellij/pom/tree/TreeAspect.java index da5bcc28cb8d..16334758f3e7 100644 --- a/platform/lang-api/src/com/intellij/pom/tree/TreeAspect.java +++ b/platform/lang-api/src/com/intellij/pom/tree/TreeAspect.java @@ -18,13 +18,12 @@ package com.intellij.pom.tree; import com.intellij.pom.PomModel; import com.intellij.pom.PomModelAspect; import com.intellij.pom.event.PomModelEvent; +import org.jetbrains.annotations.NotNull; import java.util.Collections; -import org.jetbrains.annotations.NotNull; - public class TreeAspect implements PomModelAspect{ - public TreeAspect(PomModel model) { + public TreeAspect(@NotNull PomModel model) { model.registerAspect(TreeAspect.class, this, Collections.emptySet()); } diff --git a/platform/lang-api/src/com/intellij/pom/tree/events/TreeChangeEvent.java b/platform/lang-api/src/com/intellij/pom/tree/events/TreeChangeEvent.java index 4485fe63e7ff..7520514dfe88 100644 --- a/platform/lang-api/src/com/intellij/pom/tree/events/TreeChangeEvent.java +++ b/platform/lang-api/src/com/intellij/pom/tree/events/TreeChangeEvent.java @@ -17,18 +17,21 @@ package com.intellij.pom.tree.events; import com.intellij.lang.ASTNode; import com.intellij.pom.event.PomChangeSet; +import org.jetbrains.annotations.NotNull; /** * @author ik */ public interface TreeChangeEvent extends PomChangeSet { + @NotNull ASTNode getRootElement(); + @NotNull ASTNode[] getChangedElements(); - TreeChange getChangesByElement(ASTNode element); + TreeChange getChangesByElement(@NotNull ASTNode element); - void addElementaryChange(ASTNode child, ChangeInfo change); + void addElementaryChange(@NotNull ASTNode child, @NotNull ChangeInfo change); void clear(); } diff --git a/platform/lang-impl/src/com/intellij/pom/tree/events/impl/TreeChangeEventImpl.java b/platform/lang-impl/src/com/intellij/pom/tree/events/impl/TreeChangeEventImpl.java index 73f7a5e1f71b..a24983dbd2ff 100644 --- a/platform/lang-impl/src/com/intellij/pom/tree/events/impl/TreeChangeEventImpl.java +++ b/platform/lang-impl/src/com/intellij/pom/tree/events/impl/TreeChangeEventImpl.java @@ -27,6 +27,7 @@ import com.intellij.psi.impl.source.tree.FileElement; import com.intellij.psi.impl.source.tree.TreeElement; import com.intellij.util.CharTable; import gnu.trove.THashMap; +import org.jetbrains.annotations.NotNull; import java.util.*; @@ -40,30 +41,26 @@ public class TreeChangeEventImpl implements TreeChangeEvent{ private final PomModelAspect myAspect; private final FileElement myFileElement; - public TreeChangeEventImpl(PomModelAspect aspect, FileElement treeElement) { + public TreeChangeEventImpl(@NotNull PomModelAspect aspect, @NotNull FileElement treeElement) { myAspect = aspect; myFileElement = treeElement; } + @NotNull public FileElement getRootElement() { return myFileElement; } - public TreeElement[] getChangedElements() { - final TreeElement[] ret = new TreeElement[myChangedElements.size()]; - final Iterator iterator = myChangedInOrder.iterator(); - int index = 0; - while (iterator.hasNext()) { - ret[index++] = (TreeElement)iterator.next(); - } - return ret; + @NotNull + public ASTNode[] getChangedElements() { + return myChangedInOrder.toArray(new ASTNode[myChangedInOrder.size()]); } - public TreeChange getChangesByElement(ASTNode element) { + public TreeChange getChangesByElement(@NotNull ASTNode element) { return myChangedElements.get(element); } - public void addElementaryChange(ASTNode element, ChangeInfo change) { + public void addElementaryChange(@NotNull ASTNode element, @NotNull ChangeInfo change) { final ASTNode parent = element.getTreeParent(); if(parent == null) return; ASTNode currentParent = parent; @@ -99,6 +96,7 @@ public class TreeChangeEventImpl implements TreeChangeEvent{ } public void clear() { + myChangedInOrder.clear(); myChangedElements.clear(); myOfEqualDepth.clear(); } @@ -237,11 +235,12 @@ public class TreeChangeEventImpl implements TreeChangeEvent{ return -1; } + @NotNull public PomModelAspect getAspect() { return myAspect; } - public void merge(PomChangeSet blocked) { + public void merge(@NotNull PomChangeSet blocked) { if(!(blocked instanceof TreeChangeEventImpl)) return; final TreeChangeEventImpl blockedTreeChange = (TreeChangeEventImpl)blocked; final Map changedElements = new HashMap(blockedTreeChange.myChangedElements); diff --git a/xml/impl/src/com/intellij/pom/xml/impl/XmlAspectChangeSetImpl.java b/xml/impl/src/com/intellij/pom/xml/impl/XmlAspectChangeSetImpl.java index dc1efb4d9295..50d6ea92d9b4 100644 --- a/xml/impl/src/com/intellij/pom/xml/impl/XmlAspectChangeSetImpl.java +++ b/xml/impl/src/com/intellij/pom/xml/impl/XmlAspectChangeSetImpl.java @@ -47,11 +47,12 @@ public class XmlAspectChangeSetImpl implements XmlChangeSet { return Collections.unmodifiableList(myChanges); } + @NotNull public PomModelAspect getAspect() { return myModel.getModelAspect(XmlAspect.class); } - public void merge(PomChangeSet blocked) { + public void merge(@NotNull PomChangeSet blocked) { final List changes = ((XmlAspectChangeSetImpl)blocked).myChanges; for (XmlChange xmlChange : changes) { add(xmlChange); diff --git a/xml/openapi/src/com/intellij/pom/xml/XmlChangeSet.java b/xml/openapi/src/com/intellij/pom/xml/XmlChangeSet.java index f800661c2543..6652a9d73037 100644 --- a/xml/openapi/src/com/intellij/pom/xml/XmlChangeSet.java +++ b/xml/openapi/src/com/intellij/pom/xml/XmlChangeSet.java @@ -26,6 +26,7 @@ import java.util.List; public interface XmlChangeSet extends PomChangeSet { List getChanges(); + @NotNull PomModelAspect getAspect(); void add(XmlChange xmlChange); From d151f3013f72a5334cb7e57175ef22debec98961 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 22 Feb 2011 11:59:21 +0300 Subject: [PATCH 093/169] cleanup --- .../util/src/com/intellij/util/containers/LongArrayList.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/util/src/com/intellij/util/containers/LongArrayList.java b/platform/util/src/com/intellij/util/containers/LongArrayList.java index 9a6ae1a07541..c0c9bb42ff87 100644 --- a/platform/util/src/com/intellij/util/containers/LongArrayList.java +++ b/platform/util/src/com/intellij/util/containers/LongArrayList.java @@ -15,6 +15,7 @@ */ package com.intellij.util.containers; +@Deprecated // use TLongArrayList instead public class LongArrayList implements Cloneable { private long[] myData; private int mySize; From 12eae7ea00aaaf01b750e9772ef1102acb775a74 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 22 Feb 2011 20:38:33 +0300 Subject: [PATCH 094/169] data race --- .../openapi/editor/LazyRangeMarkerFactory.java | 11 +++++++---- .../src/com/intellij/util/containers/WeakList.java | 9 ++++++++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java b/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java index ea7beabfed99..d9a9b532eaab 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java @@ -27,7 +27,8 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.containers.WeakList; import org.jetbrains.annotations.NotNull; -import java.util.Iterator; +import java.util.ArrayList; +import java.util.List; /** * Date: Mar 17, 2009 @@ -39,14 +40,16 @@ public class LazyRangeMarkerFactory extends AbstractProjectComponent { super(project); EditorFactory.getInstance().getEventMulticaster().addDocumentListener(new DocumentAdapter() { public void beforeDocumentChange(DocumentEvent e) { - for (Iterator it = myMarkers.iterator(); it.hasNext();) { - final LazyMarker marker = it.next(); + List markers = myMarkers.toStrongList(); + List markersToRemove = new ArrayList(); + for (final LazyMarker marker : markers) { final VirtualFile docFile = fileDocumentManager.getFile(e.getDocument()); if (marker.getFile() == docFile) { marker.ensureDelegate(); - it.remove(); + markersToRemove.add(marker); } } + myMarkers.removeAll(markersToRemove); } }, project); } diff --git a/platform/util/src/com/intellij/util/containers/WeakList.java b/platform/util/src/com/intellij/util/containers/WeakList.java index 0691a02d68b2..3bb72781c520 100644 --- a/platform/util/src/com/intellij/util/containers/WeakList.java +++ b/platform/util/src/com/intellij/util/containers/WeakList.java @@ -76,6 +76,13 @@ public class WeakList extends AbstractList { } } + @Override + public boolean removeAll(Collection c) { + synchronized (myArray) { + return super.removeAll(c); + } + } + public Iterator iterator() { return new MyIterator(); } @@ -88,7 +95,7 @@ public class WeakList extends AbstractList { public List toStrongList() { synchronized (myArray) { - List result = new ArrayList(); + List result = new ArrayList(myArray.size()); myArray.toStrongCollection(result); return result; } From 26a7a211fe6a0d7f83b8b2d08309de54a6452d40 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 22 Feb 2011 20:41:06 +0300 Subject: [PATCH 095/169] document leak fixed --- .../src/com/intellij/util/indexing/ID.java | 2 + .../util/indexing/FileBasedIndex.java | 15 ++-- .../util/indexing/PerIndexDocumentMap.java | 60 ---------------- .../indexing/PerIndexDocumentVersionMap.java | 72 +++++++++++++++++++ 4 files changed, 78 insertions(+), 71 deletions(-) delete mode 100644 platform/lang-impl/src/com/intellij/util/indexing/PerIndexDocumentMap.java create mode 100644 platform/lang-impl/src/com/intellij/util/indexing/PerIndexDocumentVersionMap.java diff --git a/platform/lang-api/src/com/intellij/util/indexing/ID.java b/platform/lang-api/src/com/intellij/util/indexing/ID.java index e400793c745c..463fcaee4276 100644 --- a/platform/lang-api/src/com/intellij/util/indexing/ID.java +++ b/platform/lang-api/src/com/intellij/util/indexing/ID.java @@ -78,6 +78,8 @@ public class ID { } int n = ourNameToIdRegistry.size() + 1; + assert n <= Short.MAX_VALUE : "Number of indices exceeded"; + ourNameToIdRegistry.put(name, n); writeEnumFile(); diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java index 07591f7c4d6f..76f69436607c 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java @@ -101,14 +101,7 @@ public class FileBasedIndex implements ApplicationComponent { private final Set> myNotRequiringContentIndices = new HashSet>(); private final Set myNoLimitCheckTypes = new HashSet(); - private final PerIndexDocumentMap myLastIndexedDocStamps = new PerIndexDocumentMap() { - @NotNull - @Override - protected Long createDefault(@NotNull Document document) { - return 0L; - } - }; - + private final PerIndexDocumentVersionMap myLastIndexedDocStamps = new PerIndexDocumentVersionMap(); private final ChangedFilesCollector myChangedFilesCollector; private final List myIndexableSets = ContainerUtil.createEmptyCOWList(); @@ -354,7 +347,6 @@ public class FileBasedIndex implements ApplicationComponent { * @param isCurrentVersionCorrupted */ private boolean registerIndexer(final FileBasedIndexExtension extension, final boolean isCurrentVersionCorrupted) throws IOException { - boolean versionChanged = false; final ID name = extension.getName(); final int version = extension.getVersion(); if (!extension.dependsOnFileContent()) { @@ -363,6 +355,7 @@ public class FileBasedIndex implements ApplicationComponent { myIndexIdToVersionMap.put(name, version); final File versionFile = IndexInfrastructure.getVersionFile(name); final boolean versionFileExisted = versionFile.exists(); + boolean versionChanged = false; if (isCurrentVersionCorrupted || IndexInfrastructure.versionDiffers(versionFile, version)) { if (!isCurrentVersionCorrupted && versionFileExisted) { versionChanged = true; @@ -1181,7 +1174,7 @@ public class FileBasedIndex implements ApplicationComponent { } final long currentDocStamp = content.getModificationStamp(); - if (currentDocStamp != myLastIndexedDocStamps.getAndSet(document, requestedIndexId, currentDocStamp).longValue()) { + if (currentDocStamp != myLastIndexedDocStamps.getAndSet(document, requestedIndexId, currentDocStamp)) { final Ref exRef = new Ref(null); ProgressManager.getInstance().executeNonCancelableSection(new Runnable() { public void run() { @@ -1770,10 +1763,10 @@ public class FileBasedIndex implements ApplicationComponent { if (file instanceof VirtualFileWithId) { try { - boolean oldStuff = true; if (file instanceof NewVirtualFile) { file.putUserData(NewVirtualFile.FILE_TYPE_KEY, file.getFileType()); } + boolean oldStuff = true; if (!isTooLarge(file)) { for (ID indexId : myIndices.keySet()) { try { diff --git a/platform/lang-impl/src/com/intellij/util/indexing/PerIndexDocumentMap.java b/platform/lang-impl/src/com/intellij/util/indexing/PerIndexDocumentMap.java deleted file mode 100644 index 06c42bdb001b..000000000000 --- a/platform/lang-impl/src/com/intellij/util/indexing/PerIndexDocumentMap.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2000-2009 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 com.intellij.util.indexing; - -import com.intellij.openapi.editor.Document; -import com.intellij.util.containers.ConcurrentFactoryMap; -import com.intellij.util.containers.ConcurrentWeakFactoryMap; - -import java.util.Map; - -/** - * @author Dmitry Avdeev - * @author peter - */ -public abstract class PerIndexDocumentMap { - - private final Map> myVersions = new ConcurrentWeakFactoryMap>() { - protected Map create(final Document document) { - return new ConcurrentFactoryMap() { - protected T create(ID key) { - return createDefault(document); - } - }; - } - }; - - public T get(Document document, ID indexId) { - return myVersions.get(document).get(indexId); - } - - public void put(Document document, ID indexId, T value) { - myVersions.get(document).put(indexId, value); - } - - public synchronized T getAndSet(Document document, ID indexId, T value) { - T old = get(document, indexId); - put(document, indexId, value); - return old; - } - - public void clear() { - myVersions.clear(); - } - - protected abstract T createDefault(Document document); -} diff --git a/platform/lang-impl/src/com/intellij/util/indexing/PerIndexDocumentVersionMap.java b/platform/lang-impl/src/com/intellij/util/indexing/PerIndexDocumentVersionMap.java new file mode 100644 index 000000000000..316e114b1dbe --- /dev/null +++ b/platform/lang-impl/src/com/intellij/util/indexing/PerIndexDocumentVersionMap.java @@ -0,0 +1,72 @@ +/* + * Copyright 2000-2011 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 com.intellij.util.indexing; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.UserDataHolderEx; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Dmitry Avdeev + * @author peter + */ +public class PerIndexDocumentVersionMap { + private volatile int mapVersion; + private static class IdVersionInfo { + private final ID id; + private int mapVersion; + private long docVersion; + + private IdVersionInfo(@NotNull ID id, long docVersion, int mapVersion) { + this.docVersion = docVersion; + this.mapVersion = mapVersion; + this.id = id; + } + } + + private static final Key> KEY = Key.create("UnsavedDocIdVersionInfo"); + public long getAndSet(@NotNull Document document, @NotNull ID indexId, long value) { + List list = document.getUserData(KEY); + if (list == null) { + list = ((UserDataHolderEx)document).putUserDataIfAbsent(KEY, new ArrayList()); + } + + synchronized (list) { + for (IdVersionInfo info : list) { + if (info.id == indexId) { + long old = info.docVersion; + if (info.mapVersion != mapVersion) { + old = 0; + info.mapVersion = mapVersion; + } + info.docVersion = value; + return old; + } + } + list.add(new IdVersionInfo(indexId, value, mapVersion)); + return 0; + } + } + + public void clear() { + mapVersion++; + } +} From 34443633194ddb747df3d3dade79e1ec3bbe6113 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 22 Feb 2011 20:41:38 +0300 Subject: [PATCH 096/169] obsolete class --- .../psi/PsiAspectManagerListener.java | 25 ------------------- 1 file changed, 25 deletions(-) delete mode 100644 java/openapi/src/com/intellij/psi/PsiAspectManagerListener.java diff --git a/java/openapi/src/com/intellij/psi/PsiAspectManagerListener.java b/java/openapi/src/com/intellij/psi/PsiAspectManagerListener.java deleted file mode 100644 index d2a03d0be508..000000000000 --- a/java/openapi/src/com/intellij/psi/PsiAspectManagerListener.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2000-2009 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 com.intellij.psi; - -/** - * AspectJ functionality; currently not supported. - * - * @author max - */ -public interface PsiAspectManagerListener { - void update(); -} From e45424a2d3af7b149c32cab87c82d7baa40a89a8 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 22 Feb 2011 15:14:48 +0100 Subject: [PATCH 097/169] IDEA-64852 Find usages for extension point renders strange search subject name --- plugins/devkit/src/dom/ExtensionPoint.java | 1 + .../codeInsight/extensionPointPresentation.xml | 14 ++++++++++++++ .../codeInsight/PluginXmlFunctionalTest.java | 14 ++++++++++++++ .../impl/DefaultDomTargetDescriptionProvider.java | 14 +++++++------- 4 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 plugins/devkit/testData/codeInsight/extensionPointPresentation.xml diff --git a/plugins/devkit/src/dom/ExtensionPoint.java b/plugins/devkit/src/dom/ExtensionPoint.java index 658ca26ef55b..0f75c0b2bcca 100644 --- a/plugins/devkit/src/dom/ExtensionPoint.java +++ b/plugins/devkit/src/dom/ExtensionPoint.java @@ -23,6 +23,7 @@ import org.jetbrains.idea.devkit.dom.impl.PluginPsiClassConverter; /** * @author mike */ +@Presentation(typeName = "Extension Point") public interface ExtensionPoint extends DomElement { enum Area { IDEA_PROJECT, diff --git a/plugins/devkit/testData/codeInsight/extensionPointPresentation.xml b/plugins/devkit/testData/codeInsight/extensionPointPresentation.xml new file mode 100644 index 000000000000..62e15ab49569 --- /dev/null +++ b/plugins/devkit/testData/codeInsight/extensionPointPresentation.xml @@ -0,0 +1,14 @@ + + + foo + + + + + + + + ar/> + + + \ No newline at end of file diff --git a/plugins/devkit/testSources/codeInsight/PluginXmlFunctionalTest.java b/plugins/devkit/testSources/codeInsight/PluginXmlFunctionalTest.java index 27ba8b3ef621..b3b515a2e4a9 100644 --- a/plugins/devkit/testSources/codeInsight/PluginXmlFunctionalTest.java +++ b/plugins/devkit/testSources/codeInsight/PluginXmlFunctionalTest.java @@ -15,13 +15,19 @@ */ package org.jetbrains.idea.devkit.codeInsight; +import com.intellij.codeInsight.TargetElementUtil; +import com.intellij.codeInsight.TargetElementUtilBase; import com.intellij.openapi.application.PluginPathManager; import com.intellij.openapi.application.Result; import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.psi.ElementDescriptionUtil; +import com.intellij.psi.PsiElement; import com.intellij.testFramework.PsiTestUtil; import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory; import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase; import com.intellij.testFramework.fixtures.TempDirTestFixture; +import com.intellij.usageView.UsageViewNodeTextLocation; +import com.intellij.usageView.UsageViewTypeLocation; import org.jetbrains.idea.devkit.DevKitInspectionToolProvider; import java.io.IOException; @@ -136,4 +142,12 @@ public class PluginXmlFunctionalTest extends JavaCodeInsightFixtureTestCase { myFixture.testHighlighting("pluginWithXInclude.xml", "extensionPoints.xml"); } + public void testExtensionPointPresentation() { + myFixture.configureByFile(getTestName(true) + ".xml"); + final PsiElement element = + TargetElementUtil.findTargetElement(myFixture.getEditor(), TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED); + assertEquals("Extension Point", ElementDescriptionUtil.getElementDescription(element, UsageViewTypeLocation.INSTANCE)); + assertEquals("Extension Point bar", ElementDescriptionUtil.getElementDescription(element, UsageViewNodeTextLocation.INSTANCE)); + } + } diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/DefaultDomTargetDescriptionProvider.java b/xml/dom-impl/src/com/intellij/util/xml/impl/DefaultDomTargetDescriptionProvider.java index 16c2c6ef931c..dd016e721397 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/impl/DefaultDomTargetDescriptionProvider.java +++ b/xml/dom-impl/src/com/intellij/util/xml/impl/DefaultDomTargetDescriptionProvider.java @@ -22,10 +22,7 @@ import com.intellij.psi.ElementDescriptionLocation; import com.intellij.usageView.UsageViewNodeTextLocation; import com.intellij.usageView.UsageViewTypeLocation; import com.intellij.usageView.UsageViewLongNameLocation; -import com.intellij.util.xml.DomElement; -import com.intellij.util.xml.DomTarget; -import com.intellij.util.xml.ElementPresentationManager; -import com.intellij.util.xml.TypeNameManager; +import com.intellij.util.xml.*; import com.intellij.codeInsight.highlighting.HighlightUsagesDescriptionLocation; import org.jetbrains.annotations.NotNull; @@ -39,14 +36,17 @@ public class DefaultDomTargetDescriptionProvider extends PomDescriptionProvider final DomTarget target = (DomTarget)element; DomElement domElement = target.getDomElement(); + final ElementPresentationTemplate template = domElement.getChildDescription().getPresentationTemplate(); + final ElementPresentation presentation = template != null ? template.createPresentation(domElement) : domElement.getPresentation(); + if (location == UsageViewTypeLocation.INSTANCE) { - return ElementPresentationManager.getTypeNameForObject(domElement); + return presentation.getTypeName(); } if (location == UsageViewNodeTextLocation.INSTANCE || location == UsageViewLongNameLocation.INSTANCE) { - return TypeNameManager.getTypeName(domElement.getClass()) + " " + StringUtil.notNullize(target.getName(), "''"); + return presentation.getTypeName() + " " + StringUtil.notNullize(presentation.getElementName(), "''"); } if (location instanceof HighlightUsagesDescriptionLocation) { - return TypeNameManager.getTypeName(domElement.getClass()); + return presentation.getTypeName(); } return null; } From 261bfa77a963339a268ee651fb55c684e607a3a9 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 22 Feb 2011 15:42:21 +0100 Subject: [PATCH 098/169] in field type, don't suggest fields&methods (IDEA-65639) --- .../psi/impl/source/PsiJavaCodeReferenceElementImpl.java | 4 +--- .../testData/codeInsight/completion/normal/FieldType.java | 4 ++++ .../codeInsight/completion/normal/FieldType_after.java | 4 ++++ .../codeInsight/completion/NormalCompletionTest.groovy | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/normal/FieldType.java create mode 100644 java/java-tests/testData/codeInsight/completion/normal/FieldType_after.java diff --git a/java/java-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java index 130fadd9649a..465ba6e29c9f 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java @@ -755,7 +755,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme } else { while (superParent != null) { - if (superParent instanceof PsiCodeBlock || superParent instanceof PsiVariable) { + if (superParent instanceof PsiCodeBlock || superParent instanceof PsiLocalVariable) { smartCompletion = false; break; } @@ -763,8 +763,6 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme } } if (!smartCompletion && !isCodeFragmentType(getTreeParent().getElementType()) && !(getParent() instanceof PsiAnnotation)) { - /*filter.addFilter(ElementClassFilter.CLASS); - filter.addFilter(ElementClassFilter.PACKAGE);*/ filter.addFilter(new AndFilter(ElementClassFilter.METHOD, new NotFilter(new ConstructorFilter()))); filter.addFilter(ElementClassFilter.VARIABLE); } diff --git a/java/java-tests/testData/codeInsight/completion/normal/FieldType.java b/java/java-tests/testData/codeInsight/completion/normal/FieldType.java new file mode 100644 index 000000000000..a2abc3425058 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/FieldType.java @@ -0,0 +1,4 @@ +class A { + private lo localizedStringManager; + +} diff --git a/java/java-tests/testData/codeInsight/completion/normal/FieldType_after.java b/java/java-tests/testData/codeInsight/completion/normal/FieldType_after.java new file mode 100644 index 000000000000..071e1faf557b --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/FieldType_after.java @@ -0,0 +1,4 @@ +class A { + private long localizedStringManager; + +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index 488562c7249a..8bd1531b0948 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -356,10 +356,12 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase { checkResult() } + public void testFieldType() throws Throwable { doTest(); } + public void testPackageInAnnoParam() throws Throwable { doTest(); } - + public void testClassLiteralInAnnoParam() throws Throwable { doTest(); } From 55bc513149c209b824857aff99a5ab9a9cd0f6c9 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 22 Feb 2011 16:46:46 +0100 Subject: [PATCH 099/169] IDEA-50627 Don't suggest uninitialized instance members in constructor when smart-completing --- .../completion/JavaCompletionUtil.java | 2 +- .../JavaDocCompletionContributor.java | 2 +- .../scope/JavaCompletionProcessor.java | 65 ++++++++++++++++--- .../normalSorting/DispreferDeclared.java | 1 + .../DispreferDeclaredOfExpectedType.java | 1 + .../smartType/FieldsSetAbove-out.java | 9 +++ .../completion/smartType/FieldsSetAbove.java | 9 +++ .../FieldsSetInAnotherConstructor-out.java | 13 ++++ .../FieldsSetInAnotherConstructor.java | 13 ++++ .../NoFieldsInSuperConstructorCall-out.java | 11 ++++ .../NoFieldsInSuperConstructorCall.java | 11 ++++ ...oUninitializedFieldsInConstructor-out.java | 8 +++ .../NoUninitializedFieldsInConstructor.java | 8 +++ .../second/NonInitializedField-out.java | 7 ++ .../smartType/second/NonInitializedField.java | 7 ++ .../SecondSmartTypeCompletionTest.java | 3 +- .../completion/SmartTypeCompletionTest.java | 5 ++ 17 files changed, 162 insertions(+), 13 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/FieldsSetAbove-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/FieldsSetAbove.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/FieldsSetInAnotherConstructor-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/FieldsSetInAnotherConstructor.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/NoFieldsInSuperConstructorCall-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/NoFieldsInSuperConstructorCall.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/NoUninitializedFieldsInConstructor-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/NoUninitializedFieldsInConstructor.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/second/NonInitializedField-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/second/NonInitializedField.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java index 8969ae0704a5..c96d7f3d6535 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -573,7 +573,7 @@ public class JavaCompletionUtil { return matcher.prefixMatches(s); } }; - final JavaCompletionProcessor processor = new JavaCompletionProcessor(element, elementFilter, checkAccess, nameCondition); + final JavaCompletionProcessor processor = new JavaCompletionProcessor(element, elementFilter, checkAccess, parameters.getInvocationCount() <= 1, nameCondition); javaReference.processVariants(processor); final Collection plainResults = processor.getResults(); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java index e57b990ae312..aea4cc222e4c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java @@ -77,7 +77,7 @@ public class JavaDocCompletionContributor extends CompletionContributor { if (ref instanceof PsiJavaReference) { result.stopHere(); - final JavaCompletionProcessor processor = new JavaCompletionProcessor(position, TrueFilter.INSTANCE, false, null); + final JavaCompletionProcessor processor = new JavaCompletionProcessor(position, TrueFilter.INSTANCE, false, false, null); ((PsiJavaReference) ref).processVariants(processor); for (final CompletionElement _item : processor.getResults()) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java b/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java index dc79715dc74b..e6a8a065789c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java @@ -26,12 +26,14 @@ import com.intellij.psi.infos.CandidateInfo; import com.intellij.psi.scope.BaseScopeProcessor; import com.intellij.psi.scope.ElementClassHint; import com.intellij.psi.scope.JavaScopeProcessorEvent; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Set; @@ -58,8 +60,9 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme private PsiClass myQualifierClass = null; private final Condition myMatcher; private final boolean myCheckAccess; + private final Set myNonInitializedFields = new HashSet(); - public JavaCompletionProcessor(PsiElement element, ElementFilter filter, final boolean checkAccess, @Nullable Condition nameCondition) { + public JavaCompletionProcessor(PsiElement element, ElementFilter filter, final boolean checkAccess, boolean checkInitialized, @Nullable Condition nameCondition) { myCheckAccess = checkAccess; mySettings = CodeInsightSettings.getInstance(); myResults = new ArrayList(); @@ -102,6 +105,45 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme } } } + + if (checkInitialized) { + final PsiStatement statement = PsiTreeUtil.getParentOfType(element, PsiStatement.class); + final PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class, true, PsiClass.class); + if (statement != null && method != null && method.isConstructor()) { + final PsiClass containingClass = method.getContainingClass(); + assert containingClass != null; + for (PsiField field : containingClass.getFields()) { + if (!field.hasModifierProperty(PsiModifier.STATIC) && field.getInitializer() == null) { + myNonInitializedFields.add(field); + } + } + + method.accept(new JavaRecursiveElementWalkingVisitor() { + @Override + public void visitAssignmentExpression(PsiAssignmentExpression expression) { + if (expression.getTextRange().getStartOffset() < statement.getTextRange().getStartOffset()) { + final PsiExpression lExpression = expression.getLExpression(); + if (lExpression instanceof PsiReferenceExpression) { + //noinspection SuspiciousMethodCalls + myNonInitializedFields.remove(((PsiReferenceExpression)lExpression).resolve()); + } + } + super.visitAssignmentExpression(expression); + } + + @Override + public void visitMethodCallExpression(PsiMethodCallExpression expression) { + if (expression.getTextRange().getStartOffset() < statement.getTextRange().getStartOffset()) { + final PsiReferenceExpression methodExpression = expression.getMethodExpression(); + if (methodExpression.textMatches("this")) { + myNonInitializedFields.clear(); + } + } + super.visitMethodCallExpression(expression); + } + }); + } + } } public void handleEvent(Event event, Object associated){ @@ -113,19 +155,24 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme } } - public boolean execute(PsiElement element, ResolveState state){ - if(!(element instanceof PsiClass) && element instanceof PsiModifierListOwner){ + public boolean execute(PsiElement element, ResolveState state) { + //noinspection SuspiciousMethodCalls + if (myNonInitializedFields.contains(element)) { + return true; + } + + if (!(element instanceof PsiClass) && element instanceof PsiModifierListOwner) { PsiModifierListOwner modifierListOwner = (PsiModifierListOwner)element; - if(myStatic){ - if(!modifierListOwner.hasModifierProperty(PsiModifier.STATIC)){ + if (myStatic) { + if (!modifierListOwner.hasModifierProperty(PsiModifier.STATIC)) { // we don't need non static method in static context. return true; } } - else{ - if(!mySettings.SHOW_STATIC_AFTER_INSTANCE - && modifierListOwner.hasModifierProperty(PsiModifier.STATIC) - && !myMembersFlag){ + else { + if (!mySettings.SHOW_STATIC_AFTER_INSTANCE + && modifierListOwner.hasModifierProperty(PsiModifier.STATIC) + && !myMembersFlag) { // according settings we don't need to process such fields/methods return true; } diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/DispreferDeclared.java b/java/java-tests/testData/codeInsight/completion/normalSorting/DispreferDeclared.java index e846cff17463..d2e0abca1ea5 100644 --- a/java/java-tests/testData/codeInsight/completion/normalSorting/DispreferDeclared.java +++ b/java/java-tests/testData/codeInsight/completion/normalSorting/DispreferDeclared.java @@ -2,6 +2,7 @@ public class Aaaaaaa { private final String aaa; Aaaaaaa(String aabbb) { + aaa = ""; aaa = true ? null : aa } diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/DispreferDeclaredOfExpectedType.java b/java/java-tests/testData/codeInsight/completion/normalSorting/DispreferDeclaredOfExpectedType.java index 5d79d9702a89..4acc0b1cc375 100644 --- a/java/java-tests/testData/codeInsight/completion/normalSorting/DispreferDeclaredOfExpectedType.java +++ b/java/java-tests/testData/codeInsight/completion/normalSorting/DispreferDeclaredOfExpectedType.java @@ -2,6 +2,7 @@ public class Aaaaaaa { private final String aaa; Aaaaaaa(Object aabbb) { + aaa = ""; aaa = true ? null : aa } diff --git a/java/java-tests/testData/codeInsight/completion/smartType/FieldsSetAbove-out.java b/java/java-tests/testData/codeInsight/completion/smartType/FieldsSetAbove-out.java new file mode 100644 index 000000000000..cc99ed5c463a --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/FieldsSetAbove-out.java @@ -0,0 +1,9 @@ +class A { + int doo; + int aaa; + A(int b) { + doo = b; + aaa = doo; + } +} + diff --git a/java/java-tests/testData/codeInsight/completion/smartType/FieldsSetAbove.java b/java/java-tests/testData/codeInsight/completion/smartType/FieldsSetAbove.java new file mode 100644 index 000000000000..bad8dd3a2920 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/FieldsSetAbove.java @@ -0,0 +1,9 @@ +class A { + int doo; + int aaa; + A(int b) { + doo = b; + aaa = d + } +} + diff --git a/java/java-tests/testData/codeInsight/completion/smartType/FieldsSetInAnotherConstructor-out.java b/java/java-tests/testData/codeInsight/completion/smartType/FieldsSetInAnotherConstructor-out.java new file mode 100644 index 000000000000..f78838d00bf1 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/FieldsSetInAnotherConstructor-out.java @@ -0,0 +1,13 @@ +class A { + int doo; + int aaa; + A(int b) { + doo = b; + } + + A(int aac, int aad) { + this(aac); + aaa = doo; + } +} + diff --git a/java/java-tests/testData/codeInsight/completion/smartType/FieldsSetInAnotherConstructor.java b/java/java-tests/testData/codeInsight/completion/smartType/FieldsSetInAnotherConstructor.java new file mode 100644 index 000000000000..51b47e14411a --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/FieldsSetInAnotherConstructor.java @@ -0,0 +1,13 @@ +class A { + int doo; + int aaa; + A(int b) { + doo = b; + } + + A(int aac, int aad) { + this(aac); + aaa = d + } +} + diff --git a/java/java-tests/testData/codeInsight/completion/smartType/NoFieldsInSuperConstructorCall-out.java b/java/java-tests/testData/codeInsight/completion/smartType/NoFieldsInSuperConstructorCall-out.java new file mode 100644 index 000000000000..dd4e04b8048a --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/NoFieldsInSuperConstructorCall-out.java @@ -0,0 +1,11 @@ +class A { + A(int a) {} +} + +class B extends A { + int aaa; + + B(int aab) { + super(aab); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/NoFieldsInSuperConstructorCall.java b/java/java-tests/testData/codeInsight/completion/smartType/NoFieldsInSuperConstructorCall.java new file mode 100644 index 000000000000..654cfc42cf98 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/NoFieldsInSuperConstructorCall.java @@ -0,0 +1,11 @@ +class A { + A(int a) {} +} + +class B extends A { + int aaa; + + B(int aab) { + super(a); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/NoUninitializedFieldsInConstructor-out.java b/java/java-tests/testData/codeInsight/completion/smartType/NoUninitializedFieldsInConstructor-out.java new file mode 100644 index 000000000000..e49b17247f65 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/NoUninitializedFieldsInConstructor-out.java @@ -0,0 +1,8 @@ +class A { + int aaa; + int aab; + A(int aac) { + aaa = aac; + } +} + diff --git a/java/java-tests/testData/codeInsight/completion/smartType/NoUninitializedFieldsInConstructor.java b/java/java-tests/testData/codeInsight/completion/smartType/NoUninitializedFieldsInConstructor.java new file mode 100644 index 000000000000..4d45189923f9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/NoUninitializedFieldsInConstructor.java @@ -0,0 +1,8 @@ +class A { + int aaa; + int aab; + A(int aac) { + aaa = a + } +} + diff --git a/java/java-tests/testData/codeInsight/completion/smartType/second/NonInitializedField-out.java b/java/java-tests/testData/codeInsight/completion/smartType/second/NonInitializedField-out.java new file mode 100644 index 000000000000..b74ac99da84f --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/second/NonInitializedField-out.java @@ -0,0 +1,7 @@ +class Foo { + int aaa; + int bbb; + Foo() { + aaa = bbb; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/second/NonInitializedField.java b/java/java-tests/testData/codeInsight/completion/smartType/second/NonInitializedField.java new file mode 100644 index 000000000000..e8eee5d953f6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/second/NonInitializedField.java @@ -0,0 +1,7 @@ +class Foo { + int aaa; + int bbb; + Foo() { + aaa = b + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SecondSmartTypeCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SecondSmartTypeCompletionTest.java index 85c3caba21ec..3415ee36487e 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SecondSmartTypeCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SecondSmartTypeCompletionTest.java @@ -7,8 +7,6 @@ import com.intellij.codeInsight.lookup.LookupElementDecorator; import com.intellij.codeInsight.lookup.LookupItem; import com.intellij.codeInsight.lookup.LookupManager; import com.intellij.codeInsight.lookup.impl.LookupImpl; -import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; import com.intellij.testFramework.IdeaTestUtil; import org.jetbrains.annotations.NonNls; @@ -67,6 +65,7 @@ public class SecondSmartTypeCompletionTest extends LightCompletionTestCase { checkResultByFile(BASE_PATH + "/" + getTestName(false) + "-out.java"); } + public void testNonInitializedField() throws Throwable { doTest(); } public void testIgnoreToString() throws Throwable { doTest(); } public void testDontIgnoreToStringInsideIt() throws Throwable { doTest(); } public void testDontIgnoreToStringInStringBuilders() throws Throwable { diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java index ad197fd77080..7150b0a3630c 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java @@ -431,6 +431,11 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase { public void testPrivateOverloads() throws Throwable { doTest(); } + public void testNoFieldsInSuperConstructorCall() throws Throwable { doTest(); } + public void testNoUninitializedFieldsInConstructor() throws Throwable { doTest(); } + public void testFieldsSetInAnotherConstructor() throws Throwable { doTest(); } + public void testFieldsSetAbove() throws Throwable { doTest(); } + public void testHonorSelection() throws Throwable { configureByTestName(); select(); From 10c8d2aa11cb387632ca56628b059b85b89f697f Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 22 Feb 2011 17:11:04 +0100 Subject: [PATCH 100/169] smart completion is not smart enough to require that many abstractions --- .../BasicExpressionCompletionContributor.java | 53 ++++++++----------- .../CollectionsUtilityMethodsProvider.java | 24 +++++---- .../ExpressionSmartCompletionContributor.java | 47 ---------------- .../completion/JavaCompletionData.java | 10 +++- .../JavaSmartCompletionContributor.java | 12 ++--- ...erenceExpressionCompletionContributor.java | 28 +++++----- .../filters/getters/ClassLiteralGetter.java | 24 ++++----- .../psi/filters/getters/MembersGetter.java | 12 ++--- .../AbstractCompletionContributor.java | 34 ------------ .../completion/CompletionContributor.java | 2 +- 10 files changed, 80 insertions(+), 166 deletions(-) delete mode 100644 java/java-impl/src/com/intellij/codeInsight/completion/ExpressionSmartCompletionContributor.java delete mode 100644 platform/lang-api/src/com/intellij/codeInsight/completion/AbstractCompletionContributor.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/BasicExpressionCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/BasicExpressionCompletionContributor.java index 92b9a74a0d1d..15028e8e538c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/BasicExpressionCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/BasicExpressionCompletionContributor.java @@ -31,7 +31,6 @@ import com.intellij.psi.scope.util.PsiScopesUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.Consumer; import com.intellij.util.IncorrectOperationException; -import com.intellij.util.ProcessingContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -39,16 +38,15 @@ import java.util.Map; import static com.intellij.patterns.PsiJavaPatterns.psiClass; import static com.intellij.patterns.PsiJavaPatterns.psiElement; -import static com.intellij.patterns.StandardPatterns.not; /** * @author peter */ -public class BasicExpressionCompletionContributor extends ExpressionSmartCompletionContributor{ +public class BasicExpressionCompletionContributor { public static final ElementPattern AFTER_DOT = psiElement().afterLeaf("."); - private static void addKeyword(final CompletionResultSet result, final PsiElement element, final String s) { - result.addElement(createKeywordLookupItem(element, s)); + private static void addKeyword(final Consumer result, final PsiElement element, final String s) { + result.consume(createKeywordLookupItem(element, s)); } public static LookupElement createKeywordLookupItem(final PsiElement element, final String s) { @@ -61,31 +59,29 @@ public class BasicExpressionCompletionContributor extends ExpressionSmartComplet } } + public static void fillCompletionVariants(JavaSmartCompletionParameters parameters, + final Consumer result, + PrefixMatcher matcher) { + final PsiElement element = parameters.getPosition(); + if (PsiJavaPatterns.psiElement().afterLeaf( + PsiJavaPatterns.psiElement().withText(".").afterLeaf( + PsiJavaPatterns.psiElement().withParent( + PsiJavaPatterns.psiElement().referencing(psiClass())))).accepts(element)) { + addKeyword(result, element, PsiKeyword.CLASS); + addKeyword(result, element, PsiKeyword.THIS); - public BasicExpressionCompletionContributor() { - extend(PsiJavaPatterns.psiElement().afterLeaf( - PsiJavaPatterns.psiElement().withText(".").afterLeaf( - PsiJavaPatterns.psiElement().withParent( - PsiJavaPatterns.psiElement().referencing(psiClass())))), new CompletionProvider() { - public void addCompletions(@NotNull final JavaSmartCompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result) { - final PsiElement element = parameters.getPosition(); - addKeyword(result, element, PsiKeyword.CLASS); - addKeyword(result, element, PsiKeyword.THIS); - } + } - }); + if (!AFTER_DOT.accepts(element)) { + CollectionsUtilityMethodsProvider.addCompletions(parameters, result); + ClassLiteralGetter.addCompletions(parameters, result, matcher); - extend(not(AFTER_DOT), new CollectionsUtilityMethodsProvider()); - extend(not(AFTER_DOT), new ClassLiteralGetter()); - - extend(not(AFTER_DOT), new CompletionProvider() { - protected void addCompletions(@NotNull final JavaSmartCompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result) { - final PsiElement position = parameters.getPosition(); + final PsiElement position = parameters.getPosition(); final PsiType expectedType = parameters.getExpectedType(); for (final TemplateImpl template : TemplateSettings.getInstance().getTemplates()) { if (!template.isDeactivated() && template.getTemplateContext().isEnabled(new SmartCompletionContextType())) { - result.addElement(new SmartCompletionTemplateItem(template, position)); + result.consume(new SmartCompletionTemplateItem(template, position)); } } @@ -100,17 +96,12 @@ public class BasicExpressionCompletionContributor extends ExpressionSmartComplet } for (final PsiExpression expression : ThisGetter.getThisExpressionVariants(position)) { - result.addElement(new ExpressionLookupItem(expression)); + result.consume(new ExpressionLookupItem(expression)); } } - processDataflowExpressionTypes(position, expectedType, result.getPrefixMatcher(), new Consumer() { - public void consume(LookupElement decorator) { - result.addElement(decorator); - } - }); - } - }); + processDataflowExpressionTypes(position, expectedType, matcher, result); + } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/CollectionsUtilityMethodsProvider.java b/java/java-impl/src/com/intellij/codeInsight/completion/CollectionsUtilityMethodsProvider.java index e39df303d589..a9f93fdde07b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/CollectionsUtilityMethodsProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/CollectionsUtilityMethodsProvider.java @@ -15,19 +15,21 @@ */ package com.intellij.codeInsight.completion; -import com.intellij.codeInsight.lookup.LookupItem; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.NonNls; -import com.intellij.util.ProcessingContext; -import com.intellij.psi.*; -import static com.intellij.psi.CommonClassNames.*; import com.intellij.codeInsight.lookup.AutoCompletionPolicy; +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.psi.*; +import com.intellij.util.Consumer; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +import static com.intellij.psi.CommonClassNames.*; /** * @author peter */ -class CollectionsUtilityMethodsProvider extends CompletionProvider { - public void addCompletions(@NotNull final JavaSmartCompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result) { +class CollectionsUtilityMethodsProvider { + public static void addCompletions(@NotNull final JavaSmartCompletionParameters parameters, + @NotNull final Consumer result) { final PsiElement element = parameters.getPosition(); final PsiElement parent = element.getParent(); @@ -63,7 +65,7 @@ class CollectionsUtilityMethodsProvider extends CompletionProvider result, final PsiType expectedType, final PsiType defaultType, final String baseClassName, @NonNls final String method, @NotNull final PsiClass collectionsClass) { if (isClassType(expectedType, baseClassName) || isClassType(expectedType, JAVA_UTIL_COLLECTION)) { @@ -73,7 +75,7 @@ class CollectionsUtilityMethodsProvider extends CompletionProvider result, PsiType expectedType, String methodName, PsiClass containingClass) { final PsiMethod[] methods = containingClass.findMethodsByName(methodName, false); if (methods.length == 0) { return; @@ -83,7 +85,7 @@ class CollectionsUtilityMethodsProvider extends CompletionProvider { - - private final List, CompletionProvider>> myList = - new ArrayList, CompletionProvider>>(); - - public final void extend(final ElementPattern place, CompletionProvider provider) { - myList.add(new Pair, CompletionProvider>(place, provider)); - } - - public void fillCompletionVariants(final JavaSmartCompletionParameters parameters, CompletionResultSet result) { - for (final Pair, CompletionProvider> pair : myList) { - final ProcessingContext context = new ProcessingContext(); - if (pair.first.accepts(parameters.getPosition(), context)) { - pair.second.addCompletionVariants(parameters, context, result); - } - } - } - -} diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java index bd4597559c47..4cebb6f7b19f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java @@ -39,6 +39,7 @@ import com.intellij.psi.jsp.JspElementType; import com.intellij.psi.scope.ElementClassFilter; import com.intellij.psi.templateLanguages.OuterLanguageElement; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.Consumer; import com.intellij.util.ProcessingContext; import org.jetbrains.annotations.NonNls; @@ -550,7 +551,7 @@ public class JavaCompletionData extends JavaAwareCompletionData{ } @Override - public void fillCompletions(CompletionParameters parameters, CompletionResultSet result) { + public void fillCompletions(CompletionParameters parameters, final CompletionResultSet result) { final PsiElement position = parameters.getPosition(); if (PsiTreeUtil.getParentOfType(position, PsiComment.class, false) != null) { return; @@ -631,7 +632,12 @@ public class JavaCompletionData extends JavaAwareCompletionData{ !(position.getParent() instanceof PsiLiteralExpression) && !(position.getParent().getParent() instanceof PsiSwitchLabelStatement)) { for (final ExpectedTypeInfo info : JavaSmartCompletionContributor.getExpectedTypes(parameters)) { - MembersGetter.addMembers(position, info.getDefaultType(), result); + MembersGetter.addMembers(position, info.getDefaultType(), new Consumer() { + @Override + public void consume(LookupElement element) { + result.addElement(element); + } + }); } } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java index 57b98d2a4cc6..eeaf61478398 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java @@ -197,9 +197,9 @@ public class JavaSmartCompletionContributor extends CompletionContributor { final JavaSmartCompletionParameters parameters = new JavaSmartCompletionParameters(params, info); final PsiType type = info.getType(); - final CompletionService service = CompletionService.getCompletionService(); - new BasicExpressionCompletionContributor().fillCompletionVariants(parameters, service.createResultSet(parameters, new Consumer() { - public void consume(final LookupElement lookupElement) { + BasicExpressionCompletionContributor.fillCompletionVariants(parameters, new Consumer() { + @Override + public void consume(LookupElement lookupElement) { final TypedLookupItem typed = lookupElement.as(TypedLookupItem.CLASS_CONDITION_KEY); if (typed != null) { final PsiType psiType = typed.getType(); @@ -208,12 +208,12 @@ public class JavaSmartCompletionContributor extends CompletionContributor { } } } - }, JavaSmartCompletionContributor.this)); - ReferenceExpressionCompletionContributor.fillCompletionVariants(parameters, service.createResultSet(parameters, new Consumer() { + }, result.getPrefixMatcher()); + ReferenceExpressionCompletionContributor.fillCompletionVariants(parameters, new Consumer() { public void consume(final LookupElement lookupElement) { result.addElement(decorate(lookupElement, _infos)); } - }, JavaSmartCompletionContributor.this)); + }); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java index 1f92244fec69..128fdc78843a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java @@ -104,7 +104,7 @@ public class ReferenceExpressionCompletionContributor { return TrueFilter.INSTANCE; } - public static void fillCompletionVariants(final JavaSmartCompletionParameters parameters, final CompletionResultSet result) { + public static void fillCompletionVariants(final JavaSmartCompletionParameters parameters, final Consumer result) { ApplicationManager.getApplication().runReadAction(new Runnable() { public void run() { final PsiElement element = parameters.getPosition(); @@ -115,7 +115,7 @@ public class ReferenceExpressionCompletionContributor { if (reference != null) { final ElementFilter filter = getReferenceFilter(element, false); for (final LookupElement item : completeFinalReference(element, reference, filter, parameters)) { - result.addElement(item); + result.consume(item); } final boolean secondTime = parameters.getInvocationCount() >= 2; @@ -180,7 +180,7 @@ public class ReferenceExpressionCompletionContributor { } private static void addSingleArrayElementAccess(PsiElement element, LookupElement item, JavaSmartCompletionParameters parameters, - CompletionResultSet result) { + Consumer result) { if (item.getObject() instanceof PsiLocalVariable) { final PsiLocalVariable variable = (PsiLocalVariable)item.getObject(); final PsiType type = variable.getType(); @@ -192,7 +192,7 @@ public class ReferenceExpressionCompletionContributor { if (dimensions.length == 1 && "1".equals(dimensions[0].getText()) && newExpression.getArrayInitializer() == null) { final String text = variable.getName() + "[0]"; final PsiExpression conversion = createExpression(text, element); - result.addElement(new ExpressionLookupItem(conversion).setIcon(variable.getIcon(Iconable.ICON_FLAG_VISIBILITY))); + result.consume(new ExpressionLookupItem(conversion).setIcon(variable.getIcon(Iconable.ICON_FLAG_VISIBILITY))); } } } @@ -204,7 +204,7 @@ public class ReferenceExpressionCompletionContributor { } private static void addSecondCompletionVariants(PsiElement element, PsiReference reference, LookupElement baseItem, - JavaSmartCompletionParameters parameters, CompletionResultSet result) { + JavaSmartCompletionParameters parameters, Consumer result) { final Object object = baseItem.getObject(); try { @@ -236,7 +236,7 @@ public class ReferenceExpressionCompletionContributor { } private static void addArrayMemberAccessors(final PsiElement element, final String prefix, final PsiType itemType, - final PsiElement qualifier, final CompletionResultSet result, PsiModifierListOwner object, + final PsiElement qualifier, final Consumer result, PsiModifierListOwner object, final PsiType expectedType) throws IncorrectOperationException { if (itemType instanceof PsiArrayType && expectedType.isAssignableFrom(((PsiArrayType)itemType).getComponentType())) { @@ -262,7 +262,7 @@ public class ReferenceExpressionCompletionContributor { editor.getCaretModel().moveToOffset(tailOffset + 1 + callSpace.length()); } }); - result.addElement(item); + result.consume(item); } } @@ -276,7 +276,7 @@ public class ReferenceExpressionCompletionContributor { return false; } - private static void addArraysAsListConversions(final PsiElement element, final String prefix, final PsiType itemType, final CompletionResultSet result, + private static void addArraysAsListConversions(final PsiElement element, final String prefix, final PsiType itemType, final Consumer result, @Nullable PsiElement qualifier, final PsiType expectedType) throws IncorrectOperationException { PsiType componentType = PsiUtil.extractIterableTypeParameter(expectedType, true); @@ -321,11 +321,11 @@ public class ReferenceExpressionCompletionContributor { PostprocessReformattingAspect.getInstance(project).doPostponedFormatting(); } }); - result.addElement(item); + result.consume(item); } private static void addToArrayConversions(final PsiElement element, final Object object, final String prefix, final PsiType itemType, - final CompletionResultSet result, @Nullable final PsiElement qualifier, + final Consumer result, @Nullable final PsiElement qualifier, final PsiType expectedType) { final String callSpace = getSpace(CodeStyleSettingsManager.getSettings(element.getProject()).SPACE_WITHIN_METHOD_CALL_PARENTHESES); final PsiType componentType = PsiUtil.extractIterableTypeParameter(itemType, true); @@ -380,7 +380,7 @@ public class ReferenceExpressionCompletionContributor { } private static void addChainedCallVariants(final PsiElement place, LookupElement qualifierItem, - final CompletionResultSet result, + final Consumer result, PsiType qualifierType, final PsiType expectedType, JavaSmartCompletionParameters parameters) throws IncorrectOperationException { final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(place.getProject()).getElementFactory(); @@ -404,7 +404,7 @@ public class ReferenceExpressionCompletionContributor { final ElementFilter filter = getReferenceFilter(place, true); for (final LookupElement item : completeFinalReference(place, mockRef, filter, parameters)) { if (shoudChain(place, varType, expectedType, item)) { - result.addElement(JavaChainLookupElement.chainElements(qualifierItem, item)); + result.consume(JavaChainLookupElement.chainElements(qualifierItem, item)); } } } @@ -454,7 +454,7 @@ public class ReferenceExpressionCompletionContributor { return true; } - private static void addToArrayConversion(final PsiElement element, final String prefix, @NonNls final String expressionString, @NonNls String presentableString, final CompletionResultSet result, PsiElement qualifier) { + private static void addToArrayConversion(final PsiElement element, final String prefix, @NonNls final String expressionString, @NonNls String presentableString, final Consumer result, PsiElement qualifier) { final boolean callSpace = CodeStyleSettingsManager.getSettings(element.getProject()).SPACE_WITHIN_METHOD_CALL_PARENTHESES; final PsiExpression conversion; try { @@ -490,7 +490,7 @@ public class ReferenceExpressionCompletionContributor { PostprocessReformattingAspect.getInstance(project).doPostponedFormatting(); } }); - result.addElement(item); + result.consume(item); } private static boolean isEmptyArrayInitializer(@Nullable PsiElement element) { diff --git a/java/java-impl/src/com/intellij/psi/filters/getters/ClassLiteralGetter.java b/java/java-impl/src/com/intellij/psi/filters/getters/ClassLiteralGetter.java index 747f64254254..8876359ea21b 100644 --- a/java/java-impl/src/com/intellij/psi/filters/getters/ClassLiteralGetter.java +++ b/java/java-impl/src/com/intellij/psi/filters/getters/ClassLiteralGetter.java @@ -16,30 +16,26 @@ package com.intellij.psi.filters.getters; import com.intellij.codeInsight.CodeInsightUtil; -import com.intellij.codeInsight.completion.CompletionProvider; -import com.intellij.codeInsight.completion.CompletionResultSet; import com.intellij.codeInsight.completion.JavaSmartCompletionParameters; import com.intellij.codeInsight.completion.PrefixMatcher; import com.intellij.codeInsight.lookup.AutoCompletionPolicy; +import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.util.PsiUtil; +import com.intellij.util.Consumer; import com.intellij.util.IncorrectOperationException; -import com.intellij.util.ProcessingContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class ClassLiteralGetter extends CompletionProvider { +public class ClassLiteralGetter { private static final Logger LOG = Logger.getInstance("com.intellij.psi.filters.getters.ClassLiteralGetter"); - @Override - protected void addCompletions(@NotNull final JavaSmartCompletionParameters parameters, - ProcessingContext context, - @NotNull CompletionResultSet result) { + public static void addCompletions(@NotNull final JavaSmartCompletionParameters parameters, + @NotNull Consumer result, final PrefixMatcher matcher) { - final PrefixMatcher matcher = result.getPrefixMatcher(); final Condition shortNameCondition = new Condition() { public boolean value(String s) { return matcher.prefixMatches(s); @@ -61,7 +57,7 @@ public class ClassLiteralGetter extends CompletionProvider shortNameCondition, final PsiType classParameter, - CompletionResultSet result) { + Consumer result, PrefixMatcher matcher) { final String canonicalText = classParameter.getCanonicalText(); - if (CommonClassNames.JAVA_LANG_OBJECT.equals(canonicalText) && StringUtil.isEmpty(result.getPrefixMatcher().getPrefix())) { + if (CommonClassNames.JAVA_LANG_OBJECT.equals(canonicalText) && StringUtil.isEmpty(matcher.getPrefix())) { return; } @@ -80,13 +76,13 @@ public class ClassLiteralGetter extends CompletionProvider resultSet, final PsiFile context) { if (type instanceof PsiClassType && PsiUtil.resolveClassInType(type) != null && !((PsiClassType)type).hasParameters() && !(((PsiClassType)type).resolve() instanceof PsiTypeParameter)) { try { - resultSet.addElement(AutoCompletionPolicy.NEVER_AUTOCOMPLETE.applyPolicy(new ClassLiteralLookupElement((PsiClassType)type, context))); + resultSet.consume(AutoCompletionPolicy.NEVER_AUTOCOMPLETE.applyPolicy(new ClassLiteralLookupElement((PsiClassType)type, context))); } catch (IncorrectOperationException e) { LOG.error(e); diff --git a/java/java-impl/src/com/intellij/psi/filters/getters/MembersGetter.java b/java/java-impl/src/com/intellij/psi/filters/getters/MembersGetter.java index 1ca922007a95..fc0b4d1ac854 100644 --- a/java/java-impl/src/com/intellij/psi/filters/getters/MembersGetter.java +++ b/java/java-impl/src/com/intellij/psi/filters/getters/MembersGetter.java @@ -15,10 +15,9 @@ */ package com.intellij.psi.filters.getters; -import com.intellij.codeInsight.completion.CompletionResultSet; +import com.intellij.codeInsight.completion.JavaCompletionUtil; import com.intellij.codeInsight.completion.JavaMethodCallElement; import com.intellij.codeInsight.completion.SmartCompletionDecorator; -import com.intellij.codeInsight.completion.JavaCompletionUtil; import com.intellij.codeInsight.lookup.*; import com.intellij.psi.*; import com.intellij.psi.filters.TrueFilter; @@ -27,6 +26,7 @@ import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; +import com.intellij.util.Consumer; import org.jetbrains.annotations.Nullable; /** @@ -38,7 +38,7 @@ import org.jetbrains.annotations.Nullable; */ public class MembersGetter { - public static void addMembers(PsiElement position, PsiType expectedType, CompletionResultSet results) { + public static void addMembers(PsiElement position, PsiType expectedType, Consumer results) { final PsiClass psiClass = PsiUtil.resolveClassInType(expectedType); processMembers(position, results, psiClass, PsiTreeUtil.getParentOfType(position, PsiAnnotation.class) != null, expectedType); @@ -47,7 +47,7 @@ public class MembersGetter { } } - private static void addConstantsFromTargetClass(PsiElement position, PsiType expectedType, CompletionResultSet results) { + private static void addConstantsFromTargetClass(PsiElement position, PsiType expectedType, Consumer results) { PsiElement parent = position.getParent(); if (!(parent instanceof PsiReferenceExpression)) { return; @@ -99,7 +99,7 @@ public class MembersGetter { return null; } - private static void processMembers(final PsiElement context, final CompletionResultSet results, @Nullable final PsiClass where, + private static void processMembers(final PsiElement context, final Consumer results, @Nullable final PsiClass where, final boolean acceptMethods, PsiType expectedType) { if (where == null) return; @@ -132,7 +132,7 @@ public class MembersGetter { } final PsiType itemType = ((TypedLookupItem)item).getType(); if (itemType != null && expectedType.isAssignableFrom(itemType)) { - results.addElement(item); + results.consume(item); } } } diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/AbstractCompletionContributor.java b/platform/lang-api/src/com/intellij/codeInsight/completion/AbstractCompletionContributor.java deleted file mode 100644 index 649b0ed437b7..000000000000 --- a/platform/lang-api/src/com/intellij/codeInsight/completion/AbstractCompletionContributor.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2000-2009 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 com.intellij.codeInsight.completion; - -/** - * @author peter - */ -public abstract class AbstractCompletionContributor { - - /** - * Fill completion variants. - * - * Invoked sequentially for all registered contributors in order of registration. - * - * @param parameters - * @param result - * @return Whether to continue variants collecting process. If false, remaining non-visited completion contributors are ignored. - * @see CompletionService#getVariantsFromContributors(com.intellij.openapi.extensions.ExtensionPointName, CompletionParameters, AbstractCompletionContributor , com.intellij.util.Consumer) - */ - public abstract void fillCompletionVariants(Params parameters, CompletionResultSet result); -} diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionContributor.java b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionContributor.java index 9ad079f101ee..9e0a43281237 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionContributor.java +++ b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionContributor.java @@ -125,7 +125,7 @@ import java.util.List; * * @author peter */ -public abstract class CompletionContributor extends AbstractCompletionContributor{ +public abstract class CompletionContributor { private final MultiMap, CompletionProvider>> myMap = new MultiMap, CompletionProvider>>(); From 8e00b86404bf100df6f6c0c20e510c4932093603 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 22 Feb 2011 17:15:31 +0100 Subject: [PATCH 101/169] java completion sorting on the new api, take 1 --- .../JavaClassNameCompletionContributor.java | 2 +- .../completion/JavaCompletionContributor.java | 15 +- .../completion/JavaCompletionSorting.java | 173 ++++++++++++++++++ .../JavaSmartCompletionContributor.java | 5 + .../completion/PreferDefaultTypeWeigher.java | 105 ----------- .../completion/StaticMembersWeigher.java | 61 ------ resources/src/META-INF/IdeaPlugin.xml | 6 +- 7 files changed, 181 insertions(+), 186 deletions(-) create mode 100644 java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java delete mode 100644 java/java-impl/src/com/intellij/codeInsight/completion/PreferDefaultTypeWeigher.java delete mode 100644 java/java-impl/src/com/intellij/codeInsight/completion/StaticMembersWeigher.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java index 1d3cf746af7e..cc3d3fd2178f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java @@ -56,7 +56,7 @@ public class JavaClassNameCompletionContributor extends CompletionContributor { CompletionService.getCompletionService().setAdvertisementText(CompletionBundle.message("completion.class.name.hint.2", getActionShortcut(IdeActions.ACTION_CLASS_NAME_COMPLETION))); } - final CompletionResultSet result = JavaCompletionContributor.addJavaSorting(parameters, _result); + final CompletionResultSet result = JavaCompletionSorting.addJavaSorting(parameters, _result); final PsiElement insertedElement = parameters.getPosition(); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java index 5c834c965a1b..34c72286b8e6 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java @@ -15,7 +15,6 @@ */ package com.intellij.codeInsight.completion; -import com.intellij.codeInsight.ExpectedTypeInfo; import com.intellij.codeInsight.TailType; import com.intellij.codeInsight.daemon.impl.quickfix.ImportClassFix; import com.intellij.codeInsight.hint.ShowParameterInfoHandler; @@ -182,7 +181,7 @@ public class JavaCompletionContributor extends CompletionContributor { } - final CompletionResultSet result = addJavaSorting(parameters, _result); + final CompletionResultSet result = JavaCompletionSorting.addJavaSorting(parameters, _result); if (ANNOTATION_ATTRIBUTE_NAME.accepts(position)) { completeAnnotationAttributeName(result, position, parameters); @@ -207,18 +206,6 @@ public class JavaCompletionContributor extends CompletionContributor { result.stopHere(); } - public static CompletionResultSet addJavaSorting(CompletionParameters parameters, CompletionResultSet result) { - final boolean afterNew = JavaSmartCompletionContributor.AFTER_NEW.accepts(parameters.getPosition()); - final ExpectedTypeInfo[] expectedTypes = afterNew ? JavaSmartCompletionContributor.getExpectedTypes(parameters) : ExpectedTypeInfo.EMPTY_ARRAY; - return result.withRelevanceSorter(CompletionSorter.defaultSorter(parameters).weighBefore("liftShorter", new LookupElementWeigher("expectedAfterNew") { - @NotNull - @Override - public Comparable weigh(@NotNull LookupElement element) { - return -((Enum)PreferExpectedTypeWeigher.weigh(element, expectedTypes)).ordinal(); - } - })); - } - public static void addAllClasses(CompletionParameters parameters, final CompletionResultSet result, PsiElement position, diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java new file mode 100644 index 000000000000..acb62b5a201a --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java @@ -0,0 +1,173 @@ +/* + * Copyright 2000-2011 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 com.intellij.codeInsight.completion; + +import com.intellij.codeInsight.ExpectedTypeInfo; +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.codeInsight.lookup.LookupElementWeigher; +import com.intellij.openapi.util.Pair; +import com.intellij.patterns.PsiJavaPatterns; +import com.intellij.psi.*; +import com.intellij.psi.javadoc.PsiDocComment; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; +import com.intellij.psi.util.TypeConversionUtil; +import org.jetbrains.annotations.NotNull; + +/** + * @author peter + */ +public class JavaCompletionSorting { + private JavaCompletionSorting() { + } + + public static CompletionResultSet addJavaSorting(final CompletionParameters parameters, CompletionResultSet result) { + final PsiElement position = parameters.getPosition(); + final ExpectedTypeInfo[] expectedTypes = PsiJavaPatterns.psiElement().beforeLeaf(PsiJavaPatterns.psiElement().withText(".")).accepts(position) ? ExpectedTypeInfo.EMPTY_ARRAY : JavaSmartCompletionContributor.getExpectedTypes(parameters); + final CompletionType type = parameters.getCompletionType(); + + final boolean smart = type == CompletionType.SMART; + CompletionSorter sorter = CompletionSorter.defaultSorter(parameters); + if (!smart && JavaSmartCompletionContributor.AFTER_NEW.accepts(position)) { + sorter = sorter.weighBefore("liftShorter", new LookupElementWeigher("expectedAfterNew") { + @NotNull + @Override + public Comparable weigh(@NotNull LookupElement element) { + return -((Enum)PreferExpectedTypeWeigher.weigh(element, expectedTypes)).ordinal(); + } + }); + } + if (!smart) { + sorter = preferStatics(sorter, position); + } + if (smart) { + sorter = sorter.weighAfter("negativeStats", new PreferDefaultTypeWeigher(expectedTypes, parameters)); + } + + return result.withRelevanceSorter(sorter); + } + + + + static CompletionSorter preferStatics(CompletionSorter sorter, PsiElement position) { + if (PsiTreeUtil.getParentOfType(position, PsiDocComment.class) != null) { + return sorter; + } + if (position.getParent() instanceof PsiReferenceExpression) { + final PsiReferenceExpression refExpr = (PsiReferenceExpression)position.getParent(); + final PsiElement qualifier = refExpr.getQualifier(); + if (qualifier == null) { + return sorter; + } + if (!(qualifier instanceof PsiJavaCodeReferenceElement) || !(((PsiJavaCodeReferenceElement)qualifier).resolve() instanceof PsiClass)) { + return sorter; + } + } + + return sorter.weighAfter("negativeStats", new LookupElementWeigher("statics") { + @NotNull + @Override + public Comparable weigh(@NotNull LookupElement element) { + final Object o = element.getObject(); + if (!(o instanceof PsiMember)) return 0; + + if (((PsiMember)o).hasModifierProperty(PsiModifier.STATIC)) { + if (o instanceof PsiMethod) return -5; + if (o instanceof PsiField) return -4; + } + + if (o instanceof PsiClass) return -3; + + //instance method or field + return -5; + } + }); + } + + private static class PreferDefaultTypeWeigher extends LookupElementWeigher { + private final PsiTypeParameter myTypeParameter; + private final ExpectedTypeInfo[] myExpectedTypes; + private final CompletionParameters myParameters; + private final CompletionLocation myLocation; + + public PreferDefaultTypeWeigher(ExpectedTypeInfo[] expectedTypes, CompletionParameters parameters) { + super("defaultType"); + myExpectedTypes = expectedTypes; + myParameters = parameters; + + final Pair pair = JavaSmartCompletionContributor.getTypeParameterInfo(parameters.getPosition()); + myTypeParameter = pair == null ? null : pair.first.getTypeParameters()[pair.second.intValue()]; + myLocation = new CompletionLocation(myParameters); + } + + @NotNull + @Override + public Comparable weigh(@NotNull LookupElement item) { + final Object object = item.getObject(); + + if (object instanceof PsiClass) { + if (myTypeParameter != null && object.equals(PsiUtil.resolveClassInType(TypeConversionUtil.typeParameterErasure(myTypeParameter)))) { + return MyResult.exactlyExpected; + } + } + + if (myExpectedTypes == null) return MyResult.normal; + + PsiType itemType = JavaCompletionUtil.getLookupElementType(item); + if (itemType == null || !itemType.isValid()) return MyResult.normal; + + if (object instanceof PsiClass) { + for (final ExpectedTypeInfo info : myExpectedTypes) { + if (TypeConversionUtil.erasure(info.getType().getDeepComponentType()).equals(TypeConversionUtil.erasure(itemType))) { + return AbstractExpectedTypeSkipper.skips(item, myLocation) ? MyResult.expectedNoSelect : MyResult.exactlyExpected; + } + } + } + + for (final ExpectedTypeInfo expectedInfo : myExpectedTypes) { + final PsiType defaultType = expectedInfo.getDefaultType(); + final PsiType expectedType = expectedInfo.getType(); + if (!expectedType.isValid()) { + return MyResult.normal; + } + + if (defaultType != expectedType) { + if (defaultType.equals(itemType)) { + return MyResult.exactlyDefault; + } + + if (defaultType.isAssignableFrom(itemType)) { + return MyResult.ofDefaultType; + } + } + if (PsiType.VOID.equals(itemType) && PsiType.VOID.equals(expectedType)) { + return MyResult.exactlyExpected; + } + } + + return MyResult.normal; + } + + private enum MyResult { + expectedNoSelect, + exactlyDefault, + ofDefaultType, + exactlyExpected, + normal, + } + + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java index eeaf61478398..0e44b87694ee 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java @@ -335,6 +335,11 @@ public class JavaSmartCompletionContributor extends CompletionContributor { extend(CompletionType.SMART, AFTER_NEW, new JavaInheritorsGetter(ConstructorInsertHandler.SMART_INSTANCE)); } + @Override + public void fillCompletionVariants(CompletionParameters parameters, CompletionResultSet result) { + super.fillCompletionVariants(parameters, JavaCompletionSorting.addJavaSorting(parameters, result)); + } + public static SmartCompletionDecorator decorate(LookupElement lookupElement, Collection infos) { if (lookupElement instanceof LookupItem) { final LookupItem lookupItem = (LookupItem)lookupElement; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferDefaultTypeWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferDefaultTypeWeigher.java deleted file mode 100644 index 0b66e21022c2..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferDefaultTypeWeigher.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2000-2009 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 com.intellij.codeInsight.completion; - -import com.intellij.codeInsight.ExpectedTypeInfo; -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.openapi.util.NullableLazyKey; -import com.intellij.openapi.util.Pair; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiType; -import com.intellij.psi.PsiTypeParameter; -import com.intellij.psi.util.PsiUtil; -import com.intellij.psi.util.TypeConversionUtil; -import com.intellij.util.NullableFunction; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * @author peter -*/ -public class PreferDefaultTypeWeigher extends CompletionWeigher { - private static final NullableLazyKey TYPE_PARAMETER = NullableLazyKey.create("expectedTypes", new NullableFunction() { - @Nullable - public PsiTypeParameter fun(final CompletionLocation location) { - final Pair pair = - JavaSmartCompletionContributor.getTypeParameterInfo(location.getCompletionParameters().getPosition()); - if (pair == null) return null; - return pair.first.getTypeParameters()[pair.second.intValue()]; - } - }); - - - private enum MyResult { - normal, - exactlyExpected, - ofDefaultType, - exactlyDefault, - expectedNoSelect - } - - public MyResult weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) { - if (location == null) { - return null; - } - final Object object = item.getObject(); - if (location.getCompletionType() != CompletionType.SMART) return MyResult.normal; - - if (object instanceof PsiClass) { - final PsiTypeParameter parameter = TYPE_PARAMETER.getValue(location); - if (parameter != null && object.equals(PsiUtil.resolveClassInType(TypeConversionUtil.typeParameterErasure(parameter)))) { - return MyResult.exactlyExpected; - } - } - - ExpectedTypeInfo[] expectedInfos = JavaCompletionUtil.EXPECTED_TYPES.getValue(location); - if (expectedInfos == null) return MyResult.normal; - - PsiType itemType = JavaCompletionUtil.getLookupElementType(item); - if (itemType == null || !itemType.isValid()) return MyResult.normal; - - if (object instanceof PsiClass) { - for (final ExpectedTypeInfo info : expectedInfos) { - if (TypeConversionUtil.erasure(info.getType().getDeepComponentType()).equals(TypeConversionUtil.erasure(itemType))) { - return AbstractExpectedTypeSkipper.skips(item, location) ? MyResult.expectedNoSelect : MyResult.exactlyExpected; - } - } - } - - for (final ExpectedTypeInfo expectedInfo : expectedInfos) { - final PsiType defaultType = expectedInfo.getDefaultType(); - final PsiType expectedType = expectedInfo.getType(); - if (!expectedType.isValid()) { - return MyResult.normal; - } - - if (defaultType != expectedType) { - if (defaultType.equals(itemType)) { - return MyResult.exactlyDefault; - } - - if (defaultType.isAssignableFrom(itemType)) { - return MyResult.ofDefaultType; - } - } - if (PsiType.VOID.equals(itemType) && PsiType.VOID.equals(expectedType)) { - return MyResult.exactlyExpected; - } - } - - return MyResult.normal; - } -} \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/StaticMembersWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/StaticMembersWeigher.java deleted file mode 100644 index 1ae1ce9513ff..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/completion/StaticMembersWeigher.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2000-2009 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 com.intellij.codeInsight.completion; - -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.psi.*; -import com.intellij.psi.javadoc.PsiDocComment; -import com.intellij.psi.util.PsiTreeUtil; -import org.jetbrains.annotations.NotNull; - -/** - * @author peter - */ -public class StaticMembersWeigher extends CompletionWeigher { - public Comparable weigh(@NotNull LookupElement element, @NotNull CompletionLocation loc) { - if (loc.getCompletionType() != CompletionType.BASIC) return 0; - - // cheap weigher applicability goes first - final Object o = element.getObject(); - if (!(o instanceof PsiMember)) return 0; - - final PsiElement position = loc.getCompletionParameters().getPosition(); - if (PsiTreeUtil.getParentOfType(position, PsiDocComment.class) != null) return 0; - if (position.getParent() instanceof PsiReferenceExpression) { - final PsiReferenceExpression refExpr = (PsiReferenceExpression)position.getParent(); - final PsiElement qualifier = refExpr.getQualifier(); - if (qualifier == null) { - return 0; - } - if (!(qualifier instanceof PsiJavaCodeReferenceElement) || !(((PsiJavaCodeReferenceElement)qualifier).resolve() instanceof PsiClass)) { - return 0; - } - } - - if (((PsiMember)o).hasModifierProperty(PsiModifier.STATIC)) { - if (o instanceof PsiMethod) return 5; - if (o instanceof PsiField) return 4; - } - - if (o instanceof PsiClass) { - //if (((PsiClass) o).getContainingClass() != null) return 2; - return 3; - } - - //instance method or field - return 5; - } -} diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 506ed2dc7daa..a4a86907e1ff 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -803,12 +803,8 @@ - - + order="after negativeStats, before nameEnd"/> Date: Tue, 22 Feb 2011 17:32:33 +0100 Subject: [PATCH 102/169] java completion sorting on the new api, take 2 --- .../completion/JavaCompletionSorting.java | 84 +++++++++++++- ...ariablesLiteralsAndAnnoMethodsWeigher.java | 31 +++-- .../completion/RecursionWeigher.java | 106 ------------------ resources/src/META-INF/IdeaPlugin.xml | 6 +- 4 files changed, 104 insertions(+), 123 deletions(-) delete mode 100644 java/java-impl/src/com/intellij/codeInsight/completion/RecursionWeigher.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java index acb62b5a201a..82740b64a4b1 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java @@ -18,10 +18,13 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.ExpectedTypeInfo; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementWeigher; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Pair; import com.intellij.patterns.PsiJavaPatterns; import com.intellij.psi.*; +import com.intellij.psi.filters.ElementFilter; import com.intellij.psi.javadoc.PsiDocComment; +import com.intellij.psi.search.searches.DeepestSuperMethodsSearch; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; @@ -50,17 +53,96 @@ public class JavaCompletionSorting { } }); } + sorter = sorter.weighAfter("negativeStats", new PreferLocalVariablesLiteralsAndAnnoMethodsWeigher(type)); if (!smart) { sorter = preferStatics(sorter, position); } if (smart) { sorter = sorter.weighAfter("negativeStats", new PreferDefaultTypeWeigher(expectedTypes, parameters)); } - + sorter = recursion(sorter, parameters, expectedTypes); return result.withRelevanceSorter(sorter); } + enum Result { + delegation, + normal, + passingObjectToItself, + recursive, + } + static CompletionSorter recursion(CompletionSorter sorter, CompletionParameters parameters, final ExpectedTypeInfo[] expectedInfos) { + + final PsiElement position = parameters.getPosition(); + final PsiMethod positionMethod = PsiTreeUtil.getParentOfType(position, PsiMethod.class, false); + final ElementFilter filter = JavaCompletionUtil.recursionFilter(position); + final PsiMethodCallExpression expression = PsiTreeUtil.getParentOfType(position, PsiMethodCallExpression.class, true, PsiClass.class); + final PsiReferenceExpression reference = expression != null ? expression.getMethodExpression() : PsiTreeUtil.getParentOfType(position, PsiReferenceExpression.class); + //if (reference == null) return sorter; + + return sorter.weighAfter("local", new LookupElementWeigher("recursion") { + @NotNull + @Override + public Comparable weigh(@NotNull LookupElement element) { + final Object object = element.getObject(); + if (!(object instanceof PsiMethod || object instanceof PsiVariable || object instanceof PsiExpression)) return Result.normal; + + if (filter != null && !filter.isAcceptable(object, position)) { + return Result.recursive; + } + + if (reference == null) return Result.normal; + + final PsiExpression qualifier = reference.getQualifierExpression(); + boolean isDelegate = qualifier != null && !(qualifier instanceof PsiThisExpression); + + if (isPassingObjectToItself(object, qualifier, isDelegate)) { + return Result.passingObjectToItself; + } + + if (expression != null && positionMethod != null) { + if (expectedInfos != null) { + final PsiType itemType = JavaCompletionUtil.getLookupElementType(element); + if (itemType != null) { + for (final ExpectedTypeInfo expectedInfo : expectedInfos) { + if (positionMethod.equals(expectedInfo.getCalledMethod()) && expectedInfo.getType().isAssignableFrom(itemType)) { + return isDelegate ? Result.delegation : Result.recursive; + } + } + } + } + return Result.normal; + } + + if (object instanceof PsiMethod && positionMethod != null) { + final PsiMethod method = (PsiMethod)object; + if (PsiTreeUtil.isAncestor(reference, position, false) && + Comparing.equal(method.getName(), positionMethod.getName())) { + if (!isDelegate && findDeepestSuper(method).equals(findDeepestSuper(positionMethod))) { + return Result.recursive; + } + return Result.delegation; + } + } + + return Result.normal; + } + + private boolean isPassingObjectToItself(Object object, PsiExpression qualifier, boolean delegate) { + if (object instanceof PsiThisExpression) { + return !delegate || qualifier instanceof PsiSuperExpression; + } + return qualifier instanceof PsiReferenceExpression && + object.equals(((PsiReferenceExpression)qualifier).advancedResolve(true).getElement()); + } + + @NotNull + private PsiMethod findDeepestSuper(@NotNull final PsiMethod method) { + final PsiMethod first = DeepestSuperMethodsSearch.search(method).findFirst(); + return first == null ? method : first; + } + }); + } static CompletionSorter preferStatics(CompletionSorter sorter, PsiElement position) { if (PsiTreeUtil.getParentOfType(position, PsiDocComment.class) != null) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferLocalVariablesLiteralsAndAnnoMethodsWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferLocalVariablesLiteralsAndAnnoMethodsWeigher.java index c8a837d1177a..7529eb848e53 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferLocalVariablesLiteralsAndAnnoMethodsWeigher.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/PreferLocalVariablesLiteralsAndAnnoMethodsWeigher.java @@ -16,38 +16,47 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.codeInsight.lookup.LookupElementWeigher; import com.intellij.psi.*; import org.jetbrains.annotations.NotNull; /** * @author peter */ -public class PreferLocalVariablesLiteralsAndAnnoMethodsWeigher extends CompletionWeigher { +public class PreferLocalVariablesLiteralsAndAnnoMethodsWeigher extends LookupElementWeigher { + private final CompletionType myCompletionType; - enum MyResult { - className, - classLiteral, - normal, - superMethodParameters, - localOrParameter, - annoMethod, + public PreferLocalVariablesLiteralsAndAnnoMethodsWeigher(CompletionType completionType) { + super("local"); + myCompletionType = completionType; } - public MyResult weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) { + enum MyResult { + annoMethod, + localOrParameter, + superMethodParameters, + normal, + classLiteral, + className, + } + + @NotNull + @Override + public Comparable weigh(@NotNull LookupElement item) { final Object object = item.getObject(); if (object instanceof PsiLocalVariable || object instanceof PsiParameter || object instanceof PsiThisExpression) { return MyResult.localOrParameter; } - if (location.getCompletionType() == CompletionType.SMART) { + if (myCompletionType == CompletionType.SMART) { if (object instanceof String && item.getUserData(JavaCompletionUtil.SUPER_METHOD_PARAMETERS) == Boolean.TRUE) { return MyResult.superMethodParameters; } return MyResult.normal; } - if (location.getCompletionType() == CompletionType.BASIC) { + if (myCompletionType == CompletionType.BASIC) { if (object instanceof PsiKeyword && PsiKeyword.CLASS.equals(item.getLookupString())) { return MyResult.classLiteral; } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/RecursionWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/RecursionWeigher.java deleted file mode 100644 index c481bd86145b..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/completion/RecursionWeigher.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2000-2009 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 com.intellij.codeInsight.completion; - -import com.intellij.codeInsight.ExpectedTypeInfo; -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.openapi.util.Comparing; -import com.intellij.psi.*; -import com.intellij.psi.filters.ElementFilter; -import com.intellij.psi.search.searches.DeepestSuperMethodsSearch; -import com.intellij.psi.util.PsiTreeUtil; -import org.jetbrains.annotations.NotNull; - -/** - * @author peter - */ -public class RecursionWeigher extends CompletionWeigher { - - private enum Result { - recursive, - passingObjectToItself, - normal, - delegation, - } - - public Result weigh(@NotNull final LookupElement element, @NotNull final CompletionLocation location) { - if (location.getCompletionType() != CompletionType.BASIC && location.getCompletionType() != CompletionType.SMART) return Result.normal; - - final Object object = element.getObject(); - if (!(object instanceof PsiMethod || object instanceof PsiVariable || object instanceof PsiExpression)) return Result.normal; - - final PsiMethod positionMethod = JavaCompletionUtil.POSITION_METHOD.getValue(location); - - final PsiElement position = location.getCompletionParameters().getPosition(); - final ElementFilter filter = JavaCompletionUtil.recursionFilter(position); - if (filter != null && !filter.isAcceptable(object, position)) { - return Result.recursive; - } - - final PsiMethodCallExpression expression = PsiTreeUtil.getParentOfType(position, PsiMethodCallExpression.class, true, PsiClass.class); - final PsiReferenceExpression reference = expression != null ? expression.getMethodExpression() : PsiTreeUtil.getParentOfType(position, PsiReferenceExpression.class); - if (reference == null) return Result.normal; - - final PsiExpression qualifier = reference.getQualifierExpression(); - boolean isDelegate = qualifier != null && !(qualifier instanceof PsiThisExpression); - - if (isPassingObjectToItself(object, qualifier, isDelegate)) { - return Result.passingObjectToItself; - } - - if (expression != null && positionMethod != null) { - final ExpectedTypeInfo[] expectedInfos = JavaCompletionUtil.EXPECTED_TYPES.getValue(location); - if (expectedInfos != null) { - final PsiType itemType = JavaCompletionUtil.getLookupElementType(element); - if (itemType != null) { - for (final ExpectedTypeInfo expectedInfo : expectedInfos) { - if (positionMethod.equals(expectedInfo.getCalledMethod()) && expectedInfo.getType().isAssignableFrom(itemType)) { - return isDelegate ? Result.delegation : Result.recursive; - } - } - } - } - return Result.normal; - } - - if (object instanceof PsiMethod && positionMethod != null) { - final PsiMethod method = (PsiMethod)object; - if (PsiTreeUtil.isAncestor(reference, position, false) && - Comparing.equal(method.getName(), positionMethod.getName())) { - if (!isDelegate && findDeepestSuper(method).equals(findDeepestSuper(positionMethod))) { - return Result.recursive; - } - return RecursionWeigher.Result.delegation; - } - } - - return Result.normal; - } - - private static boolean isPassingObjectToItself(Object object, PsiExpression qualifier, boolean delegate) { - if (object instanceof PsiThisExpression) { - return !delegate || qualifier instanceof PsiSuperExpression; - } - return qualifier instanceof PsiReferenceExpression && - object.equals(((PsiReferenceExpression)qualifier).advancedResolve(true).getElement()); - } - - @NotNull - private static PsiMethod findDeepestSuper(@NotNull final PsiMethod method) { - final PsiMethod first = DeepestSuperMethodsSearch.search(method).findFirst(); - return first == null ? method : first; - } -} diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index a4a86907e1ff..b232f1ff6e19 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -803,12 +803,8 @@ - - + order="after negativeStats"/> From 03cd4cdcf5e1a60649bf46cdc24ecb56a77850f7 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 22 Feb 2011 17:37:46 +0100 Subject: [PATCH 103/169] java completion sorting on the new api, take 3 --- .../completion/JavaCompletionSorting.java | 162 ++++++++++-------- 1 file changed, 92 insertions(+), 70 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java index 82740b64a4b1..9f41219e3e54 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java @@ -64,13 +64,6 @@ public class JavaCompletionSorting { return result.withRelevanceSorter(sorter); } - enum Result { - delegation, - normal, - passingObjectToItself, - recursive, - } - static CompletionSorter recursion(CompletionSorter sorter, CompletionParameters parameters, final ExpectedTypeInfo[] expectedInfos) { final PsiElement position = parameters.getPosition(); @@ -78,70 +71,9 @@ public class JavaCompletionSorting { final ElementFilter filter = JavaCompletionUtil.recursionFilter(position); final PsiMethodCallExpression expression = PsiTreeUtil.getParentOfType(position, PsiMethodCallExpression.class, true, PsiClass.class); final PsiReferenceExpression reference = expression != null ? expression.getMethodExpression() : PsiTreeUtil.getParentOfType(position, PsiReferenceExpression.class); - //if (reference == null) return sorter; + if (reference == null) return sorter; - return sorter.weighAfter("local", new LookupElementWeigher("recursion") { - @NotNull - @Override - public Comparable weigh(@NotNull LookupElement element) { - final Object object = element.getObject(); - if (!(object instanceof PsiMethod || object instanceof PsiVariable || object instanceof PsiExpression)) return Result.normal; - - if (filter != null && !filter.isAcceptable(object, position)) { - return Result.recursive; - } - - if (reference == null) return Result.normal; - - final PsiExpression qualifier = reference.getQualifierExpression(); - boolean isDelegate = qualifier != null && !(qualifier instanceof PsiThisExpression); - - if (isPassingObjectToItself(object, qualifier, isDelegate)) { - return Result.passingObjectToItself; - } - - if (expression != null && positionMethod != null) { - if (expectedInfos != null) { - final PsiType itemType = JavaCompletionUtil.getLookupElementType(element); - if (itemType != null) { - for (final ExpectedTypeInfo expectedInfo : expectedInfos) { - if (positionMethod.equals(expectedInfo.getCalledMethod()) && expectedInfo.getType().isAssignableFrom(itemType)) { - return isDelegate ? Result.delegation : Result.recursive; - } - } - } - } - return Result.normal; - } - - if (object instanceof PsiMethod && positionMethod != null) { - final PsiMethod method = (PsiMethod)object; - if (PsiTreeUtil.isAncestor(reference, position, false) && - Comparing.equal(method.getName(), positionMethod.getName())) { - if (!isDelegate && findDeepestSuper(method).equals(findDeepestSuper(positionMethod))) { - return Result.recursive; - } - return Result.delegation; - } - } - - return Result.normal; - } - - private boolean isPassingObjectToItself(Object object, PsiExpression qualifier, boolean delegate) { - if (object instanceof PsiThisExpression) { - return !delegate || qualifier instanceof PsiSuperExpression; - } - return qualifier instanceof PsiReferenceExpression && - object.equals(((PsiReferenceExpression)qualifier).advancedResolve(true).getElement()); - } - - @NotNull - private PsiMethod findDeepestSuper(@NotNull final PsiMethod method) { - final PsiMethod first = DeepestSuperMethodsSearch.search(method).findFirst(); - return first == null ? method : first; - } - }); + return sorter.weighAfter("local", new RecursionWeigher(filter, position, reference, expression, positionMethod, expectedInfos)); } static CompletionSorter preferStatics(CompletionSorter sorter, PsiElement position) { @@ -252,4 +184,94 @@ public class JavaCompletionSorting { } } + + private static class RecursionWeigher extends LookupElementWeigher { + private final ElementFilter myFilter; + private final PsiElement myPosition; + private final PsiReferenceExpression myReference; + private final PsiMethodCallExpression myExpression; + private final PsiMethod myPositionMethod; + private final ExpectedTypeInfo[] myExpectedInfos; + private final PsiExpression myQualifier; + private final boolean myDelegate; + + public RecursionWeigher(ElementFilter filter, + PsiElement position, + @NotNull PsiReferenceExpression reference, + PsiMethodCallExpression expression, + PsiMethod positionMethod, ExpectedTypeInfo[] expectedInfos) { + super("recursion"); + myFilter = filter; + myPosition = position; + myReference = reference; + myExpression = expression; + myPositionMethod = positionMethod; + myExpectedInfos = expectedInfos; + myQualifier = myReference.getQualifierExpression(); + myDelegate = myQualifier != null && !(myQualifier instanceof PsiThisExpression); + } + + enum Result { + delegation, + normal, + passingObjectToItself, + recursive, + } + + @NotNull + @Override + public Result weigh(@NotNull LookupElement element) { + final Object object = element.getObject(); + if (!(object instanceof PsiMethod || object instanceof PsiVariable || object instanceof PsiExpression)) return Result.normal; + + if (myFilter != null && !myFilter.isAcceptable(object, myPosition)) { + return Result.recursive; + } + + if (isPassingObjectToItself(object)) { + return Result.passingObjectToItself; + } + + if (myExpression != null && myPositionMethod != null) { + if (myExpectedInfos != null) { + final PsiType itemType = JavaCompletionUtil.getLookupElementType(element); + if (itemType != null) { + for (final ExpectedTypeInfo expectedInfo : myExpectedInfos) { + if (myPositionMethod.equals(expectedInfo.getCalledMethod()) && expectedInfo.getType().isAssignableFrom(itemType)) { + return myDelegate ? Result.delegation : Result.recursive; + } + } + } + } + return Result.normal; + } + + if (object instanceof PsiMethod && myPositionMethod != null) { + final PsiMethod method = (PsiMethod)object; + if (PsiTreeUtil.isAncestor(myReference, myPosition, false) && + Comparing.equal(method.getName(), myPositionMethod.getName())) { + if (!myDelegate && findDeepestSuper(method).equals(findDeepestSuper(myPositionMethod))) { + return Result.recursive; + } + return Result.delegation; + } + } + + return Result.normal; + } + + private boolean isPassingObjectToItself(Object object) { + if (object instanceof PsiThisExpression) { + return !myDelegate || myQualifier instanceof PsiSuperExpression; + } + return myQualifier instanceof PsiReferenceExpression && + object.equals(((PsiReferenceExpression)myQualifier).advancedResolve(true).getElement()); + } + + @NotNull + private static PsiMethod findDeepestSuper(@NotNull final PsiMethod method) { + final PsiMethod first = DeepestSuperMethodsSearch.search(method).findFirst(); + return first == null ? method : first; + } + } } From 315f50fdbc1fe9ae3861176627a86a8d0683749f Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 22 Feb 2011 17:51:32 +0100 Subject: [PATCH 104/169] java completion sorting on the new api, take 4 --- .../completion/JavaCompletionSorting.java | 52 +++++++++++++- .../JavaSmartCompletionContributor.java | 1 + .../NameEndMatchingDegreeWeigher.java | 36 ---------- .../completion/PreferExpectedTypeWeigher.java | 70 ------------------- resources/src/META-INF/IdeaPlugin.xml | 5 -- 5 files changed, 51 insertions(+), 113 deletions(-) delete mode 100644 java/java-impl/src/com/intellij/codeInsight/completion/NameEndMatchingDegreeWeigher.java delete mode 100644 java/java-impl/src/com/intellij/codeInsight/completion/PreferExpectedTypeWeigher.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java index 9f41219e3e54..7bcf38239969 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java @@ -44,12 +44,13 @@ public class JavaCompletionSorting { final boolean smart = type == CompletionType.SMART; CompletionSorter sorter = CompletionSorter.defaultSorter(parameters); - if (!smart && JavaSmartCompletionContributor.AFTER_NEW.accepts(position)) { + final boolean afterNew = JavaSmartCompletionContributor.AFTER_NEW.accepts(position); + if (!smart && afterNew) { sorter = sorter.weighBefore("liftShorter", new LookupElementWeigher("expectedAfterNew") { @NotNull @Override public Comparable weigh(@NotNull LookupElement element) { - return -((Enum)PreferExpectedTypeWeigher.weigh(element, expectedTypes)).ordinal(); + return getExpectedTypeMatching(element, expectedTypes); } }); } @@ -61,6 +62,25 @@ public class JavaCompletionSorting { sorter = sorter.weighAfter("negativeStats", new PreferDefaultTypeWeigher(expectedTypes, parameters)); } sorter = recursion(sorter, parameters, expectedTypes); + + sorter = sorter.weighAfter("recursion", new LookupElementWeigher("nameEnd") { + @NotNull + @Override + public Comparable weigh(@NotNull LookupElement element) { + final String name = JavaCompletionUtil.getLookupObjectName(element.getObject()); + return -JavaCompletionUtil.getNameEndMatchingDegree(name, expectedTypes, element.getPrefixMatcher().getPrefix()); + } + }); + + if (!smart) { + sorter = sorter.weighAfter("recursion", new LookupElementWeigher("expectedType") { + @NotNull + @Override + public Comparable weigh(@NotNull LookupElement item) { + return item.getObject() instanceof PsiClass && !afterNew ? ExpectedTypeMatching.normal : getExpectedTypeMatching(item, expectedTypes); + } + }); + } return result.withRelevanceSorter(sorter); } @@ -111,6 +131,28 @@ public class JavaCompletionSorting { }); } + public static ExpectedTypeMatching getExpectedTypeMatching(LookupElement item, ExpectedTypeInfo[] expectedInfos) { + PsiType itemType = JavaCompletionUtil.getLookupElementType(item); + if (itemType == null) return ExpectedTypeMatching.normal; + + for (final ExpectedTypeInfo expectedInfo : expectedInfos) { + final PsiType defaultType = expectedInfo.getDefaultType(); + final PsiType expectedType = expectedInfo.getType(); + if (!expectedType.isValid()) { + return ExpectedTypeMatching.normal; + } + + if (defaultType != expectedType && defaultType.isAssignableFrom(itemType)) { + return ExpectedTypeMatching.ofDefaultType; + } + if (expectedType.isAssignableFrom(itemType)) { + return ExpectedTypeMatching.expected; + } + } + + return ExpectedTypeMatching.normal; + } + private static class PreferDefaultTypeWeigher extends LookupElementWeigher { private final PsiTypeParameter myTypeParameter; private final ExpectedTypeInfo[] myExpectedTypes; @@ -274,4 +316,10 @@ public class JavaCompletionSorting { return first == null ? method : first; } } + + enum ExpectedTypeMatching { + ofDefaultType, + expected, + normal, + } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java index 0e44b87694ee..1866660fc41d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java @@ -402,6 +402,7 @@ public class JavaSmartCompletionContributor extends CompletionContributor { } + @NotNull public static ExpectedTypeInfo[] getExpectedTypes(final CompletionParameters parameters) { final PsiElement position = parameters.getPosition(); if (psiElement().withParent(psiElement(PsiReferenceExpression.class).withParent(PsiThrowStatement.class)).accepts(position)) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/NameEndMatchingDegreeWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/NameEndMatchingDegreeWeigher.java deleted file mode 100644 index f4b1bda9efdd..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/completion/NameEndMatchingDegreeWeigher.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2000-2009 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 com.intellij.codeInsight.completion; - -import com.intellij.codeInsight.lookup.LookupElement; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * @author peter -*/ -public class NameEndMatchingDegreeWeigher extends CompletionWeigher { - - public Integer weigh(@NotNull final LookupElement element, @NotNull final CompletionLocation location) { - if (location == null) { - return null; - } - final String name = JavaCompletionUtil.getLookupObjectName(element.getObject()); - return JavaCompletionUtil.getNameEndMatchingDegree(name, JavaCompletionUtil.EXPECTED_TYPES.getValue(location), - element.getPrefixMatcher().getPrefix()); - } - -} diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferExpectedTypeWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferExpectedTypeWeigher.java deleted file mode 100644 index 37b8ae55d171..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferExpectedTypeWeigher.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2000-2009 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 com.intellij.codeInsight.completion; - -import com.intellij.codeInsight.ExpectedTypeInfo; -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiType; -import org.jetbrains.annotations.NotNull; - -/** - * @author peter -*/ -public class PreferExpectedTypeWeigher extends CompletionWeigher { - - private enum MyResult { - normal, - expected, - ofDefaultType, - } - - public MyResult weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) { - if (location.getCompletionType() != CompletionType.BASIC) return MyResult.normal; - if (item.getObject() instanceof PsiClass) { - if (!JavaSmartCompletionContributor.AFTER_NEW.accepts(location.getCompletionParameters().getPosition())) { - return MyResult.normal; - } - } - - ExpectedTypeInfo[] expectedInfos = JavaCompletionUtil.EXPECTED_TYPES.getValue(location); - if (expectedInfos == null) return MyResult.normal; - - return weigh(item, expectedInfos); - } - - public static MyResult weigh(LookupElement item, ExpectedTypeInfo[] expectedInfos) { - PsiType itemType = JavaCompletionUtil.getLookupElementType(item); - if (itemType == null) return MyResult.normal; - - for (final ExpectedTypeInfo expectedInfo : expectedInfos) { - final PsiType defaultType = expectedInfo.getDefaultType(); - final PsiType expectedType = expectedInfo.getType(); - if (!expectedType.isValid()) { - return MyResult.normal; - } - - if (defaultType != expectedType && defaultType.isAssignableFrom(itemType)) { - return MyResult.ofDefaultType; - } - if (expectedType.isAssignableFrom(itemType)) { - return MyResult.expected; - } - } - - return MyResult.normal; - } -} diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index b232f1ff6e19..39f770dbc3ba 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -803,11 +803,6 @@ - - - Date: Tue, 22 Feb 2011 18:21:32 +0100 Subject: [PATCH 105/169] java completion sorting on the new api, take 5 --- .../completion/JavaCompletionSorting.java | 59 ++++++++++--------- .../completion/CompletionSorter.java | 4 +- .../completion/impl/CompletionSorterImpl.java | 19 ++++-- 3 files changed, 49 insertions(+), 33 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java index 7bcf38239969..7bafd33a4e8b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java @@ -28,7 +28,12 @@ import com.intellij.psi.search.searches.DeepestSuperMethodsSearch; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; /** * @author peter @@ -45,6 +50,7 @@ public class JavaCompletionSorting { final boolean smart = type == CompletionType.SMART; CompletionSorter sorter = CompletionSorter.defaultSorter(parameters); final boolean afterNew = JavaSmartCompletionContributor.AFTER_NEW.accepts(position); + if (!smart && afterNew) { sorter = sorter.weighBefore("liftShorter", new LookupElementWeigher("expectedAfterNew") { @NotNull @@ -54,26 +60,13 @@ public class JavaCompletionSorting { } }); } - sorter = sorter.weighAfter("negativeStats", new PreferLocalVariablesLiteralsAndAnnoMethodsWeigher(type)); - if (!smart) { - sorter = preferStatics(sorter, position); - } - if (smart) { - sorter = sorter.weighAfter("negativeStats", new PreferDefaultTypeWeigher(expectedTypes, parameters)); - } - sorter = recursion(sorter, parameters, expectedTypes); - - sorter = sorter.weighAfter("recursion", new LookupElementWeigher("nameEnd") { - @NotNull - @Override - public Comparable weigh(@NotNull LookupElement element) { - final String name = JavaCompletionUtil.getLookupObjectName(element.getObject()); - return -JavaCompletionUtil.getNameEndMatchingDegree(name, expectedTypes, element.getPrefixMatcher().getPrefix()); - } - }); + List afterNegativeStats = new ArrayList(); + ContainerUtil.addIfNotNull(afterNegativeStats, smart ? new PreferDefaultTypeWeigher(expectedTypes, parameters) : preferStatics(position)); + afterNegativeStats.add(new PreferLocalVariablesLiteralsAndAnnoMethodsWeigher(type)); + ContainerUtil.addIfNotNull(afterNegativeStats, recursion(parameters, expectedTypes)); if (!smart) { - sorter = sorter.weighAfter("recursion", new LookupElementWeigher("expectedType") { + afterNegativeStats.add(new LookupElementWeigher("expectedType") { @NotNull @Override public Comparable weigh(@NotNull LookupElement item) { @@ -81,37 +74,49 @@ public class JavaCompletionSorting { } }); } + afterNegativeStats.add(new LookupElementWeigher("nameEnd") { + @NotNull + @Override + public Comparable weigh(@NotNull LookupElement element) { + final String name = JavaCompletionUtil.getLookupObjectName(element.getObject()); + return -JavaCompletionUtil.getNameEndMatchingDegree(name, expectedTypes, element.getPrefixMatcher().getPrefix()); + } + }); + sorter = sorter.weighAfter("negativeStats", afterNegativeStats.toArray(new LookupElementWeigher[afterNegativeStats.size()])); + return result.withRelevanceSorter(sorter); } - static CompletionSorter recursion(CompletionSorter sorter, CompletionParameters parameters, final ExpectedTypeInfo[] expectedInfos) { + @Nullable + static LookupElementWeigher recursion(CompletionParameters parameters, final ExpectedTypeInfo[] expectedInfos) { final PsiElement position = parameters.getPosition(); final PsiMethod positionMethod = PsiTreeUtil.getParentOfType(position, PsiMethod.class, false); final ElementFilter filter = JavaCompletionUtil.recursionFilter(position); final PsiMethodCallExpression expression = PsiTreeUtil.getParentOfType(position, PsiMethodCallExpression.class, true, PsiClass.class); final PsiReferenceExpression reference = expression != null ? expression.getMethodExpression() : PsiTreeUtil.getParentOfType(position, PsiReferenceExpression.class); - if (reference == null) return sorter; + if (reference == null) return null; - return sorter.weighAfter("local", new RecursionWeigher(filter, position, reference, expression, positionMethod, expectedInfos)); + return new RecursionWeigher(filter, position, reference, expression, positionMethod, expectedInfos); } - static CompletionSorter preferStatics(CompletionSorter sorter, PsiElement position) { + @Nullable + static LookupElementWeigher preferStatics(PsiElement position) { if (PsiTreeUtil.getParentOfType(position, PsiDocComment.class) != null) { - return sorter; + return null; } if (position.getParent() instanceof PsiReferenceExpression) { final PsiReferenceExpression refExpr = (PsiReferenceExpression)position.getParent(); final PsiElement qualifier = refExpr.getQualifier(); if (qualifier == null) { - return sorter; + return null; } if (!(qualifier instanceof PsiJavaCodeReferenceElement) || !(((PsiJavaCodeReferenceElement)qualifier).resolve() instanceof PsiClass)) { - return sorter; + return null; } } - return sorter.weighAfter("negativeStats", new LookupElementWeigher("statics") { + return new LookupElementWeigher("statics") { @NotNull @Override public Comparable weigh(@NotNull LookupElement element) { @@ -128,7 +133,7 @@ public class JavaCompletionSorting { //instance method or field return -5; } - }); + }; } public static ExpectedTypeMatching getExpectedTypeMatching(LookupElement item, ExpectedTypeInfo[] expectedInfos) { diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionSorter.java b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionSorter.java index b5532add33d3..fd63710141b6 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionSorter.java +++ b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionSorter.java @@ -22,9 +22,9 @@ import org.jetbrains.annotations.NotNull; * @author peter */ public abstract class CompletionSorter { - public abstract CompletionSorter weighBefore(@NotNull String beforeId, LookupElementWeigher weigher); + public abstract CompletionSorter weighBefore(@NotNull String beforeId, LookupElementWeigher... weighers); - public abstract CompletionSorter weighAfter(@NotNull String afterId, LookupElementWeigher weigher); + public abstract CompletionSorter weighAfter(@NotNull String afterId, LookupElementWeigher... weighers); public abstract CompletionSorter weigh(LookupElementWeigher weigher); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionSorterImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionSorterImpl.java index 0d7250068c02..a82f8b9b40ef 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionSorterImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionSorterImpl.java @@ -50,12 +50,23 @@ public class CompletionSorterImpl extends CompletionSorter { }; } - @Override public CompletionSorterImpl weighBefore(@NotNull final String beforeId, final LookupElementWeigher weigher) { - return withClassifier(beforeId, true, weighingFactory(weigher)); + @Override public CompletionSorterImpl weighBefore(@NotNull final String beforeId, LookupElementWeigher... weighers) { + assert weighers.length > 0 : "there should be weighers"; + CompletionSorterImpl result = this; + for (LookupElementWeigher weigher : weighers) { + result = result.withClassifier(beforeId, true, weighingFactory(weigher)); + } + return result; } - @Override public CompletionSorterImpl weighAfter(@NotNull final String afterId, final LookupElementWeigher weigher) { - return withClassifier(afterId, false, weighingFactory(weigher)); + @Override public CompletionSorterImpl weighAfter(@NotNull final String afterId, LookupElementWeigher... weighers) { + assert weighers.length > 0 : "there should be weighers"; + CompletionSorterImpl result = this; + for (int i = weighers.length - 1; i >= 0; i--) { + LookupElementWeigher weigher = weighers[i]; + result = result.withClassifier(afterId, false, weighingFactory(weigher)); + } + return result; } @Override public CompletionSorterImpl weigh(final LookupElementWeigher weigher) { From dbe3d1360d3a3a73c5609afed39bbc3f24c63572 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 22 Feb 2011 18:34:54 +0100 Subject: [PATCH 106/169] java completion sorting on the new api, take 6 --- .../completion/JavaCompletionSorting.java | 102 +++++++++++++++++- .../completion/PreferAccessibleWeigher.java | 51 --------- .../PreferEnumConstantsWeigher.java | 45 -------- .../completion/PreferNonGenericWeigher.java | 44 -------- .../completion/PreferSimpleWeigher.java | 37 ------- resources/src/META-INF/IdeaPlugin.xml | 9 +- 6 files changed, 102 insertions(+), 186 deletions(-) delete mode 100644 java/java-impl/src/com/intellij/codeInsight/completion/PreferAccessibleWeigher.java delete mode 100644 java/java-impl/src/com/intellij/codeInsight/completion/PreferEnumConstantsWeigher.java delete mode 100644 java/java-impl/src/com/intellij/codeInsight/completion/PreferNonGenericWeigher.java delete mode 100644 java/java-impl/src/com/intellij/codeInsight/completion/PreferSimpleWeigher.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java index 7bafd33a4e8b..fc29de888258 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java @@ -18,6 +18,7 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.ExpectedTypeInfo; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementWeigher; +import com.intellij.codeInsight.lookup.PsiTypeLookupItem; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Pair; import com.intellij.patterns.PsiJavaPatterns; @@ -84,6 +85,8 @@ public class JavaCompletionSorting { }); sorter = sorter.weighAfter("negativeStats", afterNegativeStats.toArray(new LookupElementWeigher[afterNegativeStats.size()])); + sorter = sorter.weighAfter("prefix", new PreferNonGeneric(), new PreferAccessible(position), new PreferSimple(), new PreferEnumConstants(parameters)); + return result.withRelevanceSorter(sorter); } @@ -322,9 +325,106 @@ public class JavaCompletionSorting { } } - enum ExpectedTypeMatching { + private enum ExpectedTypeMatching { ofDefaultType, expected, normal, } + + private static class PreferAccessible extends LookupElementWeigher { + private final PsiElement myPosition; + + public PreferAccessible(PsiElement position) { + super("accessible"); + myPosition = position; + } + + private enum MyEnum { + NORMAL, + DEPRECATED, + INACCESSIBLE, + } + + @NotNull + @Override + public Comparable weigh(@NotNull LookupElement element) { + final Object object = element.getObject(); + if (object instanceof PsiDocCommentOwner) { + final PsiDocCommentOwner member = (PsiDocCommentOwner)object; + if (!member.isValid()) { + return MyEnum.NORMAL; + } + + if (!JavaPsiFacade.getInstance(member.getProject()).getResolveHelper().isAccessible(member, myPosition, null)) return MyEnum.INACCESSIBLE; + if (member.isDeprecated()) return MyEnum.DEPRECATED; + } + return MyEnum.NORMAL; + } + } + + private static class PreferNonGeneric extends LookupElementWeigher { + public PreferNonGeneric() { + super("nonGeneric"); + } + + @NotNull + @Override + public Comparable weigh(@NotNull LookupElement element) { + final Object object = element.getObject(); + if (object instanceof PsiMethod) { + PsiType type = ((PsiMethod)object).getReturnType(); + final JavaMethodCallElement callItem = element.as(JavaMethodCallElement.CLASS_CONDITION_KEY); + if (callItem != null) { + type = callItem.getSubstitutor().substitute(type); + } + + if (type instanceof PsiClassType && ((PsiClassType) type).resolve() instanceof PsiTypeParameter) return 1; + } + + return 0; + } + } + + private static class PreferSimple extends LookupElementWeigher { + public PreferSimple() { + super("simple"); + } + + @NotNull + @Override + public Comparable weigh(@NotNull LookupElement element) { + final PsiTypeLookupItem lookupItem = element.as(PsiTypeLookupItem.CLASS_CONDITION_KEY); + if (lookupItem != null) { + return lookupItem.getBracketsCount(); + } + if (element.as(CastingLookupElementDecorator.CLASS_CONDITION_KEY) != null) { + return 239; + } + return 0; + } + } + + private static class PreferEnumConstants extends LookupElementWeigher { + private final CompletionParameters myParameters; + + public PreferEnumConstants(CompletionParameters parameters) { + super("constants"); + myParameters = parameters; + } + + @NotNull + @Override + public Comparable weigh(@NotNull LookupElement element) { + if (element.getObject() instanceof PsiEnumConstant) return -2; + + if (!(myParameters.getOriginalFile() instanceof PsiJavaFile)) return -1; + + if (PsiKeyword.TRUE.equals(element.getLookupString()) || PsiKeyword.FALSE.equals(element.getLookupString())) { + boolean inReturn = PsiTreeUtil.getParentOfType(myParameters.getPosition(), PsiReturnStatement.class, false, PsiMember.class) != null; + return inReturn ? -2 : 0; + } + + return -1; + } + } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferAccessibleWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferAccessibleWeigher.java deleted file mode 100644 index 816f95b97f0e..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferAccessibleWeigher.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2000-2009 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 com.intellij.codeInsight.completion; - -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.psi.JavaPsiFacade; -import com.intellij.psi.PsiDocCommentOwner; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * @author peter -*/ -public class PreferAccessibleWeigher extends CompletionWeigher { - - public MyEnum weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) { - if (location == null) { - return null; - } - final Object object = item.getObject(); - if (object instanceof PsiDocCommentOwner) { - final PsiDocCommentOwner member = (PsiDocCommentOwner)object; - if (!member.isValid()) { - return MyEnum.NORMAL; - } - - if (!JavaPsiFacade.getInstance(member.getProject()).getResolveHelper().isAccessible(member, location.getCompletionParameters().getPosition(), null)) return MyEnum.INACCESSIBLE; - if (member.isDeprecated()) return MyEnum.DEPRECATED; - } - return MyEnum.NORMAL; - } - - private enum MyEnum { - INACCESSIBLE, - DEPRECATED, - NORMAL - } -} diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferEnumConstantsWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferEnumConstantsWeigher.java deleted file mode 100644 index 325fdae2bf16..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferEnumConstantsWeigher.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2000-2009 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 com.intellij.codeInsight.completion; - -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.psi.*; -import com.intellij.psi.util.PsiTreeUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * @author peter -*/ -public class PreferEnumConstantsWeigher extends CompletionWeigher { - - public Comparable weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) { - if (location == null) { - return null; - } - if (item.getObject() instanceof PsiEnumConstant) return 2; - - final CompletionParameters parameters = location.getCompletionParameters(); - if (!(parameters.getOriginalFile() instanceof PsiJavaFile)) return 1; - - if (PsiKeyword.TRUE.equals(item.getLookupString()) || PsiKeyword.FALSE.equals(item.getLookupString())) { - boolean inReturn = PsiTreeUtil.getParentOfType(parameters.getPosition(), PsiReturnStatement.class, false, PsiMember.class) != null; - return inReturn ? 2 : 0; - } - - return 1; - } -} diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferNonGenericWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferNonGenericWeigher.java deleted file mode 100644 index a3f8154cca60..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferNonGenericWeigher.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2000-2009 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 com.intellij.codeInsight.completion; - -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.psi.PsiClassType; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiType; -import com.intellij.psi.PsiTypeParameter; -import org.jetbrains.annotations.NotNull; - -/** - * @author peter -*/ -public class PreferNonGenericWeigher extends CompletionWeigher { - - public Comparable weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) { - final Object object = item.getObject(); - if (object instanceof PsiMethod) { - PsiType type = ((PsiMethod)object).getReturnType(); - final JavaMethodCallElement callItem = item.as(JavaMethodCallElement.CLASS_CONDITION_KEY); - if (callItem != null) { - type = callItem.getSubstitutor().substitute(type); - } - - if (type instanceof PsiClassType && ((PsiClassType) type).resolve() instanceof PsiTypeParameter) return -1; - } - - return 0; - } -} diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferSimpleWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferSimpleWeigher.java deleted file mode 100644 index c7361df1f7af..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferSimpleWeigher.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2000-2009 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 com.intellij.codeInsight.completion; - -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.codeInsight.lookup.PsiTypeLookupItem; -import org.jetbrains.annotations.NotNull; - -/** - * @author peter -*/ -public class PreferSimpleWeigher extends CompletionWeigher { - - public Comparable weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) { - final PsiTypeLookupItem lookupItem = item.as(PsiTypeLookupItem.CLASS_CONDITION_KEY); - if (lookupItem != null) { - return -lookupItem.getBracketsCount(); - } - if (item.as(CastingLookupElementDecorator.CLASS_CONDITION_KEY) != null) { - return -239; - } - return 0; - } -} \ No newline at end of file diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 39f770dbc3ba..da0f41b62208 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -803,14 +803,7 @@ - - - - + Date: Tue, 22 Feb 2011 18:57:36 +0100 Subject: [PATCH 107/169] java completion relevance sorting on the new api, done --- .../completion/JavaCompletionSorting.java | 230 +++++++++++++++--- .../completion/JavaCompletionUtil.java | 69 ------ .../PreferFieldsAndGettersWeigher.java | 41 ---- .../completion/PreferShorterWeigher.java | 44 ---- .../completion/SameWordsWeigher.java | 56 ----- resources/src/META-INF/IdeaPlugin.xml | 8 - 6 files changed, 196 insertions(+), 252 deletions(-) delete mode 100644 java/java-impl/src/com/intellij/codeInsight/completion/PreferFieldsAndGettersWeigher.java delete mode 100644 java/java-impl/src/com/intellij/codeInsight/completion/PreferShorterWeigher.java delete mode 100644 java/java-impl/src/com/intellij/codeInsight/completion/SameWordsWeigher.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java index fc29de888258..77ce85355add 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java @@ -16,6 +16,7 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.ExpectedTypeInfo; +import com.intellij.codeInsight.ExpectedTypeInfoImpl; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementWeigher; import com.intellij.codeInsight.lookup.PsiTypeLookupItem; @@ -23,13 +24,18 @@ import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Pair; import com.intellij.patterns.PsiJavaPatterns; import com.intellij.psi.*; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.codeStyle.NameUtil; +import com.intellij.psi.codeStyle.VariableKind; import com.intellij.psi.filters.ElementFilter; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.search.searches.DeepestSuperMethodsSearch; +import com.intellij.psi.util.PropertyUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.containers.ContainerUtil; +import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -47,51 +53,37 @@ public class JavaCompletionSorting { final PsiElement position = parameters.getPosition(); final ExpectedTypeInfo[] expectedTypes = PsiJavaPatterns.psiElement().beforeLeaf(PsiJavaPatterns.psiElement().withText(".")).accepts(position) ? ExpectedTypeInfo.EMPTY_ARRAY : JavaSmartCompletionContributor.getExpectedTypes(parameters); final CompletionType type = parameters.getCompletionType(); - final boolean smart = type == CompletionType.SMART; - CompletionSorter sorter = CompletionSorter.defaultSorter(parameters); final boolean afterNew = JavaSmartCompletionContributor.AFTER_NEW.accepts(position); - if (!smart && afterNew) { - sorter = sorter.weighBefore("liftShorter", new LookupElementWeigher("expectedAfterNew") { - @NotNull - @Override - public Comparable weigh(@NotNull LookupElement element) { - return getExpectedTypeMatching(element, expectedTypes); - } - }); - } - List afterNegativeStats = new ArrayList(); ContainerUtil.addIfNotNull(afterNegativeStats, smart ? new PreferDefaultTypeWeigher(expectedTypes, parameters) : preferStatics(position)); afterNegativeStats.add(new PreferLocalVariablesLiteralsAndAnnoMethodsWeigher(type)); ContainerUtil.addIfNotNull(afterNegativeStats, recursion(parameters, expectedTypes)); - if (!smart) { - afterNegativeStats.add(new LookupElementWeigher("expectedType") { - @NotNull - @Override - public Comparable weigh(@NotNull LookupElement item) { - return item.getObject() instanceof PsiClass && !afterNew ? ExpectedTypeMatching.normal : getExpectedTypeMatching(item, expectedTypes); - } - }); + if (!smart && !afterNew) { + afterNegativeStats.add(new PreferExpected(false, expectedTypes)); + } + afterNegativeStats.add(new PreferSimilarlyEnding(expectedTypes)); + + List afterProximity = new ArrayList(); + afterProximity.add(new PreferContainingSameWords(expectedTypes)); + if (smart) { + afterProximity.add(new PreferFieldsAndGetters()); + } + afterProximity.add(new PreferShorter(expectedTypes)); + + CompletionSorter sorter = CompletionSorter.defaultSorter(parameters); + if (!smart && afterNew) { + sorter = sorter.weighBefore("liftShorter", new PreferExpected(true, expectedTypes)); } - afterNegativeStats.add(new LookupElementWeigher("nameEnd") { - @NotNull - @Override - public Comparable weigh(@NotNull LookupElement element) { - final String name = JavaCompletionUtil.getLookupObjectName(element.getObject()); - return -JavaCompletionUtil.getNameEndMatchingDegree(name, expectedTypes, element.getPrefixMatcher().getPrefix()); - } - }); sorter = sorter.weighAfter("negativeStats", afterNegativeStats.toArray(new LookupElementWeigher[afterNegativeStats.size()])); - sorter = sorter.weighAfter("prefix", new PreferNonGeneric(), new PreferAccessible(position), new PreferSimple(), new PreferEnumConstants(parameters)); - + sorter = sorter.weighAfter("proximity", afterProximity.toArray(new LookupElementWeigher[afterProximity.size()])); return result.withRelevanceSorter(sorter); } @Nullable - static LookupElementWeigher recursion(CompletionParameters parameters, final ExpectedTypeInfo[] expectedInfos) { + private static LookupElementWeigher recursion(CompletionParameters parameters, final ExpectedTypeInfo[] expectedInfos) { final PsiElement position = parameters.getPosition(); final PsiMethod positionMethod = PsiTreeUtil.getParentOfType(position, PsiMethod.class, false); @@ -104,7 +96,7 @@ public class JavaCompletionSorting { } @Nullable - static LookupElementWeigher preferStatics(PsiElement position) { + private static LookupElementWeigher preferStatics(PsiElement position) { if (PsiTreeUtil.getParentOfType(position, PsiDocComment.class) != null) { return null; } @@ -139,7 +131,7 @@ public class JavaCompletionSorting { }; } - public static ExpectedTypeMatching getExpectedTypeMatching(LookupElement item, ExpectedTypeInfo[] expectedInfos) { + private static ExpectedTypeMatching getExpectedTypeMatching(LookupElement item, ExpectedTypeInfo[] expectedInfos) { PsiType itemType = JavaCompletionUtil.getLookupElementType(item); if (itemType == null) return ExpectedTypeMatching.normal; @@ -161,6 +153,75 @@ public class JavaCompletionSorting { return ExpectedTypeMatching.normal; } + @Nullable + private static String getLookupObjectName(Object o) { + if (o instanceof PsiVariable) { + final PsiVariable variable = (PsiVariable)o; + JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(variable.getProject()); + VariableKind variableKind = codeStyleManager.getVariableKind(variable); + return codeStyleManager.variableNameToPropertyName(variable.getName(), variableKind); + } + if (o instanceof PsiMethod) { + return ((PsiMethod)o).getName(); + } + return null; + } + + private static int getNameEndMatchingDegree(final String name, ExpectedTypeInfo[] expectedInfos, String prefix) { + int res = 0; + if (name != null && expectedInfos != null) { + if (prefix.equals(name)) { + res = Integer.MAX_VALUE; + } else { + final List words = NameUtil.nameToWordsLowerCase(name); + final List wordsNoDigits = NameUtil.nameToWordsLowerCase(truncDigits(name)); + int max1 = calcMatch(words, 0, expectedInfos); + max1 = calcMatch(wordsNoDigits, max1, expectedInfos); + res = max1; + } + } + + return res; + } + + private static String truncDigits(String name){ + int count = name.length() - 1; + while (count >= 0) { + char c = name.charAt(count); + if (!Character.isDigit(c)) break; + count--; + } + return name.substring(0, count + 1); + } + + private static int calcMatch(final List words, int max, ExpectedTypeInfo[] myExpectedInfos) { + for (ExpectedTypeInfo myExpectedInfo : myExpectedInfos) { + String expectedName = ((ExpectedTypeInfoImpl)myExpectedInfo).expectedName; + if (expectedName == null) continue; + max = calcMatch(expectedName, words, max); + max = calcMatch(truncDigits(expectedName), words, max); + } + return max; + } + + private static int calcMatch(final String expectedName, final List words, int max) { + if (expectedName == null) return max; + + String[] expectedWords = NameUtil.nameToWords(expectedName); + int limit = Math.min(words.size(), expectedWords.length); + for (int i = 0; i < limit; i++) { + String word = words.get(words.size() - i - 1); + String expectedWord = expectedWords[expectedWords.length - i - 1]; + if (word.equalsIgnoreCase(expectedWord)) { + max = Math.max(max, i + 1); + } + else { + break; + } + } + return max; + } + private static class PreferDefaultTypeWeigher extends LookupElementWeigher { private final PsiTypeParameter myTypeParameter; private final ExpectedTypeInfo[] myExpectedTypes; @@ -261,7 +322,7 @@ public class JavaCompletionSorting { myDelegate = myQualifier != null && !(myQualifier instanceof PsiThisExpression); } - enum Result { + private enum Result { delegation, normal, passingObjectToItself, @@ -427,4 +488,105 @@ public class JavaCompletionSorting { return -1; } } + + private static class PreferExpected extends LookupElementWeigher { + private final boolean myAcceptClasses; + private final ExpectedTypeInfo[] myExpectedTypes; + + public PreferExpected(boolean acceptClasses, ExpectedTypeInfo[] expectedTypes) { + super("expectedType"); + myAcceptClasses = acceptClasses; + myExpectedTypes = expectedTypes; + } + + @NotNull + @Override + public Comparable weigh(@NotNull LookupElement item) { + return item.getObject() instanceof PsiClass && !myAcceptClasses + ? ExpectedTypeMatching.normal : getExpectedTypeMatching(item, myExpectedTypes); + } + } + + private static class PreferSimilarlyEnding extends LookupElementWeigher { + private final ExpectedTypeInfo[] myExpectedTypes; + + public PreferSimilarlyEnding(ExpectedTypeInfo[] expectedTypes) { + super("nameEnd"); + myExpectedTypes = expectedTypes; + } + + @NotNull + @Override + public Comparable weigh(@NotNull LookupElement element) { + final String name = getLookupObjectName(element.getObject()); + return -getNameEndMatchingDegree(name, myExpectedTypes, element.getPrefixMatcher().getPrefix()); + } + } + + private static class PreferContainingSameWords extends LookupElementWeigher { + private final ExpectedTypeInfo[] myExpectedTypes; + + public PreferContainingSameWords(ExpectedTypeInfo[] expectedTypes) { + super("sameWords"); + myExpectedTypes = expectedTypes; + } + + @NotNull + @Override + public Comparable weigh(@NotNull LookupElement element) { + final Object object = element.getObject(); + + final String name = getLookupObjectName(object); + if (name != null) { + int max = 0; + final List wordsNoDigits = NameUtil.nameToWordsLowerCase(truncDigits(name)); + for (ExpectedTypeInfo myExpectedInfo : myExpectedTypes) { + String expectedName = ((ExpectedTypeInfoImpl)myExpectedInfo).expectedName; + if (expectedName != null) { + final THashSet set = new THashSet(NameUtil.nameToWordsLowerCase(truncDigits(expectedName))); + set.retainAll(wordsNoDigits); + max = Math.max(max, set.size()); + } + } + return -max; + } + return 0; + } + } + + private static class PreferFieldsAndGetters extends LookupElementWeigher { + public PreferFieldsAndGetters() { + super("fieldsAndGetters"); + } + + @NotNull + @Override + public Comparable weigh(@NotNull LookupElement element) { + final Object object = element.getObject(); + if (object instanceof PsiField) return -2; + if (object instanceof PsiMethod && PropertyUtil.isSimplePropertyGetter((PsiMethod)object)) return -1; + return 0; + } + } + + private static class PreferShorter extends LookupElementWeigher { + private final ExpectedTypeInfo[] myExpectedTypes; + + public PreferShorter(ExpectedTypeInfo[] expectedTypes) { + super("shorter"); + myExpectedTypes = expectedTypes; + } + + @NotNull + @Override + public Comparable weigh(@NotNull LookupElement element) { + final Object object = element.getObject(); + final String name = getLookupObjectName(object); + + if (name != null && getNameEndMatchingDegree(name, myExpectedTypes, element.getPrefixMatcher().getPrefix()) != 0) { + return NameUtil.nameToWords(name).length - 1000; + } + return 0; + } + } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java index c96d7f3d6535..69bfd73409fe 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -432,75 +432,6 @@ public class JavaCompletionUtil { return null; } - public static int getNameEndMatchingDegree(final String name, ExpectedTypeInfo[] expectedInfos, String prefix) { - int res = 0; - if (name != null && expectedInfos != null) { - if (prefix.equals(name)) { - res = Integer.MAX_VALUE; - } else { - final List words = NameUtil.nameToWordsLowerCase(name); - final List wordsNoDigits = NameUtil.nameToWordsLowerCase(truncDigits(name)); - int max1 = calcMatch(words, 0, expectedInfos); - max1 = calcMatch(wordsNoDigits, max1, expectedInfos); - res = max1; - } - } - - return res; - } - - static String truncDigits(String name){ - int count = name.length() - 1; - while (count >= 0) { - char c = name.charAt(count); - if (!Character.isDigit(c)) break; - count--; - } - return name.substring(0, count + 1); - } - - private static int calcMatch(final List words, int max, ExpectedTypeInfo[] myExpectedInfos) { - for (ExpectedTypeInfo myExpectedInfo : myExpectedInfos) { - String expectedName = ((ExpectedTypeInfoImpl)myExpectedInfo).expectedName; - if (expectedName == null) continue; - max = calcMatch(expectedName, words, max); - max = calcMatch(truncDigits(expectedName), words, max); - } - return max; - } - - static int calcMatch(final String expectedName, final List words, int max) { - if (expectedName == null) return max; - - String[] expectedWords = NameUtil.nameToWords(expectedName); - int limit = Math.min(words.size(), expectedWords.length); - for (int i = 0; i < limit; i++) { - String word = words.get(words.size() - i - 1); - String expectedWord = expectedWords[expectedWords.length - i - 1]; - if (word.equalsIgnoreCase(expectedWord)) { - max = Math.max(max, i + 1); - } - else { - break; - } - } - return max; - } - - @Nullable - static String getLookupObjectName(Object o) { - if (o instanceof PsiVariable) { - final PsiVariable variable = (PsiVariable)o; - JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(variable.getProject()); - VariableKind variableKind = codeStyleManager.getVariableKind(variable); - return codeStyleManager.variableNameToPropertyName(variable.getName(), variableKind); - } - if (o instanceof PsiMethod) { - return ((PsiMethod)o).getName(); - } - return null; - } - @Nullable public static PsiType getLookupElementType(final LookupElement element) { TypedLookupItem typed = element.as(TypedLookupItem.CLASS_CONDITION_KEY); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferFieldsAndGettersWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferFieldsAndGettersWeigher.java deleted file mode 100644 index c92faccbb46c..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferFieldsAndGettersWeigher.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2000-2009 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 com.intellij.codeInsight.completion; - -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.psi.PsiField; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.util.PropertyUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * @author peter -*/ -public class PreferFieldsAndGettersWeigher extends CompletionWeigher { - - public Comparable weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) { - if (location == null) { - return null; - } - if (location.getCompletionType() != CompletionType.SMART) return 0; - - final Object object = item.getObject(); - if (object instanceof PsiField) return 2; - if (object instanceof PsiMethod && PropertyUtil.isSimplePropertyGetter((PsiMethod)object)) return 1; - return 0; - } -} diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferShorterWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferShorterWeigher.java deleted file mode 100644 index 223559778dbd..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferShorterWeigher.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2000-2009 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 com.intellij.codeInsight.completion; - -import com.intellij.codeInsight.ExpectedTypeInfo; -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.psi.codeStyle.NameUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * @author peter -*/ -public class PreferShorterWeigher extends CompletionWeigher { - - public Comparable weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) { - if (location == null) { - return null; - } - final Object object = item.getObject(); - final String name = JavaCompletionUtil.getLookupObjectName(object); - final ExpectedTypeInfo[] expectedInfos = JavaCompletionUtil.EXPECTED_TYPES.getValue(location); - - if (name != null && expectedInfos != null && JavaCompletionUtil.getNameEndMatchingDegree(name, expectedInfos, - item.getPrefixMatcher().getPrefix()) != 0) { - return 239 - NameUtil.nameToWords(name).length; - } - return 0; - - } -} diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/SameWordsWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/SameWordsWeigher.java deleted file mode 100644 index ca315e8df12c..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/completion/SameWordsWeigher.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2000-2009 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 com.intellij.codeInsight.completion; - -import com.intellij.codeInsight.ExpectedTypeInfo; -import com.intellij.codeInsight.ExpectedTypeInfoImpl; -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.psi.codeStyle.NameUtil; -import gnu.trove.THashSet; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -/** - * @author peter -*/ -public class SameWordsWeigher extends CompletionWeigher { - - public Comparable weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) { - if (location == null) { - return null; - } - final Object object = item.getObject(); - - final String name = JavaCompletionUtil.getLookupObjectName(object); - final ExpectedTypeInfo[] myExpectedInfos = JavaCompletionUtil.EXPECTED_TYPES.getValue(location); - if (name != null && myExpectedInfos != null) { - int max = 0; - final List wordsNoDigits = NameUtil.nameToWordsLowerCase(JavaCompletionUtil.truncDigits(name)); - for (ExpectedTypeInfo myExpectedInfo : myExpectedInfos) { - String expectedName = ((ExpectedTypeInfoImpl)myExpectedInfo).expectedName; - if (expectedName != null) { - final THashSet set = new THashSet(NameUtil.nameToWordsLowerCase(JavaCompletionUtil.truncDigits(expectedName))); - set.retainAll(wordsNoDigits); - max = Math.max(max, set.size()); - } - } - return max; - } - return 0; - } -} diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index da0f41b62208..3310379d0bcf 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -803,14 +803,6 @@ - - - - - From 2bc8375a907c187194daa285986b79e0e5e0d30b Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 22 Feb 2011 12:25:07 +0100 Subject: [PATCH 108/169] Try-with-resource support: reuse variable quick fix --- .../quickfix/ReuseVariableDeclarationFix.java | 84 ++++++++++--------- .../psi/impl/PsiJavaParserFacadeImpl.java | 39 +++++++++ .../source/tree/java/PsiResourceImpl.java | 2 +- .../reuseVariableDeclaration/after7.java | 14 ++++ .../reuseVariableDeclaration/before7.java | 14 ++++ ...java => ReuseVariableDeclarationTest.java} | 6 +- .../com/intellij/psi/PsiJavaParserFacade.java | 11 +++ 7 files changed, 125 insertions(+), 45 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/reuseVariableDeclaration/after7.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/reuseVariableDeclaration/before7.java rename java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/{ReuseVariableDeclarationtTest.java => ReuseVariableDeclarationTest.java} (75%) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReuseVariableDeclarationFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReuseVariableDeclarationFix.java index 18dd2f6283bc..0e6cd0ae748e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReuseVariableDeclarationFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReuseVariableDeclarationFix.java @@ -27,21 +27,19 @@ import com.intellij.psi.scope.processor.VariablesNotProcessor; import com.intellij.psi.scope.util.PsiScopesUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** - * Created by IntelliJ IDEA. - * User: cdr + * @author cdr * Date: Nov 20, 2002 - * Time: 3:01:25 PM - * To change this template use Options | File Templates. */ public class ReuseVariableDeclarationFix implements IntentionAction { - private final PsiVariable variable; - private final PsiIdentifier identifier; + private final PsiVariable myVariable; + private final PsiIdentifier myIdentifier; - public ReuseVariableDeclarationFix(PsiVariable variable, PsiIdentifier identifier) { - this.variable = variable; - this.identifier = identifier; + public ReuseVariableDeclarationFix(final PsiVariable variable, final PsiIdentifier identifier) { + this.myVariable = variable; + this.myIdentifier = identifier; } @NotNull @@ -51,55 +49,63 @@ public class ReuseVariableDeclarationFix implements IntentionAction { @NotNull public String getText() { - return QuickFixBundle.message("reuse.variable.declaration.text", variable.getName()); + return QuickFixBundle.message("reuse.variable.declaration.text", myVariable.getName()); } - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - - PsiVariable previousVariable = findPreviousVariable(); - return - variable != null - && variable.isValid() - && variable instanceof PsiLocalVariable - && previousVariable != null - && Comparing.equal(previousVariable.getType(), variable.getType()) - && identifier != null - && identifier.isValid() - && variable.getManager().isInProject(variable); + public boolean isAvailable(@NotNull final Project project, final Editor editor, final PsiFile file) { + final PsiVariable previousVariable = findPreviousVariable(); + return myVariable != null && + myVariable.isValid() && + myVariable instanceof PsiLocalVariable && + !(myVariable.getParent() instanceof PsiResource && myVariable.getInitializer() == null) && + previousVariable != null && + Comparing.equal(previousVariable.getType(), myVariable.getType()) && + myIdentifier != null && + myIdentifier.isValid() && + myVariable.getManager().isInProject(myVariable); } - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - PsiVariable refVariable = findPreviousVariable(); + public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException { + final PsiVariable refVariable = findPreviousVariable(); if (refVariable == null) return; - if (!CodeInsightUtil.preparePsiElementsForWrite(variable, refVariable)) return; - PsiUtil.setModifierProperty(refVariable, PsiModifier.FINAL, false); - if (variable.getInitializer() == null) { - variable.delete(); + + if (!CodeInsightUtil.preparePsiElementsForWrite(myVariable, refVariable)) return; + + final PsiExpression initializer = myVariable.getInitializer(); + if (initializer == null) { + myVariable.delete(); return; } - PsiDeclarationStatement declaration = (PsiDeclarationStatement) variable.getParent(); - PsiElementFactory factory = JavaPsiFacade.getInstance(variable.getProject()).getElementFactory(); - PsiStatement statement = factory.createStatementFromText(variable.getName() + " = " + variable.getInitializer().getText()+";", variable); - declaration.replace(statement); + + PsiUtil.setModifierProperty(refVariable, PsiModifier.FINAL, false); + + final PsiElementFactory factory = JavaPsiFacade.getInstance(myVariable.getProject()).getElementFactory(); + final PsiElement replacement; + final PsiElement parent = myVariable.getParent(); + if (parent instanceof PsiResource) { + replacement = factory.createResourceFromText(myVariable.getName() + " = " + initializer.getText(), null); + } + else { + replacement = factory.createStatementFromText(myVariable.getName() + " = " + initializer.getText() + ";", null); + } + parent.replace(replacement); } + @Nullable private PsiVariable findPreviousVariable() { - PsiElement scope = variable.getParent(); + PsiElement scope = myVariable.getParent(); while (scope != null) { if (scope instanceof PsiFile || scope instanceof PsiMethod || scope instanceof PsiClassInitializer) break; scope = scope.getParent(); } if (scope == null) return null; - VariablesNotProcessor proc = new VariablesNotProcessor(variable, false); - PsiScopesUtil.treeWalkUp(proc, identifier, scope); - if(proc.size() > 0) - return proc.getResult(0); - return null; + final VariablesNotProcessor proc = new VariablesNotProcessor(myVariable, false); + PsiScopesUtil.treeWalkUp(proc, myIdentifier, scope); + return proc.size() > 0 ? proc.getResult(0) : null; } public boolean startInWriteAction() { return true; } - } diff --git a/java/java-impl/src/com/intellij/psi/impl/PsiJavaParserFacadeImpl.java b/java/java-impl/src/com/intellij/psi/impl/PsiJavaParserFacadeImpl.java index 52d766646901..49ec4a074d84 100644 --- a/java/java-impl/src/com/intellij/psi/impl/PsiJavaParserFacadeImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/PsiJavaParserFacadeImpl.java @@ -64,6 +64,13 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ } }; + private static final JavaParserUtil.ParserWrapper RESOURCE = new JavaParserUtil.ParserWrapper() { + @Override + public void parse(final PsiBuilder builder) { + DeclarationParser.parseResource(builder); + } + }; + private static final JavaParserUtil.ParserWrapper TYPE = new JavaParserUtil.ParserWrapper() { @Override public void parse(final PsiBuilder builder) { @@ -162,6 +169,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ } @NotNull + @Override public PsiAnnotation createAnnotationFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, ANNOTATION, false), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); @@ -172,16 +180,19 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ } @NotNull + @Override public PsiDocTag createDocTagFromText(@NotNull final String text) throws IncorrectOperationException { return createDocCommentFromText(join("/**\n", text, "\n */")).getTags()[0]; } @NotNull + @Override public PsiDocTag createDocTagFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { return createDocTagFromText(text); } @NotNull + @Override public PsiDocComment createDocCommentFromText(@NotNull final String text) throws IncorrectOperationException { final PsiMethod method = createMethodFromText(join(text, "void m();"), null); final PsiDocComment comment = method.getDocComment(); @@ -190,11 +201,13 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ } @NotNull + @Override public PsiDocComment createDocCommentFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { return createDocCommentFromText(text); } @NotNull + @Override public PsiClass createClassFromText(@NotNull final String body, final PsiElement context) throws IncorrectOperationException { final PsiJavaFile aFile = createDummyJavaFile(join("class _Dummy_ { ", body, " }")); final PsiClass[] classes = aFile.getClasses(); @@ -205,6 +218,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ } @NotNull + @Override public PsiField createFieldFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, DECLARATION, false), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); @@ -215,6 +229,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ } @NotNull + @Override public PsiMethod createMethodFromText(@NotNull final String text, final PsiElement context, final LanguageLevel level) throws IncorrectOperationException { final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, DECLARATION, false, level), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); @@ -225,12 +240,14 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ } @NotNull + @Override public final PsiMethod createMethodFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { final LanguageLevel level = LanguageLevelProjectExtension.getInstance(myManager.getProject()).getLanguageLevel(); return createMethodFromText(text, context, level); } @NotNull + @Override public PsiParameter createParameterFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, PARAMETER, false), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); @@ -241,11 +258,24 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ } @NotNull + @Override + public PsiResource createResourceFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { + final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, RESOURCE, false), context); + final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); + if (!(element instanceof PsiResource)) { + throw new IncorrectOperationException("Incorrect resource \"" + text + "\"."); + } + return (PsiResource)element; + } + + @NotNull + @Override public PsiType createTypeFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { return createTypeInner(text, context, false); } @NotNull + @Override public PsiTypeElement createTypeElementFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { final boolean multiCatch = context instanceof PsiParameter && context.getParent() instanceof PsiCatchSection && @@ -271,6 +301,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ } @NotNull + @Override public PsiJavaCodeReferenceElement createReferenceFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { final boolean isStaticImport = context instanceof PsiImportStaticStatement && !((PsiImportStaticStatement)context).isOnDemand(); @@ -284,6 +315,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ } @NotNull + @Override public PsiCodeBlock createCodeBlockFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, CODE_BLOCK, true), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); @@ -294,6 +326,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ } @NotNull + @Override public PsiStatement createStatementFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, STATEMENT, false), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); @@ -304,6 +337,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ } @NotNull + @Override public PsiExpression createExpressionFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, EXPRESSION, false), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); @@ -320,6 +354,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ } @NotNull + @Override public PsiTypeParameter createTypeParameterFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, TYPE_PARAMETER, false), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); @@ -330,6 +365,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ } @NotNull + @Override public PsiComment createCommentFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { final PsiJavaFile aFile = createDummyJavaFile(text); for (PsiElement aChildren : aFile.getChildren()) { @@ -347,6 +383,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ } @NotNull + @Override public PsiEnumConstant createEnumConstantFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, ENUM_CONSTANT, false), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); @@ -357,6 +394,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ } @NotNull + @Override public PsiCatchSection createCatchSection(@NotNull final PsiClassType exceptionType, @NotNull final String exceptionName, final PsiElement context) throws IncorrectOperationException { final String text = join("catch (", exceptionType.getCanonicalText(), " ", exceptionName, ") {}"); @@ -396,6 +434,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ psiCatchSection.getCatchBlock().replace(codeBlockFromText); } + @Override public PsiType createPrimitiveType(@NotNull final String text, @NotNull final PsiAnnotation[] annotations) throws IncorrectOperationException { final PsiPrimitiveType primitiveType = getPrimitiveType(text); if (primitiveType == null) { diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceImpl.java index 35faa6a76cea..6a09eefdfece 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceImpl.java @@ -61,7 +61,7 @@ public class PsiResourceImpl extends CompositePsiElement implements PsiResource } public String getName() { - final PsiElement element = getResourceElement(); + final PsiElement element = getFirstChild(); if (element instanceof PsiLocalVariable) return ((PsiLocalVariable)element).getName(); if (element instanceof PsiAssignmentExpression) return ((PsiAssignmentExpression)element).getLExpression().toString(); return ""; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/reuseVariableDeclaration/after7.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/reuseVariableDeclaration/after7.java new file mode 100644 index 000000000000..5b655ed5ba30 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/reuseVariableDeclaration/after7.java @@ -0,0 +1,14 @@ +// "Reuse previous variable 'r' declaration" "true" +import java.io.*; + +class a { + static class MyResource implements AutoCloseable { + public void close() { } + } + + void m() { + MyResource r; + try (r = new MyResource()) { + } + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/reuseVariableDeclaration/before7.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/reuseVariableDeclaration/before7.java new file mode 100644 index 000000000000..dab83655490c --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/reuseVariableDeclaration/before7.java @@ -0,0 +1,14 @@ +// "Reuse previous variable 'r' declaration" "true" +import java.io.*; + +class a { + static class MyResource implements AutoCloseable { + public void close() { } + } + + void m() { + MyResource r; + try (MyResource r = new MyResource()) { + } + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReuseVariableDeclarationtTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReuseVariableDeclarationTest.java similarity index 75% rename from java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReuseVariableDeclarationtTest.java rename to java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReuseVariableDeclarationTest.java index ccedcb111a4c..043e67830c72 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReuseVariableDeclarationtTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReuseVariableDeclarationTest.java @@ -1,9 +1,7 @@ - package com.intellij.codeInsight.daemon.quickFix; - -public class ReuseVariableDeclarationtTest extends LightQuickFixTestCase { +public class ReuseVariableDeclarationTest extends LightQuickFixTestCase { public void test() throws Exception { doAllTests(); } @@ -11,6 +9,4 @@ public class ReuseVariableDeclarationtTest extends LightQuickFixTestCase { protected String getBasePath() { return "/codeInsight/daemonCodeAnalyzer/quickFix/reuseVariableDeclaration"; } - } - diff --git a/java/openapi/src/com/intellij/psi/PsiJavaParserFacade.java b/java/openapi/src/com/intellij/psi/PsiJavaParserFacade.java index 3d9e0307f916..6e59d5430e38 100644 --- a/java/openapi/src/com/intellij/psi/PsiJavaParserFacade.java +++ b/java/openapi/src/com/intellij/psi/PsiJavaParserFacade.java @@ -116,6 +116,17 @@ public interface PsiJavaParserFacade extends PsiParserFacade { @NotNull PsiParameter createParameterFromText(@NotNull @NonNls String text, PsiElement context) throws IncorrectOperationException; + /** + * Creates a Java try-resource from the specified text. + * + * @param text the text of the resource to create. + * @param context the PSI element used as context for resolving references from the resource. + * @return the created resource instance. + * @throws com.intellij.util.IncorrectOperationException if the text is not a valid resource definition. + */ + @NotNull + PsiResource createResourceFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException; + /** * Creates a Java type from the specified text. * From dc61fe3fe0a749be7c60e8983972889de0516d4a Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 22 Feb 2011 13:06:34 +0100 Subject: [PATCH 109/169] Cleanup --- .../daemon/impl/analysis/HighlightUtil.java | 58 +++++++++---------- .../impl/analysis/HighlightVisitorImpl.java | 2 +- .../impl/analysis/HighlightInfoHolder.java | 7 +-- 3 files changed, 33 insertions(+), 34 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index 8a02cbf32e83..6d44b28cb9d8 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -73,8 +73,7 @@ public class HighlightUtil { @NonNls private static final String SERIAL_PERSISTENT_FIELDS_FIELD_NAME = "serialPersistentFields"; private static final QuickFixFactory QUICK_FIX_FACTORY = QuickFixFactory.getInstance(); - private HighlightUtil() { - } + private HighlightUtil() { } static { ourClassIncompatibleModifiers = new THashMap>(8); @@ -345,6 +344,7 @@ public class HighlightUtil { } + @Nullable static HighlightInfo checkVariableExpected(PsiExpression expression) { PsiExpression lValue; if (expression instanceof PsiAssignmentExpression) { @@ -632,6 +632,7 @@ public class HighlightUtil { } + @Nullable public static HighlightInfo checkUnhandledExceptions(PsiElement element, TextRange fixRange) { List unhandledExceptions = ExceptionUtil.getUnhandledExceptions(element); HighlightInfo errorResult = null; @@ -652,6 +653,7 @@ public class HighlightUtil { return errorResult; } + @Nullable private static HighlightInfoType getUnhandledExceptionHighlightType(final PsiElement element) { if (!JspPsiUtil.isInJspFile(element)) { return HighlightInfoType.UNHANDLED_EXCEPTION; @@ -698,6 +700,7 @@ public class HighlightUtil { } + @Nullable static HighlightInfo checkIllegalModifierCombination(PsiKeyword keyword, PsiModifierList modifierList) { @Modifier String modifier = keyword.getText(); String incompatible = getIncompatibleModifier(modifier, modifierList); @@ -949,6 +952,7 @@ public class HighlightUtil { } + @Nullable public static HighlightInfo checkSwitchSelectorType(PsiSwitchStatement statement) { PsiExpression expression = statement.getExpression(); HighlightInfo errorResult = null; @@ -1126,20 +1130,15 @@ public class HighlightUtil { final PsiClassType autoCloseable = factory.createTypeByFQClassName("java.lang.AutoCloseable", resource.getResolveScope()); if (TypeConversionUtil.isAssignable(autoCloseable, type)) return null; - final HighlightInfo highlightInfo = createIncompatibleTypeHighlightInfo(autoCloseable, type, resource.getTextRange()); - //if (addCastIntention && TypeConversionUtil.areTypesConvertible(type, autoCloseable)) { - // if (parameter instanceof PsiExpression) { - // QuickFixAction.registerQuickFixAction(highlightInfo, new AddTypeCastFix(autoCloseable, (PsiExpression)parameter)); - // } - //} - return highlightInfo; + return createIncompatibleTypeHighlightInfo(autoCloseable, type, resource.getTextRange()); } - public static void checkArrayInitalizer(final PsiExpression initializer, final HighlightInfoHolder holder) { - if (! (initializer instanceof PsiArrayInitializerExpression)) return; + @Nullable + public static Collection checkArrayInitializer(final PsiExpression initializer) { + if (! (initializer instanceof PsiArrayInitializerExpression)) return null; final PsiType arrayInitializerType = initializer.getType(); - if (! (arrayInitializerType instanceof PsiArrayType)) return; + if (! (arrayInitializerType instanceof PsiArrayType)) return null; final PsiType componentType = ((PsiArrayType) arrayInitializerType).getComponentType(); final PsiArrayInitializerExpression arrayInitializer = (PsiArrayInitializerExpression) initializer; @@ -1147,11 +1146,12 @@ public class HighlightUtil { boolean arrayTypeFixChecked = false; VariableArrayTypeFix fix = null; + final Collection result = Lists.newArrayList(); final PsiExpression[] initializers = arrayInitializer.getInitializers(); for (PsiExpression expression : initializers) { - final HighlightInfo info = checkArrayInitalizerCompatibleTypes(expression, componentType); + final HighlightInfo info = checkArrayInitializerCompatibleTypes(expression, componentType); if (info != null) { - holder.add(info); + result.add(info); if (!arrayTypeFixChecked) { final PsiType checkResult = sameType(initializers); @@ -1163,6 +1163,7 @@ public class HighlightUtil { } } } + return result; } @Nullable @@ -1174,6 +1175,7 @@ public class HighlightUtil { return null; } + @Nullable public static PsiType sameType(PsiExpression[] expressions) { PsiType type = null; for (PsiExpression expression : expressions) { @@ -1195,7 +1197,7 @@ public class HighlightUtil { } @Nullable - private static HighlightInfo checkArrayInitalizerCompatibleTypes(PsiExpression initializer, final PsiType componentType) { + private static HighlightInfo checkArrayInitializerCompatibleTypes(PsiExpression initializer, final PsiType componentType) { PsiType initializerType = initializer.getType(); if (initializerType == null) { return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, initializer, @@ -1229,16 +1231,12 @@ public class HighlightUtil { PsiVariable variable = (PsiVariable)parent; if (variable.getType() instanceof PsiArrayType) return null; } - else if (parent instanceof PsiNewExpression) { + else if (parent instanceof PsiNewExpression || parent instanceof PsiArrayInitializerExpression) { return null; } - else if (parent instanceof PsiArrayInitializerExpression) { - return null; - } - HighlightInfo info = - HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, JavaErrorMessages.message("expression.expected")); - QuickFixAction.registerQuickFixAction(info, new AddNewArrayExpressionFix(expression)); + HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, JavaErrorMessages.message("expression.expected")); + QuickFixAction.registerQuickFixAction(info, new AddNewArrayExpressionFix(expression)); return info; } @@ -1410,13 +1408,11 @@ public class HighlightUtil { if (typeOwner instanceof PsiMethod) { if (((PsiMethod)typeOwner).getReturnTypeElement() == parent) return null; } - else if (typeOwner instanceof PsiClassObjectAccessExpression && - TypeConversionUtil.isVoidType(((PsiClassObjectAccessExpression)typeOwner).getOperand().getType())) { - // like in Class c = void.class; - return null; - } - else if (typeOwner != null && PsiUtilBase.hasErrorElementChild(typeOwner)) { - // do not highlight incomplete declarations + else if (// like in Class c = void.class; + typeOwner instanceof PsiClassObjectAccessExpression && + TypeConversionUtil.isVoidType(((PsiClassObjectAccessExpression)typeOwner).getOperand().getType()) || + // do not highlight incomplete declarations + typeOwner != null && PsiUtilBase.hasErrorElementChild(typeOwner)) { return null; } else if (typeOwner instanceof JavaCodeFragment) { @@ -1527,6 +1523,7 @@ public class HighlightUtil { return checkReferenceToOurInstanceInsideThisOrSuper(expression, referencedClass, resolvedName); } + @Nullable private static HighlightInfo checkReferenceToOurInstanceInsideThisOrSuper(final PsiElement expression, final PsiClass referencedClass, final String resolvedName) { @@ -1568,6 +1565,7 @@ public class HighlightUtil { return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, description); } + @Nullable public static HighlightInfo checkImplicitThisReferenceBeforeSuper(PsiClass aClass) { if (aClass instanceof PsiAnonymousClass) return null; PsiClass superClass = aClass.getSuperClass(); @@ -1606,6 +1604,7 @@ public class HighlightUtil { return element != null; } + @Nullable private static String getMethodExpressionName(PsiElement element) { if (!(element instanceof PsiMethodCallExpression)) return null; PsiReferenceExpression methodExpression = ((PsiMethodCallExpression)element).getMethodExpression(); @@ -2099,6 +2098,7 @@ public class HighlightUtil { return aClass == null || isSerializable(aClass); } + @Nullable public static HighlightInfo checkClassReferenceAfterQualifier(final PsiReferenceExpression expression, final PsiElement resolved) { if (!(resolved instanceof PsiClass)) return null; final PsiExpression qualifier = expression.getQualifierExpression(); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index dfc4475f17e5..5f0362d1ce93 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -342,7 +342,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh } if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkCannotWriteToFinal(expression)); if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkVariableExpected(expression)); - if (!myHolder.hasErrorResults()) HighlightUtil.checkArrayInitalizer(expression, myHolder); + if (!myHolder.hasErrorResults()) myHolder.addAll(HighlightUtil.checkArrayInitializer(expression)); if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTernaryOperatorConditionIsBoolean(expression)); if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAssertOperatorTypes(expression)); if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkSynchronizedExpressionType(expression)); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightInfoHolder.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightInfoHolder.java index 84df3efe441f..ca74d4685529 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightInfoHolder.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightInfoHolder.java @@ -13,10 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -/** - * @author Alexey - */ package com.intellij.codeInsight.daemon.impl.analysis; import com.intellij.codeInsight.daemon.impl.HighlightInfo; @@ -34,6 +30,9 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +/** + * @author Alexey + */ public class HighlightInfoHolder { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.analysis.HighlightInfoHolder"); From 8915ce77a3872f5bf9227c2c650b4cb52eb16385 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 22 Feb 2011 17:48:34 +0100 Subject: [PATCH 110/169] Test cleanup --- .../daemon/AdvHighlightingJdk7Test.java | 47 +++++++++++++++++++ .../daemon/AdvHighlightingTest.java | 14 +++--- 2 files changed, 53 insertions(+), 8 deletions(-) create mode 100644 java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingJdk7Test.java diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingJdk7Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingJdk7Test.java new file mode 100644 index 000000000000..3a2c666d74b2 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingJdk7Test.java @@ -0,0 +1,47 @@ +/* + * Copyright 2000-2011 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 com.intellij.codeInsight.daemon; + +import com.intellij.codeInspection.LocalInspectionTool; +import com.intellij.codeInspection.defUse.DefUseInspection; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; +import com.intellij.openapi.roots.LanguageLevelProjectExtension; +import com.intellij.pom.java.LanguageLevel; +import org.jetbrains.annotations.NonNls; + +/** + * This class intended for "heavily-loaded" tests only, e.g. those need to setup separate project directory structure to run + * For "lightweight" tests use LightAdvHighlightingTest + */ +public class AdvHighlightingJdk7Test extends DaemonAnalyzerTestCase { + @NonNls private static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/advHighlighting"; + + @Override + protected Sdk getTestProjectJdk() { + LanguageLevelProjectExtension.getInstance(myProject).setLanguageLevel(LanguageLevel.JDK_1_7); + return JavaSdkImpl.getMockJdk17("java 1.7"); + } + + @Override + protected LocalInspectionTool[] configureLocalInspectionTools() { + return new LocalInspectionTool[]{new DefUseInspection()}; + } + + public void testStaticImportConflict() throws Exception { + doTest(BASE_PATH + "/staticImportConflict/Usage.java", BASE_PATH + "/staticImportConflict", false, false); + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java index e55f40743792..6b2196793939 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java @@ -42,6 +42,12 @@ import java.util.Collection; public class AdvHighlightingTest extends DaemonAnalyzerTestCase { @NonNls private static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/advHighlighting"; + @Override + protected Sdk getTestProjectJdk() { + LanguageLevelProjectExtension.getInstance(myProject).setLanguageLevel(LanguageLevel.JDK_1_4); + return JavaSdkImpl.getMockJdk14(); + } + public void testPackageLocals() throws Exception { doTest(BASE_PATH+"/packageLocals/x/sub/UsingMain.java", BASE_PATH+"/packageLocals", false, false); } public void testPackageLocalClassInTheMiddle() throws Exception { doTest(BASE_PATH+"/packageLocals/x/A.java", BASE_PATH+"/packageLocals", false, false); } @@ -63,14 +69,6 @@ public class AdvHighlightingTest extends DaemonAnalyzerTestCase { public void testProtectedFieldAccessFromOtherPackage() throws Exception { doTest(BASE_PATH+"/protectedAccessFromOtherPackage/a/A.java", BASE_PATH+"/protectedAccessFromOtherPackage", false, false); } public void testPackageLocalClassInTheMiddle1() throws Exception { doTest(BASE_PATH+"/foreignPackageInBetween/a/A1.java", BASE_PATH+"/foreignPackageInBetween", false, false); } - @Override - protected Sdk getTestProjectJdk() { - @NonNls boolean is50 = "StaticImportConflict".equals(getTestName(false)); - LanguageLevelProjectExtension.getInstance(myProject).setLanguageLevel(is50 ? LanguageLevel.JDK_1_5 : LanguageLevel.JDK_1_4); - return is50 ? JavaSdkImpl.getMockJdk17("java 1.5") : JavaSdkImpl.getMockJdk14(); - } - - public void testStaticImportConflict() throws Exception { doTest(BASE_PATH+"/staticImportConflict/Usage.java", BASE_PATH+"/staticImportConflict", false, false); } public void testImportOnDemand() throws Exception { doTest(BASE_PATH+"/importOnDemand/y/Y.java", BASE_PATH+"/importOnDemand", false, false); } public void testImportOnDemandVsSingle() throws Exception { doTest(BASE_PATH+"/importOnDemandVsSingle/y/Y.java", BASE_PATH+"/importOnDemandVsSingle", false, false); } public void testImportSingleVsSamePackage() throws Exception { doTest(BASE_PATH+"/importSingleVsSamePackage/y/Y.java", BASE_PATH+"/importSingleVsSamePackage", false, false); } From c59584e8ef7710c79f49b886cec5777390107ef3 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 22 Feb 2011 17:48:51 +0100 Subject: [PATCH 111/169] To JB dictionary --- .../spellchecker/src/com/intellij/spellchecker/jetbrains.dic | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/spellchecker/src/com/intellij/spellchecker/jetbrains.dic b/plugins/spellchecker/src/com/intellij/spellchecker/jetbrains.dic index b86b0bef6f9a..0d19cd4eff3b 100644 --- a/plugins/spellchecker/src/com/intellij/spellchecker/jetbrains.dic +++ b/plugins/spellchecker/src/com/intellij/spellchecker/jetbrains.dic @@ -103,6 +103,7 @@ innodb inout instantiable intellij +iphone isnull javadoc javascript @@ -204,6 +205,7 @@ permalink petersburg pipelined playlist +plist plsql plugin plugins @@ -274,6 +276,8 @@ subpackage subpartition subpartitions substring +superclass +superclasses symlink symlinks sysdate From 0f2e1cd4f67d95052fc8ee7ba261840f22adfbc5 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 22 Feb 2011 17:50:42 +0100 Subject: [PATCH 112/169] Try-with-resource support: variable usage inspection --- .../defUse/DefUseInspection.java | 2 +- .../psi/controlFlow/ControlFlowAnalyzer.java | 91 +++++++++++++------ .../intellij/psi/controlFlow/DefUseUtil.java | 32 +++---- .../TryWithResourcesWarn.java | 51 +++++++++++ .../daemon/LightAdvHighlightingJdk7Test.java | 7 +- 5 files changed, 136 insertions(+), 47 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResourcesWarn.java diff --git a/java/java-impl/src/com/intellij/codeInspection/defUse/DefUseInspection.java b/java/java-impl/src/com/intellij/codeInspection/defUse/DefUseInspection.java index 138a271602e1..34293268c478 100644 --- a/java/java-impl/src/com/intellij/codeInspection/defUse/DefUseInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/defUse/DefUseInspection.java @@ -97,7 +97,7 @@ public class DefUseInspection extends BaseLocalInspectionTool { PsiElement context = info.getContext(); PsiVariable psiVariable = info.getVariable(); - if (context instanceof PsiDeclarationStatement) { + if (context instanceof PsiDeclarationStatement || context instanceof PsiResource) { if (!info.isRead()) { if (!isOnTheFly) { holder.registerProblem(psiVariable.getNameIdentifier(), diff --git a/java/java-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java b/java/java-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java index add49f2a4f7a..a7e726fae882 100644 --- a/java/java-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java +++ b/java/java-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java @@ -474,7 +474,8 @@ class ControlFlowAnalyzer extends JavaJspElementVisitor { finishElement(statement); } - @Override public void visitDeclarationStatement(PsiDeclarationStatement statement) { + @Override + public void visitDeclarationStatement(PsiDeclarationStatement statement) { startElement(statement); int pc = myCurrentFlow.getSize(); PsiElement[] elements = statement.getDeclaredElements(); @@ -484,28 +485,7 @@ class ControlFlowAnalyzer extends JavaJspElementVisitor { element.accept(this); } else if (element instanceof PsiVariable) { - PsiExpression initializer = ((PsiVariable)element).getInitializer(); - if (initializer != null) { - myStartStatementStack.pushStatement(initializer, false); - myEndStatementStack.pushStatement(initializer, false); - initializer.accept(this); - myStartStatementStack.popStatement(); - myEndStatementStack.popStatement(); - } - if (element instanceof PsiLocalVariable && initializer != null - || element instanceof PsiField) { - if (element instanceof PsiLocalVariable && !myPolicy.isLocalVariableAccepted((PsiLocalVariable)element)) continue; - - if (myAssignmentTargetsAreElements) { - startElement(element); - } - - generateWriteInstruction((PsiVariable)element); - - if (myAssignmentTargetsAreElements) { - finishElement(element); - } - } + processVariable((PsiVariable)element); } } if (pc == myCurrentFlow.getSize()) { @@ -515,6 +495,31 @@ class ControlFlowAnalyzer extends JavaJspElementVisitor { finishElement(statement); } + private void processVariable(final PsiVariable element) { + final PsiExpression initializer = element.getInitializer(); + if (initializer != null) { + myStartStatementStack.pushStatement(initializer, false); + myEndStatementStack.pushStatement(initializer, false); + initializer.accept(this); + myStartStatementStack.popStatement(); + myEndStatementStack.popStatement(); + } + if (element instanceof PsiLocalVariable && initializer != null || + element instanceof PsiField) { + if (element instanceof PsiLocalVariable && !myPolicy.isLocalVariableAccepted((PsiLocalVariable)element)) return; + + if (myAssignmentTargetsAreElements) { + startElement(element); + } + + generateWriteInstruction(element); + + if (myAssignmentTargetsAreElements) { + finishElement(element); + } + } + } + @Override public void visitDoWhileStatement(PsiDoWhileStatement statement) { startElement(statement); myStartStatementStack.pushStatement(statement.getBody() == null ? statement : statement.getBody(), true); @@ -1030,17 +1035,17 @@ class ControlFlowAnalyzer extends JavaJspElementVisitor { myFinallyBlocks.push(finallyBlock); } + PsiResourceList resourceList = statement.getResourceList(); + if (resourceList != null) { + generateCheckedExceptionJumps(resourceList); + resourceList.accept(this); + } PsiCodeBlock tryBlock = statement.getTryBlock(); if (tryBlock != null) { // javac works as if all checked exceptions can occur at the top of the block generateCheckedExceptionJumps(tryBlock); tryBlock.accept(this); } - PsiResourceList resourceList = statement.getResourceList(); - if (resourceList != null) { - generateCheckedExceptionJumps(resourceList); - resourceList.accept(this); - } //noinspection StatementWithEmptyBody while (myUnhandledExceptionCatchBlocks.pop() != null) ; @@ -1157,8 +1162,36 @@ class ControlFlowAnalyzer extends JavaJspElementVisitor { finishElement(statement); } + @Override + public void visitResourceList(final PsiResourceList resourceList) { + startElement(resourceList); - @Override public void visitWhileStatement(PsiWhileStatement statement) { + final List resources = resourceList.getResources(); + for (PsiResource resource : resources) { + ProgressManager.checkCanceled(); + resource.accept(this); + } + + finishElement(resourceList); + } + + @Override + public void visitResource(final PsiResource resource) { + startElement(resource); + + final PsiElement resourceElement = resource.getResourceElement(); + if (resourceElement instanceof PsiLocalVariable) { + processVariable((PsiLocalVariable)resourceElement); + } + else if (resourceElement instanceof PsiExpression) { + resourceElement.accept(this); + } + + finishElement(resource); + } + + @Override + public void visitWhileStatement(PsiWhileStatement statement) { startElement(statement); if (statement.getBody() == null) { myStartStatementStack.pushStatement(statement, false); diff --git a/java/java-impl/src/com/intellij/psi/controlFlow/DefUseUtil.java b/java/java-impl/src/com/intellij/psi/controlFlow/DefUseUtil.java index fb0190f78c80..daba17413a5d 100644 --- a/java/java-impl/src/com/intellij/psi/controlFlow/DefUseUtil.java +++ b/java/java-impl/src/com/intellij/psi/controlFlow/DefUseUtil.java @@ -13,15 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -/* - * Created by IntelliJ IDEA. - * User: max - * Date: Mar 22, 2002 - * Time: 7:25:02 PM - * To change template for new class use - * Code Style | Class Templates options (Tools | IDE Options). - */ package com.intellij.psi.controlFlow; import com.intellij.openapi.diagnostic.Logger; @@ -34,16 +25,20 @@ import com.intellij.util.containers.IntArrayList; import com.intellij.util.containers.Queue; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; import java.util.Set; +/** + * @author max + * Date: Mar 22, 2002 + */ public class DefUseUtil { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.defUse.DefUseUtil"); - private DefUseUtil() { - } + private DefUseUtil() { } public static class Info { private final PsiVariable myVariable; @@ -132,6 +127,7 @@ public class DefUseUtil { } } + @Nullable public static List getUnusedDefs(PsiCodeBlock body, Set outUsedVariables) { if (body == null) { return null; @@ -232,12 +228,13 @@ public class DefUseUtil { if (instruction instanceof WriteVariableInstruction) { WriteVariableInstruction writeInstruction = (WriteVariableInstruction)instruction; if (!defsArmed[i]) { - PsiElement context = flow.getElement(i); - context = PsiTreeUtil.getNonStrictParentOfType(context, PsiStatement.class, PsiAssignmentExpression.class, - PsiPostfixExpression.class, PsiPrefixExpression.class); + PsiElement context = PsiTreeUtil.getNonStrictParentOfType(flow.getElement(i), + PsiStatement.class, PsiAssignmentExpression.class, + PsiPostfixExpression.class, PsiPrefixExpression.class, + PsiResource.class); PsiVariable psiVariable = writeInstruction.variable; if (context != null && !(context instanceof PsiTryStatement)) { - if (context instanceof PsiDeclarationStatement && psiVariable.getInitializer() == null) { + if (isDeclaration(context) && psiVariable.getInitializer() == null) { if (!assignedVariables.contains(psiVariable)) { unusedDefs.add(new Info(psiVariable, context, false)); } @@ -251,7 +248,11 @@ public class DefUseUtil { } return unusedDefs; + } + private static boolean isDeclaration(final PsiElement context) { + return context instanceof PsiDeclarationStatement || + context instanceof PsiResource && ((PsiResource)context).getResourceElement() instanceof PsiLocalVariable; } @NotNull @@ -476,5 +477,4 @@ public class DefUseUtil { return true; } }; - } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResourcesWarn.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResourcesWarn.java new file mode 100644 index 000000000000..7e72906b39d2 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResourcesWarn.java @@ -0,0 +1,51 @@ +import java.lang.Exception; + +class C { + static class MyResource implements AutoCloseable { + @Override public void close() { } + } + + void m1() throws Exception { + MyResource r1; + try (r1 = new MyResource()) { + System.out.println(r1); + } + + try (MyResource r2 = new MyResource()) { + System.out.println(r2); + } + + MyResource r3 = new MyResource(); + try (MyResource r = r3) { + System.out.println(r); + } + } + + void m2() throws Exception { + MyResource r1 = null; + try (r1 = new MyResource()) { + System.out.println(r1); + } + + try (MyResource r2 = new MyResource()) { + r2 = null; // todo: check for NPE + System.out.println(r2); + } + + MyResource r3 = null; + System.out.println(r3); + try (r3 = new MyResource()) { } + + try (MyResource r4 = new MyResource()) { } + + try (MyResource r5 = new MyResource()) { + System.out.println(r5); + r5 = new MyResource(); + } + + MyResource r6; + try (MyResource r = r6) { + System.out.println(r); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java index beba5cc637db..83a619d5559d 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java @@ -4,6 +4,7 @@ import com.intellij.ExtensionPoints; import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInspection.LocalInspectionTool; import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection; +import com.intellij.codeInspection.defUse.DefUseInspection; import com.intellij.codeInspection.reference.EntryPoint; import com.intellij.codeInspection.reference.RefElement; import com.intellij.codeInspection.uncheckedWarnings.UncheckedWarningLocalInspection; @@ -31,7 +32,7 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase { @Override protected LocalInspectionTool[] configureLocalInspectionTools() { - return new LocalInspectionTool[]{new UnusedSymbolLocalInspection(), new UncheckedWarningLocalInspection()}; + return new LocalInspectionTool[]{new UnusedSymbolLocalInspection(), new UncheckedWarningLocalInspection(), new DefUseInspection()}; } public void testDuplicateAnnotations() throws Exception { @@ -192,6 +193,10 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase { doTest(false, false); } + public void testTryWithResourcesWarn() throws Exception { + doTest(true, false); + } + public void testSafeVarargsApplicability() throws Exception { doTest(true, false); } From 07bc7abdceea1b25d2cc4da4a1a94e871cd94917 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 22 Feb 2011 20:16:06 +0100 Subject: [PATCH 113/169] To english dictionary --- plugins/spellchecker/src/com/intellij/spellchecker/english.dic | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/spellchecker/src/com/intellij/spellchecker/english.dic b/plugins/spellchecker/src/com/intellij/spellchecker/english.dic index d0646c2183a6..d7e47457dc60 100644 --- a/plugins/spellchecker/src/com/intellij/spellchecker/english.dic +++ b/plugins/spellchecker/src/com/intellij/spellchecker/english.dic @@ -79037,6 +79037,9 @@ inconveniences inconveniencing inconvenient inconveniently +inconvertibility +inconvertible +inconvertibly incorporable incorporate incorporated From 5fa72a60da2a5a6841274deeca934b3ed03dc675 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 22 Feb 2011 20:32:07 +0100 Subject: [PATCH 114/169] Try-with-resource support: highlight unhandled exceptions from close() --- .../intellij/codeInsight/ExceptionUtil.java | 38 +++++----- .../daemon/impl/analysis/HighlightUtil.java | 71 ++++++++++++------- .../impl/analysis/HighlightVisitorImpl.java | 13 ++-- .../advHighlighting7/TryWithResources.java | 11 +++ .../src/messages/JavaErrorMessages.properties | 5 +- 5 files changed, 86 insertions(+), 52 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/ExceptionUtil.java b/java/java-impl/src/com/intellij/codeInsight/ExceptionUtil.java index ea1008c5fb32..64fe99852282 100644 --- a/java/java-impl/src/com/intellij/codeInsight/ExceptionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/ExceptionUtil.java @@ -247,18 +247,12 @@ public class ExceptionUtil { } if (element instanceof PsiResource) { - final PsiType resourceType = ((PsiResource)element).getType(); - if (resourceType instanceof PsiClassType) { - final PsiClass resourceClass = ((PsiClassType)resourceType).resolve(); - if (resourceClass != null) { - final List unhandled = getUnhandledCloserExceptions(element, resourceClass, topElement); - if (unhandledExceptions == null) { - unhandledExceptions = unhandled; - } - else { - unhandledExceptions.addAll(unhandled); - } - } + final List unhandled = getUnhandledCloserExceptions((PsiResource)element, topElement); + if (unhandledExceptions == null) { + unhandledExceptions = unhandled; + } + else { + unhandledExceptions.addAll(unhandled); } } @@ -337,20 +331,24 @@ public class ExceptionUtil { } @NotNull - public static List getUnhandledCloserExceptions(final PsiElement resource, - final PsiClass resourceClass, - final PsiElement topElement) { - final PsiMethod[] closers = resourceClass.findMethodsByName("close", false); - for (final PsiMethod method : closers) { - if (method.getParameterList().getParametersCount() == 0) { - return getUnhandledExceptions(method, resource, topElement, PsiSubstitutor.EMPTY); + public static List getUnhandledCloserExceptions(final PsiResource resource, final PsiElement topElement) { + final PsiType resourceType = resource.getType(); + if (resourceType instanceof PsiClassType) { + final PsiClass resourceClass = ((PsiClassType)resourceType).resolve(); + if (resourceClass != null) { + final PsiMethod[] closers = resourceClass.findMethodsByName("close", false); + for (final PsiMethod method : closers) { + if (method.getParameterList().getParametersCount() == 0) { + return getUnhandledExceptions(method, resource, topElement, PsiSubstitutor.EMPTY); + } + } } } return Collections.emptyList(); } @Nullable - public static PsiClassType getUnhandledException(PsiThrowStatement throwStatement, PsiElement topElement){ + public static PsiClassType getUnhandledException(PsiThrowStatement throwStatement, PsiElement topElement) { final PsiExpression exception = throwStatement.getException(); if (exception != null) { final PsiType type = exception.getType(); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index 6d44b28cb9d8..f13a1b2e7171 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -36,6 +36,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.impl.source.jsp.jspJava.JspHolderMethod; import com.intellij.psi.javadoc.PsiDocComment; @@ -45,6 +46,7 @@ import com.intellij.psi.scope.util.PsiScopesUtil; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.*; import com.intellij.util.ArrayUtil; +import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; import com.intellij.xml.util.XmlStringUtil; import gnu.trove.THashMap; @@ -543,14 +545,16 @@ public class HighlightUtil { return errorResult; } - public static String getUnhandledExceptionsDescriptor(Collection unhandledExceptions) { - StringBuilder exceptionsText = new StringBuilder(); - for (PsiClassType unhandledException : unhandledExceptions) { - if (exceptionsText.length() != 0) exceptionsText.append(", "); - exceptionsText.append(formatType(unhandledException)); - } + public static String getUnhandledExceptionsDescriptor(final Collection unhandled) { + return getUnhandledExceptionsDescriptor(unhandled, null); + } - return JavaErrorMessages.message("unhandled.exceptions", exceptionsText.toString(), unhandledExceptions.size()); + private static String getUnhandledExceptionsDescriptor(final Collection unhandled, final String source) { + final String exceptions = StringUtil.join(unhandled, new Function() { + @Override public String fun(PsiClassType type) { return formatType(type); } + }, ", "); + return source != null ? JavaErrorMessages.message("unhandled.close.exceptions", exceptions, unhandled.size(), source) + : JavaErrorMessages.message("unhandled.exceptions", exceptions, unhandled.size()); } @Nullable @@ -633,26 +637,45 @@ public class HighlightUtil { @Nullable - public static HighlightInfo checkUnhandledExceptions(PsiElement element, TextRange fixRange) { - List unhandledExceptions = ExceptionUtil.getUnhandledExceptions(element); - HighlightInfo errorResult = null; - if (!unhandledExceptions.isEmpty()) { - if (fixRange == null) { - fixRange = element.getTextRange(); - } - HighlightInfoType highlightType = getUnhandledExceptionHighlightType(element); - if (highlightType == null) return null; - errorResult = HighlightInfo.createHighlightInfo(highlightType, fixRange, getUnhandledExceptionsDescriptor(unhandledExceptions)); - QuickFixAction.registerQuickFixAction(errorResult, new AddExceptionToCatchFix()); - QuickFixAction.registerQuickFixAction(errorResult, new AddExceptionToThrowsFix(element)); - QuickFixAction.registerQuickFixAction(errorResult, new SurroundWithTryCatchFix(element)); - if (unhandledExceptions.size() == 1) { - QuickFixAction.registerQuickFixAction(errorResult, new GeneralizeCatchFix(element, unhandledExceptions.get(0))); - } - } + public static HighlightInfo checkUnhandledExceptions(final PsiElement element, TextRange fixRange) { + final List unhandledExceptions = ExceptionUtil.getUnhandledExceptions(element); + if (unhandledExceptions.isEmpty()) return null; + + final HighlightInfoType highlightType = getUnhandledExceptionHighlightType(element); + if (highlightType == null) return null; + + if (fixRange == null) fixRange = element.getTextRange(); + final String description = getUnhandledExceptionsDescriptor(unhandledExceptions); + final HighlightInfo errorResult = HighlightInfo.createHighlightInfo(highlightType, fixRange, description); + registerUnhandledExceptionFixes(element, errorResult, unhandledExceptions); return errorResult; } + @Nullable + public static HighlightInfo checkUnhandledCloserExceptions(final PsiResource resource) { + final List unhandled = ExceptionUtil.getUnhandledCloserExceptions(resource, null); + if (unhandled.isEmpty()) return null; + + final HighlightInfoType highlightType = getUnhandledExceptionHighlightType(resource); + if (highlightType == null) return null; + + final String description = getUnhandledExceptionsDescriptor(unhandled, "auto-closeable resource"); + final HighlightInfo highlight = HighlightInfo.createHighlightInfo(highlightType, resource, description); + registerUnhandledExceptionFixes(resource, highlight, unhandled); + return highlight; + } + + private static void registerUnhandledExceptionFixes(final PsiElement element, + final HighlightInfo errorResult, + final List unhandled) { + QuickFixAction.registerQuickFixAction(errorResult, new AddExceptionToCatchFix()); + QuickFixAction.registerQuickFixAction(errorResult, new AddExceptionToThrowsFix(element)); + QuickFixAction.registerQuickFixAction(errorResult, new SurroundWithTryCatchFix(element)); + if (unhandled.size() == 1) { + QuickFixAction.registerQuickFixAction(errorResult, new GeneralizeCatchFix(element, unhandled.get(0))); + } + } + @Nullable private static HighlightInfoType getUnhandledExceptionHighlightType(final PsiElement element) { if (!JspPsiUtil.isInJspFile(element)) { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index 5f0362d1ce93..decc5b2d7126 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -902,13 +902,14 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh myHolder.add(HighlightUtil.checkCatchParameterIsThrowable(parameter)); myHolder.add(GenericsHighlightUtil.checkCatchParameterIsClass(parameter)); } + } + } - PsiResourceList resources = statement.getResourceList(); - if (resources != null) { - for (PsiResource resource : resources.getResources()) { - myHolder.add(HighlightUtil.checkTryResourceIsAutoCloseable(resource)); - } - } + @Override + public void visitResource(final PsiResource resource) { + myHolder.add(HighlightUtil.checkTryResourceIsAutoCloseable(resource)); + if (!myHolder.hasErrorResults()) { + myHolder.add(HighlightUtil.checkUnhandledCloserExceptions(resource)); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResources.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResources.java index 36187d86a680..4c086108583f 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResources.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResources.java @@ -16,6 +16,16 @@ class C { try (new MyResource()) { } catch (E1 | E3 ignore) { } + + MyResource r; + + try (r = new MyResource()) { } + catch (E1 e) { } + + try (r = new MyResource()) { } + catch (E3 e) { } + + try (r = new MyResource()) { } } void m2() throws Exception { @@ -27,6 +37,7 @@ class C { void m3() throws Exception { try (MyResource r = new MyResource()) { r.doSomething(); + /* todo: < error descr="Cannot assign a value to final variable 'r'">r = null;*/ } catch (E e) { r = null; diff --git a/resources-en/src/messages/JavaErrorMessages.properties b/resources-en/src/messages/JavaErrorMessages.properties index 7ac5ab1b4dd7..ee03ca9d19e2 100644 --- a/resources-en/src/messages/JavaErrorMessages.properties +++ b/resources-en/src/messages/JavaErrorMessages.properties @@ -184,8 +184,10 @@ return.outside.method=Return outside method return.from.void.method=Cannot return a value from a method with void result type missing.return.value=Missing return value -#{0] - exceptions list (comma separated). {1} - exceptions count in the list +#{0} - exceptions list (comma separated), {1} - exceptions count in the list, {2} - exception source unhandled.exceptions=Unhandled {1, choice, 0#exception|2#exceptions}: {0} +unhandled.close.exceptions=Unhandled {1, choice, 0#exception|2#exceptions} from {2}: {0} + variable.already.defined=Variable ''{0}'' is already defined in the scope break.outside.switch.or.loop=Break outside switch or loop continue.outside.loop=Continue outside of loop @@ -212,7 +214,6 @@ duplicate.default.switch.label=Duplicate default label duplicate.switch.label=Duplicate label ''{0}'' switch.colon.expected.after.case.label=':' expected -#See JLS 8.3.2.3 illegal.forward.reference=Illegal forward reference unknown.class=Unknown class: ''{0}'' From 766b4e473936b18739890cf2eba41c71d89fe00f Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 22 Feb 2011 21:03:35 +0100 Subject: [PATCH 115/169] fix NPE --- .../errorhandling/TryWithIdenticalCatchesInspection.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TryWithIdenticalCatchesInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TryWithIdenticalCatchesInspection.java index 574eb4d1320e..ad19aaa6dae0 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TryWithIdenticalCatchesInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TryWithIdenticalCatchesInspection.java @@ -84,11 +84,14 @@ public class TryWithIdenticalCatchesInspection extends BaseInspection { boolean[] duplicates = new boolean[catchSections.length]; for (int i = 0; i < catchSections.length; i++) { if (duplicates[i]) continue; - InputVariables inputVariables = new InputVariables(Collections.singletonList(catchSections[i].getParameter()), + final PsiCatchSection catchSection = catchSections[i]; + final PsiCodeBlock catchBlock = catchSection.getCatchBlock(); + if (catchBlock == null) continue; + InputVariables inputVariables = new InputVariables(Collections.singletonList(catchSection.getParameter()), statement.getProject(), - new LocalSearchScope(catchSections[i].getCatchBlock()), + new LocalSearchScope(catchBlock), false); - DuplicatesFinder finder = new DuplicatesFinder(new PsiElement[] { catchSections [i].getCatchBlock() }, + DuplicatesFinder finder = new DuplicatesFinder(new PsiElement[] {catchBlock}, inputVariables, null, Collections.emptyList()); for (int j = 0; j < catchSections.length; j++) { if (i == j || duplicates[j]) continue; From 02cf4dca65959f3bc19f9cf2ac6a0fe3741e8c97 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 22 Feb 2011 22:59:26 +0100 Subject: [PATCH 116/169] IDEA-65788 (false positive for disjunction type in "'if' replaceable with 'switch'" inspection) --- .../TooBroadCatchInspection.java | 78 ++++++++++++------- 1 file changed, 52 insertions(+), 26 deletions(-) diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TooBroadCatchInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TooBroadCatchInspection.java index 4056e04fd021..c66abe60aecd 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TooBroadCatchInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TooBroadCatchInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2010 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2011 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package com.siyeh.ig.errorhandling; import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ScrollType; @@ -30,14 +31,10 @@ import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.InspectionGadgetsFix; import com.siyeh.ig.psiutils.ExceptionUtils; -import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; import org.jetbrains.annotations.NotNull; -import javax.swing.JComponent; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import javax.swing.*; +import java.util.*; public class TooBroadCatchInspection extends BaseInspection { @@ -204,29 +201,58 @@ public class TooBroadCatchInspection extends BaseInspection { continue; } final PsiType typeCaught = parameter.getType(); - if (exceptionsThrown.contains(typeCaught)) { - exceptionsCaught.add(typeCaught); - } - final List typesMasked = new ArrayList(); - for (PsiType typeThrown : exceptionsThrown) { - if (!exceptionsCaught.contains(typeThrown) && - typeCaught.isAssignableFrom(typeThrown)) { - exceptionsCaught.add(typeThrown); - typesMasked.add(typeThrown); + if (typeCaught instanceof PsiDisjunctionType) { + final PsiDisjunctionType disjunctionType = + (PsiDisjunctionType) typeCaught; + final List types = + disjunctionType.getDisjunctions(); + for (PsiType type : types) { + final List maskedExceptions = + findMaskedExceptions(exceptionsThrown, + exceptionsCaught, type); + if (!maskedExceptions.isEmpty()) { + final PsiTypeElement typeElement = + parameter.getTypeElement(); + registerError(typeElement, maskedExceptions, + statement, catchSection); + } + } + } else { + final List maskedExceptions = + findMaskedExceptions(exceptionsThrown, + exceptionsCaught, typeCaught); + if (!maskedExceptions.isEmpty()) { + final PsiTypeElement typeElement = + parameter.getTypeElement(); + registerError(typeElement, maskedExceptions, statement, + catchSection); } } - if (onlyWarnOnRootExceptions) { - if (!ExceptionUtils.isGenericExceptionClass(typeCaught)) { - continue; - } - } - if (!typesMasked.isEmpty()) { - final PsiTypeElement typeElement = - parameter.getTypeElement(); - registerError(typeElement, typesMasked, statement, - catchSection); + + } + } + + private List findMaskedExceptions( + Set exceptionsThrown, + Set exceptionsCaught, PsiType typeCaught) { + if (exceptionsThrown.contains(typeCaught)) { + exceptionsCaught.add(typeCaught); + exceptionsThrown.remove(typeCaught); + } + final List typesMasked = new ArrayList(); + for (PsiType typeThrown : exceptionsThrown) { + if (!exceptionsCaught.contains(typeThrown) && + typeCaught.isAssignableFrom(typeThrown)) { + exceptionsCaught.add(typeThrown); + typesMasked.add(typeThrown); } } + if (onlyWarnOnRootExceptions) { + if (!ExceptionUtils.isGenericExceptionClass(typeCaught)) { + return Collections.EMPTY_LIST; + } + } + return typesMasked; } } } \ No newline at end of file From 24a7091035a32ae435fd52d603b4ef89bb27a069 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 22 Feb 2011 22:59:36 +0100 Subject: [PATCH 117/169] fix test --- .../siyeh/igtest/errorhandling/toobroadcatch/expected.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/toobroadcatch/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/toobroadcatch/expected.xml index 55b425d76f7b..b93f86c4aaad 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/toobroadcatch/expected.xml +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/toobroadcatch/expected.xml @@ -5,27 +5,27 @@ TooBroadCatchBlock.java 18 Overly broad 'catch' block - Catch of <code>IOException</code> is too broad, masking exception 'EOFException' #loc + ''catch'' of <code>IOException</code> is too broad, masking exception 'EOFException' #loc TooBroadCatchBlock.java 31 Overly broad 'catch' block - Catch of <code>IOException</code> is too broad, masking exception 'MalformedURLException' #loc + ''catch'' of <code>IOException</code> is too broad, masking exception 'MalformedURLException' #loc TooBroadCatchBlock.java 33 Overly broad 'catch' block - Catch of <code>RuntimeException</code> is too broad, masking exception 'NullPointerException' #loc + ''catch'' of <code>RuntimeException</code> is too broad, masking exception 'NullPointerException' #loc TooBroadCatchBlock.java 49 Overly broad 'catch' block - Catch of <code>ObjectStreamException</code> is too broad, masking exceptions 'NotActiveException' and 'StreamCorruptedException' #loc + ''catch'' of <code>ObjectStreamException</code> is too broad, masking exceptions 'NotActiveException' and 'StreamCorruptedException' #loc \ No newline at end of file From 82bc2bcb038c1f7b7c347192ea8ea4f4d2cbdc21 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 22 Feb 2011 22:59:54 +0100 Subject: [PATCH 118/169] minor wording --- .../src/com/siyeh/InspectionGadgetsBundle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties index 452fcd5e459c..19b949b8de96 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties @@ -1802,8 +1802,8 @@ assertequals.called.on.arrays.display.name='assertEquals()' called on array assertequals.called.on.arrays.problem.descriptor=#ref() called on array #loc assertequals.called.on.arrays.quickfix=Replace with 'assertArrayEquals()' overly.broad.throws.clause.display.name=Overly broad 'throws' clause -overly.broad.throws.clause.problem.descriptor1=Throws of #ref is too broad, masking exception ''{0}'' #loc -overly.broad.throws.clause.problem.descriptor2=Throws of #ref is too broad, masking exceptions ''{0}'' and ''{1}'' #loc +overly.broad.throws.clause.problem.descriptor1=throws #ref is too broad, masking exception ''{0}'' #loc +overly.broad.throws.clause.problem.descriptor2=throws #ref is too broad, masking exceptions ''{0}'' and ''{1}'' #loc overly.broad.throws.clause.quickfix1=Add specific exceptions overly.broad.throws.clause.quickfix2=Replace with specific exceptions unnecessarily.qualified.statically.imported.element.display.name=Unnecessarily qualified statically imported element From aa65664d6329f06af60dad2d995057c72026dba9 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 22 Feb 2011 19:58:20 +0100 Subject: [PATCH 119/169] cleanup --- .../completion/JavaCompletionUtil.java | 30 +++---------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java index 69bfd73409fe..a9eb9b56f2ae 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -105,23 +105,15 @@ public class JavaCompletionUtil { public static Set getExpectedTypes(final CompletionParameters parameters) { final PsiExpression expr = PsiTreeUtil.getContextOfType(parameters.getPosition(), PsiExpression.class, true); if (expr != null) { - final ExpectedTypeInfo[] expectedInfos = JavaSmartCompletionContributor.getExpectedTypes(parameters); - if(expectedInfos != null){ - final Set set = new THashSet(); - for (final ExpectedTypeInfo expectedInfo : expectedInfos) { - set.add(expectedInfo.getType()); - } - return set; + final Set set = new THashSet(); + for (final ExpectedTypeInfo expectedInfo : JavaSmartCompletionContributor.getExpectedTypes(parameters)) { + set.add(expectedInfo.getType()); } + return set; } return null; } - static final NullableLazyKey POSITION_METHOD = NullableLazyKey.create("positionMethod", new NullableFunction() { - public PsiMethod fun(final CompletionLocation location) { - return PsiTreeUtil.getParentOfType(location.getCompletionParameters().getPosition(), PsiMethod.class, false); - } - }); public static final Key> ALL_METHODS_ATTRIBUTE = Key.create("allMethods"); public static PsiType getQualifierType(LookupItem item) { @@ -323,26 +315,12 @@ public class JavaCompletionUtil { final PsiReference reference = file.findReferenceAt(selectionEndOffset); if(reference != null) { - /* - if(reference instanceof PsiJavaCodeReferenceElement){ - offsetMap.addOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET, element.getParent().getTextRange().getEndOffset()); - } - else{ - } - */ offsetMap.addOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET, reference.getElement().getTextRange().getStartOffset() + reference.getRangeInElement().getEndOffset()); element = file.findElementAt(offsetMap.getOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET)); } else if (isWord(element)){ - /* - if(element instanceof PsiIdentifier && element.getParent() instanceof PsiJavaCodeReferenceElement){ - offsetMap.addOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET, element.getParent().getTextRange().getEndOffset()); - } - else{ - } - */ offsetMap.addOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET, element.getTextRange().getEndOffset()); element = file.findElementAt(offsetMap.getOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET)); From c13f0636c2d6185d1b3802279082bf1d6ce4d5e6 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 22 Feb 2011 20:31:50 +0100 Subject: [PATCH 120/169] IDEA-58556 Make smart completion cast insertion aware of autoboxing --- .../completion/SmartCastProvider.java | 126 ++++++++++++------ .../smartType/CastAutoboxing-out.java | 8 ++ .../completion/smartType/CastAutoboxing.java | 8 ++ .../smartType/CastAutoboxing2-out.java | 8 ++ .../completion/smartType/CastAutoboxing2.java | 8 ++ .../smartType/CastAutoboxing3-out.java | 8 ++ .../completion/smartType/CastAutoboxing3.java | 8 ++ .../completion/SmartTypeCompletionTest.java | 4 + 8 files changed, 135 insertions(+), 43 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing2-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing2.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing3-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing3.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/SmartCastProvider.java b/java/java-impl/src/com/intellij/codeInsight/completion/SmartCastProvider.java index ce4ed9e3f2e6..7f719e60962a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/SmartCastProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/SmartCastProvider.java @@ -8,7 +8,6 @@ import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ScrollType; -import com.intellij.openapi.util.Key; import com.intellij.patterns.PlatformPatterns; import com.intellij.patterns.PsiElementPattern; import com.intellij.psi.*; @@ -16,9 +15,11 @@ import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.impl.source.PostprocessReformattingAspect; +import com.intellij.psi.impl.source.tree.java.PsiEmptyExpressionImpl; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.ProcessingContext; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author peter @@ -27,7 +28,6 @@ class SmartCastProvider extends CompletionProvider { static final PsiElementPattern.Capture INSIDE_TYPECAST_TYPE = PlatformPatterns.psiElement().afterLeaf( PlatformPatterns.psiElement().withText("(").withParent( PsiTypeCastExpression.class)); - public static final Key TYPE_CAST = Key.create("TYPE_CAST"); protected void addCompletions(@NotNull final CompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result) { for (final ExpectedTypeInfo type : JavaSmartCompletionContributor.getExpectedTypes(parameters)) { @@ -35,50 +35,90 @@ class SmartCastProvider extends CompletionProvider { continue; } - final boolean overwrite = INSIDE_TYPECAST_TYPE.accepts(parameters.getOriginalPosition()); + final PsiElement originalPosition = parameters.getOriginalPosition(); + final boolean overwrite = INSIDE_TYPECAST_TYPE.accepts(originalPosition); - final LookupElement item = AutoCompletionPolicy.ALWAYS_AUTOCOMPLETE.applyPolicy(new LookupElementDecorator( - PsiTypeLookupItem.createLookupItem(type.getDefaultType(), parameters.getPosition())) { - - @Override - public void handleInsert(InsertionContext context) { - FeatureUsageTracker.getInstance().triggerFeatureUsed("editing.completion.smarttype.casting"); - - final Editor editor = context.getEditor(); - final Document document = editor.getDocument(); - if (overwrite) { - document.deleteString(context.getSelectionEndOffset(), - context.getOffsetMap().getOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET)); + final PsiType defaultType = type.getDefaultType(); + result.addElement(createSmartCastElement(parameters, overwrite, defaultType)); + if (defaultType instanceof PsiPrimitiveType) { + final PsiType type1 = getCastedExpressionType(originalPosition); + if (type1 != null && !(type1 instanceof PsiPrimitiveType)) { + final PsiClassType boxedType = ((PsiPrimitiveType)defaultType).getBoxedType(originalPosition); + if (boxedType != null) { + result.addElement(createSmartCastElement(parameters, overwrite, boxedType)); } - - final CodeStyleSettings csSettings = CodeStyleSettingsManager.getSettings(context.getProject()); - final int oldTail = context.getTailOffset(); - context.setTailOffset(RParenthTailType.addRParenth(editor, oldTail, csSettings.SPACE_WITHIN_CAST_PARENTHESES)); - - //todo let the delegate handle insertion itself - final LookupItem typeItem = getDelegate(); - final InsertionContext typeContext = CompletionUtil.newContext(context, typeItem, context.getStartOffset(), oldTail); - new DefaultInsertHandler().handleInsert(typeContext, typeItem); - final PsiTypeCastExpression castExpression = - PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiTypeCastExpression.class, false); - if (castExpression != null) { - final PsiTypeElement typeElement = castExpression.getCastType(); - if (typeElement != null) { - CodeStyleManager.getInstance(context.getProject()).reformat(typeElement); - } - } - - PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting(); - if (csSettings.SPACE_AFTER_TYPE_CAST) { - context.setTailOffset(TailType.insertChar(editor, context.getTailOffset(), ' ')); - } - - editor.getCaretModel().moveToOffset(context.getTailOffset()); - editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); } - }); - item.putUserData(TYPE_CAST, Boolean.TRUE); - result.addElement(item); + } } } + + @Nullable + private static PsiType getCastedExpressionType(PsiElement originalPosition) { + if (INSIDE_TYPECAST_TYPE.accepts(originalPosition)) { + final PsiTypeCastExpression cast = PsiTreeUtil.getParentOfType(originalPosition, PsiTypeCastExpression.class); + if (cast != null) { + final PsiExpression operand = cast.getOperand(); + return operand == null ? null : operand.getType(); + } + } + final PsiParenthesizedExpression parens = PsiTreeUtil.getParentOfType(originalPosition, PsiParenthesizedExpression.class, true, PsiStatement.class); + if (parens != null) { + final PsiExpression rightSide = parens.getExpression(); + if (rightSide != null) { + return rightSide.getType(); + } + PsiElement next = parens.getNextSibling(); + while (next != null && (next instanceof PsiEmptyExpressionImpl || next instanceof PsiErrorElement || next instanceof PsiWhiteSpace)) { + next = next.getNextSibling(); + } + if (next instanceof PsiExpression) { + return ((PsiExpression)next).getType(); + } + return null; + } + return null; + } + + private static LookupElement createSmartCastElement(final CompletionParameters parameters, final boolean overwrite, final PsiType type) { + return AutoCompletionPolicy.ALWAYS_AUTOCOMPLETE.applyPolicy(new LookupElementDecorator( + PsiTypeLookupItem.createLookupItem(type, parameters.getPosition())) { + + @Override + public void handleInsert(InsertionContext context) { + FeatureUsageTracker.getInstance().triggerFeatureUsed("editing.completion.smarttype.casting"); + + final Editor editor = context.getEditor(); + final Document document = editor.getDocument(); + if (overwrite) { + document.deleteString(context.getSelectionEndOffset(), + context.getOffsetMap().getOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET)); + } + + final CodeStyleSettings csSettings = CodeStyleSettingsManager.getSettings(context.getProject()); + final int oldTail = context.getTailOffset(); + context.setTailOffset(RParenthTailType.addRParenth(editor, oldTail, csSettings.SPACE_WITHIN_CAST_PARENTHESES)); + + //todo let the delegate handle insertion itself + final LookupItem typeItem = getDelegate(); + final InsertionContext typeContext = CompletionUtil.newContext(context, typeItem, context.getStartOffset(), oldTail); + new DefaultInsertHandler().handleInsert(typeContext, typeItem); + final PsiTypeCastExpression castExpression = + PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiTypeCastExpression.class, false); + if (castExpression != null) { + final PsiTypeElement typeElement = castExpression.getCastType(); + if (typeElement != null) { + CodeStyleManager.getInstance(context.getProject()).reformat(typeElement); + } + } + + PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting(); + if (csSettings.SPACE_AFTER_TYPE_CAST) { + context.setTailOffset(TailType.insertChar(editor, context.getTailOffset(), ' ')); + } + + editor.getCaretModel().moveToOffset(context.getTailOffset()); + editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); + } + }); + } } diff --git a/java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing-out.java b/java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing-out.java new file mode 100644 index 000000000000..bbf0f76d3cf6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing-out.java @@ -0,0 +1,8 @@ +class A { + public abstract void zoo(int y); + + { + Object x; + zoo((Integer) x); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing.java b/java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing.java new file mode 100644 index 000000000000..661b6ea0de2d --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing.java @@ -0,0 +1,8 @@ +class A { + public abstract void zoo(int y); + + { + Object x; + zoo((x); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing2-out.java b/java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing2-out.java new file mode 100644 index 000000000000..bbf0f76d3cf6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing2-out.java @@ -0,0 +1,8 @@ +class A { + public abstract void zoo(int y); + + { + Object x; + zoo((Integer) x); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing2.java b/java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing2.java new file mode 100644 index 000000000000..fede6af603c5 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing2.java @@ -0,0 +1,8 @@ +class A { + public abstract void zoo(int y); + + { + Object x; + zoo(() x); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing3-out.java b/java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing3-out.java new file mode 100644 index 000000000000..bbf0f76d3cf6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing3-out.java @@ -0,0 +1,8 @@ +class A { + public abstract void zoo(int y); + + { + Object x; + zoo((Integer) x); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing3.java b/java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing3.java new file mode 100644 index 000000000000..4df5d6ae846f --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/CastAutoboxing3.java @@ -0,0 +1,8 @@ +class A { + public abstract void zoo(int y); + + { + Object x; + zoo((a) x); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java index 7150b0a3630c..0f694ed93607 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java @@ -431,6 +431,10 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase { public void testPrivateOverloads() throws Throwable { doTest(); } + public void testCastAutoboxing() throws Throwable { doActionItemTest(); } + public void testCastAutoboxing2() throws Throwable { doActionItemTest(); } + public void testCastAutoboxing3() throws Throwable { doActionItemTest(); } + public void testNoFieldsInSuperConstructorCall() throws Throwable { doTest(); } public void testNoUninitializedFieldsInConstructor() throws Throwable { doTest(); } public void testFieldsSetInAnotherConstructor() throws Throwable { doTest(); } From d07de05c103dae065a8f1e6e25475a45747a141d Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 22 Feb 2011 20:46:37 +0100 Subject: [PATCH 121/169] IDEA-57487 Smart completion in cast operator inserts ill-formed type --- .../completion/SmartCastProvider.java | 26 +++++++++++-------- .../smartType/CastWildcards-out.java | 6 +++++ .../completion/smartType/CastWildcards.java | 6 +++++ .../completion/SmartTypeCompletionTest.java | 1 + 4 files changed, 28 insertions(+), 11 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/CastWildcards-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/CastWildcards.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/SmartCastProvider.java b/java/java-impl/src/com/intellij/codeInsight/completion/SmartCastProvider.java index 7f719e60962a..3b27d56ae50a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/SmartCastProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/SmartCastProvider.java @@ -30,20 +30,24 @@ class SmartCastProvider extends CompletionProvider { PsiTypeCastExpression.class)); protected void addCompletions(@NotNull final CompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result) { - for (final ExpectedTypeInfo type : JavaSmartCompletionContributor.getExpectedTypes(parameters)) { - if (type.getType() == PsiType.VOID) { - continue; - } - + for (final ExpectedTypeInfo info : JavaSmartCompletionContributor.getExpectedTypes(parameters)) { final PsiElement originalPosition = parameters.getOriginalPosition(); final boolean overwrite = INSIDE_TYPECAST_TYPE.accepts(originalPosition); - final PsiType defaultType = type.getDefaultType(); - result.addElement(createSmartCastElement(parameters, overwrite, defaultType)); - if (defaultType instanceof PsiPrimitiveType) { - final PsiType type1 = getCastedExpressionType(originalPosition); - if (type1 != null && !(type1 instanceof PsiPrimitiveType)) { - final PsiClassType boxedType = ((PsiPrimitiveType)defaultType).getBoxedType(originalPosition); + PsiType type = info.getDefaultType(); + if (type instanceof PsiWildcardType) { + type = ((PsiWildcardType)type).getBound(); + } + + if (type == null || type == PsiType.VOID) { + continue; + } + + result.addElement(createSmartCastElement(parameters, overwrite, type)); + if (type instanceof PsiPrimitiveType) { + final PsiType castedType = getCastedExpressionType(originalPosition); + if (castedType != null && !(castedType instanceof PsiPrimitiveType)) { + final PsiClassType boxedType = ((PsiPrimitiveType)type).getBoxedType(originalPosition); if (boxedType != null) { result.addElement(createSmartCastElement(parameters, overwrite, boxedType)); } diff --git a/java/java-tests/testData/codeInsight/completion/smartType/CastWildcards-out.java b/java/java-tests/testData/codeInsight/completion/smartType/CastWildcards-out.java new file mode 100644 index 000000000000..307a275283ee --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/CastWildcards-out.java @@ -0,0 +1,6 @@ +abstract class A { + void foo(T x){} + void bar(A a, Object b){ + a.foo((Throwable) b); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/CastWildcards.java b/java/java-tests/testData/codeInsight/completion/smartType/CastWildcards.java new file mode 100644 index 000000000000..0570efc3184c --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/CastWildcards.java @@ -0,0 +1,6 @@ +abstract class A { + void foo(T x){} + void bar(A a, Object b){ + a.foo(() b); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java index 0f694ed93607..9e01d852bdda 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java @@ -434,6 +434,7 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase { public void testCastAutoboxing() throws Throwable { doActionItemTest(); } public void testCastAutoboxing2() throws Throwable { doActionItemTest(); } public void testCastAutoboxing3() throws Throwable { doActionItemTest(); } + public void testCastWildcards() throws Throwable { doTest(); } public void testNoFieldsInSuperConstructorCall() throws Throwable { doTest(); } public void testNoUninitializedFieldsInConstructor() throws Throwable { doTest(); } From 5d9f4ef818a5323b793e8c02f28318d5b2eedcc5 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 23 Feb 2011 11:32:36 +0100 Subject: [PATCH 122/169] IDEA-50092 Code completion added unnecessary type arguments --- .../codeInsight/completion/JavaMethodCallElement.java | 6 ++++++ .../smartType/NoSecondMethodTypeArguments-out.java | 9 +++++++++ .../smartType/NoSecondMethodTypeArguments.java | 9 +++++++++ .../codeInsight/completion/SmartTypeCompletionTest.java | 2 ++ 4 files changed, 26 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/NoSecondMethodTypeArguments-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/NoSecondMethodTypeArguments.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java index d91b3aba7e2b..e75b14747528 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java @@ -141,6 +141,12 @@ public class JavaMethodCallElement extends LookupItem implements Type return false; } } + if (leaf != null) { + final PsiElement parent = leaf.getParent(); + if (parent instanceof PsiReferenceExpression && ((PsiReferenceExpression)parent).getTypeParameters().length > 0) { + return false; + } + } return SmartCompletionDecorator.hasUnboundTypeParams(getObject()); } diff --git a/java/java-tests/testData/codeInsight/completion/smartType/NoSecondMethodTypeArguments-out.java b/java/java-tests/testData/codeInsight/completion/smartType/NoSecondMethodTypeArguments-out.java new file mode 100644 index 000000000000..ffd936e30b6f --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/NoSecondMethodTypeArguments-out.java @@ -0,0 +1,9 @@ +import java.util.Collections; +import java.util.List; + +class A { + void foo(List x){} + { + foo(Collections.emptyList()); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/NoSecondMethodTypeArguments.java b/java/java-tests/testData/codeInsight/completion/smartType/NoSecondMethodTypeArguments.java new file mode 100644 index 000000000000..d81ea0d791b3 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/NoSecondMethodTypeArguments.java @@ -0,0 +1,9 @@ +import java.util.Collections; +import java.util.List; + +class A { + void foo(List x){} + { + foo(Collections.emptyList()); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java index 9e01d852bdda..b9c898483889 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java @@ -436,6 +436,8 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase { public void testCastAutoboxing3() throws Throwable { doActionItemTest(); } public void testCastWildcards() throws Throwable { doTest(); } + public void testNoSecondMethodTypeArguments() throws Throwable { doTest(Lookup.REPLACE_SELECT_CHAR); } + public void testNoFieldsInSuperConstructorCall() throws Throwable { doTest(); } public void testNoUninitializedFieldsInConstructor() throws Throwable { doTest(); } public void testFieldsSetInAnotherConstructor() throws Throwable { doTest(); } From 53fbb28fda52e9b44ed9f3bdb1f1caff5eb35884 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 22 Feb 2011 18:22:35 +0100 Subject: [PATCH 123/169] enable documentation for directories according to containing files (IDEA-65679 ) --- .../javadoc/JavaDocInfoGenerator.java | 5 +++++ .../com/intellij/lang/LanguageDocumentation.java | 1 + .../documentation/DocumentationManager.java | 16 +++++++++++++--- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java index 4e2a522d17d1..b930439cecfd 100644 --- a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java +++ b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java @@ -221,6 +221,11 @@ public class JavaDocInfoGenerator { else if (myElement instanceof PsiVariable) { generateVariableJavaDoc(buffer, (PsiVariable)myElement); } + else if (myElement instanceof PsiDirectory) { + final PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage((PsiDirectory)myElement); + if (aPackage == null) return null; + generatePackageJavaDoc(buffer, aPackage); + } else if (myElement instanceof PsiPackage) { generatePackageJavaDoc(buffer, (PsiPackage) myElement); } else { diff --git a/platform/lang-api/src/com/intellij/lang/LanguageDocumentation.java b/platform/lang-api/src/com/intellij/lang/LanguageDocumentation.java index ddd0c5cca6f0..130a63b34452 100644 --- a/platform/lang-api/src/com/intellij/lang/LanguageDocumentation.java +++ b/platform/lang-api/src/com/intellij/lang/LanguageDocumentation.java @@ -21,6 +21,7 @@ package com.intellij.lang; import com.intellij.lang.documentation.CompositeDocumentationProvider; import com.intellij.lang.documentation.DocumentationProvider; +import org.jetbrains.annotations.NonNls; import java.util.List; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java index 9e2dd837d3d8..8606406f6a06 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java @@ -43,6 +43,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.OrderEntry; @@ -78,10 +79,8 @@ import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.lang.ref.WeakReference; -import java.util.Collections; -import java.util.LinkedHashSet; +import java.util.*; import java.util.List; -import java.util.Set; public class DocumentationManager { private static final Logger LOG = Logger.getInstance("#" + DocumentationManager.class.getName()); @@ -802,6 +801,17 @@ public class DocumentationManager { result.add(LanguageDocumentation.INSTANCE.forLanguage(baseLanguage)); } } + else if (element instanceof PsiDirectory) { + final Set langs = new HashSet(); + + for (PsiFile file : ((PsiDirectory)element).getFiles()) { + final Language baseLanguage = file.getViewProvider().getBaseLanguage(); + if (!langs.contains(baseLanguage)) { + langs.add(baseLanguage); + result.add(LanguageDocumentation.INSTANCE.forLanguage(baseLanguage)); + } + } + } return CompositeDocumentationProvider.wrapProviders(result); } From 33f885c2044ea16be955ff2b8847c1f5c66db557 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 23 Feb 2011 12:23:51 +0100 Subject: [PATCH 124/169] preserve selection during inline rename/ refixed --- .../codeInsight/template/Template.java | 2 -- .../template/impl/TemplateImpl.java | 9 ------- .../template/impl/TemplateState.java | 8 ++---- .../inplace/VariableInplaceRenamer.java | 25 ++++++++----------- 4 files changed, 13 insertions(+), 31 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/Template.java b/platform/lang-impl/src/com/intellij/codeInsight/template/Template.java index 5fa3924895d0..43dba460aa10 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/Template.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/Template.java @@ -66,6 +66,4 @@ public abstract class Template { public abstract boolean isToShortenLongNames(); public abstract void setToShortenLongNames(boolean toShortenLongNames); - - public abstract void setSubSelection(RangeMarker selection); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateImpl.java index 3d06dcf57232..ce7303c93d7d 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateImpl.java @@ -42,7 +42,6 @@ public class TemplateImpl extends Template implements SchemeElement { private ArrayList mySegments = null; private String myTemplateText = null; private String myId; - private RangeMarker mySubSelection; public boolean equals(Object o) { if (this == o) return true; @@ -452,14 +451,6 @@ public class TemplateImpl extends Template implements SchemeElement { return myVariables.get(i).skipOnStart(); } - public RangeMarker getSubSelection() { - return mySubSelection; - } - - public void setSubSelection(RangeMarker selection) { - mySubSelection = selection; - } - private static class Segment { public String name; public int offset; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java index 50df33f95cc0..7457d7e91936 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java @@ -459,12 +459,8 @@ public class TemplateState implements Disposable { myEditor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); myEditor.getSelectionModel().removeSelection(); - final RangeMarker selection = myTemplate.getSubSelection(); - if (selection != null && selection.getStartOffset() >= start && selection.getEndOffset() <= end) { - myEditor.getSelectionModel().setSelection(selection.getStartOffset(), selection.getEndOffset()); - } else { - myEditor.getSelectionModel().setSelection(start, end); - } + + myEditor.getSelectionModel().setSelection(start, end); Expression expressionNode = myTemplate.getExpressionAt(myCurrentVariableNumber); final ExpressionContext context = createExpressionContext(start); diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java index bdae42635a79..6607caac4fcb 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java @@ -185,13 +185,6 @@ public class VariableInplaceRenamer { PsiElement selectedElement = getSelectedInEditorElement(nameIdentifier, refs, offset); if (!CommonRefactoringUtil.checkReadOnlyStatus(myProject, myElementToRename)) return true; - final RangeMarker selection; - final SelectionModel selectionModel = myEditor.getSelectionModel(); - if (selectionModel.hasSelection()) { - selection = myEditor.getDocument().createRangeMarker(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()); - } else { - selection = null; - } if (nameIdentifier != null) addVariable(nameIdentifier, selectedElement, builder, nameSuggestions); for (PsiReference ref : refs) { addVariable(ref, selectedElement, builder, offset, nameSuggestions); @@ -205,9 +198,16 @@ public class VariableInplaceRenamer { ApplicationManager.getApplication().runWriteAction(new Runnable() { public void run() { final int offset = myEditor.getCaretModel().getOffset(); + final SelectionModel selectionModel = myEditor.getSelectionModel(); + final TextRange selectedRange; + if (selectionModel.hasSelection()) { + selectedRange = new TextRange(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()); + } + else { + selectedRange = null; + } Template template = builder.buildInlineTemplate(); template.setToShortenLongNames(false); - template.setSubSelection(selection); TextRange range = scope1.getTextRange(); assert range != null; myHighlighters = new ArrayList(); @@ -240,17 +240,11 @@ public class VariableInplaceRenamer { performAutomaticRename(myNewName, PsiTreeUtil.getParentOfType(containingFile.findElementAt(renameOffset), PsiNameIdentifierOwner.class)); } moveOffsetAfter(true); - if (selection != null) { - selection.dispose(); - } } public void templateCancelled(Template template) { finish(); moveOffsetAfter(false); - if (selection != null) { - selection.dispose(); - } } }); @@ -258,6 +252,9 @@ public class VariableInplaceRenamer { Runnable runnable = new Runnable() { public void run() { myEditor.getCaretModel().moveToOffset(offset); + if (selectedRange != null){ + myEditor.getSelectionModel().setSelection(selectedRange.getStartOffset(), selectedRange.getEndOffset()); + } } }; From 6034b29efd562734c6b275044d322dd24bddb5b7 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Wed, 23 Feb 2011 14:09:50 +0100 Subject: [PATCH 125/169] more verbose assertion --- .../src/com/intellij/psi/impl/source/PsiFileImpl.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java index 8424ea6566e1..9da2d00e02b7 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java @@ -883,7 +883,14 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF if (tree == null) { IElementType contentElementType = getContentElementType(); if (!(contentElementType instanceof IStubFileElementType)) { - LOG.error("ContentElementType: "+contentElementType+"; file: "+this); + final StringBuilder builder = new StringBuilder(); + builder.append("ContentElementType: ").append(contentElementType).append("; file: ").append(this); + builder.append("\n\t").append("Boolean.TRUE.equals(getUserData(BUILDING_STUB)) = ").append(Boolean.TRUE.equals(getUserData(BUILDING_STUB))); + builder.append("\n\t").append("getTreeElementNoLock() = ").append(getTreeElementNoLock()); + final VirtualFile vFile = getVirtualFile(); + builder.append("\n\t").append("vFile instanceof VirtualFileWithId = ").append(vFile instanceof VirtualFileWithId); + builder.append("\n\t").append("StubUpdatingIndex.canHaveStub(vFile) = ").append(StubUpdatingIndex.canHaveStub(vFile)); + LOG.error(builder.toString()); } final StubElement currentStubTree = ((IStubFileElementType)contentElementType).getBuilder().buildStubTree(this); tree = new StubTree((PsiFileStub)currentStubTree); From b09a5bed9ebef6a48e05fd1586b7f3b2cab50cd4 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 23 Feb 2011 12:20:53 +0100 Subject: [PATCH 126/169] IDEA-63641 Eliminate variable itself from autocomplete list --- .../psi/filters/element/ExcludeSillyAssignment.java | 7 ++++++- .../completion/smartType/ThisFieldAssignedToItself.java | 8 ++++++++ .../codeInsight/completion/SmartTypeCompletionTest.java | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/ThisFieldAssignedToItself.java diff --git a/java/java-impl/src/com/intellij/psi/filters/element/ExcludeSillyAssignment.java b/java/java-impl/src/com/intellij/psi/filters/element/ExcludeSillyAssignment.java index a5bb70e4e01b..e999d77684ad 100644 --- a/java/java-impl/src/com/intellij/psi/filters/element/ExcludeSillyAssignment.java +++ b/java/java-impl/src/com/intellij/psi/filters/element/ExcludeSillyAssignment.java @@ -39,7 +39,12 @@ public class ExcludeSillyAssignment implements ElementFilter { final PsiExpression left = ((PsiAssignmentExpression)each).getLExpression(); if (left instanceof PsiReferenceExpression) { final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)left; - if (referenceExpression.isQualified()) return true; + final PsiElement qualifier = referenceExpression.getQualifier(); + if (qualifier != null) { + if (!(qualifier instanceof PsiThisExpression) || ((PsiThisExpression)qualifier).getQualifier() != null) { + return true; + } + } return !referenceExpression.isReferenceTo((PsiElement)element); } diff --git a/java/java-tests/testData/codeInsight/completion/smartType/ThisFieldAssignedToItself.java b/java/java-tests/testData/codeInsight/completion/smartType/ThisFieldAssignedToItself.java new file mode 100644 index 000000000000..93b10fb8f3f8 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/ThisFieldAssignedToItself.java @@ -0,0 +1,8 @@ +class A { + Object field; + + A() { + field = 2; + this.field = fi + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java index b9c898483889..bfa4827e4743 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java @@ -961,6 +961,7 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase { public void testWildcardedInstanceof3() throws Throwable { doTest(); } public void testCheckStaticImportsType() throws Throwable { doAntiTest(); } + public void testThisFieldAssignedToItself() throws Throwable { doAntiTest(); } public void testTypeVariableInstanceOf() throws Throwable { configureByTestName(); From 40c073a07352c93c2ba851fe686aebece54f10fb Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 23 Feb 2011 14:57:04 +0100 Subject: [PATCH 127/169] uninitialized fields should be offered at least when initializing them --- .../scope/JavaCompletionProcessor.java | 91 +++++++++++-------- .../normal/AssigningFieldForTheFirstTime.java | 6 ++ .../AssigningFieldForTheFirstTime_after.java | 6 ++ .../completion/NormalCompletionTest.groovy | 1 + 4 files changed, 67 insertions(+), 37 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/normal/AssigningFieldForTheFirstTime.java create mode 100644 java/java-tests/testData/codeInsight/completion/normal/AssigningFieldForTheFirstTime_after.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java b/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java index e6a8a065789c..b0cd28cf2d2a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java @@ -32,10 +32,7 @@ import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; /** * Created by IntelliJ IDEA. @@ -107,43 +104,63 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme } if (checkInitialized) { - final PsiStatement statement = PsiTreeUtil.getParentOfType(element, PsiStatement.class); - final PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class, true, PsiClass.class); - if (statement != null && method != null && method.isConstructor()) { - final PsiClass containingClass = method.getContainingClass(); - assert containingClass != null; - for (PsiField field : containingClass.getFields()) { - if (!field.hasModifierProperty(PsiModifier.STATIC) && field.getInitializer() == null) { - myNonInitializedFields.add(field); - } - } + myNonInitializedFields.addAll(getNonInitializedFields(element)); + } + } - method.accept(new JavaRecursiveElementWalkingVisitor() { - @Override - public void visitAssignmentExpression(PsiAssignmentExpression expression) { - if (expression.getTextRange().getStartOffset() < statement.getTextRange().getStartOffset()) { - final PsiExpression lExpression = expression.getLExpression(); - if (lExpression instanceof PsiReferenceExpression) { - //noinspection SuspiciousMethodCalls - myNonInitializedFields.remove(((PsiReferenceExpression)lExpression).resolve()); - } - } - super.visitAssignmentExpression(expression); - } + private static Set getNonInitializedFields(PsiElement element) { + final PsiStatement statement = PsiTreeUtil.getParentOfType(element, PsiStatement.class); + final PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class, true, PsiClass.class); + if (statement == null || method == null || !method.isConstructor()) { + return Collections.emptySet(); + } - @Override - public void visitMethodCallExpression(PsiMethodCallExpression expression) { - if (expression.getTextRange().getStartOffset() < statement.getTextRange().getStartOffset()) { - final PsiReferenceExpression methodExpression = expression.getMethodExpression(); - if (methodExpression.textMatches("this")) { - myNonInitializedFields.clear(); - } - } - super.visitMethodCallExpression(expression); - } - }); + PsiElement parent = element.getParent(); + while (parent != statement) { + PsiElement next = parent.getParent(); + if (next instanceof PsiAssignmentExpression && parent == ((PsiAssignmentExpression)next).getLExpression()) { + return Collections.emptySet(); + } + if (parent instanceof PsiReferenceExpression && next instanceof PsiExpressionStatement) { + return Collections.emptySet(); + } + parent = next; + } + + final Set fields = new HashSet(); + final PsiClass containingClass = method.getContainingClass(); + assert containingClass != null; + for (PsiField field : containingClass.getFields()) { + if (!field.hasModifierProperty(PsiModifier.STATIC) && field.getInitializer() == null) { + fields.add(field); } } + + method.accept(new JavaRecursiveElementWalkingVisitor() { + @Override + public void visitAssignmentExpression(PsiAssignmentExpression expression) { + if (expression.getTextRange().getStartOffset() < statement.getTextRange().getStartOffset()) { + final PsiExpression lExpression = expression.getLExpression(); + if (lExpression instanceof PsiReferenceExpression) { + //noinspection SuspiciousMethodCalls + fields.remove(((PsiReferenceExpression)lExpression).resolve()); + } + } + super.visitAssignmentExpression(expression); + } + + @Override + public void visitMethodCallExpression(PsiMethodCallExpression expression) { + if (expression.getTextRange().getStartOffset() < statement.getTextRange().getStartOffset()) { + final PsiReferenceExpression methodExpression = expression.getMethodExpression(); + if (methodExpression.textMatches("this")) { + fields.clear(); + } + } + super.visitMethodCallExpression(expression); + } + }); + return fields; } public void handleEvent(Event event, Object associated){ diff --git a/java/java-tests/testData/codeInsight/completion/normal/AssigningFieldForTheFirstTime.java b/java/java-tests/testData/codeInsight/completion/normal/AssigningFieldForTheFirstTime.java new file mode 100644 index 000000000000..b8530645f6ca --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/AssigningFieldForTheFirstTime.java @@ -0,0 +1,6 @@ +class A { + final boolean aboo; + A() { + abo + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/AssigningFieldForTheFirstTime_after.java b/java/java-tests/testData/codeInsight/completion/normal/AssigningFieldForTheFirstTime_after.java new file mode 100644 index 000000000000..b355e702cafb --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/AssigningFieldForTheFirstTime_after.java @@ -0,0 +1,6 @@ +class A { + final boolean aboo; + A() { + aboo + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index 8bd1531b0948..801e4bc10097 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -371,6 +371,7 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase { } public void testLocalClassName() throws Throwable { doTest(); } + public void testAssigningFieldForTheFirstTime() throws Throwable { doTest(); } public void testClassTypeParameters() throws Throwable { configure() From 725873b3ce2238123edc6f1078099949938a0f01 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 23 Feb 2011 15:12:59 +0100 Subject: [PATCH 128/169] IDEA-65811 "final" variant is not suggested but it should be --- .../codeInsight/completion/JavaCompletionData.java | 9 ++++++++- .../completion/normal/FinalBeforeMethodCall.java | 5 +++++ .../completion/KeywordCompletionTest.java | 13 +++++++++++-- .../completion/NormalCompletionTest.groovy | 5 +++++ 4 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/normal/FinalBeforeMethodCall.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java index 4cebb6f7b19f..16b6c5c2064a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java @@ -557,6 +557,13 @@ public class JavaCompletionData extends JavaAwareCompletionData{ return; } + final PsiExpressionStatement expressionStatement = PsiTreeUtil.getParentOfType(position, PsiExpressionStatement.class); + if (expressionStatement != null && expressionStatement.getTextRange().getStartOffset() == position.getTextRange().getStartOffset()) { + if (!psiElement().withSuperParent(2, PsiSwitchStatement.class).accepts(expressionStatement)) { + result.addElement(createKeyword(position, PsiKeyword.FINAL)); + } + } + if (SUPER_OR_THIS_PATTERN.accepts(position)) { if (AFTER_DOT.accepts(position) && !isInsideQualifierClass(position)) return; @@ -607,7 +614,7 @@ public class JavaCompletionData extends JavaAwareCompletionData{ if (!PsiKeyword.VOID.equals(primitiveType)) { result.addElement(TailTypeDecorator.withTail(createKeyword(position, primitiveType), TailType.SPACE)); } - result.addElement(TailTypeDecorator.withTail(createKeyword(position, PsiKeyword.FINAL), TailType.SPACE)); + //result.addElement(TailTypeDecorator.withTail(createKeyword(position, PsiKeyword.FINAL), TailType.SPACE)); } } diff --git a/java/java-tests/testData/codeInsight/completion/normal/FinalBeforeMethodCall.java b/java/java-tests/testData/codeInsight/completion/normal/FinalBeforeMethodCall.java new file mode 100644 index 000000000000..c28c3b2dc1d6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/FinalBeforeMethodCall.java @@ -0,0 +1,5 @@ +class A { + A() { + finthis.toString(); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/KeywordCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/KeywordCompletionTest.java index fd8258dc7b90..5885f56d7787 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/KeywordCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/KeywordCompletionTest.java @@ -159,8 +159,17 @@ public class KeywordCompletionTest extends LightCompletionTestCase { public void testExtendsInCastTypeParameters() throws Throwable { doTest(); } public void testExtendsWithRightContextInClassTypeParameters() throws Throwable { doTest(); } - public void testExtraBracketAfterFinally() throws Throwable { doTest(); } - public void testExtraBracketAfterFinally1() throws Throwable { doTest(); } + public void testExtraBracketAfterFinally() throws Throwable { + configureByFile(BASE_PATH + "/" + getTestName(false) + ".java"); + selectItem(myItems[1]); + checkResultByFile(BASE_PATH + "/" + getTestName(false) + "-out.java"); + } + + public void testExtraBracketAfterFinally1() throws Throwable { + configureByFile(BASE_PATH + "/" + getTestName(false) + ".java"); + selectItem(myItems[1]); + checkResultByFile(BASE_PATH + "/" + getTestName(false) + "-out.java"); + } public void testTrueInVariableDeclaration() throws Throwable { doTest(); } public void testNullInIf() throws Throwable { doTest(); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index 801e4bc10097..968c25cad396 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -393,6 +393,11 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase { assertOrderedEquals myFixture.lookupElementStrings, 'Zoooz', 'Zooooo' } + public void testFinalBeforeMethodCall() throws Throwable { + configure() + assertStringItems 'final', 'finalize' + } + public void testMethodParenthesesSpaces() throws Throwable { final settings = CodeStyleSettingsManager.getSettings(getProject()) settings.SPACE_BEFORE_METHOD_CALL_PARENTHESES = true From bcb278bf2004b1c0a72b8c8572822d65dd48fd44 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Wed, 23 Feb 2011 17:45:24 +0300 Subject: [PATCH 129/169] also catch all focus events --- .../internal/focus/FocusTracesAction.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/internal/focus/FocusTracesAction.java b/platform/platform-impl/src/com/intellij/internal/focus/FocusTracesAction.java index e90aa6a7b251..07ceb7496142 100644 --- a/platform/platform-impl/src/com/intellij/internal/focus/FocusTracesAction.java +++ b/platform/platform-impl/src/com/intellij/internal/focus/FocusTracesAction.java @@ -25,6 +25,9 @@ import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.impl.FocusManagerImpl; import com.intellij.openapi.wm.impl.FocusRequestInfo; +import java.awt.*; +import java.awt.event.AWTEventListener; +import java.awt.event.FocusEvent; import java.util.ArrayList; import java.util.List; @@ -33,6 +36,7 @@ import java.util.List; */ public class FocusTracesAction extends AnAction implements DumbAware { private static boolean myActive = false; + private AWTEventListener myFocusTracker; public static boolean isActive() { return myActive; @@ -46,10 +50,23 @@ public class FocusTracesAction extends AnAction implements DumbAware { final FocusManagerImpl focusManager = (FocusManagerImpl)manager; myActive = !myActive; + if (myActive) { + myFocusTracker = new AWTEventListener() { + @Override + public void eventDispatched(AWTEvent event) { + if (event instanceof FocusEvent && event.getID() == FocusEvent.FOCUS_GAINED) { + focusManager.getRequests().add(new FocusRequestInfo(((FocusEvent)event).getComponent(), new Throwable(), false)); + } + } + }; + Toolkit.getDefaultToolkit().addAWTEventListener(myFocusTracker, AWTEvent.FOCUS_EVENT_MASK); + } if (!myActive) { final List requests = focusManager.getRequests(); new FocusTracesDialog(project, new ArrayList(requests)).show(); + Toolkit.getDefaultToolkit().removeAWTEventListener(myFocusTracker); + myFocusTracker = null; requests.clear(); } } From c54921559f0c2f83d4d9e160fa857fa576ed1556 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Wed, 23 Feb 2011 17:46:56 +0300 Subject: [PATCH 130/169] selection history --- .../com/intellij/ide/actions/Switcher.java | 62 ++++++++++--------- .../fileEditor/impl/EditorComposite.java | 6 ++ .../openapi/fileEditor/impl/EditorWindow.java | 3 +- .../impl/FileEditorManagerImpl.java | 61 ++++++++++-------- 4 files changed, 76 insertions(+), 56 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index ee52597d0427..af738d0bdfc1 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -31,6 +31,7 @@ import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Iconable; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.vcs.FileStatus; import com.intellij.openapi.vcs.FileStatusManager; import com.intellij.openapi.vfs.VirtualFile; @@ -252,12 +253,15 @@ public class Switcher extends AnAction implements DumbAware { final FileEditorManagerImpl editorManager = (FileEditorManagerImpl)FileEditorManager.getInstance(project); final ArrayList filesData = new ArrayList(); final ArrayList editors = new ArrayList(); - for (EditorsSplitters splitters : editorManager.getAllSplitters()) { - for (EditorWindow window : splitters.getWindows()) { - for (VirtualFile file : window.getFiles()) { - editors.add(new FileEditorInfo(file, window)); - } - } + //for (EditorsSplitters splitters : editorManager.getAllSplitters()) { + // for (EditorWindow window : splitters.getWindows()) { + // for (VirtualFile file : window.getFiles()) { + // editors.add(new FileEditorInfo(file, window)); + // } + // } + //} + for (Pair pair : editorManager.getSelectionHistory()) { + editors.add(new FileEditorInfo(pair.first, pair.second)); } if (editors.size() < 2) { final VirtualFile[] recentFiles = ArrayUtil.reverseArray(EditorHistoryManager.getInstance(project).getFiles()); @@ -266,10 +270,10 @@ public class Switcher extends AnAction implements DumbAware { filesData.add(new FileEditorInfo(recentFiles[i], null)); } } else { - try { - ContainerUtil.sort(editors, new RecentFilesComparator(project)); - } catch (Exception e) {// IndexNotReadyException - } + //try { + // ContainerUtil.sort(editors, new RecentFilesComparator(project)); + //} catch (Exception e) {// IndexNotReadyException + //} for (int i = 0; i < Math.min(MAX_FILES, editors.size()); i++) { filesData.add(editors.get(i)); } @@ -602,25 +606,25 @@ public class Switcher extends AnAction implements DumbAware { } } - private class RecentFilesComparator implements Comparator { - private Map tabs = new HashMap(); - - public RecentFilesComparator(Project project) { - final List history = ((FileEditorManagerImpl)FileEditorManager.getInstance(project)).getTabsHistory(); - for (int i = 0; i < history.size(); i++) { - final TabInfo info = history.get(i); - if (info.getObject() instanceof VirtualFile && info.getComponent() instanceof EditorWindowHolder) { - tabs.put(new FileEditorInfo((VirtualFile)info.getObject(), ((EditorWindowHolder)info.getComponent()).getEditorWindow()), i); - } - } - } - - public int compare(FileEditorInfo vf1, FileEditorInfo vf2) { - final Integer index1 = tabs.get(vf1); - final Integer index2 = tabs.get(vf2); - return index1 == null && index2 == null ? 0 : index1 == null ? 1 : index2 == null ? -1 : index1 - index2; - } - } + //private class RecentFilesComparator implements Comparator { + // private Map tabs = new HashMap(); + // + // public RecentFilesComparator(Project project) { + // final List history = ((FileEditorManagerImpl)FileEditorManager.getInstance(project)).getTabsHistory(); + // for (int i = 0; i < history.size(); i++) { + // final TabInfo info = history.get(i); + // if (info.getObject() instanceof VirtualFile && info.getComponent() instanceof EditorWindowHolder) { + // tabs.put(new FileEditorInfo((VirtualFile)info.getObject(), ((EditorWindowHolder)info.getComponent()).getEditorWindow()), i); + // } + // } + // } + // + // public int compare(FileEditorInfo vf1, FileEditorInfo vf2) { + // final Integer index1 = tabs.get(vf1); + // final Integer index2 = tabs.get(vf2); + // return index1 == null && index2 == null ? 0 : index1 == null ? 1 : index2 == null ? -1 : index1 - index2; + // } + //} public void mouseClicked(MouseEvent e) { final Object source = e.getSource(); diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java index 93302fc94716..8e01d4613be5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java @@ -35,6 +35,7 @@ import com.intellij.ui.PrevNextActionsDescriptor; import com.intellij.ui.SideBorder; import com.intellij.ui.TabbedPaneWrapper; import com.intellij.ui.tabs.UiDecorator; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -236,6 +237,11 @@ public abstract class EditorComposite implements Disposable { publisher.selectionChanged(event); } }); + final JComponent component = newSelectedEditor.getComponent(); + final EditorWindowHolder holder = UIUtil.getParentOfType(EditorWindowHolder.class, component); + if (holder != null) { + ((FileEditorManagerImpl)myFileEditorManager).addSelectionRecord(myFile, holder.getEditorWindow()); + } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java index 2d38e718986d..31856ce03327 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java @@ -138,7 +138,7 @@ public class EditorWindow { beforePublisher.beforeFileClosed(editorManager, file); - if (myTabbedPane != null) { + if (myTabbedPane != null && editor != null) { final int componentIndex = findComponentIndex(editor.getComponent()); if (componentIndex >= 0) { // editor could close itself on decomposition final int indexToSelect = calcIndexToSelect(file, componentIndex); @@ -167,6 +167,7 @@ public class EditorWindow { } } finally { + editorManager.getSelectionHistory().remove(new Pair(file, EditorWindow.this)); final FileEditorManagerListener afterPublisher = editorManager.getProject().getMessageBus().syncPublisher(FileEditorManagerListener.FILE_EDITOR_MANAGER); diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java index d758df4030d3..cd0290d51fce 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java @@ -61,10 +61,10 @@ import com.intellij.openapi.wm.ex.StatusBarEx; import com.intellij.ui.docking.DockContainer; import com.intellij.ui.docking.DockManager; import com.intellij.ui.tabs.TabInfo; -import com.intellij.ui.tabs.TabsListener; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.messages.impl.MessageListenerList; +import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.update.MergingUpdateQueue; import com.intellij.util.ui.update.Update; import org.jdom.Element; @@ -84,7 +84,7 @@ import java.util.List; * @author Eugene Belyaev * @author Vladimir Kondratyev */ -public class FileEditorManagerImpl extends FileEditorManagerEx implements ProjectComponent, JDOMExternalizable, TabsListener { +public class FileEditorManagerImpl extends FileEditorManagerEx implements ProjectComponent, JDOMExternalizable { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl"); private static final Key WATCH_REQUEST_KEY = Key.create("WATCH_REQUEST_KEY"); private static final Key DUMB_AWARE = Key.create("DUMB_AWARE"); @@ -96,6 +96,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec private EditorsSplitters mySplitters; private final Project myProject; private final List myTabsHistory = new ArrayList(); + private final List> mySelectionHistory = new ArrayList>(); private final MergingUpdateQueue myQueue = new MergingUpdateQueue("FileEditorManagerUpdateQueue", 50, true, null); @@ -106,7 +107,6 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec private final MyEditorPropertyChangeListener myEditorPropertyChangeListener = new MyEditorPropertyChangeListener(); private DockManager myDockManager; private DockableEditorContainerFactory myContentFactory; - private MessageBusConnection myBusConnection; public FileEditorManagerImpl(final Project project, DockManager dockManager) { /* ApplicationManager.getApplication().assertIsDispatchThread(); */ @@ -114,8 +114,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec myDockManager = dockManager; myListenerList = new MessageListenerList(myProject.getMessageBus(), FileEditorManagerListener.FILE_EDITOR_MANAGER); - myBusConnection = project.getMessageBus().connect(project); - myBusConnection.subscribe(TabsListener.TOPIC, this); + //myListenerList.add(new EditorSelectionListener()); } private void initDockableContentFactory() { @@ -501,7 +500,9 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec } private void removeHistory(VirtualFile file, EditorWindow window) { - for (Iterator i = myTabsHistory.iterator(); i.hasNext();) { + mySelectionHistory.remove(new Pair(file, window)); + + for (Iterator i = myTabsHistory.iterator(); i.hasNext(); ) { final TabInfo info = i.next(); final JComponent c = info.getComponent(); if (info.getObject() == file && c instanceof EditorWindowHolder && ((EditorWindowHolder)c).getEditorWindow() == window) { @@ -1205,7 +1206,6 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec // Dispose created editors. We do not use use closeEditor method because // it fires event and changes history. closeAllFiles(); - myBusConnection.disconnect(); } // BaseCompomemnt methods @@ -1274,6 +1274,14 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec final FileEditorManagerEvent event = new FileEditorManagerEvent(this, oldSelectedFile, oldSelectedEditor, newSelectedFile, newSelectedEditor); final FileEditorManagerListener publisher = getProject().getMessageBus().syncPublisher(FileEditorManagerListener.FILE_EDITOR_MANAGER); + + if (newSelectedEditor != null) { + final JComponent component = newSelectedEditor.getComponent(); + final EditorWindowHolder holder = UIUtil.getParentOfType(EditorWindowHolder.class, component); + if (holder != null) { + addSelectionRecord(newSelectedFile, holder.getEditorWindow()); + } + } IdeFocusManager.getInstance(myProject).doWhenFocusSettlesDown(new ExpirableRunnable.ForProject(myProject) { @Override public void run() { @@ -1624,25 +1632,26 @@ private final class MyVirtualFileListener extends VirtualFileAdapter { return splitters; } - @Override - public void selectionChanged(TabInfo oldSelection, TabInfo newSelection) { - final JComponent selected = newSelection.getComponent(); - final Iterator i = myTabsHistory.iterator(); - while (i.hasNext()) { - final TabInfo info = i.next(); - if (info.getComponent() == selected) { - i.remove(); - break; - } + public void selectionChanged(VirtualFile file, EditorWindow window) { + final Pair selection = new Pair(file, window); + mySelectionHistory.remove(selection); + mySelectionHistory.add(0, selection); + } + + public List> getSelectionHistory() { + return mySelectionHistory; + } + + public void addSelectionRecord(VirtualFile file, EditorWindow window) { + final Pair record = new Pair(file, window); + mySelectionHistory.remove(record); + mySelectionHistory.add(0, record); + } + + private class EditorSelectionListener extends FileEditorManagerAdapter { + @Override + public void selectionChanged(FileEditorManagerEvent event) { + System.out.println(event.getNewFile().getName()); } - myTabsHistory.add(0, newSelection); - } - - public List getTabsHistory() { - return myTabsHistory; - } - - @Override - public void beforeSelectionChanged(TabInfo oldSelection, TabInfo newSelection) { } } From ac3ebd37798dbfcf0f363844287594b4b0007a0f Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 23 Feb 2011 15:39:37 +0100 Subject: [PATCH 131/169] UI: GridBag class --- .../com/intellij/ui/components/JBLabel.java | 73 ++++ .../src/com/intellij/util/ui/GridBag.java | 387 ++++++++++++++++++ 2 files changed, 460 insertions(+) create mode 100644 platform/platform-api/src/com/intellij/ui/components/JBLabel.java create mode 100644 platform/util/src/com/intellij/util/ui/GridBag.java diff --git a/platform/platform-api/src/com/intellij/ui/components/JBLabel.java b/platform/platform-api/src/com/intellij/ui/components/JBLabel.java new file mode 100644 index 000000000000..d32c775ef9a1 --- /dev/null +++ b/platform/platform-api/src/com/intellij/ui/components/JBLabel.java @@ -0,0 +1,73 @@ +/* + * Copyright 2000-2011 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 com.intellij.ui.components; + +import com.intellij.openapi.util.SystemInfo; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +public class JBLabel extends JLabel { + private Style myStyle = Style.REGULAR; + + public enum Style {REGULAR, SMALL} + + public JBLabel() { + } + + public JBLabel(@NotNull Style style) { + setStyle(style); + } + + public JBLabel(@Nullable Icon image) { + super(image); + } + + public JBLabel(@NotNull String text) { + super(text); + } + + public JBLabel(@NotNull String text, @NotNull Style style) { + super(text); + setStyle(style); + } + + public JBLabel(@NotNull String text, int horizontalAlignment) { + super(text, horizontalAlignment); + } + + public JBLabel(@Nullable Icon image, int horizontalAlignment) { + super(image, horizontalAlignment); + } + + public JBLabel(@NotNull String text, @Nullable Icon icon, int horizontalAlignment) { + super(text, icon, horizontalAlignment); + } + + public void setStyle(@NotNull Style style) { + myStyle = style; + + if (SystemInfo.isMac) { + putClientProperty("JComponent.sizeVariant", style == Style.REGULAR ? "regular" : "small"); + } + // todo support other systems + } + + public Style getStyle() { + return myStyle; + } +} diff --git a/platform/util/src/com/intellij/util/ui/GridBag.java b/platform/util/src/com/intellij/util/ui/GridBag.java new file mode 100644 index 000000000000..894758668336 --- /dev/null +++ b/platform/util/src/com/intellij/util/ui/GridBag.java @@ -0,0 +1,387 @@ +/* + * Copyright 2000-2011 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 com.intellij.util.ui; + +import gnu.trove.TIntDoubleHashMap; +import gnu.trove.TIntIntHashMap; +import gnu.trove.TIntObjectHashMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.awt.*; + +@SuppressWarnings({"JavaDoc"}) +public class GridBag extends GridBagConstraints { + private int myDefaultAnchor = anchor; + @NotNull private final TIntIntHashMap myDefaultColumnAnchors = new TIntIntHashMap(); + + private int myDefaultFill = fill; + @NotNull private final TIntIntHashMap myDefaultColumnFills = new TIntIntHashMap(); + + private double myDefaultWeightX = weightx; + @NotNull private final TIntDoubleHashMap myDefaultColumnWeightsX = new TIntDoubleHashMap(); + private double myDefaultWeightY = weighty; + @NotNull private final TIntDoubleHashMap myDefaultColumnWeightsY = new TIntDoubleHashMap(); + + private int myDefaultPaddingX = ipadx; + @NotNull private final TIntIntHashMap myDefaultColumnPaddingsX = new TIntIntHashMap(); + private int myDefaultPaddingY = ipady; + @NotNull private final TIntIntHashMap myDefaultColumnPaddingsY = new TIntIntHashMap(); + + @Nullable private Insets myDefaultInsets = insets; + @NotNull private final TIntObjectHashMap myDefaultColumnInsets = new TIntObjectHashMap(); + + public GridBag() { + gridx = gridy = -1; + } + + @NotNull + public GridBag nextLine() { + gridy++; + gridx = -1; + return reset(); + } + + @NotNull + public GridBag nextCell() { + gridx++; + return reset(); + } + + public int getLine() { + return gridy; + } + + @NotNull + public GridBag setLine(int line) { + gridy = line; + return this; + } + + public int getCell() { + return gridx; + } + + @NotNull + public GridBag setCell(int cell) { + gridx = cell; + return this; + } + + @NotNull + public GridBag reset() { + gridwidth = gridheight = 1; + + int column = gridx; + + anchor(getDefaultAnchor(column)); + fill = getDefaultFill(column); + weightx(getDefaultWeightX(column)); + weighty(getDefaultWeightY(column)); + padx(getDefaultPaddingX(column)); + pady(getDefaultPaddingY(column)); + insets(getDefaultInsets(column)); + return this; + } + + @NotNull + public GridBag anchor(int anchor) { + this.anchor = anchor; + return this; + } + + @NotNull + public GridBag fillCell() { + fill = GridBagConstraints.BOTH; + return this; + } + + @NotNull + public GridBag fillCellHorizontally() { + fill = GridBagConstraints.HORIZONTAL; + return this; + } + + @NotNull + public GridBag fillCellVertically() { + fill = GridBagConstraints.VERTICAL; + return this; + } + + @NotNull + public GridBag weightx(double weight) { + weightx = weight; + return this; + } + + + @NotNull + public GridBag weighty(double weight) { + weighty = weight; + return this; + } + + @NotNull + public GridBag coverLine() { + gridwidth = GridBagConstraints.REMAINDER; + return this; + } + + @NotNull + public GridBag coverLine(int cells) { + gridwidth = cells; + return this; + } + + @NotNull + public GridBag coverColumn() { + gridheight = GridBagConstraints.REMAINDER; + return this; + } + + @NotNull + public GridBag coverColumn(int cells) { + gridheight = cells; + return this; + } + + @NotNull + public GridBag padx(int padding) { + ipadx = padding; + return this; + } + + @NotNull + public GridBag pady(int padding) { + ipady = padding; + return this; + } + + + /** + * @see #insets(java.awt.Insets) + */ + @NotNull + public GridBag insets(int top, int left, int bottom, int right) { + return insets(new Insets(top, left, bottom, right)); + } + + /** + * Pass -1 to use a default value for this column. + * E.g, Insets(10, -1, -1, -1) means that 'top' will be changed to 10 and other sides will be set to defaults for this column. + */ + @NotNull + public GridBag insets(@Nullable Insets insets) { + if (insets != null && (insets.top < 0 || insets.bottom < 0 || insets.left < 0 || insets.right < 0)) { + Insets def = getDefaultInsets(gridx); + insets = (Insets)insets.clone(); + if (insets.top < 0) insets.top = def == null ? 0 : def.top; + if (insets.left < 0) insets.left = def == null ? 0 : def.left; + if (insets.bottom < 0) insets.bottom = def == null ? 0 : def.bottom; + if (insets.right < 0) insets.right = def == null ? 0 : def.right; + } + this.insets = insets; + return this; + } + + public int getDefaultAnchor() { + return myDefaultAnchor; + } + + @NotNull + public GridBag setDefaultAnchor(int anchor) { + myDefaultAnchor = anchor; + return this; + } + + public int getDefaultAnchor(int column) { + return myDefaultColumnAnchors.containsKey(column) ? myDefaultColumnAnchors.get(column) : getDefaultAnchor(); + } + + @NotNull + public GridBag setDefaultAnchor(int column, int anchor) { + if (anchor == -1) { + myDefaultColumnAnchors.remove(column); + } + else { + myDefaultColumnAnchors.put(column, anchor); + } + return this; + } + + public int getDefaultFill() { + return myDefaultFill; + } + + @NotNull + public GridBag setDefaultFill(int fill) { + myDefaultFill = fill; + return this; + } + + public int getDefaultFill(int column) { + return myDefaultColumnFills.containsKey(column) ? myDefaultColumnFills.get(column) : getDefaultFill(); + } + + @NotNull + public GridBag setDefaultFill(int column, int fill) { + if (fill == -1) { + myDefaultColumnFills.remove(column); + } + else { + myDefaultColumnFills.put(column, fill); + } + return this; + } + + public double getDefaultWeightX() { + return myDefaultWeightX; + } + + @NotNull + public GridBag setDefaultWeightX(double weight) { + myDefaultWeightX = weight; + return this; + } + + public double getDefaultWeightX(int column) { + return myDefaultColumnWeightsX.containsKey(column) ? myDefaultColumnWeightsX.get(column) : getDefaultWeightX(); + } + + @NotNull + public GridBag setDefaultWeightX(int column, double weight) { + if (weight == -1) { + myDefaultColumnWeightsX.remove(column); + } + else { + myDefaultColumnWeightsX.put(column, weight); + } + return this; + } + + + public double getDefaultWeightY() { + return myDefaultWeightY; + } + + @NotNull + public GridBag setDefaultWeightY(double weight) { + myDefaultWeightY = weight; + return this; + } + + public double getDefaultWeightY(int column) { + return myDefaultColumnWeightsY.containsKey(column) ? myDefaultColumnWeightsY.get(column) : getDefaultWeightY(); + } + + @NotNull + public GridBag setDefaultWeightY(int column, double weight) { + if (weight == -1) { + myDefaultColumnWeightsY.remove(column); + } + else { + myDefaultColumnWeightsY.put(column, weight); + } + return this; + } + + + public int getDefaultPaddingX() { + return myDefaultPaddingX; + } + + @NotNull + public GridBag setDefaultPaddingX(int padding) { + myDefaultPaddingX = padding; + return this; + } + + public int getDefaultPaddingX(int column) { + return myDefaultColumnPaddingsX.containsKey(column) ? myDefaultColumnPaddingsX.get(column) : getDefaultPaddingX(); + } + + @NotNull + public GridBag setDefaultPaddingX(int column, int padding) { + if (padding == -1) { + myDefaultColumnPaddingsX.remove(column); + } + else { + myDefaultColumnPaddingsX.put(column, padding); + } + return this; + } + + public int getDefaultPaddingY() { + return myDefaultPaddingY; + } + + @NotNull + public GridBag setDefaultPaddingY(int padding) { + myDefaultPaddingY = padding; + return this; + } + + public int getDefaultPaddingY(int column) { + return myDefaultColumnPaddingsY.containsKey(column) ? myDefaultColumnPaddingsY.get(column) : getDefaultPaddingY(); + } + + @NotNull + public GridBag setDefaultPaddingY(int column, int padding) { + if (padding == -1) { + myDefaultColumnPaddingsY.remove(column); + } + else { + myDefaultColumnPaddingsY.put(column, padding); + } + return this; + } + + @Nullable + public Insets getDefaultInsets() { + return myDefaultInsets; + } + + @NotNull + public GridBag setDefaultInsets(int top, int left, int bottom, int right) { + return setDefaultInsets(new Insets(top, left, bottom, right)); + } + + public GridBag setDefaultInsets(@Nullable Insets insets) { + myDefaultInsets = insets; + return this; + } + + @Nullable + public Insets getDefaultInsets(int column) { + return myDefaultColumnInsets.containsKey(column) ? myDefaultColumnInsets.get(column) : getDefaultInsets(); + } + + @NotNull + public GridBag setDefaultInsets(int column, int top, int left, int bottom, int right) { + return setDefaultInsets(column, new Insets(top, left, bottom, right)); + } + + @NotNull + public GridBag setDefaultInsets(int column, @Nullable Insets insets) { + if (insets == null) { + myDefaultColumnInsets.remove(column); + } + else { + myDefaultColumnInsets.put(column, insets); + } + return this; + } +} From 1d1450ccac064ed7431c110b12b1d3289ee60837 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 23 Feb 2011 16:11:17 +0100 Subject: [PATCH 132/169] UI: GridBag class --- .../src/com/intellij/util/ui/GridBag.java | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/platform/util/src/com/intellij/util/ui/GridBag.java b/platform/util/src/com/intellij/util/ui/GridBag.java index 894758668336..78ee7982c054 100644 --- a/platform/util/src/com/intellij/util/ui/GridBag.java +++ b/platform/util/src/com/intellij/util/ui/GridBag.java @@ -23,6 +23,33 @@ import org.jetbrains.annotations.Nullable; import java.awt.*; +/** + * Usage: + *

+ * {@code
+ *
+ * // First, configure default for every or a specific column:
+ * GridBag bag = new GridBag()
+ *     .setDefaultAnchor(0, GridBagConstraints.EAST)
+ *     .setDefaultAnchor(1, GridBagConstraints.WEST)
+ *     .setDefaultWeightX(1, 1)
+ *     .setDefaultFill(GridBagConstraints.HORIZONTAL);
+ *
+ * // Then, add components to a panel:
+ *
+ * // The following code adds a new line with 2 components with default settings:
+ * panel.add(c1, bag.nextLine().next())
+ * panel.add(c1, bag.next())
+ *
+ * // The following code adds a component on the next line that covers all remaining columns:
+ * panel.add(c1, bag.nextLine().coverLine())
+ *
+ * // The following code adds a component on the next line with overridden settings:
+ * panel.add(c1, bag.nextLine().next().insets(É).weightx(É))
+ * }
+ * 
+ * Note that every call of {@link #nextLine()} or {@link #next()} resets settings to the defaults for the corresponding column. + */ @SuppressWarnings({"JavaDoc"}) public class GridBag extends GridBagConstraints { private int myDefaultAnchor = anchor; @@ -56,7 +83,7 @@ public class GridBag extends GridBagConstraints { } @NotNull - public GridBag nextCell() { + public GridBag next() { gridx++; return reset(); } @@ -71,12 +98,12 @@ public class GridBag extends GridBagConstraints { return this; } - public int getCell() { + public int getColumn() { return gridx; } @NotNull - public GridBag setCell(int cell) { + public GridBag setColumn(int cell) { gridx = cell; return this; } From 0e2d34518f634f190d978e4ddcf597200794a88f Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 23 Feb 2011 16:32:58 +0100 Subject: [PATCH 133/169] inplace introduce variable: do not preserve selection --- .../VariableInplaceIntroducer.java | 7 +++++++ .../rename/inplace/VariableInplaceRenamer.java | 17 +++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableInplaceIntroducer.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableInplaceIntroducer.java index 991546fcdc77..f1162d909db6 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableInplaceIntroducer.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableInplaceIntroducer.java @@ -26,11 +26,13 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.RangeMarker; +import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.keymap.Keymap; import com.intellij.openapi.keymap.KeymapManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.codeStyle.JavaCodeStyleManager; @@ -131,6 +133,11 @@ class VariableInplaceIntroducer extends VariableInplaceRenamer { return super.createLookupItems(lookupItems, name); } + @Override + protected TextRange preserveSelectedRange(SelectionModel selectionModel) { + return null; + } + @Override protected void moveOffsetAfter(boolean success) { try { diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java index 6607caac4fcb..5b3b39f87e27 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java @@ -32,7 +32,6 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.editor.colors.EditorColors; import com.intellij.openapi.editor.colors.EditorColorsManager; @@ -199,13 +198,7 @@ public class VariableInplaceRenamer { public void run() { final int offset = myEditor.getCaretModel().getOffset(); final SelectionModel selectionModel = myEditor.getSelectionModel(); - final TextRange selectedRange; - if (selectionModel.hasSelection()) { - selectedRange = new TextRange(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()); - } - else { - selectedRange = null; - } + final TextRange selectedRange = preserveSelectedRange(selectionModel); Template template = builder.buildInlineTemplate(); template.setToShortenLongNames(false); TextRange range = scope1.getTextRange(); @@ -279,6 +272,14 @@ public class VariableInplaceRenamer { return true; } + @Nullable + protected TextRange preserveSelectedRange(SelectionModel selectionModel) { + if (selectionModel.hasSelection()) { + return new TextRange(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()); + } + return null; + } + protected void moveOffsetAfter(boolean success) { } From 546e54a7a9af548597a6e0fee53c3c9cc4aa371a Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 23 Feb 2011 16:39:32 +0100 Subject: [PATCH 134/169] compilation fix --- platform/util/src/com/intellij/util/ui/GridBag.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/util/src/com/intellij/util/ui/GridBag.java b/platform/util/src/com/intellij/util/ui/GridBag.java index 78ee7982c054..b3e8bca93670 100644 --- a/platform/util/src/com/intellij/util/ui/GridBag.java +++ b/platform/util/src/com/intellij/util/ui/GridBag.java @@ -45,7 +45,7 @@ import java.awt.*; * panel.add(c1, bag.nextLine().coverLine()) * * // The following code adds a component on the next line with overridden settings: - * panel.add(c1, bag.nextLine().next().insets(É).weightx(É)) + * panel.add(c1, bag.nextLine().next().insets(...).weightx(...)) * } * * Note that every call of {@link #nextLine()} or {@link #next()} resets settings to the defaults for the corresponding column. From cb48b73f4a956f4ae892c039b831d43fe5bdeab9 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 23 Feb 2011 16:45:14 +0100 Subject: [PATCH 135/169] UI: GridBag javadoc --- platform/util/src/com/intellij/util/ui/GridBag.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platform/util/src/com/intellij/util/ui/GridBag.java b/platform/util/src/com/intellij/util/ui/GridBag.java index b3e8bca93670..95fd4ea59cba 100644 --- a/platform/util/src/com/intellij/util/ui/GridBag.java +++ b/platform/util/src/com/intellij/util/ui/GridBag.java @@ -46,6 +46,10 @@ import java.awt.*; * * // The following code adds a component on the next line with overridden settings: * panel.add(c1, bag.nextLine().next().insets(...).weightx(...)) + * + * // You also can pre-configure the object and pass it as a constraint: + * bag.nextLine().next(); + * panel.add(c1, bag) * } * * Note that every call of {@link #nextLine()} or {@link #next()} resets settings to the defaults for the corresponding column. From bc07306ff797bcdae9cdfb3a0014ddf185368780 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Wed, 23 Feb 2011 16:51:43 +0100 Subject: [PATCH 136/169] better assertion message --- .../src/com/intellij/util/indexing/FileBasedIndex.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java index 76f69436607c..a585930b7e12 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java @@ -1036,7 +1036,7 @@ public class FileBasedIndex implements ApplicationComponent { private void clearIndex(final ID indexId) throws StorageException { final UpdatableIndex index = getIndex(indexId); - assert index != null; + assert index != null: "Index with key " + indexId + " not found or not registered properly"; index.clear(); try { IndexInfrastructure.rewriteVersion(IndexInfrastructure.getVersionFile(indexId), myIndexIdToVersionMap.get(indexId)); From 9b206be6f20ee745e7fe5f7e486d8eba44cd9dca Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 23 Feb 2011 18:59:01 +0100 Subject: [PATCH 137/169] UI: JBLabel --- .../com/intellij/ui/components/JBLabel.java | 20 ++++++++++++++++++- .../project/MavenImportingSettingsForm.form | 5 +++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/components/JBLabel.java b/platform/platform-api/src/com/intellij/ui/components/JBLabel.java index d32c775ef9a1..952d6ba96628 100644 --- a/platform/platform-api/src/com/intellij/ui/components/JBLabel.java +++ b/platform/platform-api/src/com/intellij/ui/components/JBLabel.java @@ -16,10 +16,12 @@ package com.intellij.ui.components; import com.intellij.openapi.util.SystemInfo; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.awt.*; public class JBLabel extends JLabel { private Style myStyle = Style.REGULAR; @@ -64,7 +66,23 @@ public class JBLabel extends JLabel { if (SystemInfo.isMac) { putClientProperty("JComponent.sizeVariant", style == Style.REGULAR ? "regular" : "small"); } - // todo support other systems + else { + Font defFont = UIUtil.getLabelFont(); + Font font = getFont(); + if (style == JBLabel.Style.REGULAR) { + if (font != null) { + setFont(font.deriveFont(defFont.getSize())); + } + } + else { + if (font == null) font = defFont; + setFont(font.deriveFont(defFont.getSize() * 0.8f)); + } + } + Container p = getParent(); + if (p != null) { + SwingUtilities.updateComponentTreeUI(p); + } } public Style getStyle() { diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenImportingSettingsForm.form b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenImportingSettingsForm.form index e0e318517c93..34941f41efb3 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenImportingSettingsForm.form +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenImportingSettingsForm.form @@ -3,7 +3,7 @@ - + @@ -104,12 +104,13 @@ - + +