From e1e36b9a202caaa7e6b65d9fa4f3613e479a7f08 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Mon, 2 Jul 2012 22:52:23 +0400 Subject: [PATCH 01/20] a cleaner parameters panel 2 --- .../src/com/intellij/execution/console/LanguageConsoleImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 8ffd8ce4362b..f075a93d183d 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java @@ -280,7 +280,7 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider { EmptyAction.registerActionShortcuts(myHistoryViewer.getComponent(), myConsoleEditor.getComponent()); } - private boolean isFullEditorMode() { + public boolean isFullEditorMode() { return myPanel.getComponentCount() == 1; } From 99290d81043483ae644bb00e9cbcfd6a6d70e647 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 2 Jul 2012 23:30:43 +0400 Subject: [PATCH 02/20] avoid EOF exception on empty attribute value, consider file not indexed (EA-37015 - EOFE: DataInputOutputUtil.readTIME) --- .../intellij/util/indexing/IndexingStamp.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java b/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java index b9167e8129ec..7cc78437591f 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java @@ -50,13 +50,15 @@ public class IndexingStamp { private Timestamps(@Nullable DataInputStream stream) throws IOException { if (stream != null) { try { - long dominatingIndexStamp = DataInputOutputUtil.readTIME(stream); - while(stream.available() > 0) { - ID id = ID.findById(DataInputOutputUtil.readINT(stream)); - if (id != null) { - long stamp = IndexInfrastructure.getIndexCreationStamp(id); - if (myIndexStamps == null) myIndexStamps = new TObjectLongHashMap>(5, 0.98f); - if (stamp <= dominatingIndexStamp) myIndexStamps.put(id, stamp); + if (stream.available() > 0) { + long dominatingIndexStamp = DataInputOutputUtil.readTIME(stream); + while(stream.available() > 0) { + ID id = ID.findById(DataInputOutputUtil.readINT(stream)); + if (id != null) { + long stamp = IndexInfrastructure.getIndexCreationStamp(id); + if (myIndexStamps == null) myIndexStamps = new TObjectLongHashMap>(5, 0.98f); + if (stamp <= dominatingIndexStamp) myIndexStamps.put(id, stamp); + } } } } From 02eb01409eaf8165a395b5c3ea644d38cb1b112f Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Tue, 3 Jul 2012 08:43:53 +0400 Subject: [PATCH 03/20] IDEA-66333 Quick documentation lookup on mouse hover --- .../options/editor/EditorOptionsPanel.form | 22 +- .../options/editor/EditorOptionsPanel.java | 13 +- .../documentation/DocumentationComponent.java | 2 +- .../documentation/DocumentationManager.java | 160 +++++++---- .../QuickDocOnMouseOverManager.java | 269 ++++++++++++++++++ .../QuickDocOnMouseOverStartupActivity.java | 35 +++ .../openapi/editor/EditorFactory.java | 7 +- .../ex/EditorSettingsExternalizable.java | 14 +- .../com/intellij/ui/popup/AbstractPopup.java | 3 +- .../intellij/ui/popup/PopupFactoryImpl.java | 85 +++--- .../src/messages/ApplicationBundle.properties | 1 + .../src/META-INF/LangExtensions.xml | 5 +- 12 files changed, 510 insertions(+), 106 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocOnMouseOverManager.java create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocOnMouseOverStartupActivity.java diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.form b/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.form index aab91296ed1b..c2c5ecf9f70b 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.form +++ b/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.form @@ -304,7 +304,7 @@ - + @@ -339,9 +339,27 @@ - + + + + + + + + + + + + + + + + + + + diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.java b/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.java index 362c056a8d2c..ddf8dcddd2a6 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -21,8 +21,10 @@ import com.intellij.application.options.OptionsApplicabilityFilter; import com.intellij.codeInsight.CodeInsightSettings; import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; import com.intellij.codeInsight.daemon.impl.IdentifierHighlighterPass; +import com.intellij.codeInsight.documentation.QuickDocOnMouseOverManager; import com.intellij.ide.ui.UISettings; import com.intellij.openapi.application.ApplicationBundle; +import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorFactory; @@ -83,6 +85,7 @@ public class EditorOptionsPanel { private JTextField myCustomSoftWrapIndent; private JCheckBox myCbShowAllSoftWraps; private JCheckBox myPreselectCheckBox; + private JCheckBox myCbShowQuickDocOnCheckBox; private final ErrorHighlightingPanel myErrorHighlightingPanel = new ErrorHighlightingPanel(); private final MyConfigurable myConfigurable; @@ -156,6 +159,7 @@ public class EditorOptionsPanel { } myCbEnsureBlankLineBeforeCheckBox.setSelected(editorSettings.isEnsureNewLineAtEOF()); + myCbShowQuickDocOnCheckBox.setSelected(editorSettings.isShowQuickDocOnMouseOverElement()); // Advanced mouse myCbEnableDnD.setSelected(editorSettings.isDndEnabled()); @@ -235,6 +239,12 @@ public class EditorOptionsPanel { editorSettings.setEnsureNewLineAtEOF(myCbEnsureBlankLineBeforeCheckBox.isSelected()); + if (myCbShowQuickDocOnCheckBox.isSelected() ^ editorSettings.isShowQuickDocOnMouseOverElement()) { + boolean enabled = myCbShowQuickDocOnCheckBox.isSelected(); + editorSettings.setShowQuickDocOnMouseOverElement(enabled); + ServiceManager.getService(QuickDocOnMouseOverManager.class).setEnabled(enabled); + } + editorSettings.setDndEnabled(myCbEnableDnD.isSelected()); editorSettings.setWheelFontChangeEnabled(myCbEnableWheelFontChange.isSelected()); @@ -341,6 +351,7 @@ public class EditorOptionsPanel { // Strip trailing spaces, ensure EOL on EOF on save isModified |= !getStripTrailingSpacesValue().equals(editorSettings.getStripTrailingSpaces()); isModified |= isModified(myCbEnsureBlankLineBeforeCheckBox, editorSettings.isEnsureNewLineAtEOF()); + isModified |= isModified(myCbShowQuickDocOnCheckBox, editorSettings.isShowQuickDocOnMouseOverElement()); // advanced mouse isModified |= isModified(myCbEnableDnD, editorSettings.isDndEnabled()); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java index f356fa43587e..393e399f8254 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java @@ -146,7 +146,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr } { - enableEvents(KeyEvent.KEY_EVENT_MASK); + enableEvents(AWTEvent.KEY_EVENT_MASK); } protected void processKeyEvent(KeyEvent e) { 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 86c02c4ebaff..892e53cac7dc 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -154,7 +154,20 @@ public class DocumentationManager extends DockablePopupManager> actions = Collections.singletonList(Pair.create(new ActionListener() { + final List> actions = + Collections.singletonList(Pair.create(new ActionListener() { public void actionPerformed(ActionEvent e) { createToolWindow(element, originalElement); final JBPopup hint = getDocInfoHint(); @@ -314,63 +341,66 @@ public class DocumentationManager extends DockablePopupManager() { - public Boolean compute() { - if (fromQuickSearch()) { - ((ChooseByNameBase.JPanelProvider)myPreviouslyFocused.getParent()).unregisterHint(); - } - - Disposer.dispose(component); - myEditor = null; - myPreviouslyFocused = null; - myParameterInfoController = null; - return Boolean.TRUE; - } - }) - .createPopup(); - - - AbstractPopup oldHint = (AbstractPopup)getDocInfoHint(); - if (oldHint != null) { - DocumentationComponent oldComponent = (DocumentationComponent)oldHint.getComponent(); - PsiElement element1 = oldComponent.getElement(); - if (Comparing.equal(element, element1)) { - if (requestFocus) { - component.getComponent().requestFocus(); + .setRequestFocusCondition(project, NotLookupOrSearchCondition.INSTANCE) + .setProject(project) + .addListener(updateProcessor) + .addUserData(updateProcessor) + .setKeyboardActions(actions) + .setDimensionServiceKey(myProject, JAVADOC_LOCATION_AND_SIZE, false) + .setResizable(true) + .setMovable(true) + .setRequestFocus(requestFocus) + .setCancelOnClickOutside(!hasLookup) // otherwise selecting lookup items by mouse would close the doc + .setTitle(getTitle(element, false)) + .setCouldPin(pinCallback) + .setCancelCallback(new Computable() { + public Boolean compute() { + if (closeCallback != null) { + closeCallback.run(); } - return; + if (fromQuickSearch()) { + ((ChooseByNameBase.JPanelProvider)myPreviouslyFocused.getParent()).unregisterHint(); + } + + Disposer.dispose(component); + myEditor = null; + myPreviouslyFocused = null; + myParameterInfoController = null; + return Boolean.TRUE; } - oldHint.cancel(); + }) + .createPopup(); + + + AbstractPopup oldHint = (AbstractPopup)getDocInfoHint(); + if (oldHint != null) { + DocumentationComponent oldComponent = (DocumentationComponent)oldHint.getComponent(); + PsiElement element1 = oldComponent.getElement(); + if (Comparing.equal(element, element1)) { + if (requestFocus) { + component.getComponent().requestFocus(); + } + return; } + oldHint.cancel(); + } - component.setHint(hint); + component.setHint(hint); - if (myEditor == null) { - // subsequent invocation of javadoc popup from completion will have myEditor == null because of cancel invoked, - // so reevaluate the editor for proper popup placement - Lookup lookup = LookupManager.getInstance(myProject).getActiveLookup(); - myEditor = lookup != null ? lookup.getEditor() : null; - } - fetchDocInfo(getDefaultCollector(element, originalElement), component); + if (myEditor == null) { + // subsequent invocation of javadoc popup from completion will have myEditor == null because of cancel invoked, + // so reevaluate the editor for proper popup placement + Lookup lookup = LookupManager.getInstance(myProject).getActiveLookup(); + myEditor = lookup != null ? lookup.getEditor() : null; + } + fetchDocInfo(getDefaultCollector(element, originalElement), component); - myDocInfoHintRef = new WeakReference(hint); - myPreviouslyFocused = WindowManagerEx.getInstanceEx().getFocusedComponent(project); + myDocInfoHintRef = new WeakReference(hint); + myPreviouslyFocused = WindowManagerEx.getInstanceEx().getFocusedComponent(project); - if (fromQuickSearch()) { - ((ChooseByNameBase.JPanelProvider)myPreviouslyFocused.getParent()).registerHint(hint); - } + if (fromQuickSearch()) { + ((ChooseByNameBase.JPanelProvider)myPreviouslyFocused.getParent()).registerHint(hint); + } } private static String getTitle(@NotNull final PsiElement element, final boolean _short) { @@ -392,13 +422,19 @@ public class DocumentationManager extends DockablePopupManager + * Not thread-safe. + * + * @author Denis Zhdanov + * @since 7/2/12 9:09 AM + */ +public class QuickDocOnMouseOverManager { + + private static final long QUICK_DOC_DELAY_MILLIS; + static { + long delay = 500; + String property = System.getProperty("editor.auto.quick.doc.delay.ms"); + if (property != null) { + try { + long parsed = Long.parseLong(property); + if (parsed > 0) { + delay = parsed; + } + } + catch (Exception e) { + // Ignore. + } + } + QUICK_DOC_DELAY_MILLIS = delay; + } + + @NotNull private final EditorMouseMotionListener myEditorListener = new MyEditorMouseListener(); + @NotNull private final Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); + @NotNull private final Runnable myRequest = new MyShowQuickDocRequest(); + @NotNull private final Runnable myHintCloseCallback = new Runnable() { + @Override + public void run() { + myActiveElements.clear(); + myDocumentationManager = null; + } + }; + + private final Map myActiveElements + = new HashMap(); + + /** Holds a reference (if any) to the documentation manager used last time to show an 'auto quick doc' popup. */ + @Nullable private WeakReference myDocumentationManager; + + @Nullable private DelayedQuickDocInfo myDelayedQuickDocInfo; + private boolean myEnabled; + + public QuickDocOnMouseOverManager(@NotNull Application application) { + EditorFactory factory = EditorFactory.getInstance(); + if (factory != null) { + factory.addEditorFactoryListener(new MyEditorFactoryListener(), application); + } + } + + /** + * Instructs the manager to enable or disable 'show quick doc automatically when the mouse goes over an editor element' mode. + * + * @param enabled flag that identifies if quick doc should be automatically shown + */ + public void setEnabled(boolean enabled) { + myEnabled = enabled; + if (!enabled) { + closeAutoQuickDocComponentIfNecessary(); + myAlarm.cancelAllRequests(); + } + EditorFactory factory = EditorFactory.getInstance(); + if (factory == null) { + return; + } + for (Editor editor : factory.getAllEditors()) { + if (enabled) { + editor.addEditorMouseMotionListener(myEditorListener); + } + else { + editor.removeEditorMouseMotionListener(myEditorListener); + } + } + } + + private void processMouseMove(@NotNull EditorMouseEvent e) { + if (e.getArea() != EditorMouseEventArea.EDITING_AREA) { + // Skip if the mouse is not at the editing area. + closeAutoQuickDocComponentIfNecessary(); + return; + } + + Editor editor = e.getEditor(); + Project project = editor.getProject(); + if (project == null) { + return; + } + + DocumentationManager documentationManager = DocumentationManager.getInstance(project); + JBPopup hint = documentationManager.getDocInfoHint(); + if (hint != null) { + + // Skip the event if the control is shown because of explicit 'show quick doc' action call. + WeakReference ref = myDocumentationManager; + if (ref == null || ref.get() == null) { + return; + } + + // Skip the event if the mouse is under the opened quick doc control. + Point hintLocation = hint.getLocationOnScreen(); + Dimension hintSize = hint.getSize(); + int mouseX = e.getMouseEvent().getXOnScreen(); + int mouseY = e.getMouseEvent().getYOnScreen(); + if (mouseX >= hintLocation.x && mouseX <= hintLocation.x + hintSize.width && mouseY >= hintLocation.y + && mouseY <= hintLocation.y + hintSize.height) + { + return; + } + } + + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + if (psiFile == null) { + closeAutoQuickDocComponentIfNecessary(); + return; + } + + int mouseOffset = editor.logicalPositionToOffset(editor.xyToLogicalPosition(e.getMouseEvent().getPoint())); + PsiElement elementUnderMouse = psiFile.findElementAt(mouseOffset); + if (elementUnderMouse == null || elementUnderMouse instanceof PsiWhiteSpace) { + closeAutoQuickDocComponentIfNecessary(); + return; + } + + PsiElement targetElementUnderMouse = documentationManager.findTargetElement(editor, mouseOffset, psiFile, elementUnderMouse); + if (targetElementUnderMouse == null) { + // No PSI element is located under the current mouse position - close quick doc if any. + closeAutoQuickDocComponentIfNecessary(); + return; + } + + PsiElement activeElement = myActiveElements.get(editor); + if (targetElementUnderMouse.equals(activeElement) + && (myAlarm.getActiveRequestCount() > 0 // Request to show documentation for the target component has been already queued. + || hint != null)) // Documentation for the target component is being shown. + { + return; + } + closeAutoQuickDocComponentIfNecessary(); + myActiveElements.put(editor, targetElementUnderMouse); + myDelayedQuickDocInfo = new DelayedQuickDocInfo(documentationManager, editor, targetElementUnderMouse, elementUnderMouse); + + myAlarm.cancelAllRequests(); + myAlarm.addRequest(myRequest, QUICK_DOC_DELAY_MILLIS); + } + + private void closeAutoQuickDocComponentIfNecessary() { + myAlarm.cancelAllRequests(); + WeakReference ref = myDocumentationManager; + if (ref == null) { + return; + } + + DocumentationManager docManager = ref.get(); + if (docManager == null) { + return; + } + + JBPopup hint = docManager.getDocInfoHint(); + if (hint == null) { + return; + } + + hint.cancel(); + } + + private static class DelayedQuickDocInfo { + + @NotNull public final DocumentationManager docManager; + @NotNull public final Editor editor; + @NotNull public final PsiElement targetElement; + @NotNull public final PsiElement originalElement; + + private DelayedQuickDocInfo(@NotNull DocumentationManager docManager, + @NotNull Editor editor, @NotNull PsiElement targetElement, + @NotNull PsiElement originalElement) + { + this.docManager = docManager; + this.editor = editor; + this.targetElement = targetElement; + this.originalElement = originalElement; + } + } + + private class MyShowQuickDocRequest implements Runnable { + @Override + public void run() { + myAlarm.cancelAllRequests(); + + DelayedQuickDocInfo info = myDelayedQuickDocInfo; + if (info == null || !info.targetElement.equals(myActiveElements.get(info.editor))) { + return; + } + + info.editor.putUserData(PopupFactoryImpl.ANCHOR_POPUP_POSITION, + info.editor.offsetToVisualPosition(info.originalElement.getTextRange().getStartOffset())); + try { + info.docManager.showJavaDocInfo(info.editor, info.targetElement, info.originalElement, myHintCloseCallback); + myDocumentationManager = new WeakReference(info.docManager); + } + finally { + info.editor.putUserData(PopupFactoryImpl.ANCHOR_POPUP_POSITION, null); + } + } + } + + private class MyEditorFactoryListener implements EditorFactoryListener { + @Override + public void editorCreated(@NotNull EditorFactoryEvent event) { + if (myEnabled) { + event.getEditor().addEditorMouseMotionListener(myEditorListener); + } + } + + @Override + public void editorReleased(@NotNull EditorFactoryEvent event) { + event.getEditor().removeEditorMouseMotionListener(myEditorListener); + } + } + + private class MyEditorMouseListener extends EditorMouseMotionAdapter { + + @Override + public void mouseMoved(EditorMouseEvent e) { + processMouseMove(e); + } + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocOnMouseOverStartupActivity.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocOnMouseOverStartupActivity.java new file mode 100644 index 000000000000..72ffe987ed41 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocOnMouseOverStartupActivity.java @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2012 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.documentation; + +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.startup.StartupActivity; + +/** + * @author Denis Zhdanov + * @since 7/2/12 9:44 AM + */ +public class QuickDocOnMouseOverStartupActivity implements StartupActivity { + + @Override + public void runActivity(Project project) { + if (EditorSettingsExternalizable.getInstance().isShowQuickDocOnMouseOverElement()) { + ServiceManager.getService(QuickDocOnMouseOverManager.class).setEnabled(true); + } + } +} diff --git a/platform/platform-api/src/com/intellij/openapi/editor/EditorFactory.java b/platform/platform-api/src/com/intellij/openapi/editor/EditorFactory.java index 78c7ce26b9b0..9a231c30fbd2 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/EditorFactory.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/EditorFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -36,6 +36,7 @@ public abstract class EditorFactory implements ApplicationComponent { * * @return the editor factory instance. */ + @Nullable public static EditorFactory getInstance() { final Application application = ApplicationManager.getApplication(); return application == null ? null : application.getComponent(EditorFactory.class); @@ -168,7 +169,7 @@ public abstract class EditorFactory implements ApplicationComponent { /** * Registers a listener for receiving notifications when editor instances are created and released - * and removes the listener when {@link parentDisposable} get disposed. + * and removes the listener when the 'parentDisposable' gets disposed. * * @param listener the listener instance. * @param parentDisposable the Disposable which triggers the removal of the listener @@ -176,7 +177,7 @@ public abstract class EditorFactory implements ApplicationComponent { public abstract void addEditorFactoryListener(@NotNull EditorFactoryListener listener, @NotNull Disposable parentDisposable); /** - * Unregisters a listener for receiving notifications when editor instances are created + * Un-registers a listener for receiving notifications when editor instances are created * and released. * * @param listener the listener instance. diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorSettingsExternalizable.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorSettingsExternalizable.java index 20ee29d35212..b99fa22dce8c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorSettingsExternalizable.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorSettingsExternalizable.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -19,6 +19,7 @@ import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.components.ExportableApplicationComponent; +import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.editor.impl.softwrap.SoftWrapAppliancePlaces; import com.intellij.openapi.options.OptionsBundle; import com.intellij.openapi.util.DefaultJDOMExternalizer; @@ -50,6 +51,7 @@ public class EditorSettingsExternalizable implements NamedJDOMExternalizable, Ex public boolean IS_CARET_INSIDE_TABS; @NonNls public String STRIP_TRAILING_SPACES = "Changed"; public boolean IS_ENSURE_NEWLINE_AT_EOF = false; + public boolean SHOW_QUICK_DOC_ON_MOUSE_OVER_ELEMENT = false; public boolean IS_CARET_BLINKING = true; public int CARET_BLINKING_PERIOD = 500; public boolean IS_RIGHT_MARGIN_SHOWN = true; @@ -356,7 +358,7 @@ public class EditorSettingsExternalizable implements NamedJDOMExternalizable, Ex public void setEnsureNewLineAtEOF(boolean ensure) { myOptions.IS_ENSURE_NEWLINE_AT_EOF = ensure; } - + public String getStripTrailingSpaces() { return myOptions.STRIP_TRAILING_SPACES; } // TODO: move to CodeEditorManager or something else @@ -365,6 +367,14 @@ public class EditorSettingsExternalizable implements NamedJDOMExternalizable, Ex myOptions.STRIP_TRAILING_SPACES = stripTrailingSpaces; } + public boolean isShowQuickDocOnMouseOverElement() { + return myOptions.SHOW_QUICK_DOC_ON_MOUSE_OVER_ELEMENT; + } + + public void setShowQuickDocOnMouseOverElement(boolean show) { + myOptions.SHOW_QUICK_DOC_ON_MOUSE_OVER_ELEMENT = show; + } + public boolean isRefrainFromScrolling() { return myOptions.REFRAIN_FROM_SCROLLING; } diff --git a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java index b2e4a8e5fed1..ea31ba758f63 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -28,6 +28,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.VisualPosition; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.*; diff --git a/platform/platform-impl/src/com/intellij/ui/popup/PopupFactoryImpl.java b/platform/platform-impl/src/com/intellij/ui/popup/PopupFactoryImpl.java index 414c5ece580e..54cac050b66e 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/PopupFactoryImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/PopupFactoryImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -36,6 +36,7 @@ import com.intellij.openapi.ui.popup.*; import com.intellij.openapi.ui.popup.util.BaseListPopupStep; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.EmptyRunnable; +import com.intellij.openapi.util.Key; import com.intellij.openapi.wm.WindowManager; import com.intellij.openapi.wm.ex.WindowManagerEx; import com.intellij.openapi.wm.impl.IdeFrameImpl; @@ -65,6 +66,14 @@ import java.util.HashMap; import java.util.List; public class PopupFactoryImpl extends JBPopupFactory { + + /** + * Allows to get an editor position for which a popup with auxiliary information might be shown. + *

+ * Primary intention for this key is to hint popup position for the non-caret location. + */ + public static final Key ANCHOR_POPUP_POSITION = Key.create("popup.anchor.position"); + private static final Logger LOG = Logger.getInstance("#com.intellij.ui.popup.PopupFactoryImpl"); private static final Icon QUICK_LIST_ICON = AllIcons.Actions.QuickList; @@ -78,7 +87,7 @@ public class PopupFactoryImpl extends JBPopupFactory { } public JBPopup createMessage(String text) { - return createListPopup(new BaseListPopupStep(null, new String[]{text})); + return createListPopup(new BaseListPopupStep(null, new String[]{text})); } @Override @@ -98,28 +107,34 @@ public class PopupFactoryImpl extends JBPopupFactory { return null; } - public ListPopup createConfirmation(String title, final String yesText, String noText, final Runnable onYes, final Runnable onNo, int defaultOptionIndex) { + public ListPopup createConfirmation(String title, + final String yesText, + String noText, + final Runnable onYes, + final Runnable onNo, + int defaultOptionIndex) + { - final BaseListPopupStep step = new BaseListPopupStep(title, new String[]{yesText, noText}) { - public PopupStep onChosen(String selectedValue, final boolean finalChoice) { - if (selectedValue.equals(yesText)) { - onYes.run(); - } - else { - onNo.run(); - } - return FINAL_CHOICE; + final BaseListPopupStep step = new BaseListPopupStep(title, new String[]{yesText, noText}) { + public PopupStep onChosen(String selectedValue, final boolean finalChoice) { + if (selectedValue.equals(yesText)) { + onYes.run(); } - - public void canceled() { + else { onNo.run(); } + return FINAL_CHOICE; + } - public boolean isMnemonicsNavigationEnabled() { - return true; - } - }; - step.setDefaultOptionIndex(defaultOptionIndex); + public void canceled() { + onNo.run(); + } + + public boolean isMnemonicsNavigationEnabled() { + return true; + } + }; + step.setDefaultOptionIndex(defaultOptionIndex); final ApplicationEx app = ApplicationManagerEx.getApplicationEx(); return app == null || !app.isUnitTestMode() ? new ListPopupImpl(step) : new MockConfirmation(step, yesText); @@ -127,13 +142,13 @@ public class PopupFactoryImpl extends JBPopupFactory { private static ListPopup createActionGroupPopup(final String title, - final ActionGroup actionGroup, - @NotNull DataContext dataContext, - boolean showNumbers, - boolean useAlphaAsNumbers, - boolean showDisabledActions, - boolean honorActionMnemonics, - final Runnable disposeCallback, + final ActionGroup actionGroup, + @NotNull DataContext dataContext, + boolean showNumbers, + boolean useAlphaAsNumbers, + boolean showDisabledActions, + boolean honorActionMnemonics, + final Runnable disposeCallback, final int maxRowCount) { return createActionGroupPopup(title, actionGroup, dataContext, showNumbers, useAlphaAsNumbers, showDisabledActions, honorActionMnemonics, disposeCallback, maxRowCount, null, null); @@ -458,14 +473,18 @@ public class PopupFactoryImpl extends JBPopupFactory { } public RelativePoint guessBestPopupLocation(Editor editor) { - CaretModel caretModel = editor.getCaretModel(); - final VisualPosition visualPosition; - if (caretModel.isUpToDate()) { - visualPosition = caretModel.getVisualPosition(); - } - else { - visualPosition = editor.offsetToVisualPosition(caretModel.getOffset()); + VisualPosition visualPosition = editor.getUserData(ANCHOR_POPUP_POSITION); + + if (visualPosition == null) { + CaretModel caretModel = editor.getCaretModel(); + if (caretModel.isUpToDate()) { + visualPosition = caretModel.getVisualPosition(); + } + else { + visualPosition = editor.offsetToVisualPosition(caretModel.getOffset()); + } } + Point p = editor.visualPositionToXY(new VisualPosition(visualPosition.line + 1, visualPosition.column)); final Rectangle visibleArea = editor.getScrollingModel().getVisibleArea(); diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties index 977f08eb1ca7..3ecbbf068091 100644 --- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties +++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties @@ -372,6 +372,7 @@ checkbox.show.virtual.space.at.file.bottom=Show virtual space at file bottom checkbox.optimize.imports.on.the.fly=Optimize imports on the fly checkbox.add.unambiguous.imports.on.the.fly=Add unambiguous imports on the fly combobox.strip.trailing.spaces.on.save=Strip trailing spaces on Save: +checkbox.show.quick.doc.on.mouse.over=Show quick doc on mouse over element group.limits=Limits editbox.recent.files.limit=Recent files limit: editbox.console.history.limit=Console commands history size: diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index 14c14f44a482..054d202363db 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -733,7 +733,10 @@ - + + + + From 990efb27d2057e59be06053b7a4dedf4077c167f Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Tue, 3 Jul 2012 09:22:43 +0400 Subject: [PATCH 04/20] IDEA-87120 IDEA not usable anymore after "Indent" some java code --- .../intellij/openapi/editor/impl/FoldRegionsTree.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionsTree.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionsTree.java index ba1244039f7a..b0760c38b103 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionsTree.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionsTree.java @@ -323,16 +323,17 @@ abstract class FoldRegionsTree { } public int getLastTopLevelIndexBefore(int offset) { - if (!isFoldingEnabledAndUpToDate()) return -1; + int[] endOffsets = myCachedEndOffsets; + if (!isFoldingEnabledAndUpToDate() || endOffsets == null) return -1; int start = 0; - int end = myCachedEndOffsets.length - 1; + int end = endOffsets.length - 1; while (start <= end) { int i = (start + end) / 2; - if (offset < myCachedEndOffsets[i]) { + if (offset < endOffsets[i]) { end = i - 1; - } else if (offset > myCachedEndOffsets[i]) { + } else if (offset > endOffsets[i]) { start = i + 1; } else { From a374457a0b724511774d001c1101ad2da46adf76 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Tue, 3 Jul 2012 11:34:16 +0400 Subject: [PATCH 05/20] IDEA-87184 Soft wraps: with wrapped lines horizontal scroll bar is always shown --- .../openapi/editor/impl/EditorImpl.java | 3 +- .../mapping/SoftWrapApplianceManager.java | 5 +++ ...apAwareDocumentParsingListenerAdapter.java | 4 +-- ...apApplianceOnDocumentModificationTest.java | 36 +++++++++++++++++-- 4 files changed, 43 insertions(+), 5 deletions(-) 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 c6f987bfe094..3fcf2dac7f1c 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 @@ -2508,7 +2508,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi @NotNull Rectangle clip, @NotNull LogicalPosition clipStartPosition, int clipStartOffset, - int clipEndOffset) { + int clipEndOffset) + { myCurrentFontType = null; myLastCache = null; final int plainSpaceWidth = EditorUtil.getSpaceWidth(Font.PLAIN, this); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java index 10693301cebc..7570353813d1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java @@ -589,6 +589,7 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume myContext.currentPosition.offset--; myContext.currentPosition.logicalColumn -= columnsDiff; myContext.currentPosition.visualColumn -= columnsDiff; + myContext.currentPosition.x -= pixelsDiff; } } } @@ -899,6 +900,10 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume return myListeners.add(listener); } + public boolean removeListener(@NotNull SoftWrapAwareDocumentParsingListener listener) { + return myListeners.remove(listener); + } + @SuppressWarnings({"ForLoopReplaceableByForEach"}) private void revertListeners(int offset, int visualLine) { for (int i = 0; i < myListeners.size(); i++) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapAwareDocumentParsingListenerAdapter.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapAwareDocumentParsingListenerAdapter.java index 4145c46d4e3a..09fdff87e83d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapAwareDocumentParsingListenerAdapter.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapAwareDocumentParsingListenerAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,7 +22,7 @@ import org.jetbrains.annotations.NotNull; * @author Denis Zhdanov * @since 11/23/11 7:04 PM */ -public class SoftWrapAwareDocumentParsingListenerAdapter implements SoftWrapAwareDocumentParsingListener { +public abstract class SoftWrapAwareDocumentParsingListenerAdapter implements SoftWrapAwareDocumentParsingListener { @Override public void onVisualLineStart(@NotNull EditorPosition position) { } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java index bf71ec861559..959afe98b854 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java @@ -17,8 +17,12 @@ package com.intellij.openapi.editor.impl.softwrap.mapping; import com.intellij.codeInsight.folding.CodeFoldingManager; import com.intellij.openapi.editor.*; -import com.intellij.openapi.editor.impl.*; +import com.intellij.openapi.editor.impl.AbstractEditorProcessingOnDocumentModificationTest; +import com.intellij.openapi.editor.impl.DefaultEditorTextRepresentationHelper; +import com.intellij.openapi.editor.impl.EditorImpl; +import com.intellij.openapi.editor.impl.SoftWrapModelImpl; import com.intellij.openapi.editor.markup.TextAttributes; +import com.intellij.openapi.util.Ref; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.testFramework.TestFileType; import gnu.trove.TIntHashSet; @@ -994,9 +998,37 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP assertEquals(text.substring(0, text.indexOf("line")) + text.substring(text.indexOf('9')), myEditor.getDocument().getText()); assertEquals(position, caretModel.getVisualPosition()); } + + public void testNoUnnecessaryHorizontalScrollBar() throws IOException { + // Inspired by IDEA-87184 + final String text = "12345678 abcdefgh"; + init(15, 7, text); + myEditor.getCaretModel().moveToOffset(text.length()); + final Ref fail = new Ref(true); + SoftWrapApplianceManager applianceManager = ((SoftWrapModelImpl)myEditor.getSoftWrapModel()).getApplianceManager(); + SoftWrapAwareDocumentParsingListener listener = new SoftWrapAwareDocumentParsingListenerAdapter() { + @Override + public void beforeSoftWrapLineFeed(@NotNull EditorPosition position) { + if (position.x == text.indexOf("a") * 7) { + fail.set(false); + } + } + }; + applianceManager.addListener(listener); + try { + backspace(); + } + finally { + applianceManager.removeListener(listener); + } + assertFalse(fail.get()); + } private void init(final int visibleWidthInColumns, @NotNull String fileText) throws IOException { - int symbolWidthInPixels = 7; + init(visibleWidthInColumns, 7, fileText); + } + + private void init(final int visibleWidthInColumns, final int symbolWidthInPixels, @NotNull String fileText) throws IOException { init(visibleWidthInColumns * symbolWidthInPixels, fileText, symbolWidthInPixels); } From 034b4e138c75bddbff52ed4754b2d02c3ede0ffd Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 3 Jul 2012 10:03:07 +0200 Subject: [PATCH 06/20] refresh vfs in touch --- .../plugins/groovy/compiler/GroovyCompilerTestCase.java | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java index b2983364fcb1..d29f3b2e6927 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java @@ -224,6 +224,7 @@ public abstract class GroovyCompilerTestCase extends JavaCodeInsightFixtureTestC file.setBinaryContent(file.contentsToByteArray(), file.getModificationStamp() + 1, file.getTimeStamp() + 1); File ioFile = VfsUtil.virtualToIoFile(file); assert ioFile.setLastModified(ioFile.lastModified() - 100000); + file.refresh(false, false); } protected static void setFileText(final PsiFile file, final String barText) throws IOException { From 79befff8c74c03d4eddce26d76c1c8fb6edf8d79 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 25 Jun 2012 14:01:15 +0400 Subject: [PATCH 07/20] SOE in case of cyclic out-of-project classes --- .../intellij/psi/util/InheritanceUtil.java | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/java/java-psi-api/src/com/intellij/psi/util/InheritanceUtil.java b/java/java-psi-api/src/com/intellij/psi/util/InheritanceUtil.java index aac2fcbc77c7..2cd5c7446a52 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/InheritanceUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/InheritanceUtil.java @@ -53,7 +53,7 @@ public class InheritanceUtil { return isInheritorOrSelf(aClass, baseClass, checkDeep); } - public static boolean processSupers(@Nullable PsiClass aClass, boolean includeSelf, Processor superProcessor) { + public static boolean processSupers(@Nullable PsiClass aClass, boolean includeSelf, @NotNull Processor superProcessor) { if (aClass == null) return true; if (includeSelf && !superProcessor.process(aClass)) return false; @@ -61,7 +61,7 @@ public class InheritanceUtil { return processSupers(aClass, superProcessor, new THashSet()); } - private static boolean processSupers(@NotNull PsiClass aClass, Processor superProcessor, Set visited) { + private static boolean processSupers(@NotNull PsiClass aClass, @NotNull Processor superProcessor, @NotNull Set visited) { if (!visited.add(aClass)) return true; for (final PsiClass intf : aClass.getInterfaces()) { @@ -82,11 +82,11 @@ public class InheritanceUtil { return false; } - public static boolean isInheritor(@Nullable PsiClass psiClass, final String baseClassName) { + public static boolean isInheritor(@Nullable PsiClass psiClass, @NotNull final String baseClassName) { return isInheritor(psiClass, false, baseClassName); } - public static boolean isInheritor(@Nullable PsiClass psiClass, final boolean strict, final String baseClassName) { + public static boolean isInheritor(@Nullable PsiClass psiClass, final boolean strict, @NotNull final String baseClassName) { if (psiClass == null) { return false; } @@ -105,21 +105,22 @@ public class InheritanceUtil { * @param results * @param includeNonProject */ - public static void getSuperClasses(PsiClass aClass, Set results, boolean includeNonProject) { - getSuperClassesOfList(aClass.getSuperTypes(), results, includeNonProject); + public static void getSuperClasses(@NotNull PsiClass aClass, @NotNull Set results, boolean includeNonProject) { + getSuperClassesOfList(aClass.getSuperTypes(), results, includeNonProject, new THashSet(), aClass.getManager()); } - public static void getSuperClassesOfList(PsiClassType[] types, Set results, - boolean includeNonProject) { + private static void getSuperClassesOfList(@NotNull PsiClassType[] types, + @NotNull Set results, + boolean includeNonProject, + @NotNull Set visited, + @NotNull PsiManager manager) { for (PsiClassType type : types) { PsiClass resolved = type.resolve(); - if (resolved != null) { - if (!results.contains(resolved)) { - if (includeNonProject || resolved.getManager().isInProject(resolved)) { - results.add(resolved); - } - getSuperClasses(resolved, results, includeNonProject); + if (resolved != null && visited.add(resolved)) { + if (includeNonProject || manager.isInProject(resolved)) { + results.add(resolved); } + getSuperClassesOfList(resolved.getSuperTypes(), results, includeNonProject, visited, manager); } } } From cd083218a6cbb3816f3ddce238aa2d0d02692bbc Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 25 Jun 2012 14:03:21 +0400 Subject: [PATCH 08/20] Invalid file exception --- .../intellij/openapi/fileEditor/OpenFileDescriptor.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java index b4b3d97e4f11..8640a6db9416 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java +++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java @@ -215,7 +215,7 @@ public class OpenFileDescriptor implements Navigatable { } } - private void unfoldCurrentLine(@NotNull final Editor editor) { + private static void unfoldCurrentLine(@NotNull final Editor editor) { final FoldRegion[] allRegions = editor.getFoldingModel().getAllFoldRegions(); final int offset = editor.getCaretModel().getOffset(); int line = editor.getDocument().getLineNumber(offset); @@ -226,7 +226,7 @@ public class OpenFileDescriptor implements Navigatable { @Override public void run() { for (FoldRegion region : allRegions) { - if (!region.isExpanded() && range.intersects(TextRange.create(region))) /*region.getStartOffset() <= offset && offset <= region.getEndOffset()*/ { + if (!region.isExpanded() && range.intersects(TextRange.create(region))) { region.setExpanded(true); } } @@ -240,14 +240,15 @@ public class OpenFileDescriptor implements Navigatable { @Override public boolean canNavigate() { - return myProject != null; + return myFile.isValid(); } @Override public boolean canNavigateToSource() { - return myProject != null; + return canNavigate(); } + @NotNull public Project getProject() { return myProject; } From 08e7a41796dfab1b1e3ce4c6125e5cfc52981bdc Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 26 Jun 2012 15:59:25 +0400 Subject: [PATCH 09/20] notnull --- .../com/intellij/openapi/roots/impl/DirectoryIndexImpl.java | 3 +-- .../src/com/intellij/openapi/roots/impl/DirectoryInfo.java | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java index 2b47564cdc7b..75460d2f4fab 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java @@ -588,14 +588,13 @@ public class DirectoryIndexImpl extends DirectoryIndex { } protected void fillMapWithOrderEntries(final VirtualFile root, - final Collection orderEntries, + @NotNull final Collection orderEntries, @Nullable final Module module, @Nullable final VirtualFile libraryClassRoot, @Nullable final VirtualFile librarySourceRoot, @Nullable final DirectoryInfo parentInfo, @Nullable final ProgressIndicator progress) { VfsUtilCore.visitChildrenRecursively(root, new DirectoryVisitor() { - private final Stack> myEntries = new Stack>(); @Override diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java index 99b1d53db572..6d2b262ca8a7 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java @@ -21,6 +21,7 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.roots.OrderEntry; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; @@ -80,12 +81,13 @@ public class DirectoryInfo { "}"; } + @NotNull public List getOrderEntries() { return orderEntries == null ? Collections.emptyList() : orderEntries; } @SuppressWarnings({"unchecked"}) - public void addOrderEntries(Collection orderEntries, + public void addOrderEntries(@NotNull Collection orderEntries, @Nullable final DirectoryInfo parentInfo, @Nullable final List oldParentEntries) { if (orderEntries.isEmpty()) { From cb710a30f6a7f1ed53a8567a758724722b3e1ce2 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 26 Jun 2012 16:14:18 +0400 Subject: [PATCH 10/20] notnull --- .../com/intellij/openapi/util/Comparing.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/platform/util-rt/src/com/intellij/openapi/util/Comparing.java b/platform/util-rt/src/com/intellij/openapi/util/Comparing.java index 95c7d6df8676..bb0d90e2af5d 100644 --- a/platform/util-rt/src/com/intellij/openapi/util/Comparing.java +++ b/platform/util-rt/src/com/intellij/openapi/util/Comparing.java @@ -16,6 +16,8 @@ package com.intellij.openapi.util; import com.intellij.openapi.util.text.StringUtilRt; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Arrays; import java.util.Collection; @@ -28,24 +30,22 @@ import java.util.Set; public class Comparing { private Comparing() { } - public static boolean equal(T arg1, T arg2){ + public static boolean equal(@Nullable T arg1, @Nullable T arg2){ if (arg1 == null || arg2 == null){ return arg1 == arg2; } - else if (arg1 instanceof Object[] && arg2 instanceof Object[]){ + if (arg1 instanceof Object[] && arg2 instanceof Object[]){ Object[] arr1 = (Object[])arg1; Object[] arr2 = (Object[])arg2; return Arrays.equals(arr1, arr2); } - else if (arg1 instanceof CharSequence && arg2 instanceof CharSequence) { + if (arg1 instanceof CharSequence && arg2 instanceof CharSequence) { return equal((CharSequence)arg1, (CharSequence)arg2, true); } - else{ - return arg1.equals(arg2); - } + return arg1.equals(arg2); } - public static boolean equal(T[] arr1, T[] arr2){ + public static boolean equal(@Nullable T[] arr1, @Nullable T[] arr2){ if (arr1 == null || arr2 == null){ return arr1 == arr2; } @@ -60,7 +60,7 @@ public class Comparing { return equal(arg1, arg2, true); } - public static boolean equal(CharSequence s1, CharSequence s2, boolean caseSensitive) { + public static boolean equal(@Nullable CharSequence s1, @Nullable CharSequence s2, boolean caseSensitive) { if (s1 == s2) return true; if (s1 == null || s2 == null) return false; @@ -84,7 +84,7 @@ public class Comparing { return true; } - public static boolean equal(String arg1, String arg2, boolean caseSensitive){ + public static boolean equal(@Nullable String arg1, @Nullable String arg2, boolean caseSensitive){ if (arg1 == null || arg2 == null){ return arg1 == arg2; } @@ -97,11 +97,11 @@ public class Comparing { return strEqual(arg1, arg2, true); } - public static boolean strEqual(String arg1, String arg2, boolean caseSensitive){ + public static boolean strEqual(@Nullable String arg1, @Nullable String arg2, boolean caseSensitive){ return equal(arg1 == null ? "" : arg1, arg2 == null ? "" : arg2, caseSensitive); } - public static boolean haveEqualElements(Collection a, Collection b) { + public static boolean haveEqualElements(@NotNull Collection a, @NotNull Collection b) { if (a.size() != b.size()) { return false; } @@ -115,7 +115,7 @@ public class Comparing { return true; } - public static boolean haveEqualElements(T[] a, T[] b) { + public static boolean haveEqualElements(@Nullable T[] a, @Nullable T[] b) { if (a == null || b == null) { return a == b; } @@ -133,7 +133,7 @@ public class Comparing { return true; } - public static int hashcode(Object obj) { return obj == null ? 0 : obj.hashCode(); } + public static int hashcode(@Nullable Object obj) { return obj == null ? 0 : obj.hashCode(); } public static int hashcode(Object obj1, Object obj2) { return hashcode(obj1) ^ hashcode(obj2); } public static int compare(byte o1, byte o2) { @@ -152,7 +152,7 @@ public class Comparing { return o1 < o2 ? -1 : o1 == o2 ? 0 : 1; } - public static int compare(byte[] o1, byte[] o2) { + public static int compare(@Nullable byte[] o1, @Nullable byte[] o2) { if (o1 == o2) return 0; if (o1 == null) return 1; if (o2 == null) return -1; @@ -167,7 +167,7 @@ public class Comparing { return 0; } - public static > int compare(final T o1, final T o2) { + public static > int compare(@Nullable final T o1, @Nullable final T o2) { if (o1 == null) return o2 == null ? 0 : -1; if (o2 == null) return 1; return o1.compareTo(o2); From 03cf12b0d27a45421302f25b0a29d68c2a64acaf Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 28 Jun 2012 14:11:57 +0400 Subject: [PATCH 11/20] assertion --- .../src/com/intellij/psi/impl/source/tree/CompositeElement.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java index 0871c7c67705..57ca1b0a4ec8 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java @@ -276,7 +276,7 @@ public class CompositeElement extends TreeElement { final int len = getTextLength(); if (startStamp != myModificationsCount) { - throw new AssertionError("Tree changed while calculating text"); + throw new AssertionError("Tree changed while calculating text. startStamp:"+startStamp+"; current:"+myModificationsCount+"; myHC:"+myHC+"; assertThreading:"+ASSERT_THREADING+"; Thread.holdsLock(START_OFFSET_LOCK):"+Thread.holdsLock(START_OFFSET_LOCK)+"; Thread.holdsLock(PSI_LOCK):"+Thread.holdsLock(PsiLock.LOCK)); } char[] buffer = new char[len]; From e4ec975c17760421dc9e63134bcaf40904670511 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 28 Jun 2012 14:27:12 +0400 Subject: [PATCH 12/20] EA-29563 - assert: InjectedLanguageManagerImpl.startRunInjectors --- .../impl/source/tree/injected/InjectedLanguageManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.java index 250bcbed8cd1..af846dc238ed 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.java @@ -124,7 +124,7 @@ public class InjectedLanguageManagerImpl extends InjectedLanguageManager impleme public void startRunInjectors(@NotNull final Document hostDocument, final boolean synchronously) { if (myProject.isDisposed()) return; - assert synchronously || !ApplicationManager.getApplication().isWriteAccessAllowed(); + if (!synchronously && ApplicationManager.getApplication().isWriteAccessAllowed()) return; // use cached to avoid recreate PSI in alien project final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject); final PsiFile hostPsiFile = documentManager.getCachedPsiFile(hostDocument); From c0f542084c2d76248b2b1dcd97495aac7b50a069 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 28 Jun 2012 15:19:59 +0400 Subject: [PATCH 13/20] cleanup --- .../src/com/intellij/psi/impl/search/LowLevelSearchUtil.java | 3 ++- .../com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java | 2 +- platform/util/src/com/intellij/util/text/StringSearcher.java | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/search/LowLevelSearchUtil.java b/platform/indexing-impl/src/com/intellij/psi/impl/search/LowLevelSearchUtil.java index bf0f4ba81f26..d083c0a4c2c1 100644 --- a/platform/indexing-impl/src/com/intellij/psi/impl/search/LowLevelSearchUtil.java +++ b/platform/indexing-impl/src/com/intellij/psi/impl/search/LowLevelSearchUtil.java @@ -181,7 +181,8 @@ public class LowLevelSearchUtil { } public static int searchWord(@NotNull CharSequence text, - char[] textArray, int startOffset, + char[] textArray, + int startOffset, int endOffset, @NotNull StringSearcher searcher, @Nullable ProgressIndicator progress) { diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java index 376809278f80..994fc134d515 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java @@ -823,7 +823,7 @@ public class FSRecords implements Forceable { } } - public static void updateList(int id, int[] children) { + public static void updateList(int id, @NotNull int[] children) { try { w.lock(); DbConnection.markDirty(); diff --git a/platform/util/src/com/intellij/util/text/StringSearcher.java b/platform/util/src/com/intellij/util/text/StringSearcher.java index ce32dc0199b4..3a86ce5064a4 100644 --- a/platform/util/src/com/intellij/util/text/StringSearcher.java +++ b/platform/util/src/com/intellij/util/text/StringSearcher.java @@ -38,14 +38,14 @@ public class StringSearcher { } public StringSearcher(@NotNull String pattern, boolean caseSensitive, boolean forwardDirection) { - LOG.assertTrue(pattern.length() > 0); + LOG.assertTrue(!pattern.isEmpty()); myPattern = pattern; myCaseSensitive = caseSensitive; myForwardDirection = forwardDirection; myPatternArray = myCaseSensitive ? myPattern.toCharArray() : myPattern.toLowerCase().toCharArray(); myPatternLength = myPatternArray.length; Arrays.fill(mySearchTable, -1); - myJavaIdentifier = pattern.length() == 0 || + myJavaIdentifier = pattern.isEmpty() || Character.isJavaIdentifierPart(pattern.charAt(0)) && Character.isJavaIdentifierPart(pattern.charAt(pattern.length() - 1)); } From 96859a2b61f45417d170e3314b8158700fa03252 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 29 Jun 2012 15:05:13 +0400 Subject: [PATCH 14/20] Notnull, cleanup --- .../util/containers/ConcurrentHashMap.java | 75 ++++++++++++++----- 1 file changed, 57 insertions(+), 18 deletions(-) diff --git a/platform/util/src/com/intellij/util/containers/ConcurrentHashMap.java b/platform/util/src/com/intellij/util/containers/ConcurrentHashMap.java index f33408cea62e..f817157db891 100644 --- a/platform/util/src/com/intellij/util/containers/ConcurrentHashMap.java +++ b/platform/util/src/com/intellij/util/containers/ConcurrentHashMap.java @@ -18,6 +18,7 @@ package com.intellij.util.containers; import com.intellij.util.ConcurrencyUtil; import gnu.trove.TObjectHashingStrategy; +import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.io.Serializable; @@ -592,6 +593,7 @@ public class ConcurrentHashMap extends AbstractMap implements Concur } // inherit Map javadoc + @Override public boolean isEmpty() { final Segment[] segments = this.segments; /* @@ -625,6 +627,7 @@ public class ConcurrentHashMap extends AbstractMap implements Concur } // inherit Map javadoc + @Override public int size() { final Segment[] segments = this.segments; long sum = 0; @@ -678,6 +681,7 @@ public class ConcurrentHashMap extends AbstractMap implements Concur * @throws NullPointerException if the key is * null. */ + @Override public V get(Object key) { int hash = myHashingStrategy.computeHashCode((K)key); // throws NullPointerException if key null return segmentFor(hash).get((K)key, hash); @@ -693,6 +697,7 @@ public class ConcurrentHashMap extends AbstractMap implements Concur * @throws NullPointerException if the key is * null. */ + @Override public boolean containsKey(Object key) { int hash = myHashingStrategy.computeHashCode((K)key); // throws NullPointerException if key null return segmentFor(hash).containsKey((K)key, hash); @@ -709,9 +714,8 @@ public class ConcurrentHashMap extends AbstractMap implements Concur * specified value. * @throws NullPointerException if the value is null. */ - public boolean containsValue(Object value) { - if (value == null) - throw new NullPointerException(); + @Override + public boolean containsValue(@NotNull Object value) { // See explanation of modCount use above @@ -793,9 +797,8 @@ public class ConcurrentHashMap extends AbstractMap implements Concur * @throws NullPointerException if the key or value is * null. */ - public V put(K key, V value) { - if (value == null) - throw new NullPointerException(); + @Override + public V put(K key, @NotNull V value) { int hash = myHashingStrategy.computeHashCode(key); return segmentFor(hash).put(key, hash, value, false); } @@ -818,9 +821,8 @@ public class ConcurrentHashMap extends AbstractMap implements Concur * @throws NullPointerException if the specified key or value is * null. */ - public V putIfAbsent(K key, V value) { - if (value == null) - throw new NullPointerException(); + @Override + public V putIfAbsent(@NotNull K key, @NotNull V value) { int hash = myHashingStrategy.computeHashCode(key); return segmentFor(hash).put(key, hash, value, true); } @@ -834,6 +836,7 @@ public class ConcurrentHashMap extends AbstractMap implements Concur * * @param t Mappings to be stored in this map. */ + @Override public void putAll(Map t) { for (Iterator> it = (Iterator>) t.entrySet().iterator(); it.hasNext(); ) { Entry e = it.next(); @@ -851,6 +854,7 @@ public class ConcurrentHashMap extends AbstractMap implements Concur * @throws NullPointerException if the key is * null. */ + @Override public V remove(Object key) { int hash = myHashingStrategy.computeHashCode((K)key); return segmentFor(hash).remove((K)key, hash, null); @@ -872,7 +876,8 @@ public class ConcurrentHashMap extends AbstractMap implements Concur * @throws NullPointerException if the specified key is * null. */ - public boolean remove(Object key, Object value) { + @Override + public boolean remove(@NotNull Object key, Object value) { int hash = myHashingStrategy.computeHashCode((K)key); return segmentFor(hash).remove((K)key, hash, value) != null; } @@ -895,9 +900,8 @@ public class ConcurrentHashMap extends AbstractMap implements Concur * @throws NullPointerException if the specified key or values are * null. */ - public boolean replace(K key, V oldValue, V newValue) { - if (oldValue == null || newValue == null) - throw new NullPointerException(); + @Override + public boolean replace(@NotNull K key, @NotNull V oldValue, @NotNull V newValue) { int hash = myHashingStrategy.computeHashCode(key); return segmentFor(hash).replace(key, hash, oldValue, newValue); } @@ -918,9 +922,8 @@ public class ConcurrentHashMap extends AbstractMap implements Concur * @throws NullPointerException if the specified key or value is * null. */ - public V replace(K key, V value) { - if (value == null) - throw new NullPointerException(); + @Override + public V replace(@NotNull K key, @NotNull V value) { int hash = myHashingStrategy.computeHashCode(key); return segmentFor(hash).replace(key, hash, value); } @@ -929,9 +932,9 @@ public class ConcurrentHashMap extends AbstractMap implements Concur /** * Removes all mappings from this map. */ + @Override public void clear() { - for (int i = 0; i < segments.length; ++i) - segments[i].clear(); + for (Segment segment : segments) segment.clear(); } /** @@ -950,6 +953,7 @@ public class ConcurrentHashMap extends AbstractMap implements Concur * * @return a set view of the keys contained in this map. */ + @Override public Set keySet() { Set ks = keySet; return (ks != null) ? ks : (keySet = new KeySet()); @@ -972,6 +976,7 @@ public class ConcurrentHashMap extends AbstractMap implements Concur * * @return a collection view of the values contained in this map. */ + @Override public Collection values() { Collection vs = values; return (vs != null) ? vs : (values = new Values()); @@ -995,6 +1000,7 @@ public class ConcurrentHashMap extends AbstractMap implements Concur * * @return a collection view of the mappings contained in this map. */ + @Override public Set> entrySet() { Set> es = entrySet; return (es != null) ? es : (entrySet = (Set>) (Set) new EntrySet()); @@ -1080,12 +1086,16 @@ public class ConcurrentHashMap extends AbstractMap implements Concur } final class KeyIterator extends HashIterator implements Iterator, Enumeration { + @Override public K next() { return super.nextEntry().key; } + @Override public K nextElement() { return super.nextEntry().key; } } final class ValueIterator extends HashIterator implements Iterator, Enumeration { + @Override public V next() { return super.nextEntry().value; } + @Override public V nextElement() { return super.nextEntry().value; } } @@ -1098,23 +1108,27 @@ public class ConcurrentHashMap extends AbstractMap implements Concur * itself acts as a forwarding pseudo-entry. */ final class EntryIterator extends HashIterator implements Entry, Iterator> { + @Override public Entry next() { nextEntry(); return this; } + @Override public K getKey() { if (lastReturned == null) throw new IllegalStateException("Entry was removed"); return lastReturned.key; } + @Override public V getValue() { if (lastReturned == null) throw new IllegalStateException("Entry was removed"); return ConcurrentHashMap.this.get(lastReturned.key); } + @Override public V setValue(V value) { if (lastReturned == null) throw new IllegalStateException("Entry was removed"); @@ -1159,27 +1173,34 @@ public class ConcurrentHashMap extends AbstractMap implements Concur } final class KeySet extends AbstractSet { + @Override public Iterator iterator() { return new KeyIterator(); } + @Override public int size() { return ConcurrentHashMap.this.size(); } + @Override public boolean contains(Object o) { return ConcurrentHashMap.this.containsKey(o); } + @Override public boolean remove(Object o) { return ConcurrentHashMap.this.remove(o) != null; } + @Override public void clear() { ConcurrentHashMap.this.clear(); } + @Override public Object[] toArray() { Collection c = new ArrayList(); for (Iterator i = iterator(); i.hasNext(); ) c.add(i.next()); return c.toArray(); } + @Override public T[] toArray(T[] a) { Collection c = new ArrayList(); for (Iterator i = iterator(); i.hasNext(); ) @@ -1189,24 +1210,30 @@ public class ConcurrentHashMap extends AbstractMap implements Concur } final class Values extends AbstractCollection { + @Override public Iterator iterator() { return new ValueIterator(); } + @Override public int size() { return ConcurrentHashMap.this.size(); } + @Override public boolean contains(Object o) { return ConcurrentHashMap.this.containsValue(o); } + @Override public void clear() { ConcurrentHashMap.this.clear(); } + @Override public Object[] toArray() { Collection c = new ArrayList(); for (Iterator i = iterator(); i.hasNext(); ) c.add(i.next()); return c.toArray(); } + @Override public T[] toArray(T[] a) { Collection c = new ArrayList(); for (Iterator i = iterator(); i.hasNext(); ) @@ -1216,9 +1243,11 @@ public class ConcurrentHashMap extends AbstractMap implements Concur } final class EntrySet extends AbstractSet> { + @Override public Iterator> iterator() { return new EntryIterator(); } + @Override public boolean contains(Object o) { if (!(o instanceof Entry)) return false; @@ -1226,18 +1255,22 @@ public class ConcurrentHashMap extends AbstractMap implements Concur V v = ConcurrentHashMap.this.get(e.getKey()); return v != null && v.equals(e.getValue()); } + @Override public boolean remove(Object o) { if (!(o instanceof Entry)) return false; Entry e = (Entry)o; return ConcurrentHashMap.this.remove(e.getKey(), e.getValue()); } + @Override public int size() { return ConcurrentHashMap.this.size(); } + @Override public void clear() { ConcurrentHashMap.this.clear(); } + @Override public Object[] toArray() { // Since we don't ordinarily have distinct Entry objects, we // must pack elements using exportable SimpleEntry @@ -1246,6 +1279,7 @@ public class ConcurrentHashMap extends AbstractMap implements Concur c.add(new SimpleEntry(i.next())); return c.toArray(); } + @Override public T[] toArray(T[] a) { Collection> c = new ArrayList>(size()); for (Iterator> i = iterator(); i.hasNext(); ) @@ -1273,14 +1307,17 @@ public class ConcurrentHashMap extends AbstractMap implements Concur this.value = e.getValue(); } + @Override public K getKey() { return key; } + @Override public V getValue() { return value; } + @Override public V setValue(V value) { V oldValue = this.value; this.value = value; @@ -1368,6 +1405,7 @@ public class ConcurrentHashMap extends AbstractMap implements Concur } } + @Override public int computeHashCode(final K object) { int h = object.hashCode(); h += ~(h << 9); @@ -1377,6 +1415,7 @@ public class ConcurrentHashMap extends AbstractMap implements Concur return h; } + @Override public boolean equals(final K o1, final K o2) { return o1.equals(o2); } From 6c53536cec3ca4e9930316e8cdcf8a02d04f97e9 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Tue, 3 Jul 2012 10:34:24 +0200 Subject: [PATCH 15/20] Platform: do not try to run on selected target when no runners are available --- .../actions/ChooseRunConfigurationPopup.java | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopup.java b/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopup.java index c54209e99ea6..072e2f81583f 100644 --- a/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopup.java +++ b/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopup.java @@ -362,8 +362,9 @@ public class ChooseRunConfigurationPopup { return new ItemWrapper(settings) { @Override public void perform(@NotNull Project project, @NotNull Executor executor, @NotNull DataContext context) { - RunManagerEx.getInstanceEx(project).setSelectedConfiguration(getValue()); - ProgramRunnerUtil.executeConfiguration(project, getValue(), executor); + RunnerAndConfigurationSettings config = getValue(); + RunManagerEx.getInstanceEx(project).setSelectedConfiguration(config); + doRunConfiguration(config, executor, project); } @Override @@ -470,7 +471,7 @@ public class ChooseRunConfigurationPopup { @Override public void perform(@NotNull final Project project, @NotNull final Executor executor, @NotNull DataContext context) { ExecutionTargetManager.setActiveTarget(project, eachTarget); - ProgramRunnerUtil.executeConfiguration(project, selectedConfiguration, executor); + doRunConfiguration(selectedConfiguration, executor, project); } @Override @@ -531,12 +532,7 @@ public class ChooseRunConfigurationPopup { if (dialog.isOK()) { SwingUtilities.invokeLater(new Runnable() { public void run() { - final RunnerAndConfigurationSettings configuration = RunManager.getInstance(project).getSelectedConfiguration(); - if (configuration instanceof RunnerAndConfigurationSettingsImpl) { - if (canRun(executor, configuration)) { - ProgramRunnerUtil.executeConfiguration(project, configuration, executor); - } - } + doRunConfiguration(RunManager.getInstance(project).getSelectedConfiguration(), executor, project); } }); } @@ -616,7 +612,7 @@ public class ChooseRunConfigurationPopup { public void perform(@NotNull Project project, @NotNull Executor executor, @NotNull DataContext context) { manager.setTemporaryConfiguration(configuration); RunManagerEx.getInstanceEx(project).setSelectedConfiguration(configuration); - ProgramRunnerUtil.executeConfiguration(project, configuration, executor); + doRunConfiguration(configuration, executor, project); } @Override @@ -729,6 +725,14 @@ public class ChooseRunConfigurationPopup { } } + private static void doRunConfiguration(RunnerAndConfigurationSettings configuration, Executor executor, Project project) { + if (configuration instanceof RunnerAndConfigurationSettingsImpl) { + if (canRun(executor, configuration)) { + ProgramRunnerUtil.executeConfiguration(project, configuration, executor); + } + } + } + private static final class ConfigurationActionsStep extends BaseListPopupStep { private ConfigurationActionsStep(@NotNull final Project project, ChooseRunConfigurationPopup action, @@ -761,7 +765,7 @@ public class ChooseRunConfigurationPopup { manager.setSelectedConfiguration(settings); ExecutionTargetManager.setActiveTarget(project, eachTarget); - ProgramRunnerUtil.executeConfiguration(project, settings, action.getCurrentExecutor(), eachTarget); + doRunConfiguration(settings, action.getCurrentExecutor(), project); } }); } @@ -776,7 +780,7 @@ public class ChooseRunConfigurationPopup { final RunManagerEx manager = RunManagerEx.getInstanceEx(project); if (dynamic) manager.setTemporaryConfiguration(settings); manager.setSelectedConfiguration(settings); - ProgramRunnerUtil.executeConfiguration(project, settings, executor); + doRunConfiguration(settings, executor, project); } }); isFirst = false; From b21232591a6a2a807e9ce309b6db462b7138162b Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Tue, 3 Jul 2012 13:38:54 +0400 Subject: [PATCH 16/20] Initial AppCode UI Designer --- .../designer/AndroidDesignerBundle.java | 4 +- .../com/intellij/designer/DesignerBundle.java | 4 +- .../intellij/designer/model/MetaManager.java | 75 +++++++++++-------- .../intellij/designer/model/MetaModel.java | 4 +- 4 files changed, 52 insertions(+), 35 deletions(-) diff --git a/plugins/android-designer/src/com/intellij/android/designer/AndroidDesignerBundle.java b/plugins/android-designer/src/com/intellij/android/designer/AndroidDesignerBundle.java index 6442f216e766..ca279cb87852 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/AndroidDesignerBundle.java +++ b/plugins/android-designer/src/com/intellij/android/designer/AndroidDesignerBundle.java @@ -40,7 +40,9 @@ public class AndroidDesignerBundle { private static ResourceBundle getBundle() { ResourceBundle bundle = null; - if (ourBundle != null) bundle = ourBundle.get(); + if (ourBundle != null) { + bundle = ourBundle.get(); + } if (bundle == null) { bundle = ResourceBundle.getBundle(BUNDLE); ourBundle = new SoftReference(bundle); diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/DesignerBundle.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/DesignerBundle.java index d6ce8f409be6..fe7f687d0a08 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/DesignerBundle.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/DesignerBundle.java @@ -40,7 +40,9 @@ public class DesignerBundle { private static ResourceBundle getBundle() { ResourceBundle bundle = null; - if (ourBundle != null) bundle = ourBundle.get(); + if (ourBundle != null) { + bundle = ourBundle.get(); + } if (bundle == null) { bundle = ResourceBundle.getBundle(BUNDLE); ourBundle = new SoftReference(bundle); diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaManager.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaManager.java index 08b69a16d928..3b06ba5944e7 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaManager.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaManager.java @@ -45,7 +45,7 @@ public abstract class MetaManager { private static final String TAG = "tag"; private static final String WRAP_IN = "wrap-in"; - private static final Logger LOG = Logger.getInstance("#com.intellij.designer.model.MetaManager"); + protected static final Logger LOG = Logger.getInstance("#com.intellij.designer.model.MetaManager"); private final Map myTag2Model = new HashMap(); private final Map myTarget2Model = new HashMap(); @@ -111,7 +111,7 @@ public abstract class MetaManager { String target = element.getAttributeValue("class"); String tag = element.getAttributeValue(TAG); - MetaModel meta = new MetaModel(model, target, tag); + MetaModel meta = createModel(model, target, tag); String layout = element.getAttributeValue("layout"); if (layout != null) { @@ -144,35 +144,7 @@ public abstract class MetaManager { Element properties = element.getChild("properties"); if (properties != null) { - Attribute inplace = properties.getAttribute("inplace"); - if (inplace != null) { - meta.setInplaceProperties(StringUtil.split(inplace.getValue(), " ")); - } - - Attribute top = properties.getAttribute("top"); - if (top != null) { - meta.setTopProperties(StringUtil.split(top.getValue(), " ")); - } - - Attribute normal = properties.getAttribute("normal"); - if (normal != null) { - meta.setNormalProperties(StringUtil.split(normal.getValue(), " ")); - } - - Attribute important = properties.getAttribute("important"); - if (important != null) { - meta.setImportantProperties(StringUtil.split(important.getValue(), " ")); - } - - Attribute expert = properties.getAttribute("expert"); - if (expert != null) { - meta.setExpertProperties(StringUtil.split(expert.getValue(), " ")); - } - - Attribute deprecated = properties.getAttribute("deprecated"); - if (deprecated != null) { - meta.setDeprecatedProperties(StringUtil.split(deprecated.getValue(), " ")); - } + loadProperties(meta, properties); } Element morphing = element.getChild("morphing"); @@ -180,6 +152,8 @@ public abstract class MetaManager { modelToMorphing.put(meta, StringUtil.split(morphing.getAttribute("to").getValue(), " ")); } + loadOther(meta, element); + if (tag != null) { myTag2Model.put(tag, meta); } @@ -189,6 +163,45 @@ public abstract class MetaManager { } } + protected MetaModel createModel(Class model, String target, String tag) throws Exception { + return new MetaModel(model, target, tag); + } + + protected void loadProperties(MetaModel meta, Element properties) throws Exception { + Attribute inplace = properties.getAttribute("inplace"); + if (inplace != null) { + meta.setInplaceProperties(StringUtil.split(inplace.getValue(), " ")); + } + + Attribute top = properties.getAttribute("top"); + if (top != null) { + meta.setTopProperties(StringUtil.split(top.getValue(), " ")); + } + + Attribute normal = properties.getAttribute("normal"); + if (normal != null) { + meta.setNormalProperties(StringUtil.split(normal.getValue(), " ")); + } + + Attribute important = properties.getAttribute("important"); + if (important != null) { + meta.setImportantProperties(StringUtil.split(important.getValue(), " ")); + } + + Attribute expert = properties.getAttribute("expert"); + if (expert != null) { + meta.setExpertProperties(StringUtil.split(expert.getValue(), " ")); + } + + Attribute deprecated = properties.getAttribute("deprecated"); + if (deprecated != null) { + meta.setDeprecatedProperties(StringUtil.split(deprecated.getValue(), " ")); + } + } + + protected void loadOther(MetaModel meta, Element element) throws Exception { + } + private void loadGroup(Element element) throws Exception { PaletteGroup group = new PaletteGroup(element.getAttributeValue(NAME)); diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaModel.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaModel.java index 15769877d2a2..1c55f90cbba6 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaModel.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaModel.java @@ -35,8 +35,8 @@ public class MetaModel { private final String myTag; private DefaultPaletteItem myPaletteItem; private String myTitle; - private String myIconPath; - private Icon myIcon; + protected String myIconPath; + protected Icon myIcon; private String myCreation; private boolean myDelete = true; private List myInplaceProperties = Collections.emptyList(); From d9f95c196e25232bb1f6b76b8725504da47ad8c6 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Tue, 3 Jul 2012 11:55:34 +0200 Subject: [PATCH 17/20] Completion: rendering item tails in while when selected --- .../codeInsight/lookup/impl/LookupCellRenderer.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java index ae6e07323864..a9a3c2cee7d7 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java @@ -244,9 +244,11 @@ public class LookupCellRenderer implements ListCellRenderer { return getGrayedForeground(isSelected); } - final Color tailForeground = presentation.getTailForeground(); - if (tailForeground != null) { - return tailForeground; + if (!isSelected) { + final Color tailForeground = presentation.getTailForeground(); + if (tailForeground != null) { + return tailForeground; + } } return defaultForeground; From def118140eb67beab3a0a09b4987e447cd22d121 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 3 Jul 2012 12:08:07 +0200 Subject: [PATCH 18/20] no @Nullable --- .../util/src/com/intellij/openapi/util/text/StringUtil.java | 2 -- 1 file changed, 2 deletions(-) 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 084ac6b1fa1f..0e2df521427e 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -1658,13 +1658,11 @@ public class StringUtil extends StringUtilRt { @NonNls private static final String[] REPLACES_REFS = {"<", ">", "&", "'", """}; @NonNls private static final String[] REPLACES_DISP = {"<", ">", "&", "'", "\""}; - @Nullable public static String unescapeXml(@Nullable final String text) { if (text == null) return null; return replace(text, REPLACES_REFS, REPLACES_DISP); } - @Nullable public static String escapeXml(@Nullable final String text) { if (text == null) return null; return replace(text, REPLACES_DISP, REPLACES_REFS); From 08bd0596577ab9b2a836f3201241bc2a610ee912 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 3 Jul 2012 12:08:26 +0200 Subject: [PATCH 19/20] IDEA-87740 Property key quick definition tooltip: escape XML --- .../PropertiesDocumentationProvider.java | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/plugins/properties/src/com/intellij/lang/properties/PropertiesDocumentationProvider.java b/plugins/properties/src/com/intellij/lang/properties/PropertiesDocumentationProvider.java index d1853fce045b..c7060b7dc22f 100644 --- a/plugins/properties/src/com/intellij/lang/properties/PropertiesDocumentationProvider.java +++ b/plugins/properties/src/com/intellij/lang/properties/PropertiesDocumentationProvider.java @@ -27,6 +27,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.ui.GuiUtils; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.awt.*; @@ -35,16 +36,25 @@ public class PropertiesDocumentationProvider extends AbstractDocumentationProvid @Nullable public String getQuickNavigateInfo(PsiElement element, PsiElement originalElement) { if (element instanceof IProperty) { - @NonNls String info = "\n\"" + ((IProperty)element).getValue() + "\""; - PsiFile file = element.getContainingFile(); - if (file != null) { - info += " [" + file.getName() + "]"; - } - return info; + return "\"" + renderPropertyValue((IProperty)element) + "\"" + getLocationString(element); } return null; } + private static String getLocationString(PsiElement element) { + PsiFile file = element.getContainingFile(); + return file != null ? " [" + file.getName() + "]" : ""; + } + + @NotNull + private static String renderPropertyValue(IProperty prop) { + String raw = prop.getValue(); + if (raw == null) { + return "empty"; + } + return StringUtil.escapeXml(raw); + } + public String generateDoc(final PsiElement element, final PsiElement originalElement) { if (element instanceof IProperty) { IProperty property = (IProperty)element; @@ -63,11 +73,8 @@ public class PropertiesDocumentationProvider extends AbstractDocumentationProvid info += ""; } } - info += "\n" + property.getName() + "=\"" + ((IProperty)element).getValue() + "\""; - PsiFile file = element.getContainingFile(); - if (file != null) { - info += " [" + file.getName() + "]"; - } + info += "\n" + property.getName() + "=\"" + renderPropertyValue(((IProperty)element)) + "\""; + info += getLocationString(element); return info; } return null; From 59466627be475489abc4311a974e5fc1d2be0efe Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 3 Jul 2012 12:41:56 +0200 Subject: [PATCH 20/20] IDEA-88181 Java: complete 'return' in conditional expression --- .../intellij/codeInsight/completion/JavaCompletionData.java | 2 +- .../codeInsight/completion/keywords/returnInTernary.java | 5 +++++ .../codeInsight/completion/KeywordCompletionTest.java | 1 + .../src/com/intellij/patterns/PsiElementPattern.java | 2 +- 4 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/keywords/returnInTernary.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 c72c946efdaf..6a6cbad9b7f8 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java @@ -628,7 +628,7 @@ public class JavaCompletionData extends JavaAwareCompletionData { return false; } - if (psiElement().withSuperParent(2, PsiConditionalExpression.class).accepts(position)) { + if (psiElement().withSuperParent(2, PsiConditionalExpression.class).andNot(psiElement().insideStarting(psiElement(PsiConditionalExpression.class))).accepts(position)) { return false; } diff --git a/java/java-tests/testData/codeInsight/completion/keywords/returnInTernary.java b/java/java-tests/testData/codeInsight/completion/keywords/returnInTernary.java new file mode 100644 index 000000000000..ad957a4ae4c8 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/keywords/returnInTernary.java @@ -0,0 +1,5 @@ +public class Util { + int goo() { + retcond ? 1: 0; + } +} 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 3a7f62eba3c3..f77bee9243e8 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/KeywordCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/KeywordCompletionTest.java @@ -92,6 +92,7 @@ public class KeywordCompletionTest extends LightCompletionTestCase { public void testNewInMethodRefs() throws Exception { doTest(false); } public void testAbstractInInterface() throws Exception { doTest(1, "abstract"); } public void testCharInAnnotatedParameter() throws Exception { doTest(1, "char"); } + public void testReturnInTernary() throws Exception { doTest(1, "return"); } public void testTryInExpression() throws Exception { configureByFile(BASE_PATH + "/" + getTestName(true) + ".java"); diff --git a/platform/lang-api/src/com/intellij/patterns/PsiElementPattern.java b/platform/lang-api/src/com/intellij/patterns/PsiElementPattern.java index 155159353d10..6b784a258300 100644 --- a/platform/lang-api/src/com/intellij/patterns/PsiElementPattern.java +++ b/platform/lang-api/src/com/intellij/patterns/PsiElementPattern.java @@ -303,7 +303,7 @@ public abstract class PsiElementPattern ancestor) { + public Self insideStarting(final ElementPattern ancestor) { return with(new PatternCondition("insideStarting") { @Override public boolean accepts(@NotNull PsiElement start, ProcessingContext context) {