Merge branch 'master' of git.labs.intellij.net:idea/community

This commit is contained in:
Bas Leijdekkers
2011-01-26 14:36:09 +01:00
23 changed files with 591 additions and 53 deletions
@@ -845,14 +845,15 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract
private String myName;
private boolean myIsNew = false;
private MyColorScheme(EditorColorsScheme parenScheme) {
super(parenScheme, DefaultColorSchemesManager.getInstance());
myFontSize = parenScheme.getEditorFontSize();
myLineSpacing = parenScheme.getLineSpacing();
myFontName = parenScheme.getEditorFontName();
myName = parenScheme.getName();
if (parenScheme instanceof ExternalizableScheme) {
getExternalInfo().copy(((ExternalizableScheme)parenScheme).getExternalInfo());
private MyColorScheme(EditorColorsScheme parentScheme) {
super(parentScheme, DefaultColorSchemesManager.getInstance());
myFontSize = parentScheme.getEditorFontSize();
myLineSpacing = parentScheme.getLineSpacing();
myFontName = parentScheme.getEditorFontName();
setQuickDocFontSize(parentScheme.getQuickDocFontSize());
myName = parentScheme.getName();
if (parentScheme instanceof ExternalizableScheme) {
getExternalInfo().copy(((ExternalizableScheme)parentScheme).getExternalInfo());
}
initFonts();
}
@@ -897,6 +898,7 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract
if (myFontSize != myParentScheme.getEditorFontSize()) return true;
if (myLineSpacing != myParentScheme.getLineSpacing()) return true;
if (!myFontName.equals(myParentScheme.getEditorFontName())) return true;
if (myQuickDocFontSize != myParentScheme.getQuickDocFontSize()) return true;
return false;
}
@@ -908,6 +910,7 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract
scheme.setEditorFontSize(myFontSize);
scheme.setEditorFontName(myFontName);
scheme.setLineSpacing(myLineSpacing);
scheme.setQuickDocFontSize(getQuickDocFontSize());
for (EditorSchemeAttributeDescriptor descriptor : myDescriptors) {
descriptor.apply(scheme);
@@ -20,6 +20,7 @@ import com.intellij.application.options.SelectFontDialog;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
import com.intellij.openapi.options.FontSize;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.ui.FixedSizeButton;
@@ -34,13 +35,18 @@ import javax.swing.event.DocumentEvent;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class FontOptions extends JPanel implements OptionsPanel{
private final ColorAndFontOptions myOptions;
private JTextField myEditorFontSizeField;
private JComboBox myEditorJavaDocFontSizeBox;
private JTextField myLineSpacingField;
private JTextField myFontNameField;
@@ -67,18 +73,14 @@ public class FontOptions extends JPanel implements OptionsPanel{
myLineSpacingField.setText(Float.toString(getCurrentScheme().getLineSpacing()));
myEditorFontSizeField.setText(Integer.toString(getCurrentScheme().getEditorFontSize()));
myEditorJavaDocFontSizeBox.setSelectedItem(getCurrentScheme().getQuickDocFontSize());
myFontNameField.setText(getCurrentScheme().getEditorFontName());
if (ColorAndFontOptions.isReadOnly(myOptions.getSelectedScheme())) {
myLineSpacingField.setEnabled(false);
myEditorFontSizeField.setEditable(false);
myFontNameField.setEnabled(false);
}
else {
myLineSpacingField.setEnabled(true);
myEditorFontSizeField.setEditable(true);
myFontNameField.setEnabled(true);
}
boolean enabled = !ColorAndFontOptions.isReadOnly(myOptions.getSelectedScheme());
myLineSpacingField.setEnabled(enabled);
myEditorFontSizeField.setEditable(enabled);
myFontNameField.setEnabled(enabled);
myEditorJavaDocFontSizeBox.setEnabled(enabled);
myIsInSchemeChange = false;
@@ -100,6 +102,13 @@ public class FontOptions extends JPanel implements OptionsPanel{
}
private JPanel createFontPanel() {
JPanel result = new JPanel(new GridLayout(2, 1));
result.add(createEditorFontPanel());
result.add(createJavaDocFontPanel());
return result;
}
private JPanel createEditorFontPanel() {
JPanel editorFontPanel = new JPanel();
editorFontPanel.setBorder(IdeBorderFactory.createTitledBorder(ApplicationBundle.message("group.editor.font")));
editorFontPanel.setLayout(new GridBagLayout());
@@ -202,6 +211,31 @@ public class FontOptions extends JPanel implements OptionsPanel{
return editorFontPanel;
}
private JPanel createJavaDocFontPanel() {
JPanel result = new JPanel(new FlowLayout(FlowLayout.LEFT));
result.setBorder(IdeBorderFactory.createTitledBorder(ApplicationBundle.message("group.quickdoc.font")));
result.add(new JLabel(ApplicationBundle.message("editbox.font.size")));
myEditorJavaDocFontSizeBox = new JComboBox(FontSize.values());
result.add(myEditorJavaDocFontSizeBox);
myEditorJavaDocFontSizeBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (myIsInSchemeChange) {
return;
}
Object item = e.getItem();
if (e.getStateChange() != ItemEvent.SELECTED || !(item instanceof FontSize)) {
return;
}
getCurrentScheme().setQuickDocFontSize((FontSize)item);
updateDescription(true);
}
});
return result;
}
private void selectFont() {
initFontTables();
@@ -27,6 +27,11 @@ import com.intellij.lang.documentation.DocumentationProvider;
import com.intellij.lang.documentation.ExternalDocumentationHandler;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
import com.intellij.openapi.editor.ex.util.EditorUtil;
import com.intellij.openapi.options.FontSize;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.IconLoader;
@@ -35,7 +40,6 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.SmartPointerManager;
import com.intellij.psi.SmartPsiElementPointer;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.SideBorder;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.util.Consumer;
@@ -46,7 +50,7 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.View;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.*;
import java.util.List;
@@ -67,6 +71,7 @@ public class DocumentationComponent extends JPanel implements Disposable {
private boolean myIsEmpty;
private boolean myIsShown;
private final JLabel myElementLabel;
private Style myFontSizeStyle;
private static class Context {
final SmartPsiElementPointer element;
@@ -146,7 +151,36 @@ public class DocumentationComponent extends JPanel implements Disposable {
myEditorPane.setEditable(false);
myEditorPane.setBackground(HintUtil.INFORMATION_COLOR);
myEditorPane.setEditorKit(UIUtil.getHTMLEditorKit());
myScrollPane = ScrollPaneFactory.createScrollPane(myEditorPane);
myScrollPane = new JBScrollPane(myEditorPane) {
@Override
protected void processMouseWheelEvent(MouseWheelEvent e) {
if (!EditorSettingsExternalizable.getInstance().isWheelFontChangeEnabled() || !EditorUtil.isChangeFontSize(e)) {
super.processMouseWheelEvent(e);
return;
}
int change = Math.abs(e.getWheelRotation());
boolean increase = e.getWheelRotation() <= 0;
EditorColorsManager colorsManager = EditorColorsManager.getInstance();
EditorColorsScheme scheme = colorsManager.getGlobalScheme();
FontSize newFontSize = scheme.getQuickDocFontSize();
for (; change > 0; change--) {
if (increase) {
newFontSize = newFontSize.larger();
}
else {
newFontSize = newFontSize.smaller();
}
}
if (newFontSize == scheme.getQuickDocFontSize()) {
return;
}
scheme.setQuickDocFontSize(newFontSize);
applyFontSize();
}
};
myScrollPane.setBorder(null);
final MouseAdapter mouseAdapter = new MouseAdapter() {
@@ -332,12 +366,14 @@ public class DocumentationComponent extends JPanel implements Disposable {
if (!myIsShown && myHint != null) {
myEditorPane.setText(text);
applyFontSize();
myManager.showHint(myHint);
myIsShown = justShown = true;
}
if (!justShown) {
myEditorPane.setText(text);
applyFontSize();
}
if (!skip) {
@@ -351,6 +387,23 @@ public class DocumentationComponent extends JPanel implements Disposable {
});
}
private void applyFontSize() {
Document document = myEditorPane.getDocument();
if (!(document instanceof StyledDocument)) {
return;
}
StyledDocument styledDocument = (StyledDocument)document;
if (myFontSizeStyle == null) {
myFontSizeStyle = styledDocument.addStyle("active", null);
}
EditorColorsManager colorsManager = EditorColorsManager.getInstance();
EditorColorsScheme scheme = colorsManager.getGlobalScheme();
StyleConstants.setFontSize(myFontSizeStyle, scheme.getQuickDocFontSize().getSize());
styledDocument.setCharacterAttributes(0, document.getLength(), myFontSizeStyle, true);
}
private void goBack() {
if (myBackStack.isEmpty()) return;
Context context = myBackStack.pop();
@@ -16,9 +16,11 @@
package com.intellij.openapi.editor.colors;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.options.FontSize;
import com.intellij.openapi.options.Scheme;
import com.intellij.openapi.util.JDOMExternalizable;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
@@ -39,6 +41,9 @@ public interface EditorColorsScheme extends Cloneable, JDOMExternalizable, Schem
int getEditorFontSize();
void setEditorFontSize(int fontSize);
FontSize getQuickDocFontSize();
void setQuickDocFontSize(@NotNull FontSize fontSize);
String getEditorFontName();
void setEditorFontName(String fontName);
@@ -0,0 +1,76 @@
/*
* 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.options;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.text.html.StyleSheet;
/**
* Enumerates common font size values (inspired by CSS <code>'font-size'</code> property values).
* <p/>
* Note that such elements selection (and this enum existence at all) is based on the fact that standard Swing {@link JEditorPane}
* used by IJ for providing quick doc works only with predefined set of font sizes (see {@link StyleSheet#sizeMapDefault}).
*
* @author Denis Zhdanov
* @since 1/26/11 10:22 AM
*/
public enum FontSize {
XX_SMALL(8), X_SMALL(10), SMALL(12), MEDIUM(14), LARGE(18), X_LARGE(24), XX_LARGE(36);
private final String myName;
private final int mySize;
FontSize(int size) {
myName = ApplicationBundle.message("font.size." + StringUtil.toLowerCase(name().replace("_", "")));
mySize = size;
}
public int getSize() {
return mySize;
}
/**
* @return {@link FontSize} that is one unit large than the current one; current object if it already stands for a maximum size
*/
@NotNull
public FontSize larger() {
int i = ordinal();
return i >= values().length - 1 ? this : values()[i + 1];
}
/**
* @return {@link FontSize} that is one unit smaller than the current one; current object if it already stands for a minimum size
*/
@NotNull
public FontSize smaller() {
int i = ordinal();
return i > 0 ? values()[i - 1] : this;
}
public String getEnumName() {
return super.toString();
}
@Override
public String toString() {
return myName;
}
}
@@ -24,6 +24,7 @@ import com.intellij.openapi.editor.colors.*;
import com.intellij.openapi.editor.colors.ex.DefaultColorSchemesManager;
import com.intellij.openapi.editor.markup.EffectType;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.options.FontSize;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
@@ -32,15 +33,20 @@ import com.intellij.util.containers.HashMap;
import gnu.trove.THashMap;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.util.*;
import java.util.List;
public abstract class AbstractColorsScheme implements EditorColorsScheme {
private static final FontSize DEFAULT_FONT_SIZE = FontSize.SMALL;
protected EditorColorsScheme myParentScheme;
protected int myEditorFontSize;
protected FontSize myQuickDocFontSize = DEFAULT_FONT_SIZE;
protected float myLineSpacing;
private final Map<EditorFontType, Font> myFonts = new EnumMap<EditorFontType, Font>(EditorFontType.class);
@@ -71,6 +77,7 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
@NonNls private static final String BACKGROUND_COLOR_NAME = "BACKGROUND";
@NonNls private static final String LINE_SPACING = "LINE_SPACING";
@NonNls private static final String EDITOR_FONT_SIZE = "EDITOR_FONT_SIZE";
@NonNls private static final String EDITOR_QUICK_JAVADOC_FONT_SIZE = "EDITOR_QUICK_DOC_FONT_SIZE";
protected AbstractColorsScheme(EditorColorsScheme parentScheme, DefaultColorSchemesManager defaultColorSchemesManager) {
myParentScheme = parentScheme;
@@ -109,6 +116,7 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
newScheme.myEditorFontSize = myEditorFontSize;
newScheme.myLineSpacing = myLineSpacing;
newScheme.setEditorFontName(getEditorFontName());
newScheme.myQuickDocFontSize = myQuickDocFontSize;
final Set<EditorFontType> types = myFonts.keySet();
for (EditorFontType type : types) {
@@ -130,6 +138,11 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
myEditorFontSize = fontSize;
initFonts();
}
@Override
public void setQuickDocFontSize(@NotNull FontSize fontSize) {
myQuickDocFontSize = fontSize;
}
public void setLineSpacing(float lineSpacing) {
myLineSpacing = lineSpacing;
@@ -154,6 +167,12 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
return myEditorFontSize;
}
@NotNull
@Override
public FontSize getQuickDocFontSize() {
return myQuickDocFontSize;
}
public float getLineSpacing() {
return myLineSpacing <= 0 ? 1.0f : myLineSpacing;
}
@@ -307,6 +326,9 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
else if (EDITOR_FONT_SIZE.equals(name)) {
myEditorFontSize = Integer.parseInt(value);
}
else if (EDITOR_QUICK_JAVADOC_FONT_SIZE.equals(name)) {
myQuickDocFontSize = FontSize.valueOf(value);
}
else if (AbstractColorsScheme.EDITOR_FONT_NAME.equals(name)) {
setEditorFontName(value);
}
@@ -330,6 +352,13 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
element.setAttribute(VALUE_ELEMENT, String.valueOf(getEditorFontSize()));
parentNode.addContent(element);
if (DEFAULT_FONT_SIZE != getQuickDocFontSize()) {
element = new Element(OPTION_ELEMENT);
element.setAttribute(NAME_ATTR, EDITOR_QUICK_JAVADOC_FONT_SIZE);
element.setAttribute(VALUE_ELEMENT, getQuickDocFontSize().getEnumName());
parentNode.addContent(element);
}
element = new Element(OPTION_ELEMENT);
element.setAttribute(NAME_ATTR, EDITOR_FONT_NAME);
element.setAttribute(VALUE_ELEMENT, getEditorFontName());
@@ -20,6 +20,7 @@ import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.colors.EditorFontType;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.options.FontSize;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import org.jdom.Element;
@@ -87,6 +88,16 @@ public abstract class DelegateColorScheme implements EditorColorsScheme {
myDelegate.setEditorFontSize(fontSize);
}
@Override
public FontSize getQuickDocFontSize() {
return myDelegate.getQuickDocFontSize();
}
@Override
public void setQuickDocFontSize(@NotNull FontSize fontSize) {
myDelegate.setQuickDocFontSize(fontSize);
}
@Override
public String getEditorFontName() {
return myDelegate.getEditorFontName();
@@ -24,10 +24,12 @@ import com.intellij.openapi.editor.impl.ComplementaryFontsRegistry;
import com.intellij.openapi.editor.impl.FontInfo;
import com.intellij.openapi.editor.impl.IterationState;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.awt.event.MouseWheelEvent;
import java.util.List;
public class EditorUtil {
@@ -576,6 +578,12 @@ public class EditorUtil {
editor.getSelectionModel().removeSelection();
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
}
public static boolean isChangeFontSize(MouseWheelEvent e) {
return SystemInfo.isMac
? !e.isControlDown() && e.isMetaDown() && !e.isAltDown() && !e.isShiftDown()
: e.isControlDown() && !e.isMetaDown() && !e.isAltDown() && !e.isShiftDown();
}
}
@@ -55,6 +55,7 @@ import com.intellij.openapi.editor.impl.softwrap.SoftWrapHelper;
import com.intellij.openapi.editor.markup.*;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory;
import com.intellij.openapi.options.FontSize;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Queryable;
@@ -4973,6 +4974,16 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
initFonts();
}
@Override
public FontSize getQuickDocFontSize() {
return myGlobalScheme.getQuickDocFontSize();
}
@Override
public void setQuickDocFontSize(@NotNull FontSize fontSize) {
myGlobalScheme.setQuickDocFontSize(fontSize);
}
public String getEditorFontName() {
if (myFaceName == null) {
return getGlobal().getEditorFontName();
@@ -5520,12 +5531,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
info.put("caret", visual.getLine() + ":" + visual.getColumn());
}
public static boolean isChangeFontSize(MouseWheelEvent e) {
return SystemInfo.isMac
? !e.isControlDown() && e.isMetaDown() && !e.isAltDown() && !e.isShiftDown()
: e.isControlDown() && !e.isMetaDown() && !e.isAltDown() && !e.isShiftDown();
}
private class MyScrollPane extends JBScrollPane {
@@ -5535,7 +5540,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
protected void processMouseWheelEvent(MouseWheelEvent e) {
if (mySettings.isWheelFontChangeEnabled()) {
if (isChangeFontSize(e)) {
if (EditorUtil.isChangeFontSize(e)) {
setFontSize(myScheme.getEditorFontSize() - e.getWheelRotation());
return;
}
@@ -477,6 +477,14 @@ title.colors.and.fonts=Colors \\& Fonts
progress.analysing.font=Analysing font: {0}
button.edit.scopes=Edit Scopes...
group.editor.font=Editor Font
group.quickdoc.font=QuickDoc Font
font.size.xxsmall=xx-small
font.size.xsmall=x-small
font.size.small=small
font.size.medium=medium
font.size.large=large
font.size.xlarge=x-large
font.size.xxlarge=xx-large
label.font.name=Name:
editbox.font.size=Size:
editbox.line.spacing=Line spacing:
@@ -20,6 +20,8 @@ import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.filters.HyperlinkInfo;
import com.intellij.execution.filters.OpenFileHyperlinkInfo;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ProgramRunner;
@@ -190,6 +192,11 @@ public class XDebugSessionImpl implements XDebugSession {
myDependentBreakpointListener = new MyDependentBreakpointListener();
dependentBreakpointManager.addListener(myDependentBreakpointListener);
myDebugProcess.getProcessHandler().addProcessListener(new ProcessAdapter() {
public void processTerminated(final ProcessEvent event) {
stopImpl();
}
});
if (!myShowTabOnSuspend) {
initSessionTab();
}
@@ -562,7 +569,7 @@ public class XDebugSessionImpl implements XDebugSession {
return myStopped;
}
public void stopImpl() {
private void stopImpl() {
if (myStopped) return;
myDebugProcess.stop();
@@ -184,9 +184,11 @@ public class XDebuggerManagerImpl extends XDebuggerManager implements ProjectCom
public void removeSession(@NotNull XDebugSessionImpl session) {
XDebugSessionTab sessionTab = session.getSessionTab();
XDebugSessionData data = sessionTab.saveData();
mySessions.remove(session);
mySessionData.put(session.getDebugProcess().getProcessHandler(), data);
if (sessionTab != null) {
XDebugSessionData data = sessionTab.saveData();
mySessionData.put(session.getDebugProcess().getProcessHandler(), data);
}
if (myActiveSession == session) {
myActiveSession = null;
onActiveSessionChanged();
@@ -21,8 +21,6 @@ import com.intellij.execution.ExecutionResult;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ProgramRunner;
@@ -35,7 +33,10 @@ import com.intellij.execution.ui.actions.CloseAction;
import com.intellij.execution.ui.layout.PlaceInGrid;
import com.intellij.ide.CommonActionsManager;
import com.intellij.ide.actions.ContextHelpAction;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.ui.content.Content;
@@ -44,7 +45,6 @@ import com.intellij.util.ArrayUtil;
import com.intellij.xdebugger.XDebugProcess;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XDebuggerBundle;
import com.intellij.xdebugger.impl.XDebugSessionImpl;
import com.intellij.xdebugger.impl.actions.XDebuggerActions;
import com.intellij.xdebugger.impl.frame.XDebugViewBase;
import com.intellij.xdebugger.impl.frame.XFramesView;
@@ -145,11 +145,6 @@ public class XDebugSessionTab extends DebuggerSessionTabBase {
private static ExecutionResult createExecutionResult(@NotNull final XDebugSession session) {
final XDebugProcess debugProcess = session.getDebugProcess();
ProcessHandler processHandler = debugProcess.getProcessHandler();
processHandler.addProcessListener(new ProcessAdapter() {
public void processTerminated(final ProcessEvent event) {
((XDebugSessionImpl)session).stopImpl();
}
});
return new DefaultExecutionResult(debugProcess.createConsole(), processHandler);
}
@@ -0,0 +1,6 @@
<html>
<body>
<font face="verdana" size="-1">
This inspection reports all references which exceed access rights.
</font><br><small>Powered by InspectorGroovy</small></body>
</html>
@@ -178,7 +178,7 @@ change.modifier=Make ''{0}'' {1}
change.modifier.not=Make ''{0}'' not {1}
change.modifier.family.name=Change modifiers
# suppress inspection "UnusedProperty"
packageLocal.visibility.presentation=property
packageLocal.visibility.presentation=default visible
# suppress inspection "UnusedProperty"
protected.visibility.presentation=protected
# suppress inspection "UnusedProperty"
@@ -25,16 +25,16 @@ import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.search.searches.SuperMethodsSearch;
import com.intellij.psi.util.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.MethodSignature;
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.HashSet;
import com.intellij.util.containers.MultiMap;
import gnu.trove.THashSet;
@@ -185,13 +185,13 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
if (resolved instanceof PsiMember) {
highlightMemberResolved(myHolder, referenceExpression, ((PsiMember)resolved));
}
if (!resolveResult.isAccessible()) {
/*if (!resolveResult.isAccessible()) {
String message = GroovyBundle.message("cannot.access", referenceExpression.getReferenceName());
final Annotation annotation = myHolder.createWarningAnnotation(getElementToHighlight(referenceExpression), message);
if (resolved instanceof PsiMember) {
registerAccessFix(annotation, referenceExpression, ((PsiMember)resolved));
}
}
}*/
//todo uncomment when correct isStatic() is working
if (!resolveResult.isStaticsOK() && resolved instanceof PsiModifierListOwner) {
@@ -252,6 +252,7 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
}
}
/*
private static void registerAccessFix(Annotation annotation, PsiElement place, PsiMember refElement) {
if (refElement instanceof PsiCompiledElement) return;
PsiModifierList modifierList = refElement.getModifierList();
@@ -284,6 +285,7 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
LOG.error(e);
}
}
*/
private static void registerStaticImportFix(GrReferenceExpression referenceExpression, Annotation annotation) {
final String referenceName = referenceExpression.getReferenceName();
@@ -580,7 +582,7 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
checkDefaultMapConstructor(myHolder, argList, constructor);
}
if (!constructorResolveResult.isAccessible()) {
/* if (!constructorResolveResult.isAccessible()) {
String message = GroovyBundle.message("cannot.access", PsiFormatUtil.formatMethod((PsiMethod)constructor, PsiSubstitutor.EMPTY,
PsiFormatUtil.SHOW_NAME |
PsiFormatUtil.SHOW_TYPE |
@@ -590,7 +592,7 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
));
final Annotation annotation = myHolder.createWarningAnnotation(getElementToHighlight(refElement), message);
registerAccessFix(annotation, refElement, ((PsiMember)constructor));
}
}*/
}
else {
@@ -35,6 +35,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner;
public abstract class GroovyFix implements LocalQuickFix {
public static final GroovyFix[] EMPTY_ARRAY = new GroovyFix[0];
//to appear in "Apply Fix" statement when multiple Quick Fixes exist
@NotNull
public String getFamilyName() {
@@ -59,3 +59,7 @@ pointless.boolean.quickfix=Simplify
Cannot.perform.undo.operation=Cannot perform undo operation
Undo.disable=Undo disabled
field.already.defined=Variables with field names
access.to.inaccessible.element=Access to inaccessible element
cannot.reference.nonstatic=Cannot reference nonstatic symbol ''{0}'' from static context
@@ -135,6 +135,7 @@ public class GroovyInspectionProvider implements InspectionToolProvider, Applica
GroovyInfiniteRecursionInspection.class,
GroovyDivideByZeroInspection.class,
GroovyResultOfObjectAllocationIgnoredInspection.class,
GroovyAccessibilityInspection.class,
GroovyClassNamingConventionInspection.class,
GroovyInterfaceNamingConventionInspection.class,
@@ -0,0 +1,253 @@
/*
* 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.jetbrains.plugins.groovy.codeInspection.bugs;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiFormatUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.GroovyBundle;
import org.jetbrains.plugins.groovy.codeInspection.BaseInspection;
import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor;
import org.jetbrains.plugins.groovy.codeInspection.GroovyFix;
import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle;
import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrConstructorCall;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
import java.util.ArrayList;
import java.util.List;
/**
* @author Maxim.Medvedev
*/
public class GroovyAccessibilityInspection extends BaseInspection {
private static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.codeInspection.bugs.GroovyAccessibilityInspection");
@Override
protected BaseInspectionVisitor buildVisitor() {
return new MyVisitor();
}
@Nls
@NotNull
@Override
public String getGroupDisplayName() {
return PROBABLE_BUGS;
}
@Nls
@NotNull
@Override
public String getDisplayName() {
return GroovyInspectionBundle.message("access.to.inaccessible.element");
}
@Override
protected String buildErrorString(Object... args) {
return GroovyBundle.message("cannot.access", args);
}
@Override
protected GroovyFix[] buildFixes(PsiElement location) {
if (!(location instanceof GrReferenceElement || location instanceof GrConstructorCall)) {
location = location.getParent();
}
final GroovyResolveResult resolveResult;
if (location instanceof GrConstructorCall) {
resolveResult = ((GrConstructorCall)location).advancedResolve();
}
else {
resolveResult = ((GrReferenceElement)location).advancedResolve();
}
final PsiElement element = resolveResult.getElement();
if (!(element instanceof PsiMember)) return GroovyFix.EMPTY_ARRAY;
final PsiMember refElement = (PsiMember)element;
if (refElement instanceof PsiCompiledElement) return GroovyFix.EMPTY_ARRAY;
PsiModifierList modifierList = refElement.getModifierList();
if (modifierList == null) return GroovyFix.EMPTY_ARRAY;
List<GroovyFix> fixes = new ArrayList<GroovyFix>();
try {
Project project = refElement.getProject();
JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
PsiModifierList modifierListCopy = facade.getElementFactory().createFieldFromText("int a;", null).getModifierList();
modifierListCopy.setModifierProperty(PsiModifier.STATIC, modifierList.hasModifierProperty(PsiModifier.STATIC));
@Modifier String minModifier = PsiModifier.PROTECTED;
if (refElement.hasModifierProperty(PsiModifier.PROTECTED)) {
minModifier = PsiModifier.PUBLIC;
}
String[] modifiers = {PsiModifier.PROTECTED, PsiModifier.PUBLIC, PsiModifier.PACKAGE_LOCAL};
PsiClass accessObjectClass = PsiTreeUtil.getParentOfType(location, PsiClass.class, false);
if (accessObjectClass == null) {
accessObjectClass = ((GroovyFile)location.getContainingFile()).getScriptClass();
}
for (int i = ArrayUtil.indexOf(modifiers, minModifier); i < modifiers.length; i++) {
String modifier = modifiers[i];
modifierListCopy.setModifierProperty(modifier, true);
if (facade.getResolveHelper().isAccessible(refElement, modifierListCopy, location, accessObjectClass, null)) {
fixes.add(new GrModifierFix(refElement, refElement.getModifierList(), modifier, true));
}
}
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
return fixes.toArray(new GroovyFix[fixes.size()]);
}
private static class GrModifierFix extends GroovyFix {
private PsiMember myMember;
private PsiModifierList myModifierList;
private String myModifier;
private boolean myDoSet;
public GrModifierFix(@NotNull PsiMember member,
@NotNull PsiModifierList modifierList,
String modifier,
boolean doSet) {
myMember = member;
myModifierList = modifierList;
myModifier = modifier;
myDoSet = doSet;
}
@Override
protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
myModifierList.setModifierProperty(myModifier, myDoSet);
}
@NotNull
@Override
public String getName() {
String name;
final PsiClass containingClass = myMember.getContainingClass();
String containingClassName;
if (containingClass != null) {
containingClassName = containingClass.getName() + ".";
}
else {
containingClassName = "";
}
name = containingClassName + myMember.getName();
String modifierText = toPresentableText(myModifier);
if (myDoSet) {
return GroovyBundle.message("change.modifier", name, modifierText);
}
else {
return GroovyBundle.message("change.modifier.not", name, modifierText);
}
}
}
private static String toPresentableText(String modifier) {
return GroovyBundle.message(modifier + ".visibility.presentation");
}
@Override
public boolean isEnabledByDefault() {
return true;
}
private static class MyVisitor extends BaseInspectionVisitor {
@Override
public void visitCodeReferenceElement(GrCodeReferenceElement refElement) {
super.visitCodeReferenceElement(refElement);
checkRef(refElement);
}
@Override
public void visitReferenceExpression(GrReferenceExpression ref) {
super.visitReferenceExpression(ref);
checkRef(ref);
}
@Override
public void visitNewExpression(GrNewExpression newExpression) {
checkConstructorCall(newExpression);
}
private void checkConstructorCall(GrConstructorCall call) {
final GroovyResolveResult result = call.advancedResolve();
if (result.getElement() == null) return;
final PsiElement constructor = result.getElement();
if (!(constructor instanceof PsiMethod)) return;
if (!result.isAccessible()) {
PsiElement refElement = null;
if (call instanceof GrNewExpression) {
refElement = ((GrNewExpression)call).getReferenceElement();
}
else if (call instanceof GrConstructorInvocation) {
refElement = ((GrConstructorInvocation)call).getThisOrSuperKeyword();
}
if (refElement == null) {
refElement = call;
}
registerError(refElement,
PsiFormatUtil.formatMethod((PsiMethod)constructor, PsiSubstitutor.EMPTY,
PsiFormatUtil.SHOW_NAME |
PsiFormatUtil.SHOW_TYPE |
PsiFormatUtil.TYPE_AFTER |
PsiFormatUtil.SHOW_PARAMETERS,
PsiFormatUtil.SHOW_TYPE
));
}
}
@Override
public void visitConstructorInvocation(GrConstructorInvocation invocation) {
super.visitConstructorInvocation(invocation);
checkConstructorCall(invocation);
}
private void checkRef(GrReferenceElement ref) {
final GroovyResolveResult result = ref.advancedResolve();
if (result == null) return;
if (result.getElement() == null) return;
if (!result.isAccessible()) {
registerError(getErrorLocation(ref), ref.getReferenceName());
}
}
@NotNull
private static PsiElement getErrorLocation(GrReferenceElement ref) {
final PsiElement nameElement = ref.getReferenceNameElement();
if (nameElement != null) return nameElement;
return ref;
}
}
}
@@ -48,6 +48,7 @@ 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.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod;
@@ -432,7 +433,12 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements
PsiClass containingClass = method.getContainingClass();
if (containingClass != null && CommonClassNames.JAVA_LANG_OBJECT.equals(containingClass.getQualifiedName()) &&
"getClass".equals(method.getName())) {
result = getTypeForObjectGetClass(facade, method);
if (seemsToBeQualifiedClassName(getQualifierExpression())) {
result = createJavaLangClassType(facade, facade.getElementFactory().createTypeFromText(getQualifier().getText(), this));
}
else {
result = getTypeForObjectGetClass(facade, method);
}
} else {
result = PsiUtil.getSmartReturnType(method);
}
@@ -454,7 +460,12 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements
else if (resolved == null) {
GrExpression qualifier = getQualifierExpression();
if ("class".equals(getReferenceName())) {
result = createJavaLangClassType(JavaPsiFacade.getInstance(getProject()), getQualifierType());
if (seemsToBeQualifiedClassName(qualifier)) {
assert qualifier != null;
result = createJavaLangClassType(facade, facade.getElementFactory().createTypeFromText(qualifier.getText(), this));
} else {
result = createJavaLangClassType(facade, getQualifierType());
}
}
else {
if (qualifier != null) {
@@ -487,6 +498,15 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements
}
}
private static boolean seemsToBeQualifiedClassName(@Nullable GrExpression qualifier) {
if (qualifier == null) return false;
while (qualifier instanceof GrReferenceExpression) {
if (((GrReferenceExpression)qualifier).getReferenceNameElement() instanceof GrLiteral) return false;
qualifier = ((GrReferenceExpression)qualifier).getQualifierExpression();
}
return qualifier == null;
}
@Nullable
private PsiType createJavaLangClassType(JavaPsiFacade facade, @Nullable PsiType type) {
PsiType result = null;
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.codeInspection.GroovyImportsTracker;
import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection;
import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyUncheckedAssignmentOfMemberOfRawTypeInspection;
import org.jetbrains.plugins.groovy.codeInspection.bugs.GroovyAccessibilityInspection;
import org.jetbrains.plugins.groovy.codeInspection.bugs.GroovyResultOfObjectAllocationIgnoredInspection;
import org.jetbrains.plugins.groovy.codeInspection.control.GroovyTrivialConditionalInspection;
import org.jetbrains.plugins.groovy.codeInspection.control.GroovyTrivialIfInspection;
@@ -262,12 +263,16 @@ public class GroovyHighlightingTest extends LightCodeInsightFixtureTestCase {
public void testTupleTypeAssignments() throws Exception{doTest(new GroovyAssignabilityCheckInspection());}
public void testUnusedImportsForImportsOnDemand() throws Exception {
doTest();
doTest(new GroovyAccessibilityInspection());
final Set<GrImportStatement> unusedImportStatements =
GroovyImportsTracker.getInstance(getProject()).getUnusedImportStatements(((GroovyFile)myFixture.getFile()));
assertEquals(0, unusedImportStatements.size());
}
public void testInaccessibleConstructorCall() {
doTest(new GroovyAccessibilityInspection());
}
public void testSignatureIsNotApplicableToList() throws Exception {
doTest(new GroovyAssignabilityCheckInspection());
}
@@ -0,0 +1,9 @@
class Base {
private Base(int i){}
}
class Extension extends Base {
def Extension() {
<warning descr="Access to 'Base(int)' exceeds its access rights">super</warning>(1)
}
}