Merge remote-tracking branch 'origin/master'

This commit is contained in:
Ekaterina Tuzova
2014-03-26 13:48:27 +04:00
150 changed files with 2099 additions and 787 deletions
@@ -17,7 +17,6 @@ package com.intellij.debugger.ui;
import com.intellij.debugger.DebuggerBundle;
import com.intellij.util.PlatformIcons;
import com.intellij.xdebugger.XDebuggerBundle;
import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroup;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -26,13 +25,6 @@ import javax.swing.*;
public class XBreakpointClassGroup extends XBreakpointGroup {
private static final String DEFAULT_PACKAGE_NAME = DebuggerBundle.message("default.package.name");
public static final XBreakpointClassGroup UNKNOWN = new XBreakpointClassGroup("", "") {
@NotNull
@Override
public String getName() {
return XDebuggerBundle.message("xbreakpoint.group.unknown");
}
};
private String myPackageName;
private String myClassName;
@@ -42,18 +42,17 @@ class XBreakpointGroupingByClassRule<B> extends XBreakpointGroupingRule<B, XBrea
return XBreakpointsGroupingPriorities.BY_CLASS;
}
@NotNull
@Override
public XBreakpointClassGroup getGroup(@NotNull B b, @NotNull Collection<XBreakpointClassGroup> groups) {
if (b instanceof XBreakpoint) {
Breakpoint javaBreakpoint = BreakpointManager.findBreakpoint((XBreakpoint)b);
if (javaBreakpoint == null) {
return XBreakpointClassGroup.UNKNOWN;
return null;
}
String className = javaBreakpoint.getShortClassName();
String packageName = javaBreakpoint.getPackageName();
if (className == null) {
return XBreakpointClassGroup.UNKNOWN;
return null;
}
for (XBreakpointClassGroup group : groups) {
if (group.getClassName().equals(className) && group.getPackageName().equals(packageName)) {
@@ -62,7 +61,7 @@ class XBreakpointGroupingByClassRule<B> extends XBreakpointGroupingRule<B, XBrea
}
return new XBreakpointClassGroup(packageName, className);
}
return XBreakpointClassGroup.UNKNOWN;
return null;
}
@Nullable
@@ -39,7 +39,6 @@ public class XBreakpointGroupingByPackageRule<B> extends XBreakpointGroupingRule
return XBreakpointsGroupingPriorities.BY_PACKAGE;
}
@NotNull
@Override
public XBreakpointPackageGroup getGroup(@NotNull B breakpoint, @NotNull Collection<XBreakpointPackageGroup> groups) {
String packageName = null;
@@ -50,7 +49,7 @@ public class XBreakpointGroupingByPackageRule<B> extends XBreakpointGroupingRule
}
}
if (packageName == null) {
return XBreakpointPackageGroup.UNKNOWN;
return null;
}
for (XBreakpointPackageGroup group : groups) {
if (StringUtil.equals(group.getPackageName(), packageName)) {
@@ -18,30 +18,17 @@ package com.intellij.debugger.ui;
import com.intellij.debugger.DebuggerBundle;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.PlatformIcons;
import com.intellij.xdebugger.XDebuggerBundle;
import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroup;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
public class XBreakpointPackageGroup extends XBreakpointGroup {
private static final String DEFAULT_PACKAGE_NAME = DebuggerBundle.message("default.package.name");
public static final XBreakpointPackageGroup UNKNOWN = new XBreakpointPackageGroup() {
@NotNull
@Override
public String getName() {
return XDebuggerBundle.message("xbreakpoint.group.unknown");
}
};
private String myPackageName;
private XBreakpointPackageGroup() {
myPackageName = null;
}
public XBreakpointPackageGroup(@NotNull String packageName) {
public XBreakpointPackageGroup(String packageName) {
myPackageName = packageName;
}
@@ -57,7 +44,7 @@ public class XBreakpointPackageGroup extends XBreakpointGroup {
return StringUtil.isEmpty(packageName) ? DEFAULT_PACKAGE_NAME : packageName;
}
@Nullable
@NotNull
public String getPackageName() {
return myPackageName;
}
@@ -133,6 +133,16 @@ public class BreakpointManager {
@Override
public void changeEvent(@NotNull DebuggerContextImpl newContext, int event) {
if (event == DebuggerSession.EVENT_ATTACHED) {
// notify about possibly slow method breakpoints
for (XLineBreakpoint breakpoint : getXBreakpointManager().getBreakpoints(JavaMethodBreakpointType.class)) {
if (breakpoint.isEnabled()) {
XDebugSessionImpl.NOTIFICATION_GROUP.createNotification("Method breakpoints may dramatically slow down debugging", MessageType.WARNING).notify(
myProject);
break;
}
}
}
if (newContext.getDebuggerSession() != myPreviousSession || event == DebuggerSession.EVENT_DETACHED) {
updateBreakpointsUI();
myPreviousSession = newContext.getDebuggerSession();
@@ -18,7 +18,12 @@ package com.intellij.codeInspection.varScopeCanBeNarrowed;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInsight.daemon.ImplicitUsageProvider;
import com.intellij.codeInspection.*;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInspection.BaseJavaBatchLocalInspectionTool;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.codeInspection.util.SpecialAnnotationsUtilBase;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.JDOMExternalizableStringList;
@@ -28,15 +33,14 @@ import com.intellij.psi.*;
import com.intellij.psi.controlFlow.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Processor;
import com.siyeh.InspectionGadgetsBundle;
import gnu.trove.THashSet;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
public class FieldCanBeLocalInspectionBase extends BaseJavaBatchLocalInspectionTool {
@NonNls public static final String SHORT_NAME = "FieldCanBeLocal";
@@ -69,10 +73,26 @@ public class FieldCanBeLocalInspectionBase extends BaseJavaBatchLocalInspectionT
if (candidates.isEmpty()) return;
final ImplicitUsageProvider[] implicitUsageProviders = Extensions.getExtensions(ImplicitUsageProvider.EP_NAME);
for (PsiField field : candidates) {
for (final PsiField field : candidates) {
if (usedFields.contains(field) && !hasImplicitReadOrWriteUsage(field, implicitUsageProviders)) {
final String message = InspectionsBundle.message("inspection.field.can.be.local.problem.descriptor");
holder.registerProblem(field.getNameIdentifier(), message, createFix());
final ArrayList<LocalQuickFix> fixes = new ArrayList<LocalQuickFix>();
SpecialAnnotationsUtilBase.createAddToSpecialAnnotationFixes(field, new Processor<String>() {
@Override
public boolean process(String qualifiedName) {
final LocalQuickFix quickFix = SpecialAnnotationsUtilBase.createAddToSpecialAnnotationsListQuickFix(
InspectionGadgetsBundle.message("add.0.to.ignore.if.annotated.by.list.quickfix", qualifiedName),
QuickFixBundle.message("fix.add.special.annotation.family"),
EXCLUDE_ANNOS, qualifiedName, field);
fixes.add(quickFix);
return true;
}
});
final LocalQuickFix fix = createFix();
if (fix != null) {
fixes.add(fix);
}
holder.registerProblem(field.getNameIdentifier(), message, fixes.toArray(new LocalQuickFix[fixes.size()]));
}
}
}
@@ -16,6 +16,7 @@
package com.intellij.application.options;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
@@ -23,6 +24,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.ToolbarDecorator;
import com.intellij.ui.components.JBList;
@@ -204,6 +206,7 @@ public class CodeStyleGenerationConfigurable implements Configurable {
}*/
public void reset(CodeStyleSettings settings) {
CommonCodeStyleSettings javaCommonSettings = settings.getCommonSettings(JavaLanguage.INSTANCE);
myCbPreferLongerNames.setSelected(settings.PREFER_LONGER_NAMES);
myFieldPrefixField.setText(settings.FIELD_NAME_PREFIX);
@@ -216,8 +219,8 @@ public class CodeStyleGenerationConfigurable implements Configurable {
myParameterSuffixField.setText(settings.PARAMETER_NAME_SUFFIX);
myLocalVariableSuffixField.setText(settings.LOCAL_VARIABLE_NAME_SUFFIX);
myCbLineCommentAtFirstColumn.setSelected(settings.LINE_COMMENT_AT_FIRST_COLUMN);
myCbBlockCommentAtFirstColumn.setSelected(settings.BLOCK_COMMENT_AT_FIRST_COLUMN);
myCbLineCommentAtFirstColumn.setSelected(javaCommonSettings.LINE_COMMENT_AT_FIRST_COLUMN);
myCbBlockCommentAtFirstColumn.setSelected(javaCommonSettings.BLOCK_COMMENT_AT_FIRST_COLUMN);
myCbGenerateFinalLocals.setSelected(settings.GENERATE_FINAL_LOCALS);
myCbGenerateFinalParameters.setSelected(settings.GENERATE_FINAL_PARAMETERS);
@@ -233,6 +236,7 @@ public class CodeStyleGenerationConfigurable implements Configurable {
}
public void apply(CodeStyleSettings settings) throws ConfigurationException {
CommonCodeStyleSettings javaCommonSettings = settings.getCommonSettings(JavaLanguage.INSTANCE);
settings.PREFER_LONGER_NAMES = myCbPreferLongerNames.isSelected();
settings.FIELD_NAME_PREFIX = setPrefixSuffix(myFieldPrefixField.getText(), true);
@@ -245,8 +249,8 @@ public class CodeStyleGenerationConfigurable implements Configurable {
settings.PARAMETER_NAME_SUFFIX = setPrefixSuffix(myParameterSuffixField.getText(), false);
settings.LOCAL_VARIABLE_NAME_SUFFIX = setPrefixSuffix(myLocalVariableSuffixField.getText(), false);
settings.LINE_COMMENT_AT_FIRST_COLUMN = myCbLineCommentAtFirstColumn.isSelected();
settings.BLOCK_COMMENT_AT_FIRST_COLUMN = myCbBlockCommentAtFirstColumn.isSelected();
javaCommonSettings.LINE_COMMENT_AT_FIRST_COLUMN = myCbLineCommentAtFirstColumn.isSelected();
javaCommonSettings.BLOCK_COMMENT_AT_FIRST_COLUMN = myCbBlockCommentAtFirstColumn.isSelected();
settings.GENERATE_FINAL_LOCALS = myCbGenerateFinalLocals.isSelected();
settings.GENERATE_FINAL_PARAMETERS = myCbGenerateFinalParameters.isSelected();
@@ -276,6 +280,8 @@ public class CodeStyleGenerationConfigurable implements Configurable {
}
public boolean isModified(CodeStyleSettings settings) {
CommonCodeStyleSettings javaCommonSettings = settings.getCommonSettings(JavaLanguage.INSTANCE);
boolean isModified = isModified(myCbPreferLongerNames, settings.PREFER_LONGER_NAMES);
isModified |= isModified(myFieldPrefixField, settings.FIELD_NAME_PREFIX);
@@ -288,8 +294,8 @@ public class CodeStyleGenerationConfigurable implements Configurable {
isModified |= isModified(myParameterSuffixField, settings.PARAMETER_NAME_SUFFIX);
isModified |= isModified(myLocalVariableSuffixField, settings.LOCAL_VARIABLE_NAME_SUFFIX);
isModified |= isModified(myCbLineCommentAtFirstColumn, settings.LINE_COMMENT_AT_FIRST_COLUMN);
isModified |= isModified(myCbBlockCommentAtFirstColumn, settings.BLOCK_COMMENT_AT_FIRST_COLUMN);
isModified |= isModified(myCbLineCommentAtFirstColumn, javaCommonSettings.LINE_COMMENT_AT_FIRST_COLUMN);
isModified |= isModified(myCbBlockCommentAtFirstColumn, javaCommonSettings.BLOCK_COMMENT_AT_FIRST_COLUMN);
isModified |= isModified(myCbGenerateFinalLocals, settings.GENERATE_FINAL_LOCALS);
@@ -109,7 +109,9 @@ public class JavaMemberNameCompletionContributor extends CompletionContributor {
String propertyName = null;
if (variableKind == VariableKind.PARAMETER) {
final PsiMethod method = PsiTreeUtil.getParentOfType(var, PsiMethod.class);
propertyName = PropertyUtil.getPropertyName(method);
if (method != null) {
propertyName = PropertyUtil.getPropertyName(method);
}
if (method != null && method.getName().startsWith("with")) {
propertyName = StringUtil.decapitalize(method.getName().substring(4));
}
@@ -133,7 +135,7 @@ public class JavaMemberNameCompletionContributor extends CompletionContributor {
addLookupItems(set, null, matcher, project, getOverlappedNameVersions(matcher.getPrefix(), suggestedNames, ""));
}
PsiElement parent = PsiTreeUtil.getParentOfType(var, PsiCodeBlock.class);
if(parent == null) parent = PsiTreeUtil.getParentOfType(var, PsiMethod.class);
if(parent == null) parent = PsiTreeUtil.getParentOfType(var, PsiMethod.class, PsiLambdaExpression.class);
addLookupItems(set, suggestedNameInfo, matcher, project, getUnresolvedReferences(parent, false));
if (var instanceof PsiParameter && parent instanceof PsiMethod) {
addSuggestionsInspiredByFieldNames(set, matcher, var, project, codeStyleManager);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -20,7 +20,6 @@ import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.codeInsight.completion.JavaClassReferenceCompletionContributor;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorModificationUtil;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.highlighter.HighlighterIterator;
import com.intellij.openapi.fileTypes.FileType;
@@ -132,7 +131,7 @@ public class JavaTypedHandler extends TypedHandlerDelegate {
return Result.CONTINUE;
}
if (PsiTreeUtil.getParentOfType(leaf, PsiCodeBlock.class, false, PsiMember.class) != null) {
EditorModificationUtil.insertStringAtCaret(editor, "{", false, true);
EditorModificationUtil.typeInStringAtCaretHonorMultipleCarets(editor, "{");
TypedHandler.indentOpenedBrace(project, editor);
return Result.STOP;
}
@@ -170,8 +169,7 @@ public class JavaTypedHandler extends TypedHandlerDelegate {
char charAt = editor.getDocument().getCharsSequence().charAt(offset);
if (charAt != ';') return false;
editor.getCaretModel().moveToOffset(offset + 1);
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
EditorModificationUtil.moveAllCaretsRelatively(editor, 1);
return true;
}
@@ -211,8 +209,7 @@ public class JavaTypedHandler extends TypedHandlerDelegate {
}
if (balance == 0) {
editor.getCaretModel().moveToOffset(offset + 1);
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
EditorModificationUtil.moveAllCaretsRelatively(editor, 1);
return true;
}
@@ -251,7 +248,12 @@ public class JavaTypedHandler extends TypedHandlerDelegate {
}
if (balance == 1) {
editor.getDocument().insertString(offset, ">");
if (editor.getCaretModel().supportsMultipleCarets()) {
EditorModificationUtil.typeInStringAtCaretHonorMultipleCarets(editor, ">", 0);
}
else {
editor.getDocument().insertString(offset, ">");
}
}
}
@@ -103,7 +103,7 @@ public class PropertyUtil {
return Comparing.equal(PsiUtil.resolveClassInType(TypeConversionUtil.erasure(returnType)), method.getContainingClass());
}
@Nullable public static String getPropertyName(PsiMethod method) {
@Nullable public static String getPropertyName(@NotNull PsiMethod method) {
if (isSimplePropertyGetter(method)) {
return getPropertyNameByGetter(method);
}
@@ -163,7 +163,7 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
if (containingClass != null) {
PsiMethod[] methods = null;
if (element instanceof PsiIdentifier) {
methods = containingClass.findMethodsByName(element.getText(), true);
methods = containingClass.findMethodsByName(element.getText(), !qualifierResolveResult.isReferenceTypeQualified());
}
else if (isConstructor()) {
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(getProject());
@@ -0,0 +1,15 @@
import java.util.function.ToIntFunction;
class Test {
{
fooBar(String::length);
}
class Foo<K> {
Foo<K> then() {
return null;
}
}
static <T> Foo<T> fooBar(ToIntFunction<? super T> keyExtractor) {
return null;
}
}
@@ -0,0 +1,8 @@
class Foo {
void m() {
if (true)
{<caret>
if (true)
{<caret>
}
}
@@ -0,0 +1,8 @@
class Foo {
void m() {
if (true)
<caret>
if (true)
<caret>
}
}
@@ -0,0 +1,10 @@
class Foo {
void m() {
if (true) {
System.out.println();
}<caret>
if (true) {
System.out.println();
}<caret>
}
}
@@ -0,0 +1,10 @@
class Foo {
void m() {
if (true) {
System.out.println();
<caret>
if (true) {
System.out.println();
<caret>
}
}
@@ -0,0 +1,10 @@
class Foo {
void m() {
if (true) {
List<<caret>>
}
if (true) {
List<<caret>>
}
}
}
@@ -0,0 +1,10 @@
class Foo {
void m() {
if (true) {
List<caret>
}
if (true) {
List<caret>
}
}
}
@@ -0,0 +1,6 @@
class Foo {
void m() {
System.out.println("<caret>");
System.out.println("<caret>");
}
}
@@ -0,0 +1,6 @@
class Foo {
void m() {
System.out.println(<caret>);
System.out.println(<caret>);
}
}
@@ -0,0 +1,6 @@
class Foo {
void m() {
System.exit(<caret>)
System.exit(<caret>)
}
}
@@ -0,0 +1,6 @@
class Foo {
void m() {
System.exit<caret>
System.exit<caret>
}
}
@@ -0,0 +1,6 @@
class Foo {
void m() {
java.util.List<String> l1 = new java.util.ArrayList<><caret>();
java.util.List<String> l2 = new java.util.ArrayList<><caret>();
}
}
@@ -0,0 +1,6 @@
class Foo {
void m() {
java.util.List<String> l1 = new java.util.ArrayList<<caret>>();
java.util.List<String> l2 = new java.util.ArrayList<<caret>>();
}
}
@@ -0,0 +1,6 @@
class Foo {
void m() {
System.out.println(""<caret>);
System.out.println(""<caret>);
}
}
@@ -0,0 +1,6 @@
class Foo {
void m() {
System.out.println("<caret>");
System.out.println("<caret>");
}
}
@@ -0,0 +1,6 @@
class Foo {
void m() {
System.exit()<caret>
System.exit()<caret>
}
}
@@ -0,0 +1,6 @@
class Foo {
void m() {
System.exit(<caret>)
System.exit(<caret>)
}
}
@@ -0,0 +1,6 @@
class Foo {
void m() {
System.out.println();<caret>
System.out.println();<caret>
}
}
@@ -0,0 +1,6 @@
class Foo {
void m() {
System.out.println()<caret>;
System.out.println()<caret>;
}
}
@@ -0,0 +1,70 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
import java.io.File;
public class JavaTypingTest extends LightPlatformCodeInsightFixtureTestCase {
public void testMulticaretIndentLBrace() {
doTest('{');
}
public void testMulticaretIndentRBrace() {
doTest('}');
}
public void testMulticaretSkipSemicolon() {
doTest(';');
}
public void testMulticaretSkipGt() {
doTest('>');
}
public void testMulticaretInsertGt() {
doTest('<');
}
public void testMulticaretSkipRParen() {
doTest(')');
}
public void testMulticaretInsertRParen() {
doTest('(');
}
public void testMulticaretSkipQuote() {
doTest('"');
}
public void testMulticaretInsertQuote() {
doTest('"');
}
private void doTest(char c) {
myFixture.configureByFile(getTestName(true) + "_before.java");
myFixture.type(c);
myFixture.checkResultByFile(getTestName(true) + "_after.java");
}
@Override
protected String getTestDataPath() {
return PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/') + "/java/java-tests/testData/codeInsight/typing";
}
}
@@ -209,6 +209,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
doTest();
}
public void testIDEA112191() throws Exception {
doTest();
}
private void doTest() {
doTest(false);
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

+1
View File
@@ -31,6 +31,7 @@
<orderEntry type="module" module-name="jps-model-impl" />
<orderEntry type="module" module-name="analysis-impl" exported="" />
<orderEntry type="module" module-name="structure-view-impl" exported="" />
<orderEntry type="module" module-name="RegExpSupport" />
</component>
</module>
@@ -191,7 +191,7 @@ public class TypedHandler extends TypedActionHandlerBase {
}
}
if (!editor.getSelectionModel().hasBlockSelection() && editor.getCaretModel().getCaretCount() == 1) {
if (!editor.getSelectionModel().hasBlockSelection()) {
if (')' == charTyped || ']' == charTyped || '}' == charTyped) {
if (FileTypes.PLAIN_TEXT != fileType) {
if (handleRParen(editor, fileType, charTyped)) return;
@@ -210,7 +210,7 @@ public class TypedHandler extends TypedActionHandlerBase {
if (('(' == charTyped || '[' == charTyped || '{' == charTyped) &&
CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET &&
!editor.getSelectionModel().hasBlockSelection() && editor.getCaretModel().getCaretCount() == 1 && fileType != FileTypes.PLAIN_TEXT) {
!editor.getSelectionModel().hasBlockSelection() && fileType != FileTypes.PLAIN_TEXT) {
handleAfterLParen(editor, fileType, charTyped);
}
else if ('}' == charTyped) {
@@ -361,7 +361,12 @@ public class TypedHandler extends TypedActionHandlerBase {
else {
throw new AssertionError("Unknown char "+lparenChar);
}
editor.getDocument().insertString(offset, text);
if (editor.getCaretModel().supportsMultipleCarets()) {
EditorModificationUtil.typeInStringAtCaretHonorMultipleCarets(editor, text, 0);
}
else {
editor.getDocument().insertString(offset, text);
}
}
}
@@ -417,8 +422,7 @@ public class TypedHandler extends TypedActionHandlerBase {
if (!matched) return false;
editor.getCaretModel().moveToOffset(offset + 1);
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
EditorModificationUtil.moveAllCaretsRelatively(editor, 1);
return true;
}
@@ -436,8 +440,7 @@ public class TypedHandler extends TypedActionHandlerBase {
if (offset < length && chars.charAt(offset) == quote){
if (isClosingQuote(editor, quoteHandler, offset)){
editor.getCaretModel().moveToOffset(offset + 1);
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
EditorModificationUtil.moveAllCaretsRelatively(editor, 1);
return true;
}
}
@@ -456,7 +459,9 @@ public class TypedHandler extends TypedActionHandlerBase {
}
}
myOriginalHandler.execute(editor, quote, dataContext);
if (myOriginalHandler != null) {
myOriginalHandler.execute(editor, quote, dataContext);
}
offset = editor.getCaretModel().getOffset();
if (quoteHandler instanceof MultiCharQuoteHandler) {
@@ -464,7 +469,12 @@ public class TypedHandler extends TypedActionHandlerBase {
if (closingQuote != null && hasNonClosedLiterals(editor, quoteHandler, offset - 1)) {
if (offset == document.getTextLength() ||
!Character.isUnicodeIdentifierPart(document.getCharsSequence().charAt(offset))) { //any better heuristic or an API?
document.insertString(offset, closingQuote);
if (editor.getCaretModel().supportsMultipleCarets()) {
EditorModificationUtil.typeInStringAtCaretHonorMultipleCarets(editor, closingQuote.toString(), 0);
}
else {
document.insertString(offset, closingQuote);
}
return true;
}
}
@@ -473,7 +483,12 @@ public class TypedHandler extends TypedActionHandlerBase {
if (isOpeningQuote(editor, quoteHandler, offset - 1) && hasNonClosedLiterals(editor, quoteHandler, offset - 1)) {
if (offset == document.getTextLength() ||
!Character.isUnicodeIdentifierPart(document.getCharsSequence().charAt(offset))) { //any better heuristic or an API?
document.insertString(offset, String.valueOf(quote));
if (editor.getCaretModel().supportsMultipleCarets()) {
EditorModificationUtil.typeInStringAtCaretHonorMultipleCarets(editor, String.valueOf(quote), 0);
}
else {
document.insertString(offset, String.valueOf(quote));
}
}
}
@@ -558,67 +573,72 @@ public class TypedHandler extends TypedActionHandlerBase {
}
private static void indentBrace(@NotNull final Project project, @NotNull final Editor editor, final char braceChar) {
final int offset = editor.getCaretModel().getOffset() - 1;
final Document document = editor.getDocument();
CharSequence chars = document.getCharsSequence();
if (offset < 0 || chars.charAt(offset) != braceChar) return;
editor.getCaretModel().runForEachCaret(new CaretAction() {
@Override
public void perform(Caret caret) {
final int offset = editor.getCaretModel().getOffset() - 1;
final Document document = editor.getDocument();
CharSequence chars = document.getCharsSequence();
if (offset < 0 || chars.charAt(offset) != braceChar) return;
int spaceStart = CharArrayUtil.shiftBackward(chars, offset - 1, " \t");
if (spaceStart < 0 || chars.charAt(spaceStart) == '\n' || chars.charAt(spaceStart) == '\r'){
PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
documentManager.commitDocument(document);
int spaceStart = CharArrayUtil.shiftBackward(chars, offset - 1, " \t");
if (spaceStart < 0 || chars.charAt(spaceStart) == '\n' || chars.charAt(spaceStart) == '\r'){
PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
documentManager.commitDocument(document);
final PsiFile file = documentManager.getPsiFile(document);
if (file == null || !file.isWritable()) return;
PsiElement element = file.findElementAt(offset);
if (element == null) return;
final PsiFile file = documentManager.getPsiFile(document);
if (file == null || !file.isWritable()) return;
PsiElement element = file.findElementAt(offset);
if (element == null) return;
EditorHighlighter highlighter = ((EditorEx)editor).getHighlighter();
HighlighterIterator iterator = highlighter.createIterator(offset);
EditorHighlighter highlighter = ((EditorEx)editor).getHighlighter();
HighlighterIterator iterator = highlighter.createIterator(offset);
final FileType fileType = file.getFileType();
BraceMatcher braceMatcher = BraceMatchingUtil.getBraceMatcher(fileType, iterator);
boolean rBraceToken = braceMatcher.isRBraceToken(iterator, chars, fileType);
final boolean isBrace = braceMatcher.isLBraceToken(iterator, chars, fileType) || rBraceToken;
int lBraceOffset = -1;
final FileType fileType = file.getFileType();
BraceMatcher braceMatcher = BraceMatchingUtil.getBraceMatcher(fileType, iterator);
boolean rBraceToken = braceMatcher.isRBraceToken(iterator, chars, fileType);
final boolean isBrace = braceMatcher.isLBraceToken(iterator, chars, fileType) || rBraceToken;
int lBraceOffset = -1;
if (CodeInsightSettings.getInstance().REFORMAT_BLOCK_ON_RBRACE &&
rBraceToken &&
braceMatcher.isStructuralBrace(iterator, chars, fileType) && offset > 0) {
lBraceOffset = BraceMatchingUtil.findLeftLParen(
highlighter.createIterator(offset - 1),
braceMatcher.getOppositeBraceTokenType(iterator.getTokenType()),
editor.getDocument().getCharsSequence(),
fileType
);
}
if (element.getNode() != null && isBrace) {
final int finalLBraceOffset = lBraceOffset;
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run(){
try{
int newOffset;
if (finalLBraceOffset != -1) {
RangeMarker marker = document.createRangeMarker(offset, offset + 1);
CodeStyleManager.getInstance(project).reformatRange(file, finalLBraceOffset, offset, true);
newOffset = marker.getStartOffset();
marker.dispose();
} else {
newOffset = CodeStyleManager.getInstance(project).adjustLineIndent(file, offset);
}
editor.getCaretModel().moveToOffset(newOffset + 1);
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
editor.getSelectionModel().removeSelection();
}
catch(IncorrectOperationException e){
LOG.error(e);
}
if (CodeInsightSettings.getInstance().REFORMAT_BLOCK_ON_RBRACE &&
rBraceToken &&
braceMatcher.isStructuralBrace(iterator, chars, fileType) && offset > 0) {
lBraceOffset = BraceMatchingUtil.findLeftLParen(
highlighter.createIterator(offset - 1),
braceMatcher.getOppositeBraceTokenType(iterator.getTokenType()),
editor.getDocument().getCharsSequence(),
fileType
);
}
});
if (element.getNode() != null && isBrace) {
final int finalLBraceOffset = lBraceOffset;
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run(){
try{
int newOffset;
if (finalLBraceOffset != -1) {
RangeMarker marker = document.createRangeMarker(offset, offset + 1);
CodeStyleManager.getInstance(project).reformatRange(file, finalLBraceOffset, offset, true);
newOffset = marker.getStartOffset();
marker.dispose();
} else {
newOffset = CodeStyleManager.getInstance(project).adjustLineIndent(file, offset);
}
editor.getCaretModel().moveToOffset(newOffset + 1);
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
editor.getSelectionModel().removeSelection();
}
catch(IncorrectOperationException e){
LOG.error(e);
}
}
});
}
}
}
}
});
}
}
@@ -36,8 +36,8 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.codeStyle.Indent;
import com.intellij.psi.templateLanguages.MultipleLangCommentProvider;
import com.intellij.psi.templateLanguages.OuterLanguageElement;
@@ -55,7 +55,7 @@ import java.util.List;
public class CommentByBlockCommentHandler implements CodeInsightActionHandler {
private Project myProject;
private Editor myEditor;
private PsiFile myFile;
private @NotNull PsiFile myFile;
private Document myDocument;
private CommenterDataHolder mySelfManagedCommenterData;
@@ -402,7 +402,7 @@ public class CommentByBlockCommentHandler implements CodeInsightActionHandler {
if (startOffset == 0 || chars.charAt(startOffset - 1) == '\n') {
if (endOffset == myDocument.getTextLength() || endOffset > 0 && chars.charAt(endOffset - 1) == '\n') {
CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(myProject);
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(myProject);
CommonCodeStyleSettings settings = CodeStyleSettingsManager.getSettings(myProject).getCommonSettings(myFile.getLanguage());
String space;
if (!settings.BLOCK_COMMENT_AT_FIRST_COLUMN) {
final FileType fileType = myFile.getFileType();
@@ -260,7 +260,8 @@ public class CommentByLineCommentHandler implements CodeInsightActionHandler {
}
boolean allLineCommented = true;
boolean commentWithIndent = !CodeStyleSettingsManager.getSettings(myProject).LINE_COMMENT_AT_FIRST_COLUMN;
boolean commentWithIndent =
!CodeStyleSettingsManager.getSettings(myProject).getCommonSettings(myFile.getLanguage()).LINE_COMMENT_AT_FIRST_COLUMN;
for (int line = myStartLine; line <= myEndLine; line++) {
Commenter commenter = blockSuitableCommenter != null ? blockSuitableCommenter : findCommenter(line);
@@ -60,15 +60,6 @@ public abstract class BaseConsoleExecuteActionHandler extends ConsoleExecuteActi
throw new AbstractMethodError();
}
@Deprecated
/**
* @deprecated to remove in IDEA 14
*
* Never used. It is Python specific implementation.
*/
public void finishExecution() {
}
public String getEmptyExecuteAction() {
return ConsoleExecuteAction.CONSOLE_EXECUTE_ACTION_ID;
}
@@ -152,11 +152,16 @@ public class ConsoleExecuteAction extends DumbAwareAction {
return true;
}
public void setAddCurrentToHistory(boolean addCurrentToHistory) {
public final void setAddCurrentToHistory(boolean addCurrentToHistory) {
myAddToHistory = addCurrentToHistory;
}
protected void beforeExecution(@NotNull LanguageConsoleImpl console) {
}
final void runExecuteAction(@NotNull LanguageConsoleImpl console, @Nullable LanguageConsoleView consoleView) {
beforeExecution(console);
String text = console.prepareExecuteAction(myAddToHistory, myPreserveMarkup, true);
((UndoManagerImpl)UndoManager.getInstance(console.getProject())).invalidateActionsFor(DocumentReferenceManager.getInstance().create(console.getCurrentEditor().getDocument()));
addToCommandHistoryAndExecute(console, consoleView, text);
@@ -92,6 +92,8 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
private String myTitle;
@Nullable
private String myPrompt = "> ";
private TextAttributes myPromptAttributes = ConsoleViewContentType.USER_INPUT.getAttributes();
private final LightVirtualFile myHistoryFile;
private Editor myCurrentEditor;
@@ -332,6 +334,10 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
return myPrompt;
}
public void setPromptAttributes(@NotNull TextAttributes textAttributes) {
myPromptAttributes = textAttributes;
}
public void setPrompt(@Nullable String prompt) {
// always add space to the prompt otherwise it may look ugly
myPrompt = prompt != null && !prompt.endsWith(" ") ? prompt + " " : prompt;
@@ -344,7 +350,7 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
myConsoleEditor.setPrefixTextAndAttributes(prompt, ConsoleViewContentType.USER_INPUT.getAttributes());
myConsoleEditor.setPrefixTextAndAttributes(prompt, myPromptAttributes);
if (myPanel.isVisible()) {
queueUiUpdate(false);
}
@@ -540,7 +546,7 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
}
protected void doAddPromptToHistory() {
addTextToHistory(myPrompt, ConsoleViewContentType.USER_INPUT.getAttributes());
addTextToHistory(myPrompt, myPromptAttributes);
}
// returns the real (cyclic-buffer-aware) start offset of the inserted text
@@ -28,8 +28,7 @@ import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.fileTypes.PlainTextFileType;
import com.intellij.openapi.help.HelpManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
@@ -56,7 +55,7 @@ import com.intellij.ui.components.labels.LinkListener;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.intellij.lang.regexp.RegExpFileType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -668,15 +667,10 @@ public class FindDialog extends DialogWrapper {
final Component editorComponent = inputComboBox.getEditor().getEditorComponent();
if (editorComponent instanceof EditorTextField) {
boolean selected = myCbRegularExpressions.isSelectedWhenSelectable();
@NonNls final String s = selected ? "*.regexp" : "*.txt";
FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(s);
if (selected && fileType == FileTypes.UNKNOWN) {
fileType = FileTypeManager.getInstance().getFileTypeByFileName("*.txt"); // RegExp plugin is not installed
}
final PsiFile file = PsiFileFactory.getInstance(myProject).createFileFromText(s, fileType, ((EditorTextField)editorComponent).getText(), -1, true);
boolean isRegexp = myCbRegularExpressions.isSelectedWhenSelectable();
FileType fileType = isRegexp ? RegExpFileType.INSTANCE : PlainTextFileType.INSTANCE;
String fileName = isRegexp ? "a.regexp" : "a.txt";
final PsiFile file = PsiFileFactory.getInstance(myProject).createFileFromText(fileName, fileType, ((EditorTextField)editorComponent).getText(), -1, true);
((EditorTextField)editorComponent).setNewDocumentAndFileType(fileType, PsiDocumentManager.getInstance(myProject).getDocument(file));
}
@@ -34,6 +34,7 @@ import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.util.ProgressWrapper;
import com.intellij.openapi.progress.util.TooManyUsagesStatus;
import com.intellij.openapi.project.DumbServiceImpl;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
@@ -71,14 +72,16 @@ public class FindInProjectUtil {
private FindInProjectUtil() {}
public static void setDirectoryName(@NotNull FindModel model, @NotNull DataContext dataContext) {
PsiElement psiElement;
try {
psiElement = CommonDataKeys.PSI_ELEMENT.getData(dataContext);
}
catch (IndexNotReadyException e) {
psiElement = null;
PsiElement psiElement = null;
Project project = CommonDataKeys.PROJECT.getData(dataContext);
if (project != null && !DumbServiceImpl.getInstance(project).isDumb()) {
try {
psiElement = CommonDataKeys.PSI_ELEMENT.getData(dataContext);
} catch (IndexNotReadyException ignore) {}
}
String directoryName = null;
if (psiElement instanceof PsiDirectory) {
@@ -994,8 +994,8 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
}
Color bg = cmp.getBackground();
cmp.setBackground(UIUtil.getListBackground(isSelected));
if (bg == null) {
cmp.setBackground(UIUtil.getListBackground(isSelected));
bg = cmp.getBackground();
}
myMainPanel.setBorder(new CustomLineBorder(bg, 0, 0, 2, 0));
@@ -56,21 +56,24 @@ class RootIndex {
private final Map<VirtualFile, DirectoryInfo> myInfoCache = ContainerUtil.newConcurrentMap();
private final List<JpsModuleSourceRootType<?>> myRootTypes = ContainerUtil.newArrayList();
private final TObjectIntHashMap<JpsModuleSourceRootType<?>> myRootTypeId = new TObjectIntHashMap<JpsModuleSourceRootType<?>>();
@NotNull private final Project myProject;
private volatile Map<VirtualFile, OrderEntry[]> myOrderEntries;
RootIndex(@NotNull final Project project) {
myProject = project;
final RootInfo info = buildRootInfo(project);
Set<VirtualFile> allRoots = info.getAllRoots();
for (VirtualFile root : allRoots) {
List<VirtualFile> hierarchy = getHierarchy(root, allRoots, info);
Pair<DirectoryInfo, String> pair = hierarchy == null ? new Pair<DirectoryInfo, String>(null, null) : info.calcDirectoryInfo(root, hierarchy);
Pair<DirectoryInfo, String> pair = hierarchy == null ? new Pair<DirectoryInfo, String>(null, null) : calcDirectoryInfo(root, hierarchy, info);
cacheInfos(root, root, pair.first);
myPackagePrefixRoots.putValue(pair.second, root);
if (info.shouldMarkAsProjectExcluded(root, hierarchy)) {
myProjectExcludedRoots.add(root);
}
}
myModuleExcludedRoots = info.excludedFromModule.keySet();
}
@@ -78,17 +81,14 @@ class RootIndex {
final RootInfo info = new RootInfo();
for (final Module module : ModuleManager.getInstance(project).getModules()) {
final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
final OrderEntry[] orderEntries = moduleRootManager.getOrderEntries();
final ContentEntry[] contentEntries = moduleRootManager.getContentEntries();
final VirtualFile[] contentRoots = moduleRootManager.getContentRoots();
for (final VirtualFile contentRoot : contentRoots) {
for (final VirtualFile contentRoot : moduleRootManager.getContentRoots()) {
if (!info.contentRootOf.containsKey(contentRoot)) {
info.contentRootOf.put(contentRoot, module);
}
}
for (ContentEntry contentEntry : contentEntries) {
for (ContentEntry contentEntry : moduleRootManager.getContentEntries()) {
for (VirtualFile excludeRoot : contentEntry.getExcludeFolderFiles()) {
info.excludedFromModule.put(excludeRoot, module);
}
@@ -105,21 +105,8 @@ class RootIndex {
}
}
for (OrderEntry orderEntry : orderEntries) {
// init ordered entries
if (orderEntry instanceof ModuleOrderEntry) {
final Module depModule = ((ModuleOrderEntry)orderEntry).getModule();
if (depModule != null) {
VirtualFile[] importedClassRoots = OrderEnumerator.orderEntries(depModule).exportedOnly().recursively().classes().usingCache().getRoots();
for (VirtualFile importedClassRoot : importedClassRoots) {
info.depEntries.putValue(importedClassRoot, orderEntry);
}
}
for (VirtualFile sourceRoot : orderEntry.getFiles(OrderRootType.SOURCES)) {
info.depEntries.putValue(sourceRoot, orderEntry);
}
}
else if (orderEntry instanceof LibraryOrSdkOrderEntry) {
for (OrderEntry orderEntry : moduleRootManager.getOrderEntries()) {
if (orderEntry instanceof LibraryOrSdkOrderEntry) {
final LibraryOrSdkOrderEntry entry = (LibraryOrSdkOrderEntry)orderEntry;
final VirtualFile[] sourceRoots = entry.getRootFiles(OrderRootType.SOURCES);
final VirtualFile[] classRoots = entry.getRootFiles(OrderRootType.CLASSES);
@@ -127,14 +114,14 @@ class RootIndex {
// Init library sources
for (final VirtualFile sourceRoot : sourceRoots) {
info.classAndSourceRoots.add(sourceRoot);
info.libSourceRootEntries.putValue(sourceRoot, orderEntry);
info.libraryOrSdkSources.add(sourceRoot);
info.packagePrefix.put(sourceRoot, "");
}
// init library classes
for (final VirtualFile classRoot : classRoots) {
info.classAndSourceRoots.add(classRoot);
info.libClassRootEntries.putValue(classRoot, orderEntry);
info.libraryOrSdkClasses.add(classRoot);
info.packagePrefix.put(classRoot, "");
}
@@ -163,6 +150,77 @@ class RootIndex {
return info;
}
private Map<VirtualFile, OrderEntry[]> getOrderEntries() {
Map<VirtualFile, OrderEntry[]> result = myOrderEntries;
if (result != null) return result;
MultiMap<VirtualFile, OrderEntry> libClassRootEntries = MultiMap.createSmartList();
MultiMap<VirtualFile, OrderEntry> libSourceRootEntries = MultiMap.createSmartList();
MultiMap<VirtualFile, OrderEntry> depEntries = MultiMap.createSmartList();
for (final Module module : ModuleManager.getInstance(myProject).getModules()) {
final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
for (OrderEntry orderEntry : moduleRootManager.getOrderEntries()) {
if (orderEntry instanceof ModuleOrderEntry) {
final Module depModule = ((ModuleOrderEntry)orderEntry).getModule();
if (depModule != null) {
VirtualFile[] importedClassRoots = OrderEnumerator.orderEntries(depModule).exportedOnly().recursively().classes().usingCache().getRoots();
for (VirtualFile importedClassRoot : importedClassRoots) {
depEntries.putValue(importedClassRoot, orderEntry);
}
}
for (VirtualFile sourceRoot : orderEntry.getFiles(OrderRootType.SOURCES)) {
depEntries.putValue(sourceRoot, orderEntry);
}
}
else if (orderEntry instanceof LibraryOrSdkOrderEntry) {
final LibraryOrSdkOrderEntry entry = (LibraryOrSdkOrderEntry)orderEntry;
for (final VirtualFile sourceRoot : entry.getRootFiles(OrderRootType.SOURCES)) {
libSourceRootEntries.putValue(sourceRoot, orderEntry);
}
for (final VirtualFile classRoot : entry.getRootFiles(OrderRootType.CLASSES)) {
libClassRootEntries.putValue(classRoot, orderEntry);
}
}
}
}
RootInfo rootInfo = buildRootInfo(myProject);
result = ContainerUtil.newHashMap();
Set<VirtualFile> allRoots = rootInfo.getAllRoots();
for (VirtualFile file : allRoots) {
List<VirtualFile> hierarchy = getHierarchy(file, allRoots, rootInfo);
result.put(file, hierarchy == null ? OrderEntry.EMPTY_ARRAY : calcOrderEntries(rootInfo, depEntries, libClassRootEntries, libSourceRootEntries, hierarchy));
}
myOrderEntries = result;
return result;
}
private static OrderEntry[] calcOrderEntries(RootInfo info,
MultiMap<VirtualFile, OrderEntry> depEntries,
MultiMap<VirtualFile, OrderEntry> libClassRootEntries,
MultiMap<VirtualFile, OrderEntry> libSourceRootEntries, List<VirtualFile> hierarchy) {
@Nullable VirtualFile libraryClassRoot = info.findLibraryRootInfo(hierarchy, false);
@Nullable VirtualFile librarySourceRoot = info.findLibraryRootInfo(hierarchy, true);
Set<OrderEntry> orderEntries = ContainerUtil.newLinkedHashSet();
orderEntries.addAll(info.getLibraryOrderEntries(hierarchy, libraryClassRoot, librarySourceRoot, libClassRootEntries, libSourceRootEntries));
for (VirtualFile root : hierarchy) {
orderEntries.addAll(depEntries.get(root));
}
VirtualFile moduleContentRoot = info.findModuleRootInfo(hierarchy);
if (moduleContentRoot != null) {
ContainerUtil.addIfNotNull(orderEntries, info.getModuleSourceEntry(hierarchy, moduleContentRoot, libClassRootEntries));
}
if (orderEntries.isEmpty()) {
return null;
}
OrderEntry[] array = orderEntries.toArray(new OrderEntry[orderEntries.size()]);
Arrays.sort(array, DirectoryInfo.BY_OWNER_MODULE);
return array;
}
public void checkConsistency() {
for (VirtualFile file : myProjectExcludedRoots) {
assert file.exists() : file.getPath() + " does not exist";
@@ -338,19 +396,18 @@ class RootIndex {
// getDirectoriesByPackageName used to be in this order, some clients might rely on that
@NotNull final LinkedHashSet<VirtualFile> classAndSourceRoots = ContainerUtil.newLinkedHashSet();
@NotNull final Set<VirtualFile> libraryOrSdkSources = ContainerUtil.newHashSet();
@NotNull final Set<VirtualFile> libraryOrSdkClasses = ContainerUtil.newHashSet();
@NotNull final Map<VirtualFile, Module> contentRootOf = ContainerUtil.newHashMap();
@NotNull final MultiMap<VirtualFile, Module> sourceRootOf = MultiMap.createSet();
@NotNull final TObjectIntHashMap<VirtualFile> rootTypeId = new TObjectIntHashMap<VirtualFile>();
@NotNull final MultiMap<VirtualFile, OrderEntry> libClassRootEntries = MultiMap.createSmartList();
@NotNull final MultiMap<VirtualFile, OrderEntry> libSourceRootEntries = MultiMap.createSmartList();
@NotNull final MultiMap<VirtualFile, OrderEntry> depEntries = MultiMap.createSmartList();
@NotNull final MultiMap<VirtualFile, Library> excludedFromLibraries = MultiMap.createSmartList();
@NotNull final MultiMap<VirtualFile, Library> classOfLibraries = MultiMap.createSmartList();
@NotNull final MultiMap<VirtualFile, Library> sourceOfLibraries = MultiMap.createSmartList();
@NotNull final Set<VirtualFile> excludedFromProject = ContainerUtil.newHashSet();
@NotNull final Map<VirtualFile, Module> excludedFromModule = ContainerUtil.newHashMap();
@NotNull final Map<VirtualFile, String> packagePrefix = ContainerUtil.newHashMap();
Set<VirtualFile> getAllRoots() {
LinkedHashSet<VirtualFile> result = ContainerUtil.newLinkedHashSet();
result.addAll(classAndSourceRoots);
@@ -371,7 +428,7 @@ class RootIndex {
}
}) == null;
}
@Nullable
private VirtualFile findModuleRootInfo(List<VirtualFile> hierarchy) {
for (VirtualFile root : hierarchy) {
@@ -392,10 +449,10 @@ class RootIndex {
Set<Library> librariesToIgnore = ContainerUtil.newHashSet();
for (VirtualFile root : hierarchy) {
librariesToIgnore.addAll(excludedFromLibraries.get(root));
if (source && libSourceRootEntries.containsKey(root) &&
if (source && libraryOrSdkSources.contains(root) &&
(!sourceOfLibraries.containsKey(root) || !librariesToIgnore.containsAll(sourceOfLibraries.get(root)))) {
return root;
} else if (!source && libClassRootEntries.containsKey(root) &&
} else if (!source && libraryOrSdkClasses.contains(root) &&
(!classOfLibraries.containsKey(root) || !librariesToIgnore.containsAll(classOfLibraries.get(root)))) {
return root;
}
@@ -403,35 +460,6 @@ class RootIndex {
return null;
}
@NotNull
private Pair<DirectoryInfo, String> calcDirectoryInfo(VirtualFile root, @NotNull final List<VirtualFile> hierarchy) {
VirtualFile moduleContentRoot = findModuleRootInfo(hierarchy);
VirtualFile libraryClassRoot = findLibraryRootInfo(hierarchy, false);
VirtualFile librarySourceRoot = findLibraryRootInfo(hierarchy, true);
if (moduleContentRoot == null && libraryClassRoot == null && librarySourceRoot == null) {
return new Pair<DirectoryInfo, String>(null, null);
}
VirtualFile sourceRoot = findPackageRootInfo(hierarchy, moduleContentRoot, null, librarySourceRoot);
VirtualFile moduleSourceRoot = findPackageRootInfo(hierarchy, moduleContentRoot, null, null);
boolean inModuleSources = moduleSourceRoot != null;
boolean inLibrarySource = librarySourceRoot != null;
int typeId = moduleSourceRoot != null ? rootTypeId.get(moduleSourceRoot) : 0;
OrderEntry[] entries = getOrderEntries(hierarchy, moduleContentRoot, libraryClassRoot, librarySourceRoot);
DirectoryInfo directoryInfo = new DirectoryInfo(contentRootOf.get(moduleContentRoot),
moduleContentRoot,
sourceRoot,
libraryClassRoot,
(byte)DirectoryInfo.createSourceRootTypeData(inModuleSources, inLibrarySource, typeId),
entries);
String packagePrefix = calcPackagePrefix(root, hierarchy, moduleContentRoot, libraryClassRoot, librarySourceRoot);
return Pair.create(directoryInfo, packagePrefix);
}
private String calcPackagePrefix(VirtualFile root,
List<VirtualFile> hierarchy,
VirtualFile moduleContentRoot,
@@ -467,31 +495,28 @@ class RootIndex {
return null;
}
private void collectDependencyOrderEntries(List<VirtualFile> hierarchy, Set<OrderEntry> result) {
for (VirtualFile root : hierarchy) {
result.addAll(depEntries.get(root));
}
}
private void collectLibraryOrderEntries(List<VirtualFile> hierarchy,
@Nullable VirtualFile libraryClassRoot,
@Nullable VirtualFile librarySourceRoot,
Set<OrderEntry> result) {
private LinkedHashSet<OrderEntry> getLibraryOrderEntries(List<VirtualFile> hierarchy,
@Nullable VirtualFile libraryClassRoot,
@Nullable VirtualFile librarySourceRoot,
MultiMap<VirtualFile, OrderEntry> libClassRootEntries,
MultiMap<VirtualFile, OrderEntry> libSourceRootEntries) {
LinkedHashSet<OrderEntry> orderEntries = ContainerUtil.newLinkedHashSet();
for (VirtualFile root : hierarchy) {
if (root == libraryClassRoot && !sourceRootOf.containsKey(root)) {
result.addAll(libClassRootEntries.get(root));
orderEntries.addAll(libClassRootEntries.get(root));
}
if (root == librarySourceRoot && libraryClassRoot == null) {
result.addAll(libSourceRootEntries.get(root));
orderEntries.addAll(libSourceRootEntries.get(root));
}
if (libClassRootEntries.containsKey(root) || sourceRootOf.containsKey(root) && librarySourceRoot == null) {
break;
}
}
return orderEntries;
}
@Nullable
private ModuleSourceOrderEntry getModuleSourceEntry(List<VirtualFile> hierarchy, @NotNull VirtualFile moduleContentRoot) {
private ModuleSourceOrderEntry getModuleSourceEntry(List<VirtualFile> hierarchy, @NotNull VirtualFile moduleContentRoot, MultiMap<VirtualFile, OrderEntry> libClassRootEntries) {
Module module = contentRootOf.get(moduleContentRoot);
for (VirtualFile root : hierarchy) {
if (sourceRootOf.get(root).contains(module)) {
@@ -504,24 +529,42 @@ class RootIndex {
return null;
}
private OrderEntry[] getOrderEntries(List<VirtualFile> hierarchy,
@Nullable VirtualFile moduleContentRoot,
@Nullable VirtualFile libraryClassRoot,
@Nullable VirtualFile librarySourceRoot) {
LinkedHashSet<OrderEntry> orderEntries = ContainerUtil.newLinkedHashSet();
collectLibraryOrderEntries(hierarchy, libraryClassRoot, librarySourceRoot, orderEntries);
collectDependencyOrderEntries(hierarchy, orderEntries);
if (moduleContentRoot != null) {
ContainerUtil.addIfNotNull(orderEntries, getModuleSourceEntry(hierarchy, moduleContentRoot));
}
if (orderEntries.isEmpty()) {
return null;
}
OrderEntry[] array = orderEntries.toArray(new OrderEntry[orderEntries.size()]);
Arrays.sort(array, DirectoryInfo.BY_OWNER_MODULE);
return array;
}
}
@NotNull
private Pair<DirectoryInfo, String> calcDirectoryInfo(final VirtualFile root, @NotNull final List<VirtualFile> hierarchy, RootInfo info) {
VirtualFile moduleContentRoot = info.findModuleRootInfo(hierarchy);
VirtualFile libraryClassRoot = info.findLibraryRootInfo(hierarchy, false);
VirtualFile librarySourceRoot = info.findLibraryRootInfo(hierarchy, true);
if (moduleContentRoot == null && libraryClassRoot == null && librarySourceRoot == null) {
return new Pair<DirectoryInfo, String>(null, null);
}
VirtualFile sourceRoot = info.findPackageRootInfo(hierarchy, moduleContentRoot, null, librarySourceRoot);
VirtualFile moduleSourceRoot = info.findPackageRootInfo(hierarchy, moduleContentRoot, null, null);
boolean inModuleSources = moduleSourceRoot != null;
boolean inLibrarySource = librarySourceRoot != null;
int typeId = moduleSourceRoot != null ? info.rootTypeId.get(moduleSourceRoot) : 0;
DirectoryInfo directoryInfo = new DirectoryInfo(info.contentRootOf.get(moduleContentRoot),
moduleContentRoot,
sourceRoot,
libraryClassRoot,
(byte)DirectoryInfo.createSourceRootTypeData(inModuleSources, inLibrarySource, typeId),
null) {
@NotNull
@Override
public OrderEntry[] getOrderEntries() {
OrderEntry[] entries = RootIndex.this.getOrderEntries().get(root);
return entries == null ? OrderEntry.EMPTY_ARRAY : entries;
}
};
String packagePrefix = info.calcPackagePrefix(root, hierarchy, moduleContentRoot, libraryClassRoot, librarySourceRoot);
return Pair.create(directoryInfo, packagePrefix);
}
}
@@ -218,7 +218,7 @@ public class DeferredIconImpl<T> implements DeferredIcon {
private void setDone(@NotNull Icon result) {
if (myEvalListener != null) {
myEvalListener.evalDone(myParam, result);
myEvalListener.evalDone(this, myParam, result);
}
myDone = true;
@@ -334,6 +334,6 @@ public class DeferredIconImpl<T> implements DeferredIcon {
}
public interface IconListener<T> {
void evalDone(T key, @NotNull Icon result);
void evalDone(DeferredIconImpl<T> source, T key, @NotNull Icon result);
}
}
@@ -82,7 +82,7 @@ public class IconDeferrerImpl extends IconDeferrer {
return deferImpl(base, param, f, true);
}
private <T> Icon deferImpl(Icon base, T param, @NotNull Function<T, Icon> f, boolean autoupdatable) {
private <T> Icon deferImpl(Icon base, T param, @NotNull Function<T, Icon> f, final boolean autoupdatable) {
if (myEvaluationIsInProgress.get().booleanValue()) {
return f.fun(param);
}
@@ -93,11 +93,11 @@ public class IconDeferrerImpl extends IconDeferrer {
final long started = myLastClearTimestamp;
result = new DeferredIconImpl<T>(base, param, f, new DeferredIconImpl.IconListener<T>() {
@Override
public void evalDone(T key, @NotNull Icon r) {
public void evalDone(DeferredIconImpl<T> source, T key, @NotNull Icon r) {
synchronized (LOCK) {
// check if our results is not outdated yet
if (started == myLastClearTimestamp) {
myIconsCache.put(key, r);
myIconsCache.put(key, autoupdatable ? source: r);
}
}
}
@@ -49,7 +49,11 @@ import java.util.concurrent.ConcurrentMap;
* and set its indexed state to unindexed
* if we get other event we set indexed state to outdated
*
* Index stamp is file timestamp of the index directory, we assume that index stamps are monotonically increasing
* Index stamp is file timestamp of the index directory, it is assumed that index stamps are monotonically increasing, but
* still << Long.MAX_VALUE: there are two negative special timestamps used for marking outdated / unindexed index state.
* The code doesn't take overflow of real file timestaps (or their coincidence to negative special timestamps) into account because
* it will happen (if time will go as forward as it does today) near year 292277094 (=new java.util.Date(Long.MAX_VALUE).getYear()).
* At that time (if this code will be still actual) we can use positive small timestamps for special cases.
*/
public class IndexingStamp {
private static final long UNINDEXED_STAMP = -1L; // we don't store trivial "absent" state
@@ -16,20 +16,19 @@
package com.intellij.history.integration.ui.actions;
import com.intellij.ide.actions.NonTrivialActionGroup;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.project.DumbAware;
public class LocalHistoryGroup extends DefaultActionGroup implements DumbAware {
public class LocalHistoryGroup extends NonTrivialActionGroup implements DumbAware {
public void update(AnActionEvent event) {
Presentation p = event.getPresentation();
boolean hasProject = event.getData(CommonDataKeys.PROJECT) != null;
p.setVisible(hasProject);
p.setEnabled(hasProject);
if (event.getData(CommonDataKeys.PROJECT) == null) {
event.getPresentation().setEnabledAndVisible(false);
}
else {
super.update(event);
}
}
}
@@ -17,6 +17,7 @@
package com.intellij.history.integration.ui.actions;
import com.intellij.history.LocalHistory;
import com.intellij.history.core.LocalHistoryFacade;
import com.intellij.history.integration.IdeaGateway;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.Project;
@@ -34,4 +35,9 @@ public class PutLabelAction extends LocalHistoryActionWithDialog {
if (labelName == null) return;
LocalHistory.getInstance().putUserLabel(p, labelName);
}
@Override
protected boolean isEnabled(LocalHistoryFacade vcs, IdeaGateway gw, VirtualFile f, AnActionEvent e) {
return f != null && gw.isVersioned(f);
}
}
@@ -178,6 +178,18 @@ public class EditorModificationUtil {
if (editor.getCaretModel().supportsMultipleCarets()) {
int caretCount = editor.getCaretModel().getCaretCount();
if (caretCount == 1 && editor.isColumnMode()) {
int pastedLineCount = LineTokenizer.calcLineCount(text, true);
deleteSelectedText(editor);
Caret caret = editor.getCaretModel().getPrimaryCaret();
for (int i = 0; i < pastedLineCount - 1; i++) {
caret = caret.clone(false);
if (caret == null) {
break;
}
}
caretCount = editor.getCaretModel().getCaretCount();
}
final Iterator<String> segments = new ClipboardTextPerCaretSplitter().split(text, caretCount).iterator();
editor.getCaretModel().runForEachCaret(new CaretAction() {
@Override
@@ -403,6 +415,14 @@ public class EditorModificationUtil {
}
}
public static void typeInStringAtCaretHonorMultipleCarets(final Editor editor, @NotNull final String str) {
typeInStringAtCaretHonorMultipleCarets(editor, str, true, str.length());
}
public static void typeInStringAtCaretHonorMultipleCarets(final Editor editor, @NotNull final String str, final int caretShift) {
typeInStringAtCaretHonorMultipleCarets(editor, str, true, caretShift);
}
public static void typeInStringAtCaretHonorMultipleCarets(final Editor editor, @NotNull final String str, final boolean toProcessOverwriteMode) {
typeInStringAtCaretHonorMultipleCarets(editor, str, toProcessOverwriteMode, str.length());
}
@@ -35,7 +35,7 @@ public class TextBrowseFolderListener extends ComponentWithBrowseButton.BrowseFo
myTextComponent = component;
}
FileChooserDescriptor gFileChooserDescriptor() {
FileChooserDescriptor getFileChooserDescriptor() {
return myFileChooserDescriptor;
}
}
@@ -59,7 +59,7 @@ public class TextFieldWithBrowseButton extends ComponentWithBrowseButton<JTextFi
public void addBrowseFolderListener(@NotNull TextBrowseFolderListener listener) {
listener.setOwnerComponent(this);
addBrowseFolderListener(null, listener, true);
installPathCompletion(listener.gFileChooserDescriptor());
installPathCompletion(listener.getFileChooserDescriptor());
}
protected void installPathCompletion(final FileChooserDescriptor fileChooserDescriptor) {
@@ -182,8 +182,10 @@ public abstract class FocusCommand extends ActiveRunnable implements Expirable {
// This change seems reasonable to me. But as far as some implementations
// can ignore the "forced" parameter we can get bad focus behaviour.
// So let's start from mac.
if (!myToFocus.requestFocusInWindow() && (isForced() && SystemInfo.isMac)) {
myToFocus.requestFocus();
if (!(myToFocus.requestFocusInWindow())) {
if (!SystemInfo.isMac || isForced() ) {
myToFocus.requestFocus();
}
}
}
}
@@ -123,10 +123,20 @@ public interface ToolWindow extends BusyObject {
/**
* Sets new window title.
* @exception IllegalStateException if tool window isn't installed.
*/
void setTitle(String title);
/**
* @return window stripe button text.
*/
@NotNull
String getStripeTitle();
/**
* Sets new window stripe button text.
*/
void setStripeTitle(@NotNull String title);
/**
* @return whether the window is available or not.
*/
@@ -21,8 +21,8 @@ public class ToolWindowContentUiType {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.ToolWindowContentUiType");
public static ToolWindowContentUiType TABBED = new ToolWindowContentUiType("tabs");
public static ToolWindowContentUiType COMBO = new ToolWindowContentUiType("combo");
public static final ToolWindowContentUiType TABBED = new ToolWindowContentUiType("tabs");
public static final ToolWindowContentUiType COMBO = new ToolWindowContentUiType("combo");
private final String myName;
@@ -40,9 +40,10 @@ public class ColorPanel extends JComponent {
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (!isEnabled() || !isEditable) return;
Color color = ColorChooser.chooseColor(ColorPanel.this, UIBundle.message("color.panel.select.color.dialog.description"), myColor);
if (color != null) {
myColor = color;
setSelectedColor(color);
fireActionEvent();
}
}
@@ -87,7 +88,7 @@ public class ColorPanel extends JComponent {
return null;
}
StringBuilder buffer = new StringBuilder("0x").append(ColorUtil.toHex(myColor).toUpperCase());
if (isEnabled()) {
if (isEnabled() && isEditable) {
buffer.append(" (Click to customize)");
}
return buffer.toString();
@@ -16,6 +16,7 @@
package com.intellij.util.ui;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
@@ -34,7 +35,7 @@ public class FadeInFadeOut extends JComponent {
private final BufferedImage myComponentImage;
private Rectangle myComponentBounds;
@NotNull
@Nullable
private final Component myIcon;
private Rectangle myIconBounds;
@@ -46,7 +47,7 @@ public class FadeInFadeOut extends JComponent {
private Runnable myOnDone = null;
public FadeInFadeOut(@NotNull Component component, int timeToComplete, boolean fadeIn, @NotNull Component icon) {
public FadeInFadeOut(@NotNull Component component, int timeToComplete, boolean fadeIn, @Nullable Component icon) {
setFocusable(false);
myComponent = component;
myFadeIn = fadeIn;
@@ -81,7 +82,11 @@ public class FadeInFadeOut extends JComponent {
super.reshape(x, y, w, h);
if (!myTriggered) {
myComponentBounds = SwingUtilities.convertRectangle(myComponent.getParent(), myComponent.getBounds(), this);
myIconBounds = SwingUtilities.convertRectangle(myIcon.getParent(), myIcon.getBounds(), this);
if (myIcon == null) {
myIconBounds = myComponentBounds;
} else {
myIconBounds = SwingUtilities.convertRectangle(myIcon.getParent(), myIcon.getBounds(), this);
}
}
}
@@ -16,12 +16,14 @@
*/
package com.intellij.ide.actions;
import com.intellij.icons.AllIcons;
import com.intellij.ide.IdeBundle;
import com.intellij.notification.EventLog;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.keymap.Keymap;
import com.intellij.openapi.keymap.KeymapManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.ui.SizedIcon;
@@ -55,6 +57,9 @@ public class ActivateToolWindowAction extends AnAction implements DumbAware {
presentation.setVisible(toolWindow!=null);
if (toolWindow != null) {
Icon icon = toolWindow.getIcon();
if (EventLog.LOG_TOOL_WINDOW_ID.equals(myToolWindowId)) {
icon = AllIcons.Ide.Info_notifications;
}
presentation.setIcon(icon == null ? null : new SizedIcon(icon, icon.getIconHeight(), icon.getIconHeight()));
}
}
@@ -15,7 +15,7 @@
*/
package com.intellij.ide.passwordSafe.impl.providers.masterKey;
import com.intellij.openapi.ui.Messages;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.ui.ValidationInfo;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
@@ -47,7 +47,7 @@ public abstract class PasswordComponentBase {
mySafe = safe;
myTitle = title;
myIconLabel.setText("");
myIconLabel.setIcon(Messages.getQuestionIcon()); // todo add some lock icon
myIconLabel.setIcon(AllIcons.General.PasswordLock);
//myPromptLabel.setUI(new MultiLineLabelUI());
myPromptLabel.setFont(UIUtil.getLabelFont(UIUtil.FontSize.SMALL));
@@ -15,6 +15,7 @@
*/
package com.intellij.openapi.actionSystem.impl;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
@@ -227,6 +228,10 @@ public class ActionMenuItem extends JCheckBoxMenuItem {
public void actionPerformed(final ActionEvent e) {
final IdeFocusManager fm = IdeFocusManager.findInstanceByContext(myContext);
final ActionCallback typeAhead = new ActionCallback();
final String id = ActionManager.getInstance().getId(myAction.getAction());
if (id != null) {
FeatureUsageTracker.getInstance().triggerFeatureUsed("context.menu.click.stats." + id.replace(' ', '.'));
}
fm.typeAheadUntil(typeAhead);
fm.runOnOwnContext(myContext, new Runnable() {
@Override
@@ -17,12 +17,14 @@
package com.intellij.openapi.editor.actions;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.ex.EditorEx;
import org.jetbrains.annotations.Nullable;
/**
* @author max
@@ -35,17 +37,23 @@ public class EscapeAction extends EditorAction {
private static class Handler extends EditorActionHandler {
@Override
public void execute(Editor editor, DataContext dataContext) {
public void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
if (editor instanceof EditorEx) {
EditorEx editorEx = (EditorEx)editor;
if (editorEx.isStickySelection()) {
editorEx.setStickySelection(false);
}
}
editor.getCaretModel().removeSecondaryCarets();
retainOldestCaret(editor.getCaretModel());
editor.getSelectionModel().removeSelection();
}
private static void retainOldestCaret(CaretModel caretModel) {
while(caretModel.getCaretCount() > 1) {
caretModel.removeCaret(caretModel.getPrimaryCaret());
}
}
@Override
public boolean isEnabled(Editor editor, DataContext dataContext) {
SelectionModel selectionModel = editor.getSelectionModel();
@@ -1445,7 +1445,19 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
CharSequence text = myEditor.getDocument().getCharsSequence();
int selectionStart = getSelectionStart();
int selectionEnd = getSelectionEnd();
return text.subSequence(selectionStart, selectionEnd).toString();
String selectedText = text.subSequence(selectionStart, selectionEnd).toString();
if (isVirtualSelectionEnabled() && myEndVirtualOffset > myStartVirtualOffset) {
int padding = myEndVirtualOffset - myStartVirtualOffset;
StringBuilder builder = new StringBuilder(selectedText.length() + padding);
builder.append(selectedText);
for (int i = 0; i < padding; i++) {
builder.append(' ');
}
return builder.toString();
}
else {
return selectedText;
}
}
private void validateContext(boolean isWrite) {
@@ -306,6 +306,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
private LogicalPosition myLastMousePressedLocation;
private VisualPosition myTargetMultiSelectionPosition;
private boolean myMultiSelectionInProgress;
private boolean myLastPressCreatedCaret;
private CaretImpl myPrimaryCaret;
@@ -5670,22 +5671,31 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
final int oldStart = mySelectionModel.getSelectionStart();
final int oldEnd = mySelectionModel.getSelectionEnd();
boolean toggleCaret = myCaretModel.supportsMultipleCarets() && e.getSource() != myGutterComponent && isToggleCaretEvent(e);
boolean lastPressCreatedCaret = myLastPressCreatedCaret;
if (e.getClickCount() == 1) {
myLastPressCreatedCaret = false;
}
// Don't move caret on mouse press above gutter line markers area (a place where break points, 'override', 'implements' etc icons
// are drawn) and annotations area. E.g. we don't want to change caret position if a user sets new break point (clicks
// at 'line markers' area).
if (e.getSource() != myGutterComponent
|| (eventArea != EditorMouseEventArea.LINE_MARKERS_AREA && eventArea != EditorMouseEventArea.ANNOTATIONS_AREA))
{
boolean toggleCaret = myCaretModel.supportsMultipleCarets() && e.getSource() != myGutterComponent && isToggleCaretEvent(e);
LogicalPosition pos = getLogicalPositionForScreenPos(x, y, true);
if (toggleCaret) {
VisualPosition visualPosition = logicalToVisualPosition(pos);
Caret caret = getCaretModel().getCaretAt(visualPosition);
if (caret == null) {
getCaretModel().addCaret(visualPosition);
if (e.getClickCount() == 1) {
if (caret == null) {
myLastPressCreatedCaret = getCaretModel().addCaret(visualPosition) != null;
}
else {
getCaretModel().removeCaret(caret);
}
}
else {
getCaretModel().removeCaret(caret);
else if (e.getClickCount() == 3 && lastPressCreatedCaret) {
getCaretModel().moveToLogicalPosition(pos);
}
}
else {
@@ -5755,7 +5765,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
else {
if (!e.isPopupTrigger()
&& (eventArea == EditorMouseEventArea.EDITING_AREA || eventArea == EditorMouseEventArea.LINE_NUMBERS_AREA))
&& (eventArea == EditorMouseEventArea.EDITING_AREA || eventArea == EditorMouseEventArea.LINE_NUMBERS_AREA)
&& (!toggleCaret || lastPressCreatedCaret))
{
switch (e.getClickCount()) {
case 2:
@@ -482,8 +482,8 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
public String getSelectedText(boolean allCarets) {
validateContext(false);
CharSequence text = myEditor.getDocument().getCharsSequence();
if (hasBlockSelection() || (myEditor.getCaretModel().supportsMultipleCarets() && allCarets)) {
if (hasBlockSelection()) {
CharSequence text = myEditor.getDocument().getCharsSequence();
int[] starts = getBlockSelectionStarts();
int[] ends = getBlockSelectionEnds();
int width = myEditor.getCaretModel().supportsMultipleCarets() ? 0 : Math.abs(myBlockEnd.column - myBlockStart.column);
@@ -496,8 +496,22 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
}
return buf.toString();
}
return myEditor.getCaretModel().getCurrentCaret().getSelectedText();
else if (myEditor.getCaretModel().supportsMultipleCarets() && allCarets) {
final StringBuilder buf = new StringBuilder();
String separator = "";
for (Caret caret : myEditor.getCaretModel().getAllCarets()) {
buf.append(separator);
String caretSelectedText = caret.getSelectedText();
if (caretSelectedText != null) {
buf.append(caretSelectedText);
}
separator = "\n";
}
return buf.toString();
}
else {
return myEditor.getCaretModel().getCurrentCaret().getSelectedText();
}
}
private static void appendCharSequence(@NotNull StringBuilder buf, @NotNull CharSequence s, int srcOffset, int len) {
@@ -148,7 +148,7 @@ public final class UpdateChecker {
private static void doUpdateAndShowResult(final @Nullable Project project,
final boolean enableLink,
final boolean showDialog,
final boolean manualCheck,
final @Nullable PluginHostsConfigurable hostsConfigurable,
final UpdateSettings updateSettings,
final @Nullable ProgressIndicator indicator,
@@ -161,17 +161,17 @@ public final class UpdateChecker {
settings.setKnownChannelIds(result.getAllChannelsIds());
}
else if (result.getState() == UpdateStrategy.State.CONNECTION_ERROR) {
showErrorMessage(showDialog, project, IdeBundle.message("updates.error.connection.failed"));
showErrorMessage(manualCheck, project, IdeBundle.message("updates.error.connection.failed"));
return;
}
boolean platformUpdate = newChannelReady(result.getChannelToPropose()) || result.getUpdatedChannel() != null;
final List<PluginDownloader> updatedPlugins = platformUpdate ? null : updatePlugins(showDialog, project, hostsConfigurable, indicator);
final List<PluginDownloader> updatedPlugins = platformUpdate ? null : updatePlugins(manualCheck, project, hostsConfigurable, indicator);
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
showUpdateResult(project, result, updatedPlugins, enableLink, showDialog);
showUpdateResult(project, result, updatedPlugins, enableLink, manualCheck);
if (callback != null) {
callback.setDone();
}
@@ -179,7 +179,7 @@ public final class UpdateChecker {
});
}
private static List<PluginDownloader> updatePlugins(boolean showDialog,
private static List<PluginDownloader> updatePlugins(boolean manualCheck,
@Nullable Project project,
@Nullable PluginHostsConfigurable hostsConfigurable,
@Nullable ProgressIndicator indicator) {
@@ -250,12 +250,12 @@ public final class UpdateChecker {
return null;
}
catch (Exception e) {
showErrorMessage(showDialog, project, e.getMessage());
showErrorMessage(manualCheck, project, e.getMessage());
}
}
if (!failed.isEmpty()) {
showErrorMessage(showDialog, project, IdeBundle.message("updates.error.plugin.description.failed", StringUtil.join(failed, ",")));
showErrorMessage(manualCheck, project, IdeBundle.message("updates.error.plugin.description.failed", StringUtil.join(failed, ",")));
}
return downloaded.isEmpty() ? null : downloaded;
@@ -278,7 +278,6 @@ public final class UpdateChecker {
});
}
else {
showNotification(project, message, true, null);
LOG.warn(message);
}
}
@@ -29,6 +29,7 @@ public interface ToolWindowEx extends ToolWindow {
@NonNls String PROP_AVAILABLE = "available";
@NonNls String PROP_ICON = "icon";
@NonNls String PROP_TITLE = "title";
@NonNls String PROP_STRIPE_TITLE = "stripe-title";
/**
* Removes specified property change listener.
@@ -15,6 +15,7 @@
*/
package com.intellij.openapi.wm.impl;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.ide.actions.ActivateToolWindowAction;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.actionSystem.ActionGroup;
@@ -289,6 +290,7 @@ public final class StripeButton extends AnchoredButton implements ActionListener
myDecorator.fireActivated();
}
myPressedWhenSelected = false;
FeatureUsageTracker.getInstance().triggerFeatureUsed("toolwindow.clickstat." + myDecorator.getToolWindow().getId());
}
public void apply(@NotNull WindowInfoImpl info) {
@@ -323,7 +325,7 @@ public final class StripeButton extends AnchoredButton implements ActionListener
* and short cut registered in the key map.
*/
void updateText() {
String toolWindowId = myDecorator.getToolWindow().getTitle();
String toolWindowId = myDecorator.getToolWindow().getStripeTitle();
String text = toolWindowId;
if (UISettings.getInstance().SHOW_TOOL_WINDOW_NUMBERS) {
final int mnemonic = ActivateToolWindowAction.getMnemonicForToolWindow(toolWindowId);
@@ -364,7 +366,7 @@ public final class StripeButton extends AnchoredButton implements ActionListener
if (ToolWindowEx.PROP_AVAILABLE.equals(name)) {
updateState();
}
else if (ToolWindowEx.PROP_TITLE.equals(name)) {
else if (ToolWindowEx.PROP_STRIPE_TITLE.equals(name)) {
updateText();
}
else if (ToolWindowEx.PROP_ICON.equals(name)) {
@@ -266,7 +266,7 @@ public final class TestWindowManager extends WindowManagerEx implements Applicat
@Override
public IdeFrame findFrameFor(@Nullable Project project) {
throw new UnsupportedOperationException();
return null;
}
@NotNull
@@ -163,6 +163,16 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
public void setTitle(String title) {
}
@NotNull
@Override
public String getStripeTitle() {
return "";
}
@Override
public void setStripeTitle(@NotNull String title) {
}
@Override
public boolean isAvailable() {
return false;
@@ -61,7 +61,7 @@ public final class ToolWindowImpl implements ToolWindowEx {
private boolean myAvailable;
private final ContentManager myContentManager;
private Icon myIcon;
private String myTitle;
private String myStripeTitle;
private static final Content EMPTY_CONTENT = new ContentImpl(new JLabel(), "", false);
private final ToolWindowContentUi myContentUI;
@@ -344,7 +344,13 @@ public final class ToolWindowImpl implements ToolWindowEx {
public final String getTitle() {
ApplicationManager.getApplication().assertIsDispatchThread();
return ObjectUtils.notNull(myTitle, myId);
return getSelectedContent().getDisplayName();
}
@NotNull
public final String getStripeTitle() {
ApplicationManager.getApplication().assertIsDispatchThread();
return ObjectUtils.notNull(myStripeTitle, myId);
}
public final void setIcon(final Icon icon) {
@@ -360,11 +366,18 @@ public final class ToolWindowImpl implements ToolWindowEx {
public final void setTitle(String title) {
ApplicationManager.getApplication().assertIsDispatchThread();
final String oldTitle = getTitle();
myTitle = title;
String oldTitle = getTitle();
getSelectedContent().setDisplayName(title);
myChangeSupport.firePropertyChange(PROP_TITLE, oldTitle, title);
}
public final void setStripeTitle(@NotNull String stripeTitle) {
ApplicationManager.getApplication().assertIsDispatchThread();
String oldTitle = myStripeTitle;
myStripeTitle = stripeTitle;
myChangeSupport.firePropertyChange(PROP_STRIPE_TITLE, oldTitle, stripeTitle);
}
private Content getSelectedContent() {
final Content selected = getContentManager().getSelectedContent();
return selected != null ? selected : EMPTY_CONTENT;
@@ -575,7 +575,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
@Override
public void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener l) {
myDispatcher.addListener(l);
myDispatcher.removeListener(l);
}
/**
@@ -71,7 +71,7 @@ abstract class ContentLayout {
public abstract boolean shouldDrawDecorations();
protected void updateIdLabel(BaseLabel label) {
label.setText(myUi.myWindow.getTitle() + (shouldDrawDecorations() ? ":" : ""));
label.setText(myUi.myWindow.getStripeTitle() + (shouldDrawDecorations() ? ":" : ""));
label.setBorder(new EmptyBorder(0, 2, 0, 8));
if (myUi.myManager.getContentCount() == 1) {
@@ -30,7 +30,6 @@ import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.*;
import com.intellij.openapi.wm.impl.IdeFrameImpl;
import com.intellij.openapi.wm.impl.ToolWindowImpl;
import com.intellij.ui.GotItMessage;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.UIBundle;
@@ -146,7 +145,7 @@ class ToolWindowsWidget extends JLabel implements CustomStatusBarWidget, StatusB
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
final ToolWindow toolWindow = (ToolWindow)value;
label.setText(toolWindow instanceof ToolWindowImpl ? ((ToolWindowImpl)toolWindow).getId() : toolWindow.getTitle());
label.setText(toolWindow.getStripeTitle());
label.setIcon(toolWindow.getIcon());
label.setBorder(IdeBorderFactory.createEmptyBorder(4, 10, 4, 10));
label.setForeground(UIUtil.getListForeground(isSelected));
@@ -111,7 +111,7 @@ public class PlatformProjectOpenProcessor extends ProjectOpenProcessor {
if (baseDir == null) { // no reasonable directory -> create new temp one or use parent
if (Registry.is("ide.open.file.in.temp.project.dir")) {
try {
dummyProjectName = virtualFile.getPath();
dummyProjectName = virtualFile.getName();
File directory = FileUtil.createTempDirectory(dummyProjectName, null, true);
baseDir = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(directory);
dummyProject = true;
@@ -48,6 +48,8 @@ public class SheetController {
private JButton myDefaultButton;
private JButton myFocusedButton;
private static int RIGHT_OFFSET = 15;
public int SHADOW_BORDER = 10;
// SHEET
@@ -132,13 +134,17 @@ public class SheetController {
private void handleMnemonics(int i, String buttonTitle) {
buttons[i].setName(buttonTitle);
if (buttonTitle.indexOf('&') != -1) {
buttons[i].setMnemonic(buttonTitle.charAt(buttonTitle.indexOf('&') + 1));
buttonTitle = buttonTitle.replace("&","");
}
buttons[i].setText(buttonTitle);
setMnemonicsFromChar('&', buttons[i]);
setMnemonicsFromChar('_', buttons[i]);
}
private static void setMnemonicsFromChar(char mnemonicChar, JButton button) {
String buttonTitle = button.getText();
if (buttonTitle.indexOf(mnemonicChar) != -1) {
button.setMnemonic(buttonTitle.charAt(buttonTitle.indexOf(mnemonicChar) + 1));
button.setText(buttonTitle.replace(Character.toString(mnemonicChar), ""));
}
}
void requestFocus() {
@@ -172,9 +178,7 @@ public class SheetController {
}
private final static int TOP_SHEET_PADDING = 15;
private final static int GAP_BETWEEN_TITLE_AND_MESSAGE = 10;
private final static int GAP_BETWEEN_MESSAGE_AND_BUTTONS = 10;
private final static int BUTTONS_PLUS_CHECKBOX = 70;
private final static int GAP_BETWEEN_LINES = 10;
private final static int LEFT_SHEET_PADDING = 35;
private final static int LEFT_SHEET_OFFSET = 120;
@@ -242,9 +246,22 @@ public class SheetController {
messageTextPane.setEditable(false);
messageTextPane.setContentType("text/html");
messageTextPane.setSize(250, Short.MAX_VALUE);
FontMetrics fontMetrics = mySheetMessage.getFontMetrics(regularFont);
int widestWordWidth = 250;
String [] words = message.split(" ");
for (String word : words) {
widestWordWidth = Math.max(fontMetrics.stringWidth(word), widestWordWidth);
}
messageTextPane.setSize(widestWordWidth, Short.MAX_VALUE);
messageTextPane.setText(message);
messageArea.setSize(250, messageTextPane.getPreferredSize().height);
messageArea.setSize(widestWordWidth, messageTextPane.getPreferredSize().height);
SHEET_WIDTH = Math.max(LEFT_SHEET_OFFSET + widestWordWidth + RIGHT_OFFSET, SHEET_WIDTH);
messageTextPane.setSize(messageArea);
messageTextPane.setOpaque(false);
@@ -254,15 +271,23 @@ public class SheetController {
messageTextPane.repaint();
SHEET_HEIGHT = TOP_SHEET_PADDING + headerLabel.getPreferredSize().height + GAP_BETWEEN_TITLE_AND_MESSAGE + messageArea.height
+ GAP_BETWEEN_MESSAGE_AND_BUTTONS + BUTTONS_PLUS_CHECKBOX;
ico.setOpaque(false);
ico.setSize(new Dimension(AllIcons.Logo_welcomeScreen.getIconWidth(), AllIcons.Logo_welcomeScreen.getIconHeight()));
ico.setLocation(LEFT_SHEET_PADDING, TOP_SHEET_PADDING);
sheetPanel.add(ico);
headerLabel.setLocation(LEFT_SHEET_OFFSET, TOP_SHEET_PADDING);
messageTextPane.setLocation(LEFT_SHEET_OFFSET, TOP_SHEET_PADDING + headerLabel.getPreferredSize().height + GAP_BETWEEN_TITLE_AND_MESSAGE);
messageTextPane.setLocation(LEFT_SHEET_OFFSET, TOP_SHEET_PADDING + headerLabel.getPreferredSize().height + GAP_BETWEEN_LINES);
SHEET_HEIGHT = TOP_SHEET_PADDING + headerLabel.getPreferredSize().height + GAP_BETWEEN_LINES + messageArea.height
+ GAP_BETWEEN_LINES;
if (myDoNotAskOption != null) {
layoutDoNotAskCheckbox(sheetPanel);
}
layoutWithAbsoluteLayout(buttons, sheetPanel);
sheetPanel.setFocusCycleRoot(true);
@@ -281,11 +306,6 @@ public class SheetController {
private void layoutWithAbsoluteLayout(JButton[] buttons, JPanel sheetPanel) {
layoutButtons(buttons, sheetPanel);
if (myDoNotAskOption != null) {
layoutDoNotAskCheckbox();
sheetPanel.add(doNotAskCheckBox);
}
}
private void paintShadow(Graphics2D g2d) {
@@ -297,7 +317,9 @@ public class SheetController {
private void layoutButtons(final JButton[] buttons, JPanel panel) {
int buttonsWidth = 15;
int buttonsWidth = RIGHT_OFFSET;
for (JButton button : buttons) {
panel.add(button);
@@ -313,14 +335,16 @@ public class SheetController {
Dimension size = button.getPreferredSize();
buttonShift += size.width;
button.setBounds(SHEET_WIDTH - buttonShift,
SHEET_HEIGHT - 40,
SHEET_HEIGHT,
size.width, size.height);
buttonShift += 10;
}
SHEET_HEIGHT += buttons[0].getHeight() + GAP_BETWEEN_LINES;
}
private void layoutDoNotAskCheckbox() {
doNotAskCheckBox = new JCheckBox(myDoNotAskOption.getDoNotShowMessage());
private void layoutDoNotAskCheckbox(JPanel sheetPanel) {
doNotAskCheckBox = new JCheckBox(myDoNotAskOption.getDoNotShowMessage(), !myDoNotAskOption.isToBeShown());
doNotAskCheckBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
@@ -329,7 +353,12 @@ public class SheetController {
});
doNotAskCheckBox.repaint();
doNotAskCheckBox.setSize(doNotAskCheckBox.getPreferredSize());
doNotAskCheckBox.setLocation(LEFT_SHEET_OFFSET, SHEET_HEIGHT - BUTTONS_PLUS_CHECKBOX);
doNotAskCheckBox.setLocation(LEFT_SHEET_OFFSET, SHEET_HEIGHT);
sheetPanel.add(doNotAskCheckBox);
SHEET_HEIGHT += doNotAskCheckBox.getHeight() + GAP_BETWEEN_LINES;
}
/**
@@ -17,7 +17,9 @@ package com.intellij.ui.messages;
import com.apple.eawt.FullScreenUtilities;
import com.intellij.openapi.application.impl.LaterInvocator;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.JBColor;
import com.intellij.ui.mac.MacMainFrameDecorator;
import com.intellij.util.ui.Animator;
@@ -28,12 +30,17 @@ import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Created by Denis Fokin
*/
public class SheetMessage {
private static final Logger LOG = Logger.getInstance("#com.intellij.ui.messages.SheetMessage");
private JDialog myWindow;
private Window myParent;
private SheetController myController;
@@ -73,19 +80,51 @@ public class SheetMessage {
registerMoveResizeHandler();
myWindow.setFocusable(true);
myWindow.setFocusableWindowState(true);
if (SystemInfo.isJavaVersionAtLeast("1.7")) {
myWindow.setSize(myController.SHEET_NC_WIDTH, 0);
setWindowOpacity(0.0f);
myWindow.addComponentListener(new ComponentAdapter() {
@Override
public void componentShown(ComponentEvent e) {
super.componentShown(e);
setWindowOpacity(1.0f);
myWindow.setSize(myController.SHEET_NC_WIDTH, myController.SHEET_NC_HEIGHT);
}
});
} else {
myWindow.setModal(true);
myWindow.setSize(myController.SHEET_NC_WIDTH, myController.SHEET_NC_HEIGHT);
setPositionRelativeToParent();
}
startAnimation(true);
myWindow.setSize(myController.SHEET_NC_WIDTH, myController.SHEET_NC_HEIGHT);
restoreFullscreenButton = couldBeInFullScreen();
if (restoreFullscreenButton) {
FullScreenUtilities.setWindowCanFullScreen(myParent, false);
}
setPositionRelativeToParent();
LaterInvocator.enterModal(myWindow);
myWindow.setVisible(true);
LaterInvocator.leaveModal(myWindow);
}
private void setWindowOpacity(float opacity) {
try {
Method setOpacityMethod = myWindow.getClass().getMethod("setOpacity", Float.TYPE);
setOpacityMethod.invoke(myWindow, opacity);
}
catch (NoSuchMethodException e) {
LOG.error(e);
}
catch (InvocationTargetException e) {
LOG.error(e);
}
catch (IllegalAccessException e) {
LOG.error(e);
}
}
private boolean couldBeInFullScreen() {
if (myParent instanceof JFrame) {
JRootPane rootPane = ((JFrame)myParent).getRootPane();
@@ -189,6 +228,11 @@ public class SheetMessage {
}
});
}
FontMetrics getFontMetrics(Font f) {
return myParent.getGraphics().getFontMetrics(f);
}
}
@@ -44,7 +44,6 @@ xbreakpoint.master.breakpoint.none=<None>
xbreakpoint.master.breakpoint.description=Disabled until selected breakpoint is hit:
rule.name.group.by.file=Group by file
xbreakpoint.default.display.text=Line {0} in {1}
xbreakpoint.group.unknown=Unknown
xbreakpoint.reached.text=Breakpoint reached:
@@ -1,2 +1,2 @@
some text
some other t<caret>ext
so<caret>me text
some other text
@@ -271,6 +271,32 @@ public class EditorMultiCaretColumnModeTest extends AbstractEditorTest {
"ccS<caret>cc");
}
public void testCopyPasteOfShortLines() throws Exception {
init("a\n" +
"bbb\n" +
"ccccc");
mouse().clickAt(0, 2).dragTo(2, 4).release();
executeAction("EditorCopy");
executeAction("EditorLineStart");
executeAction("EditorPaste");
checkResultByText(" <caret>a\n" +
"b <caret>bbb\n" +
"cc<caret>ccccc");
}
public void testPasteOfBlockToASingleCaret() throws Exception {
init("a\n" +
"bbb\n" +
"ccccc");
mouse().clickAt(1, 2).dragTo(2, 4).release();
executeAction("EditorCopy");
mouse().clickAt(0, 2);
executeAction("EditorPaste");
checkResultByText("a b <caret>\n" +
"bbcc<caret>b\n" +
"ccccc");
}
private void init(String text) throws IOException {
configureFromFileText(getTestName(false) + ".txt", text);
setEditorVisibleSize(1000, 1000);
@@ -233,7 +233,8 @@ public class EditorMultiCaretTest extends AbstractEditorTest {
"three<caret></selection> four \n" +
"five <selection>six \n" +
"seven<caret></selection> eight",
TestFileType.TEXT);
TestFileType.TEXT
);
executeAction("EditorCut");
executeAction("EditorLineEnd");
executeAction("EditorPaste");
@@ -242,4 +243,66 @@ public class EditorMultiCaretTest extends AbstractEditorTest {
"five eightsix \n" +
"seven<caret>");
}
public void testEscapeAfterDragDown() throws Exception {
init("line1\n" +
"line2",
TestFileType.TEXT
);
setEditorVisibleSize(1000, 1000);
mouse().alt().clickAt(0, 1).dragTo(1, 2).release();
executeAction("EditorEscape");
checkResultByText("li<caret>ne1\n" +
"line2");
}
public void testEscapeAfterDragUp() throws Exception {
init("line1\n" +
"line2",
TestFileType.TEXT);
setEditorVisibleSize(1000, 1000);
mouse().alt().clickAt(1, 1).dragTo(0, 2).release();
executeAction("EditorEscape");
checkResultByText("line1\n" +
"li<caret>ne2");
}
public void testAltShiftDoubleClick() throws Exception {
init("q<caret>uick brown fox",
TestFileType.TEXT);
mouse().alt().shift().doubleClickAt(0, 8);
checkResultByText("q<caret>uick <selection>brown<caret></selection> fox");
}
public void testAltShiftDoubleClickAtExistingCaret() throws Exception {
init("q<caret>uick br<caret>own fox",
TestFileType.TEXT);
mouse().alt().shift().doubleClickAt(0, 8);
checkResultByText("q<caret>uick brown fox");
}
public void testAltShiftTripleClick() throws Exception {
init("q<caret>uick\n" +
"brown\n" +
"fox",
TestFileType.TEXT
);
mouse().alt().shift().tripleClickAt(1, 2);
checkResultByText("q<caret>uick\n" +
"<selection>br<caret>own\n" +
"</selection>fox");
}
public void testAltShiftTripleClickAtExistingCaret() throws Exception {
init("q<caret>uick\n" +
"br<caret>own\n" +
"fox",
TestFileType.TEXT);
mouse().alt().shift().tripleClickAt(1, 2);
checkResultByText("q<caret>uick\n" +
"brown\n" +
"fox");
}
}
@@ -185,6 +185,15 @@ public class SelectUnselectOccurrenceActionsTest extends LightPlatformCodeInsigh
checkResult("text <selection><caret>text</selection> <selection><caret>text</selection>");
}
public void testEscapeReturnsToInitialPosition() throws Exception {
init("l<caret>ine\n" +
"another line");
executeAction();
myFixture.performEditorAction("EditorEscape");
checkResult("l<caret>ine\n" +
"another line");
}
private void init(String text) {
myFixture.configureByText(FileTypes.PLAIN_TEXT, text);
}
@@ -35,7 +35,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public final class DirectoryInfo {
public class DirectoryInfo {
public static final int MAX_ROOT_TYPE_ID = (1 << (Byte.SIZE - 2)) - 1;
private final Module module; // module to which content it belongs or null
private final VirtualFile libraryClassRoot; // class root in library
@@ -81,7 +81,7 @@ public final class DirectoryInfo {
Comparing.equal(contentRoot, info.contentRoot) &&
Comparing.equal(libraryClassRoot, info.libraryClassRoot) &&
Comparing.equal(module, info.module) &&
Arrays.equals(orderEntries, info.orderEntries) &&
Arrays.equals(getOrderEntries(), info.getOrderEntries()) &&
Comparing.equal(sourceRoot, info.sourceRoot);
}
@@ -105,7 +105,7 @@ public final class DirectoryInfo {
", libraryClassRoot=" + getLibraryClassRoot() +
", contentRoot=" + getContentRoot() +
", sourceRoot=" + getSourceRoot() +
", orderEntries=" + Arrays.toString(orderEntries) +
", orderEntries=" + Arrays.toString(getOrderEntries()) +
"}";
}
@@ -117,10 +117,7 @@ public final class DirectoryInfo {
@Nullable
OrderEntry findOrderEntryWithOwnerModule(@NotNull Module ownerModule) {
OrderEntry[] entries = orderEntries;
if (entries == null) {
return null;
}
OrderEntry[] entries = getOrderEntries();
if (entries.length < 10) {
for (OrderEntry entry : entries) {
if (entry.getOwnerModule() == ownerModule) return entry;
@@ -133,10 +130,7 @@ public final class DirectoryInfo {
@NotNull
List<OrderEntry> findAllOrderEntriesWithOwnerModule(@NotNull Module ownerModule) {
OrderEntry[] entries = orderEntries;
if (entries == null) {
return Collections.emptyList();
}
OrderEntry[] entries = getOrderEntries();
if (entries.length == 1) {
OrderEntry entry = entries[0];
return entry.getOwnerModule() == ownerModule ? Arrays.asList(entries) : Collections.<OrderEntry>emptyList();
@@ -271,10 +265,6 @@ public final class DirectoryInfo {
return sourceRoot;
}
public boolean hasSourceRoot() {
return getSourceRoot() != null;
}
public VirtualFile getLibraryClassRoot() {
return libraryClassRoot;
}
@@ -37,6 +37,10 @@ public class EditorMouseFixture {
}
public EditorMouseFixture pressAt(int visualLine, int visualColumn) {
return pressAt(1, visualLine, visualColumn);
}
private EditorMouseFixture pressAt(int clickCount, int visualLine, int visualColumn) {
JComponent component = myEditor.getContentComponent();
Point p = getPoint(visualLine, visualColumn);
component.dispatchEvent(new MouseEvent(component,
@@ -45,13 +49,17 @@ public class EditorMouseFixture {
getModifiers(),
myX = p.x,
myY = p.y,
1,
clickCount,
false,
myButton));
return this;
}
public EditorMouseFixture release() {
return release(1);
}
private EditorMouseFixture release(int clickCount) {
int oldLastId = myLastId;
JComponent component = myEditor.getContentComponent();
component.dispatchEvent(new MouseEvent(component,
@@ -60,7 +68,7 @@ public class EditorMouseFixture {
getModifiers(),
myX,
myY,
1,
clickCount,
false,
myButton));
if (oldLastId == MouseEvent.MOUSE_PRESSED) {
@@ -70,7 +78,7 @@ public class EditorMouseFixture {
getModifiers(),
myX,
myY,
1,
clickCount,
false,
myButton));
}
@@ -81,6 +89,14 @@ public class EditorMouseFixture {
return pressAt(visualLine, visualColumn).release();
}
public EditorMouseFixture doubleClickAt(int visualLine, int visualColumn) {
return clickAt(visualLine, visualColumn).pressAt(2, visualLine, visualColumn).release(2);
}
public EditorMouseFixture tripleClickAt(int visualLine, int visualColumn) {
return doubleClickAt(visualLine, visualColumn).pressAt(3, visualLine, visualColumn).release(3);
}
public EditorMouseFixture dragTo(int visualLine, int visualColumn) {
JComponent component = myEditor.getContentComponent();
Point p = getPoint(visualLine, visualColumn);
@@ -437,6 +437,7 @@ public class AllIcons {
public static final Icon OverridenMethod = IconLoader.getIcon("/general/overridenMethod.png"); // 10x14
public static final Icon OverridingMethod = IconLoader.getIcon("/general/overridingMethod.png"); // 10x14
public static final Icon PackagesTab = IconLoader.getIcon("/general/packagesTab.png"); // 16x16
public static final Icon PasswordLock = IconLoader.getIcon("/general/passwordLock.png"); // 64x64
public static final Icon PathVariables = IconLoader.getIcon("/general/pathVariables.png"); // 32x32
public static final Icon Pin_tab = IconLoader.getIcon("/general/pin_tab.png"); // 16x16
public static final Icon PluginManager = IconLoader.getIcon("/general/pluginManager.png"); // 32x32
@@ -53,7 +53,7 @@ public abstract class XBreakpointGroupingRule<B, G extends XBreakpointGroup> {
return XBreakpointsGroupingPriorities.DEFAULT;
}
@NotNull
@Nullable
public abstract G getGroup(@NotNull B breakpoint, @NotNull Collection<G> groups);
@Nullable
@@ -15,11 +15,9 @@
*/
package com.intellij.xdebugger.impl.breakpoints.ui.grouping;
import com.intellij.icons.AllIcons;
import com.intellij.ide.presentation.VirtualFilePresentation;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.xdebugger.XDebuggerBundle;
import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroup;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -29,26 +27,8 @@ import javax.swing.*;
* @author nik
*/
public class XBreakpointFileGroup extends XBreakpointGroup {
public static final XBreakpointFileGroup UNKNOWN = new XBreakpointFileGroup() {
@NotNull
@Override
public String getName() {
return XDebuggerBundle.message("xbreakpoint.group.unknown");
}
@Nullable
@Override
public Icon getIcon(boolean isOpen) {
return AllIcons.FileTypes.Text;
}
};
private final VirtualFile myFile;
private XBreakpointFileGroup() {
myFile = null;
}
public XBreakpointFileGroup(@NotNull VirtualFile file) {
myFile = file;
}
@@ -63,7 +43,6 @@ public class XBreakpointFileGroup extends XBreakpointGroup {
return myFile.getPresentableUrl();
}
@Nullable
public VirtualFile getFile() {
return myFile;
}
@@ -16,7 +16,6 @@
package com.intellij.xdebugger.impl.breakpoints.ui.grouping;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.xdebugger.XDebuggerBundle;
import com.intellij.xdebugger.XSourcePosition;
@@ -42,20 +41,17 @@ public class XBreakpointFileGroupingRule<B> extends XBreakpointGroupingRule<B, X
return XBreakpointsGroupingPriorities.BY_FILE;
}
@NotNull
public XBreakpointFileGroup getGroup(@NotNull final B breakpoint, @NotNull final Collection<XBreakpointFileGroup> groups) {
if (!(breakpoint instanceof XLineBreakpoint)) {
return XBreakpointFileGroup.UNKNOWN;
return null;
}
XSourcePosition position = ((XLineBreakpoint)breakpoint).getSourcePosition();
if (position == null) {
return XBreakpointFileGroup.UNKNOWN;
}
if (position == null) return null;
VirtualFile file = position.getFile();
for (XBreakpointFileGroup group : groups) {
if (Comparing.equal(group.getFile(), file)) {
if (group.getFile().equals(file)) {
return group;
}
}
@@ -45,7 +45,6 @@ public class XBreakpointGroupingByTypeRule<B> extends XBreakpointGroupingRule<B,
return XBreakpointsGroupingPriorities.BY_TYPE;
}
@NotNull
@Override
public XBreakpointTypeGroup getGroup(@NotNull B b, @NotNull Collection<XBreakpointTypeGroup> groups) {
if (b instanceof XBreakpoint) {
@@ -57,6 +56,6 @@ public class XBreakpointGroupingByTypeRule<B> extends XBreakpointGroupingRule<B,
}
return new XBreakpointTypeGroup(breakpoint.getType());
}
return XBreakpointTypeGroup.UNKNOWN;
return null;
}
}
@@ -15,31 +15,17 @@
*/
package com.intellij.xdebugger.impl.breakpoints.ui.grouping;
import com.intellij.icons.AllIcons;
import com.intellij.util.ArrayUtil;
import com.intellij.xdebugger.XDebuggerBundle;
import com.intellij.xdebugger.breakpoints.XBreakpointType;
import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
import com.intellij.xdebugger.breakpoints.XLineBreakpointType;
import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroup;
import com.intellij.xdebugger.impl.breakpoints.XBreakpointUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
public class XBreakpointTypeGroup extends XBreakpointGroup {
public static final XBreakpointTypeGroup UNKNOWN = new XBreakpointTypeGroup(null) {
@NotNull
@Override
public String getName() {
return XDebuggerBundle.message("xbreakpoint.group.unknown");
}
@Override
public Icon getIcon(boolean isOpen) {
return AllIcons.Debugger.Db_set_breakpoint;
}
};
private XBreakpointType myBreakpointType;
@@ -53,7 +39,6 @@ public class XBreakpointTypeGroup extends XBreakpointGroup {
return myBreakpointType.getTitle();
}
@Nullable
public XBreakpointType getBreakpointType() {
return myBreakpointType;
}
@@ -129,8 +129,7 @@ public class BreakpointItemsTreeController implements BreakpointsCheckboxTree.De
private CheckedTreeNode getParentNode(final BreakpointItem breakpoint) {
CheckedTreeNode parent = myRoot;
for (int i = 0; i < myGroupingRules.size(); i++) {
Collection<XBreakpointGroup> existingGroups = getGroupNodes(parent);
XBreakpointGroup group = myGroupingRules.get(i).getGroup(breakpoint.getBreakpoint(), existingGroups);
XBreakpointGroup group = myGroupingRules.get(i).getGroup(breakpoint.getBreakpoint(), Collections.emptyList());
if (group != null) {
parent = getOrCreateGroupNode(parent, group, i);
}
@@ -1877,6 +1877,7 @@ if.can.be.switch.quickfix=Replace with 'switch'
if.can.be.switch.minimum.branch.option=Minimum number of branches:
if.can.be.switch.int.option=Suggest switch on numbers
if.can.be.switch.enum.option=Suggest switch on enums
if.can.be.switch.null.safe.option=Only suggest on null-safe expressions
unnecessarily.qualified.inner.class.access.option=Ignore references for which an import is needed
unqualified.inner.class.access.option=Ignore references to local inner classes
try.with.identical.catches.quickfix=Collapse 'catch' blocks
@@ -16,6 +16,7 @@
package com.siyeh.ig.maturity;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.siyeh.HardcodedMethodConstants;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
@@ -69,8 +70,7 @@ public class ThrowablePrintStackTraceInspectionBase extends BaseInspection {
if (containingClass == null) {
return;
}
final String name = containingClass.getQualifiedName();
if (!CommonClassNames.JAVA_LANG_THROWABLE.equals(name)) {
if (!InheritanceUtil.isInheritor(containingClass, false, CommonClassNames.JAVA_LANG_THROWABLE)) {
return;
}
registerMethodCallError(expression, expression);
@@ -1,5 +1,5 @@
/*
* Copyright 2011-2013 Bas Leijdekkers
* Copyright 2011-2014 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,20 +15,19 @@
*/
package com.siyeh.ig.migration;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.ui.DocumentAdapter;
import com.intellij.util.ui.CheckBox;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.psiutils.ControlFlowUtils;
import com.siyeh.ig.psiutils.EquivalenceChecker;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ig.psiutils.SwitchUtils;
import com.siyeh.ig.psiutils.SwitchUtils.IfStatementBranch;
import org.jetbrains.annotations.Nls;
@@ -37,8 +36,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.text.Document;
import java.awt.*;
@@ -58,6 +55,9 @@ public class IfCanBeSwitchInspection extends BaseInspection {
@SuppressWarnings({"PublicField"})
public boolean suggestEnumSwitches = false;
@SuppressWarnings("PublicField")
public boolean onlySuggestNullSafe = true;
@Override
public boolean isEnabledByDefault() {
return true;
@@ -121,26 +121,16 @@ public class IfCanBeSwitchInspection extends BaseInspection {
constraints.gridx = 0;
constraints.gridy = 1;
constraints.gridwidth = 2;
final JCheckBox checkBox1 = new JCheckBox(InspectionGadgetsBundle.message("if.can.be.switch.int.option"), suggestIntSwitches);
final ButtonModel model1 = checkBox1.getModel();
model1.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
suggestIntSwitches = model1.isSelected();
}
});
final CheckBox checkBox1 = new CheckBox(InspectionGadgetsBundle.message("if.can.be.switch.int.option"), this, "suggestIntSwitches");
panel.add(checkBox1, constraints);
constraints.gridy = 2;
constraints.weighty = 1.0;
final JCheckBox checkBox2 = new JCheckBox(InspectionGadgetsBundle.message("if.can.be.switch.enum.option"), suggestEnumSwitches);
final ButtonModel model2 = checkBox2.getModel();
model2.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
suggestEnumSwitches = model2.isSelected();
}
});
final CheckBox checkBox2 = new CheckBox(InspectionGadgetsBundle.message("if.can.be.switch.enum.option"), this, "suggestEnumSwitches");
panel.add(checkBox2, constraints);
constraints.gridy = 3;
constraints.weighty = 1.0;
final CheckBox checkBox3 =
new CheckBox(InspectionGadgetsBundle.message("if.can.be.switch.null.safe.option"), this, "onlySuggestNullSafe");
panel.add(checkBox3, constraints);
return panel;
}
@@ -508,18 +498,10 @@ public class IfCanBeSwitchInspection extends BaseInspection {
if (parent instanceof PsiIfStatement) {
return;
}
final PsiExpression switchExpression = SwitchUtils.getSwitchExpression(statement, minimumBranches);
final PsiExpression switchExpression = SwitchUtils.getSwitchExpression(statement, minimumBranches, onlySuggestNullSafe);
if (switchExpression == null) {
return;
}
final PsiExpression unwrappedExpression = ParenthesesUtils.stripParentheses(switchExpression);
if (unwrappedExpression instanceof PsiReferenceExpression) {
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)unwrappedExpression;
final PsiElement target = referenceExpression.resolve();
if (target instanceof PsiModifierListOwner && NullableNotNullManager.isNullable((PsiModifierListOwner)target)) {
return;
}
}
final PsiType type = switchExpression.getType();
if (!suggestIntSwitches) {
if (type instanceof PsiClassType) {
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2013 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2014 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.
@@ -15,6 +15,7 @@
*/
package com.siyeh.ig.psiutils;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
@@ -47,16 +48,21 @@ public class SwitchUtils {
@Nullable
public static PsiExpression getSwitchExpression(PsiIfStatement statement, int minimumBranches) {
return getSwitchExpression(statement, minimumBranches, false);
}
@Nullable
public static PsiExpression getSwitchExpression(PsiIfStatement statement, int minimumBranches, boolean nullSafe) {
final PsiExpression condition = statement.getCondition();
final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(statement);
final PsiExpression possibleSwitchExpression = determinePossibleSwitchExpressions(condition, languageLevel);
final PsiExpression possibleSwitchExpression = determinePossibleSwitchExpressions(condition, languageLevel, nullSafe);
if (!canBeSwitchExpression(possibleSwitchExpression, languageLevel)) {
return null;
}
int branchCount = 0;
while (true) {
branchCount++;
if (!canBeMadeIntoCase(statement.getCondition(), possibleSwitchExpression, languageLevel)) {
if (!canBeMadeIntoCase(statement.getCondition(), possibleSwitchExpression, languageLevel, false)) {
break;
}
final PsiStatement elseBranch = statement.getElseBranch();
@@ -74,10 +80,11 @@ public class SwitchUtils {
return null;
}
private static boolean canBeMadeIntoCase(PsiExpression expression, PsiExpression switchExpression, LanguageLevel languageLevel) {
private static boolean canBeMadeIntoCase(PsiExpression expression, PsiExpression switchExpression, LanguageLevel languageLevel,
boolean nullSafe) {
expression = ParenthesesUtils.stripParentheses(expression);
if (languageLevel.isAtLeast(LanguageLevel.JDK_1_7)) {
final PsiExpression stringSwitchExpression = determinePossibleStringSwitchExpression(expression);
final PsiExpression stringSwitchExpression = determinePossibleStringSwitchExpression(expression, nullSafe);
if (EquivalenceChecker.expressionsAreEquivalent(switchExpression, stringSwitchExpression)) {
return true;
}
@@ -90,7 +97,7 @@ public class SwitchUtils {
final PsiExpression[] operands = polyadicExpression.getOperands();
if (operation.equals(JavaTokenType.OROR)) {
for (PsiExpression operand : operands) {
if (!canBeMadeIntoCase(operand, switchExpression, languageLevel)) {
if (!canBeMadeIntoCase(operand, switchExpression, languageLevel, nullSafe)) {
return false;
}
}
@@ -114,6 +121,9 @@ public class SwitchUtils {
return true;
}
else if (type instanceof PsiClassType) {
if (isAnnotatedNullable(expression)) {
return false;
}
if (type.equalsToText(CommonClassNames.JAVA_LANG_CHARACTER) || type.equalsToText(CommonClassNames.JAVA_LANG_BYTE) ||
type.equalsToText(CommonClassNames.JAVA_LANG_SHORT) || type.equalsToText(CommonClassNames.JAVA_LANG_INTEGER)) {
return true;
@@ -132,13 +142,13 @@ public class SwitchUtils {
return false;
}
private static PsiExpression determinePossibleSwitchExpressions(PsiExpression expression, LanguageLevel languageLevel) {
private static PsiExpression determinePossibleSwitchExpressions(PsiExpression expression, LanguageLevel languageLevel, boolean nullSafe) {
expression = ParenthesesUtils.stripParentheses(expression);
if (expression == null) {
return null;
}
if (languageLevel.isAtLeast(LanguageLevel.JDK_1_7)) {
final PsiExpression jdk17Expression = determinePossibleStringSwitchExpression(expression);
final PsiExpression jdk17Expression = determinePossibleStringSwitchExpression(expression, nullSafe);
if (jdk17Expression != null) {
return jdk17Expression;
}
@@ -150,7 +160,7 @@ public class SwitchUtils {
final IElementType operation = polyadicExpression.getOperationTokenType();
final PsiExpression[] operands = polyadicExpression.getOperands();
if (operation.equals(JavaTokenType.OROR) && operands.length > 0) {
return determinePossibleSwitchExpressions(operands[0], languageLevel);
return determinePossibleSwitchExpressions(operands[0], languageLevel, nullSafe);
}
else if (operation.equals(JavaTokenType.EQEQ) && operands.length == 2) {
final PsiExpression lhs = operands[0];
@@ -165,7 +175,7 @@ public class SwitchUtils {
return null;
}
private static PsiExpression determinePossibleStringSwitchExpression(PsiExpression expression) {
private static PsiExpression determinePossibleStringSwitchExpression(PsiExpression expression, boolean nullSafe) {
if (!(expression instanceof PsiMethodCallExpression)) {
return null;
}
@@ -194,6 +204,9 @@ public class SwitchUtils {
return null;
}
if (PsiUtil.isConstantExpression(qualifierExpression)) {
if (nullSafe && !isAnnotatedNotNull(argument)) {
return null;
}
return argument;
}
else if (PsiUtil.isConstantExpression(argument)) {
@@ -202,6 +215,34 @@ public class SwitchUtils {
return null;
}
private static boolean isAnnotatedNotNull(PsiExpression expression) {
expression = ParenthesesUtils.stripParentheses(expression);
if (!(expression instanceof PsiReferenceExpression)) {
return false;
}
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)expression;
final PsiElement target = referenceExpression.resolve();
if (!(target instanceof PsiModifierListOwner)) {
return false;
}
final PsiModifierListOwner modifierListOwner = (PsiModifierListOwner)target;
return NullableNotNullManager.isNotNull(modifierListOwner);
}
private static boolean isAnnotatedNullable(PsiExpression expression) {
expression = ParenthesesUtils.stripParentheses(expression);
if (!(expression instanceof PsiReferenceExpression)) {
return false;
}
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)expression;
final PsiElement target = referenceExpression.resolve();
if (!(target instanceof PsiModifierListOwner)) {
return false;
}
final PsiModifierListOwner modifierListOwner = (PsiModifierListOwner)target;
return NullableNotNullManager.isNullable(modifierListOwner);
}
private static boolean canBeCaseLabel(PsiExpression expression, LanguageLevel languageLevel) {
if (expression == null) {
return false;
@@ -14,6 +14,8 @@ primitive and boxed numbers and characters.
Use the second checkbox below to have this inspection suggest switch statements on
enum constants.
<p>
Use the third checkbox below to only suggest switch statements which can't introduce a <b>NullPointerException</b>
<p>
<small>New in 10.5</small>
</body>
</html>
@@ -1,5 +1,5 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
class IfCanBeSwitch {
void m1(int i) { // ok
if (i == 0) System.out.println("zero"); else if (i == 1) System.out.println("one"); else System.out.println("many");
@@ -23,10 +23,10 @@ class IfCanBeSwitch {
void polyadic() {
String s = null;
if ("asdf".equals(s) || "addd".equals(s) || "lkjh".equals(s)) {
if (s.equals("asdf") || s.equals("addd") || s.equals("lkjh")) {
System.out.println("asdf");
} else if ("null".equals(s)) {
} else if (s.equals("null")) {
System.out.println("null");
} else {
@@ -35,7 +35,7 @@ class IfCanBeSwitch {
}
void nullable(@Nullable String s) {
if ("a".equals(s)) {
if ("a".equals((s))) {
System.out.println(1);
} else if ("b".equals(s)) {
System.out.println(2);
@@ -45,4 +45,34 @@ class IfCanBeSwitch {
System.out.println(4);
}
}
void notNullSafe() {
String narf = null;
if ("foo".equals(narf)) {
// do this
} else if ("bar".equals(narf)){
// do that
}
else {
// do something else.
}
}
void nullSafe(String earth) {
if (earth.equals("foo")) {
} else if ("bar".equals(earth)) {
} else {
}
}
void nullSafe2(@NotNull String narf) {
if ("foo".equals((narf))) {
// do this
} else if ("bar".equals(narf)){
// do that
}
else {
// do something else.
}
}
}
@@ -27,4 +27,18 @@
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">'if' replaceable with 'switch'</problem_class>
<description>&lt;code&gt;if&lt;/code&gt; statement replaceable with 'switch' statement #loc</description>
</problem>
<problem>
<file>IfCanBeSwitch.java</file>
<line>62</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">'if' replaceable with 'switch'</problem_class>
<description>&lt;code&gt;if&lt;/code&gt; statement replaceable with 'switch' statement #loc</description>
</problem>
<problem>
<file>IfCanBeSwitch.java</file>
<line>69</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">'if' replaceable with 'switch'</problem_class>
<description>&lt;code&gt;if&lt;/code&gt; statement replaceable with 'switch' statement #loc</description>
</problem>
</problems>
@@ -37,6 +37,16 @@ public class ThrowablePrintStackTraceInspectionTest extends LightInspectionTestC
"}");
}
public void testPrintStacktraceOverridden() throws Exception {
addEnvironmentClass("public class FException extends Exception {\n" +
" @Override\n" +
" public void printStackTrace() {\n" +
" super.printStackTrace();\n" +
" }\n" +
"}\n");
doStatementTest("new FException()./*Call to 'printStackTrace()' should probably be replaced with more robust logging*/printStackTrace/**/();");
}
@Override
protected InspectionProfileEntry getInspection() {
return new ThrowablePrintStackTraceInspection();
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -33,6 +33,7 @@ public class IfCanBeSwitchInspectionTest extends IGInspectionTestCase {
public void test() throws Exception {
final IfCanBeSwitchInspection inspection = new IfCanBeSwitchInspection();
inspection.suggestIntSwitches = true;
doTest("com/siyeh/igtest/migration/if_switch", new LocalInspectionToolWrapper(inspection));
inspection.onlySuggestNullSafe = true;
doTest("com/siyeh/igtest/migration/if_switch", new LocalInspectionToolWrapper(inspection));
}
}

Some files were not shown because too many files have changed in this diff Show More