diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java
index 6beb28ed4419..c65a3d9a45fd 100644
--- a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java
+++ b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java
@@ -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);
diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java b/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java
index b5af79290948..43ba211fd2f0 100644
--- a/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java
+++ b/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java
@@ -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();
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 96acbd3ec591..a76ea0da0af5 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java
@@ -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();
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java b/platform/platform-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java
index f1577314dade..379056243569 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java
+++ b/platform/platform-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java
@@ -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);
diff --git a/platform/platform-api/src/com/intellij/openapi/options/FontSize.java b/platform/platform-api/src/com/intellij/openapi/options/FontSize.java
new file mode 100644
index 000000000000..1963791c5adf
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/openapi/options/FontSize.java
@@ -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 'font-size' property values).
+ *
+ * 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;
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java
index 25bde40ea7aa..8f347c825d37 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java
@@ -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 myFonts = new EnumMap(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 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());
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/DelegateColorScheme.java b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/DelegateColorScheme.java
index f5e6dfc1f0ce..8475188e09af 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/DelegateColorScheme.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/DelegateColorScheme.java
@@ -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();
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java
index 26c9c2c6b443..070e853c27b8 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java
@@ -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();
+ }
}
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 3887e3583e17..af207585d4a5 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
@@ -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;
}
diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties
index fcdb403e126b..d359268ed914 100644
--- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties
+++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties
@@ -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:
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java
index 1d72e0b3f8a4..365a0c64bab4 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java
@@ -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();
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java
index cc132d1a7ecc..ceb0cf688dfd 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java
@@ -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();
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java
index 3adb2a26a7fb..ae440c5402c3 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java
@@ -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);
}
diff --git a/plugins/groovy/resources/inspectionDescriptions/GroovyAccessibility.html b/plugins/groovy/resources/inspectionDescriptions/GroovyAccessibility.html
new file mode 100644
index 000000000000..4a1c9cc15c75
--- /dev/null
+++ b/plugins/groovy/resources/inspectionDescriptions/GroovyAccessibility.html
@@ -0,0 +1,6 @@
+
+
+
+This inspection reports all references which exceed access rights.
+
Powered by InspectorGroovy
+
\ No newline at end of file
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties
index ce1156ed033a..7d372d9b73c1 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties
@@ -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"
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java
index 258571806c4a..9704abc4cfb7 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java
@@ -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 {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyFix.java
index 49ea83d4bf0a..1309857a4275 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyFix.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyFix.java
@@ -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() {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties
index 6fa06f83eb3a..8f08a7f701cf 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties
@@ -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
\ No newline at end of file
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionProvider.java
index e89d519e06bc..cf7199c1f789 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionProvider.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionProvider.java
@@ -135,6 +135,7 @@ public class GroovyInspectionProvider implements InspectionToolProvider, Applica
GroovyInfiniteRecursionInspection.class,
GroovyDivideByZeroInspection.class,
GroovyResultOfObjectAllocationIgnoredInspection.class,
+ GroovyAccessibilityInspection.class,
GroovyClassNamingConventionInspection.class,
GroovyInterfaceNamingConventionInspection.class,
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyAccessibilityInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyAccessibilityInspection.java
new file mode 100644
index 000000000000..a1d885d4a0dc
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyAccessibilityInspection.java
@@ -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 fixes = new ArrayList();
+ 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;
+ }
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java
index 268e8fc0d27d..c20426953418 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java
@@ -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;
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java
index e2693ef2ab23..5f7ffd506860 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java
@@ -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 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());
}
diff --git a/plugins/groovy/testdata/highlighting/InaccessibleConstructorCall.groovy b/plugins/groovy/testdata/highlighting/InaccessibleConstructorCall.groovy
new file mode 100644
index 000000000000..ab047c55d7d5
--- /dev/null
+++ b/plugins/groovy/testdata/highlighting/InaccessibleConstructorCall.groovy
@@ -0,0 +1,9 @@
+class Base {
+ private Base(int i){}
+}
+
+class Extension extends Base {
+ def Extension() {
+ super(1)
+ }
+}
\ No newline at end of file