Merge remote-tracking branch 'origin/master'

This commit is contained in:
Roman Shevchenko
2015-05-20 16:11:17 +02:00
56 changed files with 363 additions and 373 deletions
@@ -15,19 +15,14 @@
*/
package org.intellij.images.options.impl;
import com.intellij.ide.ui.ConfigurableOptionsTopHitProvider;
import com.intellij.application.options.editor.EditorOptionsTopHitProviderBase;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.project.Project;
/**
* @author Sergey.Malenkov
*/
public class ImagesOptionsTopHitProvider extends ConfigurableOptionsTopHitProvider {
@Override
public String getId() {
return "editor";
}
public class ImagesOptionsTopHitProvider extends EditorOptionsTopHitProviderBase {
@Override
protected Configurable getConfigurable(Project project) {
return new OptionsConfigurabe();
@@ -941,6 +941,10 @@ public class HighlightUtil extends HighlightUtilBase {
isAllowed &= modifierOwnerParent instanceof PsiClass && !((PsiClass)modifierOwnerParent).isInterface();
}
if (containingClass != null && containingClass.isInterface()) {
isAllowed &= !PsiModifier.NATIVE.equals(modifier);
}
if (containingClass != null && containingClass.isAnnotationType()) {
isAllowed &= !PsiModifier.STATIC.equals(modifier);
isAllowed &= !PsiModifier.DEFAULT.equals(modifier);
@@ -1518,6 +1522,12 @@ public class HighlightUtil extends HighlightUtilBase {
.descriptionAndTooltip(JavaErrorMessages.message("bad.qualifier.in.super.method.reference", format(aClass), formatClass(superClass))).create();
}
}
if (expr instanceof PsiSuperExpression && !classT.isInheritor(aClass, false)) {
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
.range(qualifier)
.descriptionAndTooltip(JavaErrorMessages.message("no.enclosing.instance.in.scope", format(aClass))).create();
}
}
}
@@ -22,6 +22,7 @@ import com.intellij.pom.Navigatable;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull;
/**
@@ -95,7 +96,7 @@ public class ReplaceWithTernaryOperatorFix implements LocalQuickFix {
return false;
}
return !(expression.getParent() instanceof PsiExpressionStatement);
return !(expression.getParent() instanceof PsiExpressionStatement) && !PsiUtil.isAccessedForWriting(expression);
}
private static String suggestDefaultValue(@NotNull PsiExpression expression) {
@@ -0,0 +1,5 @@
interface A {
default <error descr="Modifier 'native' not allowed here">native</error> void m(){}
static <error descr="Modifier 'native' not allowed here">native</error> void m1(){}
<error descr="Modifier 'native' not allowed here">native</error> void m2();
}
@@ -38,5 +38,12 @@ class Test {
}
};
}
interface D extends J {
default void m() {
<error descr="No enclosing instance of type 'Test.D' is in scope">D</error>.super.toString();
J.super.toString();
}
}
}
@@ -0,0 +1,9 @@
// "Replace with 'a != null ?:'" "false"
class A{
void test(){
A a = null;
<caret>a.field = 2;
}
int field;
}
@@ -36,6 +36,7 @@ public class Interface8MethodsHighlightingTest extends LightCodeInsightFixtureTe
public void testStaticMethodCalls() { doTest(false, false); }
public void testStaticMethodCallsAndOverloadResolution() { doTest(false, false); }
public void testDefaultMethodOverrideEquivalentObject() { doTest(false, false); }
public void testModifierNativeInInterface() { doTest(false, false); }
public void testStaticMethods() { doTest(false, false); }
public void testFinalStaticDefaultMethods() { doTest(false, false); }
public void testIDEA122720() { doTest(false, false); }
@@ -17,10 +17,7 @@ package com.intellij.codeInspection;
import com.intellij.codeInsight.completion.NormalCompletionDfaTest;
import com.intellij.codeInsight.completion.SmartTypeCompletionDfaTest;
import com.intellij.codeInsight.daemon.quickFix.AddAssertStatementFixTest;
import com.intellij.codeInsight.daemon.quickFix.ReplaceFromOfNullableFixTest;
import com.intellij.codeInsight.daemon.quickFix.ReplaceWithOfNullableFixTest;
import com.intellij.codeInsight.daemon.quickFix.SurroundWithIfFixTest;
import com.intellij.codeInsight.daemon.quickFix.*;
import com.intellij.slicer.SliceBackwardTest;
import com.intellij.slicer.SliceTreeTest;
import junit.framework.Test;
@@ -51,6 +48,7 @@ public class DataFlowInspectionTestSuite {
suite.addTestSuite(AddAssertStatementFixTest.class);
suite.addTestSuite(SurroundWithIfFixTest.class);
suite.addTestSuite(ReplaceWithTernaryOperatorTest.class);
suite.addTestSuite(ReplaceWithOfNullableFixTest.class);
suite.addTestSuite(ReplaceFromOfNullableFixTest.class);
return suite;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -53,18 +53,18 @@ public class FileStatusMap implements Disposable {
private final Map<Document,FileStatus> myDocumentToStatusMap = new WeakHashMap<Document, FileStatus>(); // all dirty if absent
private volatile boolean myAllowDirt = true;
public FileStatusMap(@NotNull Project project) {
FileStatusMap(@NotNull Project project) {
myProject = project;
}
@Override
public void dispose() {
// clear dangling references to PsiFiles/Documents. SCR#10358
markAllFilesDirty();
markAllFilesDirty("FileStatusMap dispose");
}
@Nullable("null means the file is clean")
public static TextRange getDirtyTextRange(@NotNull Editor editor, int passId) {
static TextRange getDirtyTextRange(@NotNull Editor editor, int passId) {
Document document = editor.getDocument();
FileStatusMap me = DaemonCodeAnalyzerEx.getInstanceEx(editor.getProject()).getFileStatusMap();
@@ -87,7 +87,7 @@ public class FileStatusMap implements Disposable {
}
}
public boolean wasErrorFound(@NotNull Document document) {
boolean wasErrorFound(@NotNull Document document) {
synchronized(myDocumentToStatusMap) {
FileStatus status = myDocumentToStatusMap.get(document);
return status != null && status.errorFound;
@@ -164,9 +164,9 @@ public class FileStatusMap implements Disposable {
}
}
public void markAllFilesDirty() {
void markAllFilesDirty(@NotNull @NonNls Object reason) {
assertAllowModifications();
LOG.debug("********************************* Mark all dirty");
LOG.debug("Mark all dirty: ", reason);
synchronized (myDocumentToStatusMap) {
myDocumentToStatusMap.clear();
}
@@ -220,10 +220,10 @@ public class FileStatusMap implements Disposable {
}
}
public void markFileScopeDirtyDefensively(@NotNull PsiFile file) {
void markFileScopeDirtyDefensively(@NotNull PsiFile file, @NotNull @NonNls Object reason) {
assertAllowModifications();
if (LOG.isDebugEnabled()) {
LOG.debug("********************************* Mark dirty file defensively: "+file.getName());
LOG.debug("Mark dirty file defensively: "+file.getName()+": "+reason);
}
// mark whole file dirty in case no subsequent PSI events will come, but file requires rehighlighting nevertheless
// e.g. in the case of quick typing/backspacing char
@@ -236,10 +236,10 @@ public class FileStatusMap implements Disposable {
}
}
public void markFileScopeDirty(@NotNull Document document, @NotNull TextRange scope, int fileLength) {
void markFileScopeDirty(@NotNull Document document, @NotNull TextRange scope, int fileLength, @NotNull @NonNls Object reason) {
assertAllowModifications();
if (LOG.isDebugEnabled()) {
LOG.debug("********************************* Mark dirty: "+scope);
LOG.debug("Mark scope dirty: "+scope+" : "+reason);
}
synchronized(myDocumentToStatusMap) {
FileStatus status = myDocumentToStatusMap.get(document);
@@ -270,7 +270,7 @@ public class FileStatusMap implements Disposable {
return document.createRangeMarker(union);
}
public boolean allDirtyScopesAreNull(@NotNull Document document) {
boolean allDirtyScopesAreNull(@NotNull Document document) {
synchronized (myDocumentToStatusMap) {
PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(document);
if (!ProblemHighlightFilter.shouldHighlightFile(file)) return true;
@@ -342,7 +342,7 @@ public class FileStatusMap implements Disposable {
@Override
public <T> T getUserData(@NotNull Key<T> key) {
throw null;
throw new UnsupportedOperationException();
}
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -42,7 +42,7 @@ public class PsiTreeChangeEventImpl extends PsiTreeChangeEvent{
private PsiEventType myCode;
public PsiTreeChangeEventImpl(PsiManager manager) {
public PsiTreeChangeEventImpl(@NotNull PsiManager manager) {
super(manager);
}
@@ -124,8 +124,9 @@ public class PsiTreeChangeEventImpl extends PsiTreeChangeEvent{
isGenericChange = genericChange;
}
@NotNull
@Override
public String toString() {
return "PsiTreeChangeEventImpl{myCode=" + myCode + (isGenericChange ? " (generic)" : "") + '}';
return "PsiTreeChangeEventImpl{" + myCode + (isGenericChange ? " (generic)" : "") + '}';
}
}
@@ -55,6 +55,7 @@ import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy;
import com.intellij.ui.HintHint;
import com.intellij.ui.LightweightHint;
import com.intellij.ui.components.panels.Wrapper;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
@@ -87,9 +88,9 @@ public abstract class DiffRequestProcessor implements Disposable {
@NotNull private final JPanel myPanel;
@NotNull private final MyPanel myMainPanel;
@NotNull private final ModifiablePanel myContentPanel;
@NotNull private final ModifiablePanel myToolbarPanel; // TODO: allow to call 'updateToolbar' from Viewer ?
@NotNull private final ModifiablePanel myToolbarStatusPanel;
@NotNull private final Wrapper myContentPanel;
@NotNull private final Wrapper myToolbarPanel; // TODO: allow to call 'updateToolbar' from Viewer ?
@NotNull private final Wrapper myToolbarStatusPanel;
@NotNull private DiffRequest myActiveRequest;
@@ -118,9 +119,10 @@ public abstract class DiffRequestProcessor implements Disposable {
myPanel = new JPanel(new BorderLayout());
myMainPanel = new MyPanel();
myContentPanel = new ModifiablePanel();
myToolbarPanel = new ModifiablePanel();
myToolbarStatusPanel = new ModifiablePanel();
myContentPanel = new Wrapper();
myToolbarPanel = new Wrapper();
myToolbarPanel.setFocusable(true);
myToolbarStatusPanel = new Wrapper();
myPanel.add(myMainPanel, BorderLayout.CENTER);
@@ -469,7 +471,7 @@ public abstract class DiffRequestProcessor implements Disposable {
@Nullable
public JComponent getPreferredFocusedComponent() {
JComponent component = myState.getPreferredFocusedComponent();
return component != null ? component : myToolbarPanel.getContent();
return component != null ? component : myToolbarPanel.getTargetComponent();
}
@Nullable
@@ -832,7 +834,7 @@ public abstract class DiffRequestProcessor implements Disposable {
public Object getData(@NonNls String dataId) {
Object data;
DataProvider contentProvider = DataManagerImpl.getDataProviderEx(myContentPanel.getContent());
DataProvider contentProvider = DataManagerImpl.getDataProviderEx(myContentPanel.getTargetComponent());
if (contentProvider != null) {
data = contentProvider.getData(dataId);
if (data != null) return data;
@@ -1016,8 +1018,6 @@ public abstract class DiffRequestProcessor implements Disposable {
FrameDiffTool.ToolbarComponents init = myViewer.init();
buildToolbar(init.toolbarActions);
myPanel.validate();
}
@Override
@@ -1060,16 +1060,12 @@ public abstract class DiffRequestProcessor implements Disposable {
myContentPanel.setContent(myViewer.getComponent());
setTitle(myActiveRequest.getTitle());
myPanel.validate();
FrameDiffTool.ToolbarComponents toolbarComponents = myViewer.init();
buildToolbar(toolbarComponents.toolbarActions);
buildActionPopup(toolbarComponents.popupActions);
myToolbarStatusPanel.setContent(toolbarComponents.statusPanel);
myPanel.validate();
}
@Override
@@ -1118,8 +1114,6 @@ public abstract class DiffRequestProcessor implements Disposable {
myContentPanel.setContent(myWrapperViewer.getComponent());
setTitle(myActiveRequest.getTitle());
myPanel.validate();
FrameDiffTool.ToolbarComponents toolbarComponents1 = myViewer.init();
FrameDiffTool.ToolbarComponents toolbarComponents2 = myWrapperViewer.init();
@@ -1142,8 +1136,6 @@ public abstract class DiffRequestProcessor implements Disposable {
myToolbarStatusPanel.setContent(toolbarComponents1.statusPanel); // TODO: combine both panels ?
myPanel.validate();
}
@Override
@@ -82,14 +82,6 @@ public class ChangedBlock {
return myLine2;
}
public boolean hasInsertion() {
return myStartOffset2 != myEndOffset2;
}
public boolean hasDeletion() {
return myStartOffset1 != myEndOffset1;
}
@NotNull
public LineFragment getLineFragment() {
return myLineFragment;
@@ -235,6 +235,7 @@ public class OnesideDiffChange {
@Nullable
public GutterIconRenderer createRenderer() {
if (myViewer.isStateIsOutOfDate()) return null;
if (!myViewer.isEditable(mySide.other(), true)) return null;
boolean bothEditable = myViewer.isEditable(mySide, true);
@@ -288,6 +289,9 @@ public class OnesideDiffChange {
myViewer.applyChange(OnesideDiffChange.this, sourceSide);
}
});
// applyChange() will schedule rediff, but we want to try to do it in sync
// and we can't do it inside write action
myViewer.rediff();
}
};
}
@@ -37,25 +37,19 @@ public class OnesideDiffPanel extends DiffPanelBase {
private static final String OPERATION_CANCELED_CONTENT = "OperationCanceledContent";
private static final String ERROR_CONTENT = "ErrorContent";
@NotNull private final Editor myEditor;
@NotNull private final JPanel myEditorPanel;
@NotNull private final AsyncProcessIcon.Big myBusyIcon;
public OnesideDiffPanel(@Nullable Project project,
@NotNull OnesideContentPanel content,
@NotNull Editor editor,
@NotNull DataProvider provider,
@NotNull DiffContext context) {
super(project, provider, context);
myEditor = editor;
myEditorPanel = content;
myBusyIcon = new AsyncProcessIcon.Big("OnesideDiff");
JPanel centerPanel = new JPanel(new BorderLayout());
centerPanel.add(myNotificationsPanel, BorderLayout.NORTH);
centerPanel.add(myEditorPanel, BorderLayout.CENTER);
centerPanel.add(content, BorderLayout.CENTER);
myContentPanel.add(centerPanel, GOOD_CONTENT);
myContentPanel.add(myBusyIcon, LOADING_CONTENT);
@@ -135,7 +135,7 @@ public class OnesideDiffViewer extends TextDiffViewerBase {
List<JComponent> titles = DiffUtil.createTextTitles(myRequest, ContainerUtil.list(myEditor, myEditor));
OnesideContentPanel contentPanel = new OnesideContentPanel(titles, myEditor);
myPanel = new OnesideDiffPanel(myProject, contentPanel, myEditor, this, myContext);
myPanel = new OnesideDiffPanel(myProject, contentPanel, this, myContext);
myFoldingModel = new MyFoldingModel(myEditor, this);
@@ -383,6 +383,22 @@ public class OnesideDiffViewer extends TextDiffViewerBase {
updateEditorCanBeTyped();
}
@CalledInAwt
protected void markSuppressEditorTyping() {
mySuppressEditorTyping = true;
updateEditorCanBeTyped();
}
@CalledInAwt
protected void markStateIsOutOfDate() {
myStateIsOutOfDate = true;
if (myChangedBlockData != null) {
for (OnesideDiffChange diffChange : myChangedBlockData.getDiffChanges()) {
diffChange.updateGutterActions();
}
}
}
@Nullable
private EditorHighlighter buildHighlighter(@Nullable Project project,
@NotNull DocumentContent content1,
@@ -611,8 +627,7 @@ public class OnesideDiffViewer extends TextDiffViewerBase {
if (twosideStartLine == -1 || twosideEndLine == -1) {
// this should never happen
logDebugInfo(e, onesideStartPosition, onesideEndPosition, twosideStartLine, twosideEndLine);
mySuppressEditorTyping = true;
updateEditorCanBeTyped();
markSuppressEditorTyping();
return;
}
@@ -630,7 +645,7 @@ public class OnesideDiffViewer extends TextDiffViewerBase {
finally {
// TODO: we can avoid marking state out-of-date in some simple cases (like in SimpleDiffViewer)
// but this will greatly increase complexity, so let's wait if it's actually required by users
myStateIsOutOfDate = true;
markStateIsOutOfDate();
myFoldingModel.onDocumentChanged(e);
scheduleRediff();
@@ -673,9 +688,8 @@ public class OnesideDiffViewer extends TextDiffViewerBase {
protected void onDocumentChange(@NotNull DocumentEvent e) {
if (myDuringTwosideDocumentModification) return;
myStateIsOutOfDate = true;
mySuppressEditorTyping = true;
updateEditorCanBeTyped();
markStateIsOutOfDate();
markSuppressEditorTyping();
myFoldingModel.onDocumentChanged(e);
scheduleRediff();
@@ -701,7 +715,7 @@ public class OnesideDiffViewer extends TextDiffViewerBase {
// no need to mark myStateIsOutOfDate - it will be made by DocumentListener
// TODO: we can apply change manually, without marking state out-of-date. But we'll have to schedule rediff anyway.
rediff();
scheduleRediff();
}
//
@@ -1103,21 +1103,18 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
@Override
protected boolean doScrollToChange() {
if (myScrollToChange == null) return false;
SimpleDiffViewer.this.doScrollToChange(myScrollToChange);
return true;
return SimpleDiffViewer.this.doScrollToChange(myScrollToChange);
}
@Override
protected boolean doScrollToFirstChange() {
SimpleDiffViewer.this.doScrollToChange(ScrollToPolicy.FIRST_CHANGE);
return true;
return SimpleDiffViewer.this.doScrollToChange(ScrollToPolicy.FIRST_CHANGE);
}
@Override
protected boolean doScrollToContext() {
if (myNavigationContext == null) return false;
SimpleDiffViewer.this.doScrollToContext(myNavigationContext);
return true;
return SimpleDiffViewer.this.doScrollToContext(myNavigationContext);
}
}
}
@@ -672,14 +672,12 @@ public class SimpleThreesideDiffViewer extends ThreesideTextDiffViewer {
@Override
protected boolean doScrollToChange() {
if (myScrollToChange == null) return false;
SimpleThreesideDiffViewer.this.doScrollToChange(myScrollToChange);
return true;
return SimpleThreesideDiffViewer.this.doScrollToChange(myScrollToChange);
}
@Override
protected boolean doScrollToFirstChange() {
SimpleThreesideDiffViewer.this.doScrollToChange(ScrollToPolicy.FIRST_CHANGE);
return true;
return SimpleThreesideDiffViewer.this.doScrollToChange(ScrollToPolicy.FIRST_CHANGE);
}
}
}
@@ -85,14 +85,6 @@ public class FoldingModelSupport {
// Init
//
@Deprecated
protected void install(@Nullable final Iterator<int[]> changedLines,
@NotNull final UserDataHolder context,
final boolean defaultExpanded,
final int range) {
install(changedLines, context, new Settings(range, defaultExpanded));
}
/*
* Iterator returns ranges of changed lines: start1, end1, start2, end2, ...
*/
@@ -498,11 +490,6 @@ public class FoldingModelSupport {
}
}
@Deprecated
public void updateContext(@NotNull UserDataHolder context, boolean defaultState) {
updateContext(context, new Settings(0, defaultState));
}
public void updateContext(@NotNull UserDataHolder context, @NotNull final Settings settings) {
if (myFoldings.isEmpty()) return; // do not rewrite cache by initial state
context.putUserData(CACHE_KEY, getFoldingCache(settings));
@@ -47,14 +47,6 @@ public class LineFragmentCache {
myFragments = new HashMap<ComparisonPolicy, PolicyData>(3);
}
public long getStamp1() {
return myModificationStamp1;
}
public long getStamp2() {
return myModificationStamp2;
}
public boolean checkStamps(long stamp1, long stamp2) {
return myModificationStamp1 == stamp1 && myModificationStamp2 == stamp2;
}
@@ -28,17 +28,14 @@ public class SimpleDiffPanel extends DiffPanelBase {
private static final String GOOD_CONTENT = "GoodContent";
private static final String ERROR_CONTENT = "ErrorContent";
@NotNull private final JComponent myEditorsPanel;
public SimpleDiffPanel(@NotNull JComponent editorPanel,
@NotNull DataProvider dataProvider,
@NotNull DiffContext context) {
super(context.getProject(), dataProvider, context);
myEditorsPanel = editorPanel;
JPanel centerPanel = new JPanel(new BorderLayout());
centerPanel.add(myNotificationsPanel, BorderLayout.NORTH);
centerPanel.add(myEditorsPanel, BorderLayout.CENTER);
centerPanel.add(editorPanel, BorderLayout.CENTER);
myContentPanel.add(centerPanel, GOOD_CONTENT);
myContentPanel.add(DiffUtil.createMessagePanel("Error"), ERROR_CONTENT);
@@ -68,9 +68,9 @@ public class SyncScrollSupport {
return myDuringSyncScroll;
}
public boolean setDisabled(boolean value) {
public void setDisabled(boolean value) {
if (myDisabled == value) LOG.warn(new Throwable("myDisabled == value: " + myDisabled + " - " + value));
return myDisabled = value;
myDisabled = value;
}
@NotNull
@@ -170,9 +170,9 @@ public class SyncScrollSupport {
myHelper22 = create(editors.get(2), editors.get(1), myScrollable2, Side.RIGHT);
}
public boolean setDisabled(boolean value) {
public void setDisabled(boolean value) {
if (myDisabled == value) LOG.warn(new Throwable("myDisabled == value: " + myDisabled + " - " + value));
return myDisabled = value;
myDisabled = value;
}
public void visibleAreaChanged(VisibleAreaEvent e) {
@@ -127,6 +127,7 @@ public abstract class DiffViewerBase implements DiffViewer, DataProvider {
@CalledInAwt
public final void rediff(boolean trySync) {
if (isDisposed()) return;
abortRediff();
onBeforeRediff();
@@ -15,19 +15,13 @@
*/
package com.intellij.application.options.editor;
import com.intellij.ide.ui.ConfigurableOptionsTopHitProvider;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.project.Project;
/**
* @author Sergey.Malenkov
*/
public class AutoImportOptionsTopHitProvider extends ConfigurableOptionsTopHitProvider {
@Override
public String getId() {
return "editor";
}
public class AutoImportOptionsTopHitProvider extends EditorOptionsTopHitProviderBase {
@Override
protected Configurable getConfigurable(Project project) {
return new AutoImportOptionsConfigurable();
@@ -15,7 +15,6 @@
*/
package com.intellij.application.options.editor;
import com.intellij.ide.ui.ConfigurableOptionsTopHitProvider;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.project.Project;
@@ -24,25 +23,15 @@ import javax.swing.*;
/**
* @author Sergey.Malenkov
*/
public class CodeFoldingOptionsTopHitProvider extends ConfigurableOptionsTopHitProvider {
public class CodeFoldingOptionsTopHitProvider extends EditorOptionsTopHitProviderBase.NoPrefix {
private int myCount;
@Override
public String getId() {
return "editor";
}
@Override
protected Configurable getConfigurable(Project project) {
myCount = 0;
return new CodeFoldingConfigurable();
}
@Override
protected String getName(Configurable configurable) {
return null;
}
@Override
protected String getOptionName(JCheckBox checkbox) {
String name = super.getOptionName(checkbox);
@@ -15,26 +15,15 @@
*/
package com.intellij.application.options.editor;
import com.intellij.ide.ui.ConfigurableOptionsTopHitProvider;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.project.Project;
/**
* @author Sergey.Malenkov
*/
public class EditorOptionsTopHitProvider extends ConfigurableOptionsTopHitProvider {
@Override
public String getId() {
return "editor";
}
public class EditorOptionsTopHitProvider extends EditorOptionsTopHitProviderBase.NoPrefix {
@Override
protected Configurable getConfigurable(Project project) {
return new EditorOptions();
}
@Override
protected String getName(Configurable configurable) {
return null;
}
}
@@ -13,29 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.diff.impl;
package com.intellij.application.options.editor;
import org.jetbrains.annotations.Nullable;
import com.intellij.ide.ui.ConfigurableOptionsTopHitProvider;
import com.intellij.openapi.options.Configurable;
import javax.swing.*;
import java.awt.*;
public class ModifiablePanel extends JPanel {
@Nullable private JComponent myContent;
public ModifiablePanel() {
super(new BorderLayout());
/**
* @author Konstantin Bulenkov
*/
public abstract class EditorOptionsTopHitProviderBase extends ConfigurableOptionsTopHitProvider {
@Override
public String getId() {
return "editor";
}
public void setContent(@Nullable JComponent content) {
myContent = content;
removeAll();
if (content != null) add(content, BorderLayout.CENTER);
invalidate();
}
@Nullable
public JComponent getContent() {
return myContent;
public static abstract class NoPrefix extends EditorOptionsTopHitProviderBase {
@Override
protected String getName(Configurable configurable) {
return null;
}
}
}
@@ -15,19 +15,13 @@
*/
package com.intellij.application.options.editor;
import com.intellij.ide.ui.ConfigurableOptionsTopHitProvider;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.project.Project;
/**
* @author Sergey.Malenkov
*/
public class EditorSmartKeysOptionsTopHitProvider extends ConfigurableOptionsTopHitProvider {
@Override
public String getId() {
return "editor";
}
public class EditorSmartKeysOptionsTopHitProvider extends EditorOptionsTopHitProviderBase {
@Override
protected Configurable getConfigurable(Project project) {
return new EditorSmartKeysConfigurable();
@@ -15,26 +15,15 @@
*/
package com.intellij.application.options.editor;
import com.intellij.ide.ui.ConfigurableOptionsTopHitProvider;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.project.Project;
/**
* @author Sergey.Malenkov
*/
public class EditorTabsOptionsTopHitProvider extends ConfigurableOptionsTopHitProvider {
@Override
public String getId() {
return "editor";
}
public class EditorTabsOptionsTopHitProvider extends EditorOptionsTopHitProviderBase.NoPrefix {
@Override
protected Configurable getConfigurable(Project project) {
return new EditorTabsConfigurable();
}
@Override
protected String getName(Configurable configurable) {
return null;
}
}
@@ -143,7 +143,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzerEx implements Pers
myInitialized = true;
myDisposed = false;
myFileStatusMap.markAllFilesDirty();
myFileStatusMap.markAllFilesDirty("DCAI init");
Disposer.register(this, new Disposable() {
@Override
public void dispose() {
@@ -477,7 +477,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzerEx implements Pers
@Override
public void restart() {
myFileStatusMap.markAllFilesDirty();
myFileStatusMap.markAllFilesDirty("Global restart");
stopProcess(true, "Global restart");
}
@@ -485,8 +485,9 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzerEx implements Pers
public void restart(@NotNull PsiFile file) {
Document document = myPsiDocumentManager.getCachedDocument(file);
if (document == null) return;
myFileStatusMap.markFileScopeDirty(document, new TextRange(0, document.getTextLength()), file.getTextLength());
stopProcess(true, "Psi file restart");
String reason = "Psi file restart: " + file.getName();
myFileStatusMap.markFileScopeDirty(document, new TextRange(0, document.getTextLength()), file.getTextLength(), reason);
stopProcess(true, reason);
}
@NotNull
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -178,7 +178,7 @@ class PsiChangeHandler extends PsiTreeChangeAdapter implements Disposable {
// mark file dirty just in case
PsiFile psiFile = event.getFile();
if (psiFile != null) {
myFileStatusMap.markFileScopeDirtyDefensively(psiFile);
myFileStatusMap.markFileScopeDirtyDefensively(psiFile, event);
}
}
@@ -186,15 +186,15 @@ class PsiChangeHandler extends PsiTreeChangeAdapter implements Disposable {
public void propertyChanged(@NotNull PsiTreeChangeEvent event) {
String propertyName = event.getPropertyName();
if (!propertyName.equals(PsiTreeChangeEvent.PROP_WRITABLE)) {
myFileStatusMap.markAllFilesDirty();
myFileStatusMap.markAllFilesDirty(event);
}
}
private void queueElement(PsiElement child, final boolean whitespaceOptimizationAllowed, PsiTreeChangeEvent event) {
private void queueElement(@NotNull PsiElement child, final boolean whitespaceOptimizationAllowed, @NotNull PsiTreeChangeEvent event) {
PsiFile file = event.getFile();
if (file == null) file = child.getContainingFile();
if (file == null) {
myFileStatusMap.markAllFilesDirty();
myFileStatusMap.markAllFilesDirty(child);
return;
}
@@ -216,30 +216,30 @@ class PsiChangeHandler extends PsiTreeChangeAdapter implements Disposable {
file = child.getContainingFile();
}
catch (PsiInvalidElementAccessException e) {
myFileStatusMap.markAllFilesDirty();
myFileStatusMap.markAllFilesDirty(e);
return;
}
if (file == null || file instanceof PsiCompiledElement) {
myFileStatusMap.markAllFilesDirty();
myFileStatusMap.markAllFilesDirty(child);
return;
}
int fileLength = file.getTextLength();
if (!file.getViewProvider().isPhysical()) {
myFileStatusMap.markFileScopeDirty(document, new TextRange(0, fileLength), fileLength);
myFileStatusMap.markFileScopeDirty(document, new TextRange(0, fileLength), fileLength, "Non-physical file update: "+file);
return;
}
PsiElement element = whitespaceOptimizationAllowed && UpdateHighlightersUtil.isWhitespaceOptimizationAllowed(document) ? child : child.getParent();
while (true) {
if (element == null || element instanceof PsiFile || element instanceof PsiDirectory) {
myFileStatusMap.markAllFilesDirty();
myFileStatusMap.markAllFilesDirty("Top element: "+element);
return;
}
final PsiElement scope = getChangeHighlightingScope(element);
if (scope != null) {
myFileStatusMap.markFileScopeDirty(document, scope.getTextRange(), fileLength);
myFileStatusMap.markFileScopeDirty(document, scope.getTextRange(), fileLength, "Scope: "+scope);
return;
}
@@ -50,7 +50,10 @@ import com.intellij.openapi.progress.*;
import com.intellij.openapi.progress.util.ProgressIndicatorUtils;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectCoreUtil;
import com.intellij.openapi.project.ProjectUtilCore;
import com.intellij.openapi.roots.FileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.FileUtil;
@@ -507,10 +510,12 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
@Override
public void run() {
try {
final FileIndex fileIndex = ProjectRootManager.getInstance(getProject()).getFileIndex();
scope.accept(new Processor<VirtualFile>() {
@Override
public boolean process(final VirtualFile file) {
progressIndicator.checkCanceled();
if (ProjectCoreUtil.isProjectOrWorkspaceFile(file) || !fileIndex.isInContent(file)) return true;
final PsiFile[] psiFile = new PsiFile[1];
Document document = ApplicationManager.getApplication().runReadAction(new Computable<Document>() {
@@ -814,7 +814,7 @@ public abstract class ChooseByNameBase {
}
@NotNull public String getTrimmedText() {
return StringUtil.notNullize(myTextField.getText()).trim();
return StringUtil.trimLeading(StringUtil.notNullize(myTextField.getText()));
}
public void setFixLostTyping(boolean fixLostTyping) {
@@ -285,6 +285,7 @@ public class ProjectRootManagerComponent extends ProjectRootManagerImpl {
if (!myStartupActivityPerformed) return;
if (myDoLogCachesUpdate) LOG.info(new Throwable("sync roots"));
else LOG.info("project roots have changed");
DumbServiceImpl dumbService = DumbServiceImpl.getInstance(myProject);
if (FileBasedIndex.getInstance() instanceof FileBasedIndexImpl) {
@@ -17,6 +17,7 @@ package com.intellij.openapi.util;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.application.PathManager;
@@ -48,9 +49,15 @@ public class SwitchBootJdkAction extends AnAction implements DumbAware {
@NonNls private static final Logger LOG = Logger.getInstance("#com.intellij.ide.actions.SwitchBootJdkAction");
@NonNls private static final String productJdkConfigFileName = ApplicationNamesInfo.getInstance().getScriptName() + ".jdk";
@NonNls private static final File productJdkConfigFile = new File(PathManager.getConfigPath(), productJdkConfigFileName);
@NonNls private static final File customJdkFile = new File(PathManager.getHomePath() + File.separator + "jre" + File.separator + "jdk");
@Override
public void update(AnActionEvent e) {
Presentation presentation = e.getPresentation();
if (!SystemInfo.isMac || !customJdkFile.exists()) {
presentation.setEnabledAndVisible(false);
return;
}
e.getPresentation().setText("Switch Boot JDK");
}
@@ -190,7 +197,7 @@ public class SwitchBootJdkAction extends AnAction implements DumbAware {
@Nullable
@Override
protected JComponent createNorthPanel() {
return new JBLabel("Specify Boot JDK path");
return new JBLabel("Select Boot JDK");
}
@Nullable
@@ -218,7 +225,10 @@ public class SwitchBootJdkAction extends AnAction implements DumbAware {
ArrayList<JdkBundleDescriptor> jdkPathsList = new ArrayList<JdkBundleDescriptor>();
if (!SystemInfo.isMac) return jdkPathsList;
jdkPathsList.add(new JdkBundleDescriptor(new File(PathManager.getHomePath() + File.separator + "jre" + File.separator + "jdk" ), "JDK bundled with IDE"));
if (customJdkFile.exists()) {
jdkPathsList.add(new JdkBundleDescriptor(customJdkFile, "JDK bundled with IDE"));
}
jdkPathsList.addAll(jdkBundlesFromLocation(STANDARD_JDK_6_LOCATION_ON_MAC_OS_X, "1.6.0"));
jdkPathsList.addAll(jdkBundlesFromLocation(STANDARD_JDK_LOCATION_ON_MAC_OS_X, "jdk1.8.0_(\\d*).jdk"));
@@ -227,7 +227,7 @@ public class FileBasedIndexImpl extends FileBasedIndex {
LOG.info(e);
}
}
scheduleIndexRebuild();
scheduleIndexRebuild("File type change");
}
});
@@ -1248,7 +1248,7 @@ public class FileBasedIndexImpl extends FileBasedIndex {
try {
doClearIndex(indexId);
if (!cleanupOnly) {
scheduleIndexRebuild();
scheduleIndexRebuild("checkRebuild");
}
}
catch (StorageException e) {
@@ -1286,7 +1286,8 @@ public class FileBasedIndexImpl extends FileBasedIndex {
}
}
private static void scheduleIndexRebuild() {
private static void scheduleIndexRebuild(String reason) {
LOG.info("scheduleIndexRebuild, reason: " + reason);
for (Project project : ProjectManager.getInstance().getOpenProjects()) {
DumbService.getInstance(project).queueTask(new UnindexedFilesUpdater(project, false));
}
@@ -366,6 +366,7 @@ public class AdvancedEnhancer extends AbstractClassGenerator
protected ClassLoader getDefaultClassLoader() {
int maxIndex = -1;
ClassLoader bestLoader = null;
ClassLoader nonPluginLoader = null;
if (interfaces != null && interfaces.length > 0) {
for (final Class anInterface : interfaces) {
final ClassLoader loader = anInterface.getClassLoader();
@@ -376,6 +377,9 @@ public class AdvancedEnhancer extends AbstractClassGenerator
bestLoader = loader;
}
}
else if (nonPluginLoader == null) {
nonPluginLoader = loader;
}
}
}
ClassLoader superLoader = null;
@@ -387,7 +391,7 @@ public class AdvancedEnhancer extends AbstractClassGenerator
}
}
if (bestLoader != null) return bestLoader;
return superLoader;
return superLoader == null ? nonPluginLoader : superLoader;
}
private static Signature rename(Signature sig, int index) {
@@ -274,7 +274,7 @@ public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataP
myChangeDecorator = changeDecorator;
}
public void setDoubleClickHandler(final Runnable doubleClickHandler) {
public void setDoubleClickHandler(@NotNull final Runnable doubleClickHandler) {
myDoubleClickHandler = doubleClickHandler;
}
@@ -68,12 +68,22 @@ public class XVariablesView extends XVariablesViewBase {
}
@Override
protected void clear() {
XDebuggerTree tree = getTree();
public void dispose() {
clearInlineData(getTree());
super.dispose();
}
private static void clearInlineData(XDebuggerTree tree) {
tree.getProject().putUserData(DEBUG_VARIABLES, null);
tree.getProject().putUserData(DEBUG_VARIABLES_TIMESTAMPS, null);
tree.setSourcePosition(null);
tree.updateEditor();
}
@Override
protected void clear() {
XDebuggerTree tree = getTree();
tree.setSourcePosition(null);
clearInlineData(tree);
XDebuggerTreeNode node;
XDebugSession session = getSession(getPanel());
@@ -13,6 +13,7 @@ instance.variable.of.concrete.class.display.name=Type of instance field is concr
instance.variable.of.concrete.class.problem.descriptor=Type of field ''{0}'' is concrete class <code>#ref</code> #loc
chain.of.instanceof.checks.display.name=Chain of 'instanceof' checks
chain.of.instanceof.checks.problem.descriptor=Chain of 'instanceof' checks indicates abstraction failure #loc
chain.of.class.equality.checks.problem.descriptor=Chain of class equality checks indicates abstraction failure #loc
instanceof.concrete.class.display.name='instanceof' a concrete class
instanceof.concrete.class.problem.descriptor='instanceof' concrete class <code>#ref</code> #loc
instanceof.check.for.this.display.name='instanceof' check for 'this'
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2013 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2015 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,7 +21,9 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.ControlFlowUtils;
import com.siyeh.ig.psiutils.LibraryUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -46,6 +48,10 @@ public class InstanceofChainInspection extends BaseInspection {
@Override
@NotNull
protected String buildErrorString(Object... infos) {
final Check check = (Check)infos[0];
if (check == Check.CLASS_EQUALITY) {
return InspectionGadgetsBundle.message("chain.of.class.equality.checks.problem.descriptor");
}
return InspectionGadgetsBundle.message("chain.of.instanceof.checks.problem.descriptor");
}
@@ -60,36 +66,41 @@ public class InstanceofChainInspection extends BaseInspection {
return new InstanceofChainVisitor();
}
private enum Check {
CLASS_EQUALITY, INSTANCEOF, NEITHER
}
private class InstanceofChainVisitor extends BaseInspectionVisitor {
@Override
public void visitIfStatement(@NotNull PsiIfStatement ifStatement) {
super.visitIfStatement(ifStatement);
final PsiElement parent = ifStatement.getParent();
if (parent instanceof PsiIfStatement) {
final PsiIfStatement parentStatement = (PsiIfStatement)parent;
final PsiStatement elseBranch = parentStatement.getElseBranch();
if (ifStatement.equals(elseBranch)) {
return;
}
if (ControlFlowUtils.isElseIf(ifStatement)) {
return;
}
final PsiStatement previousStatement = PsiTreeUtil.getPrevSiblingOfType(ifStatement, PsiStatement.class);
if (previousStatement instanceof PsiIfStatement) {
final PsiIfStatement previousIfStatement = (PsiIfStatement)previousStatement;
if (isInstanceofCheck(previousIfStatement.getCondition())) {
final PsiExpression condition = previousIfStatement.getCondition();
if (chainCheck(condition, null) != Check.NEITHER) {
return;
}
}
int numChecks = 0;
PsiIfStatement branch = ifStatement;
Check check = null;
while (true) {
final PsiExpression condition = branch.getCondition();
if (!isInstanceofCheck(condition)) {
final Check chainCheck = chainCheck(condition, check);
if (chainCheck == Check.NEITHER) {
if (numChecks > 1) {
break;
}
return;
}
else {
check = chainCheck;
}
numChecks++;
final PsiStatement elseBranch = branch.getElseBranch();
if (elseBranch instanceof PsiIfStatement) {
@@ -109,32 +120,30 @@ public class InstanceofChainInspection extends BaseInspection {
if (numChecks < 2) {
return;
}
registerStatementError(ifStatement);
registerStatementError(ifStatement, check);
}
private boolean isInstanceofCheck(PsiExpression condition) {
private Check chainCheck(PsiExpression condition, Check check) {
while (true) {
if (condition == null) {
return false;
return Check.NEITHER;
}
else if (condition instanceof PsiInstanceOfExpression) {
if (ignoreInstanceofOnLibraryClasses) {
final PsiInstanceOfExpression instanceOfExpression = (PsiInstanceOfExpression)condition;
if (isInstanceofOnLibraryClass(instanceOfExpression)) {
return false;
}
}
return true;
else if (check != Check.CLASS_EQUALITY && isInstanceofExpression(condition)) {
return Check.INSTANCEOF;
}
else if (condition instanceof PsiPolyadicExpression) {
if (check != Check.INSTANCEOF && isClassEqualityExpression(condition)) {
return Check.CLASS_EQUALITY;
}
final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)condition;
final PsiExpression[] operands = polyadicExpression.getOperands();
for (PsiExpression operand : operands) {
if (!isInstanceofCheck(operand)) {
return false;
final Check chainCheck = chainCheck(operand, check);
if (chainCheck != Check.NEITHER) {
return chainCheck;
}
}
return true;
return Check.NEITHER;
}
else if (condition instanceof PsiParenthesizedExpression) {
final PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression)condition;
@@ -151,22 +160,39 @@ public class InstanceofChainInspection extends BaseInspection {
condition = postfixExpression.getOperand();
continue;
}
return false;
return Check.NEITHER;
}
}
private boolean isInstanceofOnLibraryClass(PsiInstanceOfExpression instanceOfExpression) {
final PsiTypeElement checkType = instanceOfExpression.getCheckType();
if (checkType == null) {
private boolean isClassEqualityExpression(PsiExpression expression) {
if (!(expression instanceof PsiBinaryExpression)) {
return false;
}
final PsiType type = checkType.getType();
if (!(type instanceof PsiClassType)) {
final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)expression;
if (binaryExpression.getOperationTokenType() != JavaTokenType.EQEQ) {
return false;
}
final PsiClassType classType = (PsiClassType)type;
final PsiClass aClass = classType.resolve();
return LibraryUtil.classIsInLibrary(aClass);
return isClassObjectAccessExpression(binaryExpression.getLOperand()) ||
isClassObjectAccessExpression(binaryExpression.getROperand());
}
private boolean isClassObjectAccessExpression(PsiExpression expression) {
expression = ParenthesesUtils.stripParentheses(expression);
if (!(expression instanceof PsiClassObjectAccessExpression)) {
return false;
}
final PsiClassObjectAccessExpression classObjectAccessExpression = (PsiClassObjectAccessExpression)expression;
final PsiTypeElement typeElement = classObjectAccessExpression.getOperand();
return !ignoreInstanceofOnLibraryClasses || !LibraryUtil.isTypeInLibrary(typeElement.getType());
}
private boolean isInstanceofExpression(PsiExpression expression) {
if (!(expression instanceof PsiInstanceOfExpression)) {
return false;
}
final PsiInstanceOfExpression instanceOfExpression = (PsiInstanceOfExpression)expression;
final PsiTypeElement typeElement = instanceOfExpression.getCheckType();
return !ignoreInstanceofOnLibraryClasses || typeElement == null || !LibraryUtil.isTypeInLibrary(typeElement.getType());
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2013 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2015 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@ import com.intellij.psi.tree.IElementType;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.ControlFlowUtils;
import com.siyeh.ig.psiutils.EquivalenceChecker;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -69,13 +70,8 @@ public class DuplicateConditionInspection extends BaseInspection {
@Override
public void visitIfStatement(@NotNull PsiIfStatement statement) {
super.visitIfStatement(statement);
final PsiElement parent = statement.getParent();
if (parent instanceof PsiIfStatement) {
final PsiIfStatement parentStatement = (PsiIfStatement)parent;
final PsiStatement elseBranch = parentStatement.getElseBranch();
if (statement.equals(elseBranch)) {
return;
}
if (ControlFlowUtils.isElseIf(statement)) {
return;
}
final Set<PsiExpression> conditions = new HashSet<PsiExpression>();
collectConditionsForIfStatement(statement, conditions, 0);
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2007 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2015 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,12 +16,12 @@
package com.siyeh.ig.controlflow;
import com.intellij.codeInspection.ui.SingleIntegerFieldOptionsPanel;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiIfStatement;
import com.intellij.psi.PsiStatement;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.ControlFlowUtils;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -73,13 +73,8 @@ public class IfStatementWithTooManyBranchesInspection
@Override
public void visitIfStatement(@NotNull PsiIfStatement statement) {
super.visitIfStatement(statement);
final PsiElement parent = statement.getParent();
if (parent instanceof PsiIfStatement) {
final PsiIfStatement parentStatement = (PsiIfStatement)parent;
final PsiStatement elseBranch = parentStatement.getElseBranch();
if (statement.equals(elseBranch)) {
return;
}
if (ControlFlowUtils.isElseIf(statement)) {
return;
}
final int branchCount = calculateBranchCount(statement);
if (branchCount <= m_limit) {
@@ -25,6 +25,16 @@ public class ControlFlowUtils {
private ControlFlowUtils() {}
public static boolean isElseIf(PsiIfStatement ifStatement) {
final PsiElement parent = ifStatement.getParent();
if (!(parent instanceof PsiIfStatement)) {
return false;
}
final PsiIfStatement parentStatement = (PsiIfStatement)parent;
final PsiStatement elseBranch = parentStatement.getElseBranch();
return ifStatement.equals(elseBranch);
}
public static boolean statementMayCompleteNormally(@Nullable PsiStatement statement) {
if (statement == null) {
return true;
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2010 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2015 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,8 +21,15 @@ import org.jetbrains.annotations.Nullable;
public class LibraryUtil {
private LibraryUtil() {
super();
private LibraryUtil() {}
public static boolean isTypeInLibrary(@Nullable PsiType type) {
if (!(type instanceof PsiClassType)) {
return false;
}
final PsiClassType classType = (PsiClassType)type;
final PsiClass aClass = classType.resolve();
return classIsInLibrary(aClass);
}
public static boolean classIsInLibrary(@Nullable PsiClass aClass) {
@@ -1,7 +1,8 @@
<html>
<body>
Reports any chains of if-else statements all of whose conditions are <b>instanceof</b> expressions
(or combinations of such expressions). Such constructions usually indicate a failure of object-oriented design, which
Reports any chains of <b>if</b>-<b>else</b> statements all of whose conditions are <b>instanceof</b> expressions
or class equality expressions (e.g. comparison with <b>String.class</b>).
Such constructions usually indicate a failure of object-oriented design, which
dictates that such type-based dispatch should be done via polymorphic method calls rather than explicit chains
of type tests.
<!-- tooltip end -->
@@ -2,7 +2,7 @@ package com.siyeh.igtest.abstraction.instanceof_chain;
public class InstanceofChain {
void arg(Object o) {
if (o instanceof String || o instanceof String || o instanceof String) {
<warning descr="Chain of 'instanceof' checks indicates abstraction failure">if</warning> (o != null || o instanceof String || o instanceof String || o instanceof String) {
} else if (o instanceof Integer) {
@@ -12,7 +12,7 @@ public class InstanceofChain {
}
void m(boolean b, Object o) {
if (o instanceof String) {
<warning descr="Chain of 'instanceof' checks indicates abstraction failure">if</warning> (o instanceof String) {
} else if (o instanceof Boolean) {
@@ -20,8 +20,38 @@ public class InstanceofChain {
}
void n(Object o) {
if (o instanceof Integer) {}
<warning descr="Chain of 'instanceof' checks indicates abstraction failure">if</warning> (o instanceof Integer) {}
if (o instanceof Byte) {}
if (o instanceof Long) {}
}
void f(Class objClass1, Class objClass2) {
<warning descr="Chain of class equality checks indicates abstraction failure">if</warning> (objClass1 == String.class) {
<warning descr="Chain of class equality checks indicates abstraction failure">if</warning> (objClass2 == Integer.class || objClass2 == Double.class) {
} else if (objClass2 == Boolean.class) {
}
} else if (objClass1 == Byte.class){
if (objClass2 == Float.class){
}
}
}
void g(Object obj1, Object obj2) {
<warning descr="Chain of class equality checks indicates abstraction failure">if</warning> (obj1.getClass() == String.class) {
<warning descr="Chain of class equality checks indicates abstraction failure">if</warning> (obj2.getClass() == Integer.class || obj2.getClass() == Double.class) {
} else if (obj2.getClass() == Boolean.class) {
}
} else if (obj1.getClass() == Byte.class){
if (obj2.getClass() == Float.class){
}
}
}
void h(Object o) {
if (o instanceof String) {
} else if (o == null) {
}
}
}
@@ -1,23 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
<problem>
<file>InstanceofChain.java</file>
<line>5</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Chain of 'instanceof' checks</problem_class>
<description>Chain of 'instanceof' checks indicates abstraction failure #loc</description>
</problem>
<problem>
<file>InstanceofChain.java</file>
<line>23</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Chain of 'instanceof' checks</problem_class>
<description>Chain of 'instanceof' checks indicates abstraction failure #loc</description>
</problem>
<problem>
<file>InstanceofChain.java</file>
<line>15</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Chain of 'instanceof' checks</problem_class>
<description>Chain of 'instanceof' checks indicates abstraction failure #loc</description>
</problem>
</problems>
@@ -1,27 +0,0 @@
package com.siyeh.igtest.bugs;
public class DuplicateCondition {
public void foo()
{
if(bar()||bar())
{
System.out.println("1");
}else if(bar()|| true)
{
System.out.println("2");
}
}
public boolean bar()
{
return true;
}
void incompleteCode(String s) {
if (s.contains(A)) {
} else if (s.contains(B)) {
}
}
}
@@ -3,10 +3,34 @@ package com.siyeh.igtest.controlflow.duplicate_condition;
public class DuplicateCondition {
void x(boolean b) {
if (b || b || b ) {
if (<warning descr="Duplicate condition 'b'">b</warning> || <warning descr="Duplicate condition 'b'">b</warning> || <warning descr="Duplicate condition 'b'">b</warning> ) {
} else if (b) {
} else if (<warning descr="Duplicate condition 'b'">b</warning>) {
} else if (b) {}
} else if (<warning descr="Duplicate condition 'b'">b</warning>) {}
}
public void foo()
{
if(<warning descr="Duplicate condition 'bar()'">bar()</warning>||<warning descr="Duplicate condition 'bar()'">bar()</warning>)
{
System.out.println("1");
}else if(<warning descr="Duplicate condition 'bar()'">bar()</warning>|| true)
{
System.out.println("2");
}
}
public boolean bar()
{
return true;
}
void incompleteCode(String s) {
if (s.contains(<error descr="Cannot resolve symbol 'A'">A</error>)) {
} else if (s.contains(<error descr="Cannot resolve symbol 'B'">B</error>)) {
}
}
}
@@ -1,37 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
<problem>
<file>DuplicateCondition.java</file>
<line>6</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Duplicate condition in 'if' statement</problem_class>
<description>Duplicate condition &lt;code&gt;b&lt;/code&gt; #loc</description>
</problem>
<problem>
<file>DuplicateCondition.java</file>
<line>6</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Duplicate condition in 'if' statement</problem_class>
<description>Duplicate condition &lt;code&gt;b&lt;/code&gt; #loc</description>
</problem>
<problem>
<file>DuplicateCondition.java</file>
<line>8</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Duplicate condition in 'if' statement</problem_class>
<description>Duplicate condition &lt;code&gt;b&lt;/code&gt; #loc</description>
</problem>
<problem>
<file>DuplicateCondition.java</file>
<line>6</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Duplicate condition in 'if' statement</problem_class>
<description>Duplicate condition &lt;code&gt;b&lt;/code&gt; #loc</description>
</problem>
<problem>
<file>DuplicateCondition.java</file>
<line>10</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Duplicate condition in 'if' statement</problem_class>
<description>Duplicate condition &lt;code&gt;b&lt;/code&gt; #loc</description>
</problem>
</problems>
@@ -1,11 +1,18 @@
package com.siyeh.ig.abstraction;
import com.siyeh.ig.IGInspectionTestCase;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.siyeh.ig.LightInspectionTestCase;
import org.jetbrains.annotations.Nullable;
public class InstanceofChainInspectionTest extends IGInspectionTestCase {
public class InstanceofChainInspectionTest extends LightInspectionTestCase {
public void test() throws Exception {
doTest("com/siyeh/igtest/abstraction/instanceof_chain",
new InstanceofChainInspection());
public void testInstanceofChain() {
doTest();
}
@Nullable
@Override
protected InspectionProfileEntry getInspection() {
return new InstanceofChainInspection();
}
}
@@ -1,10 +1,18 @@
package com.siyeh.ig.controlflow;
import com.siyeh.ig.IGInspectionTestCase;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.siyeh.ig.LightInspectionTestCase;
import org.jetbrains.annotations.Nullable;
public class DuplicateConditionInspectionTest extends IGInspectionTestCase {
public class DuplicateConditionInspectionTest extends LightInspectionTestCase {
public void test() throws Exception {
doTest("com/siyeh/igtest/controlflow/duplicate_condition", new DuplicateConditionInspection());
public void testDuplicateCondition() {
doTest();
}
@Nullable
@Override
protected InspectionProfileEntry getInspection() {
return new DuplicateConditionInspection();
}
}
@@ -5,7 +5,6 @@ import com.intellij.diff.FrameDiffTool.DiffViewer;
import com.intellij.diff.FrameDiffTool.ToolbarComponents;
import com.intellij.diff.contents.DiffContent;
import com.intellij.diff.contents.EmptyContent;
import com.intellij.diff.impl.ModifiablePanel;
import com.intellij.diff.requests.DiffRequest;
import com.intellij.diff.requests.ErrorDiffRequest;
import com.intellij.diff.tools.ErrorDiffTool;
@@ -23,6 +22,7 @@ import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.ui.EditorNotificationPanel;
import com.intellij.ui.JBColor;
import com.intellij.ui.components.panels.Wrapper;
import com.intellij.util.containers.HashMap;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
@@ -60,7 +60,7 @@ public class SvnDiffViewer implements DiffViewer {
@NotNull private final JPanel myPanel;
@NotNull private final Splitter mySplitter;
@NotNull private final ModifiablePanel myNotificationPanel;
@NotNull private final Wrapper myNotificationPanel;
@NotNull private final DiffViewer myContentViewer;
@NotNull private final DiffViewer myPropertiesViewer;
@@ -85,7 +85,7 @@ public class SvnDiffViewer implements DiffViewer {
mySplitter.setProportion(mySettings.getSplitterProportion());
mySplitter.setFirstComponent(myContentViewer.getComponent());
myNotificationPanel = new ModifiablePanel();
myNotificationPanel = new Wrapper();
MyPropertyContext propertyContext = initPropertyContext(context);
myPropertiesViewer = createPropertiesViewer(propertyRequest, propertyContext);
@@ -8,11 +8,11 @@ import com.intellij.openapi.util.UserDataHolder;
import com.intellij.diff.DiffContext;
import com.intellij.diff.FrameDiffTool;
import com.intellij.diff.chains.DiffRequestProducerException;
import com.intellij.diff.impl.ModifiablePanel;
import com.intellij.diff.requests.DiffRequest;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.actions.diff.ChangeDiffRequestProducer;
import com.intellij.openapi.vcs.changes.actions.diff.ChangeDiffRequestProvider;
import com.intellij.ui.components.panels.Wrapper;
import com.intellij.util.ThreeState;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -91,7 +91,7 @@ public class SvnTreeConflictDiffRequestProvider implements ChangeDiffRequestProv
private static class SvnTreeConflictDiffViewer implements FrameDiffTool.DiffViewer {
@NotNull private final DiffContext myContext;
@NotNull private final SvnTreeConflictDiffRequest myRequest;
@NotNull private final ModifiablePanel myPanel = new ModifiablePanel();
@NotNull private final Wrapper myPanel = new Wrapper();
@NotNull private final BackgroundTaskQueue myQueue;
@NotNull private final TreeConflictRefreshablePanel myDelegate;
@@ -15,19 +15,14 @@
*/
package com.intellij.uiDesigner;
import com.intellij.ide.ui.ConfigurableOptionsTopHitProvider;
import com.intellij.application.options.editor.EditorOptionsTopHitProviderBase;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.project.Project;
/**
* @author Sergey.Malenkov
*/
public class GuiDesignerOptionsTopHitProvider extends ConfigurableOptionsTopHitProvider {
@Override
public String getId() {
return "editor";
}
public class GuiDesignerOptionsTopHitProvider extends EditorOptionsTopHitProviderBase {
@Override
protected Configurable getConfigurable(Project project) {
return new GuiDesignerConfigurable(project);
@@ -160,7 +160,7 @@ public class XmlRefCountHolder {
return myUsedNamespaces.contains(ns);
}
private static class IdGatheringRecursiveVisitor extends XmlRecursiveElementVisitor {
private static class IdGatheringRecursiveVisitor extends XmlRecursiveElementWalkingVisitor {
private final XmlRefCountHolder myHolder;
private IdGatheringRecursiveVisitor(@NotNull XmlRefCountHolder holder) {