diff --git a/bin/win/runnerw.exe b/bin/win/runnerw.exe index 5c5f103adca8..29c5d336d08c 100644 Binary files a/bin/win/runnerw.exe and b/bin/win/runnerw.exe differ diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java index 69cbb140be86..2569559d2d11 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java @@ -30,7 +30,10 @@ import com.intellij.debugger.engine.evaluation.EvaluateRuntimeException; import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; import com.intellij.debugger.impl.DebuggerUtilsEx; import com.intellij.openapi.diagnostic.Logger; -import com.sun.jdi.*; +import com.sun.jdi.ClassType; +import com.sun.jdi.Method; +import com.sun.jdi.ObjectReference; +import com.sun.jdi.ReferenceType; import java.util.ArrayList; import java.util.List; @@ -127,14 +130,16 @@ public class MethodEvaluator implements Evaluator { _refType = ((ClassType)referenceType).superclass(); } Method jdiMethod = DebuggerUtils.findMethod(_refType, myMethodName, signature); - if (jdiMethod == null || jdiMethod.argumentTypes().size() != args.size()) { + if (signature == null) { + // we know nothing about expected method's signature, so trying to match my method name and parameter count // dummy matching, may be improved with types matching later - List methods = _refType.methodsByName(myMethodName); - for (Method method : methods) { - List types = method.argumentTypes(); - if (types.size() == args.size()) { - jdiMethod = method; - break; + // IMPORTANT! using argumentTypeNames() instead of argumentTypes() to avoid type resolution inside JDI, which may be time-consuming + if (jdiMethod == null || jdiMethod.argumentTypeNames().size() != args.size()) { + for (Method method : _refType.methodsByName(myMethodName)) { + if (method.argumentTypeNames().size() == args.size()) { + jdiMethod = method; + break; + } } } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java index b60094ffbd6f..ad53d9484959 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java @@ -138,8 +138,8 @@ public class PreferByKindWeigher extends LookupElementWeigher { qualifiedWithField, qualifiedWithGetter, superMethodParameters, - expectedTypeConstant, field, + expectedTypeConstant, getter, normal, collectionFactory, diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingCatchBodyFixer.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingCatchBodyFixer.java index 1d4d281aea68..08e06283d4a5 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingCatchBodyFixer.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingCatchBodyFixer.java @@ -36,7 +36,7 @@ public class MissingCatchBodyFixer implements Fixer { final Document doc = editor.getDocument(); PsiCodeBlock body = catchSection.getCatchBlock(); - if (body != null && startLine(doc, body) == startLine(doc, catchSection)) return; + if (body != null && body.getLBrace() != null && body.getRBrace() != null) return; final PsiJavaToken rParenth = catchSection.getRParenth(); if (rParenth == null) return; @@ -44,7 +44,4 @@ public class MissingCatchBodyFixer implements Fixer { doc.insertString(rParenth.getTextRange().getEndOffset(), "{}"); } - private static int startLine(Document doc, PsiElement psiElement) { - return doc.getLineNumber(psiElement.getTextRange().getStartOffset()); - } } \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/PlainEnterProcessor.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/PlainEnterProcessor.java index 6bafcc00d983..884442c778cc 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/PlainEnterProcessor.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/PlainEnterProcessor.java @@ -83,6 +83,22 @@ public class PlainEnterProcessor implements EnterProcessor { @Nullable private static PsiCodeBlock getControlStatementBlock(int caret, PsiElement element) { + if (element instanceof PsiTryStatement) { + PsiCodeBlock tryBlock = ((PsiTryStatement)element).getTryBlock(); + if (tryBlock != null && caret < tryBlock.getTextRange().getEndOffset()) return tryBlock; + + for (PsiCodeBlock catchBlock : ((PsiTryStatement)element).getCatchBlocks()) { + if (catchBlock != null && caret < catchBlock.getTextRange().getEndOffset()) return catchBlock; + } + + return ((PsiTryStatement)element).getFinallyBlock(); + } + + if (element instanceof PsiMethod) { + PsiCodeBlock methodBody = ((PsiMethod)element).getBody(); + if (methodBody != null) return methodBody; + } + PsiStatement body = null; if (element instanceof PsiIfStatement) { body = ((PsiIfStatement)element).getThenBranch(); @@ -102,10 +118,6 @@ public class PlainEnterProcessor implements EnterProcessor { else if (element instanceof PsiDoWhileStatement) { body = ((PsiDoWhileStatement)element).getBody(); } - else if (element instanceof PsiMethod) { - PsiCodeBlock methodBody = ((PsiMethod)element).getBody(); - if (methodBody != null) return methodBody; - } return body instanceof PsiBlockStatement ? ((PsiBlockStatement)body).getCodeBlock() : null; } diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/FieldFromParameterUtils.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/FieldFromParameterUtils.java index 52adc200eb0c..37fb882e5e66 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/FieldFromParameterUtils.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/FieldFromParameterUtils.java @@ -187,14 +187,14 @@ public final class FieldFromParameterUtils { modifierList.setModifierProperty(PsiModifier.FINAL, isFinal); final NullableNotNullManager manager = NullableNotNullManager.getInstance(project); - final String nullable = manager.getNullable(parameter); + final PsiAnnotation nullable = manager.getNullableAnnotation(parameter, false); if (nullable != null && !manager.isContainerAnnotation(nullable)) { - modifierList.addAfter(factory.createAnnotationFromText("@" + nullable, field), null); + modifierList.addAfter(factory.createAnnotationFromText("@" + nullable.getQualifiedName(), field), null); } else if (isFinal) { - final String notNull = manager.getNotNull(parameter); + final PsiAnnotation notNull = manager.getNotNullAnnotation(parameter, false); if (notNull != null && !manager.isContainerAnnotation(notNull)) { - modifierList.addAfter(factory.createAnnotationFromText("@" + notNull, field), null); + modifierList.addAfter(factory.createAnnotationFromText("@" + notNull.getQualifiedName(), field), null); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/CastExpressionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/CastExpressionPostfixTemplate.java index 952987a72c19..14059174cc16 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/CastExpressionPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/CastExpressionPostfixTemplate.java @@ -20,13 +20,17 @@ import com.intellij.openapi.editor.Editor; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; -public class CastExpressionPostfixTemplate extends JavaPostfixTemplateWithChooser { +import static com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils.selectorWithChooser; +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_NON_VOID; +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO; + +public class CastExpressionPostfixTemplate extends PostfixTemplateWithExpressionSelector { public CastExpressionPostfixTemplate() { - super("cast", "((SomeType) expr)"); + super("cast", "((SomeType) expr)", JAVA_PSI_INFO, selectorWithChooser(IS_NON_VOID)); } @Override - protected void doIt(@NotNull final Editor editor, @NotNull final PsiElement expression) { + protected void expandForChooseExpression(@NotNull PsiElement expression, @NotNull Editor editor) { PostfixTemplatesUtils.surround(new JavaWithCastSurrounder(), editor, expression); } } \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceFieldPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceFieldPostfixTemplate.java index 40da7fd94b88..2bac79d890bd 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceFieldPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceFieldPostfixTemplate.java @@ -23,13 +23,17 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.introduceField.IntroduceFieldHandler; import org.jetbrains.annotations.NotNull; -public class IntroduceFieldPostfixTemplate extends JavaPostfixTemplateWithChooser { +import static com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils.selectorWithChooser; +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_NON_VOID; +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO; + +public class IntroduceFieldPostfixTemplate extends PostfixTemplateWithExpressionSelector { public IntroduceFieldPostfixTemplate() { - super("field", "myField = expr"); + super("field", "myField = expr", JAVA_PSI_INFO, selectorWithChooser(IS_NON_VOID)); } @Override - protected void doIt(@NotNull Editor editor, @NotNull PsiElement expression) { + protected void expandForChooseExpression(@NotNull PsiElement expression, @NotNull Editor editor) { IntroduceFieldHandler handler = ApplicationManager.getApplication().isUnitTestMode() ? getMockHandler(expression) : new IntroduceFieldHandler(); handler.invoke(expression.getProject(), new PsiElement[]{expression}, null); diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceVariablePostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceVariablePostfixTemplate.java index 57c03f9501fa..be2dc23850e7 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceVariablePostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceVariablePostfixTemplate.java @@ -28,14 +28,18 @@ import com.intellij.refactoring.introduceVariable.IntroduceVariableSettings; import com.intellij.refactoring.ui.TypeSelectorManagerImpl; import org.jetbrains.annotations.NotNull; +import static com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils.selectorWithChooser; +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_NON_VOID; +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO; + // todo: support for int[].var (parses as .class access!) -public class IntroduceVariablePostfixTemplate extends JavaPostfixTemplateWithChooser { +public class IntroduceVariablePostfixTemplate extends PostfixTemplateWithExpressionSelector { public IntroduceVariablePostfixTemplate() { - super("var", "T name = expr"); + super("var", "T name = expr", JAVA_PSI_INFO, selectorWithChooser(IS_NON_VOID)); } @Override - protected void doIt(@NotNull Editor editor, @NotNull PsiElement expression) { + protected void expandForChooseExpression(@NotNull PsiElement expression, @NotNull Editor editor) { // for advanced stuff use ((PsiJavaCodeReferenceElement)expression).advancedResolve(true).getElement(); IntroduceVariableHandler handler = ApplicationManager.getApplication().isUnitTestMode() ? getMockHandler() : new IntroduceVariableHandler(); diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateWithChooser.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateWithChooser.java deleted file mode 100644 index 72de706f4858..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateWithChooser.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.template.postfix.templates; - - -import com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils; -import com.intellij.openapi.util.Condition; -import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NotNull; - -import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO; - -public abstract class JavaPostfixTemplateWithChooser extends ExpressionPostfixTemplateWithChooser { - - - protected JavaPostfixTemplateWithChooser(@NotNull String name, @NotNull String example) { - super(name, example, JAVA_PSI_INFO); - } - - protected JavaPostfixTemplateWithChooser(@NotNull String name, @NotNull String key, @NotNull String example) { - super(name, key, example, JAVA_PSI_INFO); - } - - @NotNull - @Override - protected Condition getTypeCondition() { - return JavaPostfixTemplatesUtils.IS_NON_VOID; - } -} diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java index ac6f22c5092f..6160433cefe3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java @@ -15,26 +15,16 @@ */ package com.intellij.codeInsight.template.postfix.templates; -import com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils; -import com.intellij.openapi.util.Condition; -import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NotNull; - +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_BOOLEAN; import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO; public class NotExpressionPostfixTemplate extends NotPostfixTemplate { public NotExpressionPostfixTemplate() { - super(JAVA_PSI_INFO); + super(JAVA_PSI_INFO, IS_BOOLEAN); } public NotExpressionPostfixTemplate(String alias) { - super(alias, alias, "!expr", JAVA_PSI_INFO); - } - - @NotNull - @Override - protected Condition getTypeCondition() { - return JavaPostfixTemplatesUtils.IS_BOOLEAN; + super(alias, alias, "!expr", JAVA_PSI_INFO, IS_BOOLEAN); } } \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedExpressionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedExpressionPostfixTemplate.java index 68b5c48fcd15..46c0c30b24f5 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedExpressionPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedExpressionPostfixTemplate.java @@ -15,21 +15,11 @@ */ package com.intellij.codeInsight.template.postfix.templates; -import com.intellij.openapi.util.Condition; -import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NotNull; - import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_NON_VOID; import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO; public class ParenthesizedExpressionPostfixTemplate extends ParenthesizedPostfixTemplate { public ParenthesizedExpressionPostfixTemplate() { - super(JAVA_PSI_INFO); - } - - @NotNull - @Override - protected Condition getTypeCondition() { - return IS_NON_VOID; + super(JAVA_PSI_INFO, IS_NON_VOID); } } \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/JavaPostfixTemplatesUtils.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/JavaPostfixTemplatesUtils.java index e217175cdab9..8457bc24cd5c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/JavaPostfixTemplatesUtils.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/JavaPostfixTemplatesUtils.java @@ -16,7 +16,7 @@ package com.intellij.codeInsight.template.postfix.util; import com.intellij.codeInsight.CodeInsightServicesUtil; -import com.intellij.codeInsight.template.postfix.templates.PostfixTemplatePsiInfoBase; +import com.intellij.codeInsight.template.postfix.templates.PostfixTemplatePsiInfo; import com.intellij.openapi.editor.Document; import com.intellij.openapi.util.Condition; import com.intellij.psi.*; @@ -36,7 +36,7 @@ public abstract class JavaPostfixTemplatesUtils { private JavaPostfixTemplatesUtils() { } - public static final PostfixTemplatePsiInfoBase JAVA_PSI_INFO = new PostfixTemplatePsiInfoBase() { + public static final PostfixTemplatePsiInfo JAVA_PSI_INFO = new PostfixTemplatePsiInfo() { @NotNull @Override diff --git a/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java b/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java index b0cbc06d048e..56f873148857 100644 --- a/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java +++ b/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java @@ -19,10 +19,14 @@ import com.intellij.navigation.ChooseByNameContributorEx; import com.intellij.navigation.GotoClassContributor; import com.intellij.navigation.NavigationItem; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiClass; +import com.intellij.psi.codeStyle.MinusculeMatcher; +import com.intellij.psi.codeStyle.NameUtil; import com.intellij.psi.presentation.java.SymbolPresentationUtil; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiShortNamesCache; +import com.intellij.psi.util.ClassUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.CommonProcessors; import com.intellij.util.Processor; @@ -74,7 +78,7 @@ public class DefaultClassNavigationContributor implements ChooseByNameContributo @Override public String getQualifiedNameSeparator() { - return "."; + return "$"; } @Override @@ -86,12 +90,21 @@ public class DefaultClassNavigationContributor implements ChooseByNameContributo public void processElementsWithName(@NotNull String name, @NotNull final Processor processor, @NotNull final FindSymbolParameters parameters) { + String namePattern = StringUtil.getShortName(parameters.getCompletePattern()); + boolean innerClass = namePattern.contains("$"); + final MinusculeMatcher innerMatcher = innerClass ? new MinusculeMatcher("*" + namePattern, NameUtil.MatchingCaseSensitivity.NONE) : null; PsiShortNamesCache.getInstance(parameters.getProject()).processClassesWithName(name, new Processor() { final boolean isAnnotation = parameters.getLocalPatternName().startsWith("@"); + @Override public boolean process(PsiClass aClass) { if (aClass.getContainingFile().getVirtualFile() == null || !aClass.isPhysical()) return true; if (isAnnotation && !aClass.isAnnotationType()) return true; + if (innerMatcher != null) { + if (aClass.getContainingClass() == null) return true; + String jvmQName = ClassUtil.getJVMClassName(aClass); + if (jvmQName == null || !innerMatcher.matches(StringUtil.getShortName(jvmQName))) return true; + } return processor.process(aClass); } }, parameters.getSearchScope(), parameters.getIdFilter()); diff --git a/java/java-psi-api/src/com/intellij/codeInsight/AnnotationTargetUtil.java b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationTargetUtil.java new file mode 100644 index 000000000000..c7d9e303aae3 --- /dev/null +++ b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationTargetUtil.java @@ -0,0 +1,136 @@ +/* + * 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.openapi.diagnostic.Logger; +import com.intellij.psi.*; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.Set; + +/** + * @author peter + */ +public class AnnotationTargetUtil { + public static final Set DEFAULT_TARGETS = Collections.unmodifiableSet(ContainerUtil.newHashSet( + PsiAnnotation.TargetType.PACKAGE, PsiAnnotation.TargetType.TYPE, PsiAnnotation.TargetType.ANNOTATION_TYPE, + PsiAnnotation.TargetType.FIELD, PsiAnnotation.TargetType.METHOD, PsiAnnotation.TargetType.CONSTRUCTOR, + PsiAnnotation.TargetType.PARAMETER, PsiAnnotation.TargetType.LOCAL_VARIABLE)); + private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.AnnotationUtil"); + private static final PsiAnnotation.TargetType[] PACKAGE_TARGETS = {PsiAnnotation.TargetType.PACKAGE}; + private static final PsiAnnotation.TargetType[] TYPE_USE_TARGETS = {PsiAnnotation.TargetType.TYPE_USE}; + private static final PsiAnnotation.TargetType[] ANNOTATION_TARGETS = {PsiAnnotation.TargetType.ANNOTATION_TYPE, PsiAnnotation.TargetType.TYPE, PsiAnnotation.TargetType.TYPE_USE}; + private static final PsiAnnotation.TargetType[] TYPE_TARGETS = {PsiAnnotation.TargetType.TYPE, PsiAnnotation.TargetType.TYPE_USE}; + private static final PsiAnnotation.TargetType[] TYPE_PARAMETER_TARGETS = { + PsiAnnotation.TargetType.TYPE_PARAMETER, PsiAnnotation.TargetType.TYPE_USE}; + private static final PsiAnnotation.TargetType[] CONSTRUCTOR_TARGETS = {PsiAnnotation.TargetType.CONSTRUCTOR, PsiAnnotation.TargetType.TYPE_USE}; + private static final PsiAnnotation.TargetType[] METHOD_TARGETS = {PsiAnnotation.TargetType.METHOD, PsiAnnotation.TargetType.TYPE_USE}; + private static final PsiAnnotation.TargetType[] FIELD_TARGETS = {PsiAnnotation.TargetType.FIELD, PsiAnnotation.TargetType.TYPE_USE}; + private static final PsiAnnotation.TargetType[] PARAMETER_TARGETS = {PsiAnnotation.TargetType.PARAMETER, PsiAnnotation.TargetType.TYPE_USE}; + private static final PsiAnnotation.TargetType[] LOCAL_VARIABLE_TARGETS ={ + PsiAnnotation.TargetType.LOCAL_VARIABLE, PsiAnnotation.TargetType.TYPE_USE}; + + @NotNull + public static PsiAnnotation.TargetType[] getTargetsForLocation(@Nullable PsiAnnotationOwner owner) { + if (owner == null) { + return PsiAnnotation.TargetType.EMPTY_ARRAY; + } + + if (owner instanceof PsiType || owner instanceof PsiTypeElement) { + return TYPE_USE_TARGETS; + } + + if (owner instanceof PsiTypeParameter) { + return TYPE_PARAMETER_TARGETS; + } + + if (owner instanceof PsiModifierList) { + PsiElement element = ((PsiModifierList)owner).getParent(); + if (element instanceof PsiPackageStatement) { + return PACKAGE_TARGETS; + } + if (element instanceof PsiClass) { + if (((PsiClass)element).isAnnotationType()) { + return ANNOTATION_TARGETS; + } + else { + return TYPE_TARGETS; + } + } + if (element instanceof PsiMethod) { + if (((PsiMethod)element).isConstructor()) { + return CONSTRUCTOR_TARGETS; + } + else { + return METHOD_TARGETS; + } + } + if (element instanceof PsiField) { + return FIELD_TARGETS; + } + if (element instanceof PsiParameter) { + return PARAMETER_TARGETS; + } + if (element instanceof PsiLocalVariable) { + return LOCAL_VARIABLE_TARGETS; + } + } + + return PsiAnnotation.TargetType.EMPTY_ARRAY; + } + + @Nullable + public static Set extractRequiredAnnotationTargets(@Nullable PsiAnnotationMemberValue value) { + if (value instanceof PsiReference) { + PsiAnnotation.TargetType targetType = translateTargetRef((PsiReference)value); + if (targetType != null) { + return Collections.singleton(targetType); + } + } + else if (value instanceof PsiArrayInitializerMemberValue) { + Set targets = ContainerUtil.newHashSet(); + for (PsiAnnotationMemberValue initializer : ((PsiArrayInitializerMemberValue)value).getInitializers()) { + if (initializer instanceof PsiReference) { + PsiAnnotation.TargetType targetType = translateTargetRef((PsiReference)initializer); + if (targetType != null) { + targets.add(targetType); + } + } + } + return targets; + } + + return null; + } + + @Nullable + private static PsiAnnotation.TargetType translateTargetRef(@NotNull PsiReference reference) { + PsiElement field = reference.resolve(); + if (field instanceof PsiEnumConstant) { + String name = ((PsiEnumConstant)field).getName(); + try { + return PsiAnnotation.TargetType.valueOf(name); + } + catch (IllegalArgumentException e) { + LOG.warn("Unknown target: " + name); + } + } + return null; + } +} diff --git a/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java index c2c79a9d9d8a..25034e9ab7ba 100644 --- a/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java +++ b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java @@ -379,14 +379,14 @@ public class AnnotationUtil { @NotNull public static PsiAnnotation[] getAllAnnotations(@NotNull PsiModifierListOwner owner, boolean inHierarchy, - Set visited) { + @Nullable Set visited) { return getAllAnnotations(owner, inHierarchy, visited, true); } @NotNull public static PsiAnnotation[] getAllAnnotations(@NotNull PsiModifierListOwner owner, boolean inHierarchy, - Set visited, boolean withInferred) { + @Nullable Set visited, boolean withInferred) { final PsiModifierList list = owner.getModifierList(); PsiAnnotation[] annotations = PsiAnnotation.EMPTY_ARRAY; if (list != null) { diff --git a/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java b/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java index 9435fc872845..2210e02a080a 100644 --- a/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java +++ b/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java @@ -27,7 +27,6 @@ import com.intellij.psi.*; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.containers.ContainerUtil; import org.jdom.Element; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -39,18 +38,19 @@ import java.util.*; */ public class NullableNotNullManager implements PersistentStateComponent { private static final Logger LOG = Logger.getInstance("#" + NullableNotNullManager.class.getName()); - @NonNls private static final String NULLABLE_CONTAINER_ANNOTATION = "javax.annotation.ParametersAreNullableByDefault"; - @NonNls private static final String NONNULL_CONTAINER_ANNOTATION = "javax.annotation.ParametersAreNonnullByDefault"; public String myDefaultNullable = AnnotationUtil.NULLABLE; public String myDefaultNotNull = AnnotationUtil.NOT_NULL; public final JDOMExternalizableStringList myNullables = new JDOMExternalizableStringList(); public final JDOMExternalizableStringList myNotNulls = new JDOMExternalizableStringList(); - public static final String[] DEFAULT_NULLABLES = {AnnotationUtil.NULLABLE, "javax.annotation.Nullable", + private static final String JAVAX_ANNOTATION_NULLABLE = "javax.annotation.Nullable"; + private static final String JAVAX_ANNOTATION_NONNULL = "javax.annotation.Nonnull"; + + public static final String[] DEFAULT_NULLABLES = {AnnotationUtil.NULLABLE, JAVAX_ANNOTATION_NULLABLE, "edu.umd.cs.findbugs.annotations.Nullable", "android.support.annotation.Nullable" }; - public static final String[] DEFAULT_NOT_NULLS = {AnnotationUtil.NOT_NULL, "javax.annotation.Nonnull", + public static final String[] DEFAULT_NOT_NULLS = {AnnotationUtil.NOT_NULL, JAVAX_ANNOTATION_NONNULL, "edu.umd.cs.findbugs.annotations.NonNull", "android.support.annotation.NonNull" }; @@ -106,8 +106,9 @@ public class NullableNotNullManager implements PersistentStateComponent return findNullabilityAnnotation(owner, checkBases, true); } - public boolean isContainerAnnotation(String anno) { - return NULLABLE_CONTAINER_ANNOTATION.equals(anno) || NONNULL_CONTAINER_ANNOTATION.equals(anno); + public boolean isContainerAnnotation(@NotNull PsiAnnotation anno) { + PsiAnnotation.TargetType[] acceptAnyTarget = PsiAnnotation.TargetType.values(); + return isNullabilityDefault(anno, true, acceptAnyTarget) || isNullabilityDefault(anno, false, acceptAnyTarget); } public void setDefaultNullable(@NotNull String defaultNullable) { @@ -145,15 +146,20 @@ public class NullableNotNullManager implements PersistentStateComponent return annotation; } - if (owner instanceof PsiParameter && !TypeConversionUtil.isPrimitiveAndNotNull(((PsiParameter)owner).getType())) { - // even if javax.annotation.Nullable is not configured, it should still take precedence over ByDefault annotations - if (AnnotationUtil.isAnnotated(owner, nullable ? Arrays.asList(DEFAULT_NOT_NULLS) : Arrays.asList(DEFAULT_NULLABLES), checkBases, false)) { - return null; - } - return findContainerAnnotation(owner, nullable - ? NULLABLE_CONTAINER_ANNOTATION - : NONNULL_CONTAINER_ANNOTATION); + PsiType type = getOwnerType(owner); + if (type == null || TypeConversionUtil.isPrimitiveAndNotNull(type)) return null; + + // even if javax.annotation.Nullable is not configured, it should still take precedence over ByDefault annotations + if (AnnotationUtil.isAnnotated(owner, nullable ? Arrays.asList(DEFAULT_NOT_NULLS) : Arrays.asList(DEFAULT_NULLABLES), checkBases, false)) { + return null; } + return findNullabilityDefaultInHierarchy(owner, nullable); + } + + @Nullable + private static PsiType getOwnerType(PsiModifierListOwner owner) { + if (owner instanceof PsiVariable) return ((PsiVariable)owner).getType(); + if (owner instanceof PsiMethod) return ((PsiMethod)owner).getReturnType(); return null; } @@ -166,11 +172,13 @@ public class NullableNotNullManager implements PersistentStateComponent } @Nullable - private static PsiAnnotation findContainerAnnotation(PsiModifierListOwner owner, String annotationFQN) { + private static PsiAnnotation findNullabilityDefaultInHierarchy(PsiModifierListOwner owner, boolean nullable) { + PsiAnnotation.TargetType[] placeTargetTypes = AnnotationTargetUtil.getTargetsForLocation(owner.getModifierList()); + PsiElement element = owner.getParent(); while (element != null) { if (element instanceof PsiModifierListOwner) { - PsiAnnotation annotation = AnnotationUtil.findAnnotation((PsiModifierListOwner)element, annotationFQN); + PsiAnnotation annotation = getNullabilityDefault((PsiModifierListOwner)element, nullable, placeTargetTypes); if (annotation != null) { return annotation; } @@ -179,7 +187,7 @@ public class NullableNotNullManager implements PersistentStateComponent if (element instanceof PsiClassOwner) { String packageName = ((PsiClassOwner)element).getPackageName(); PsiPackage psiPackage = JavaPsiFacade.getInstance(element.getProject()).findPackage(packageName); - return AnnotationUtil.findAnnotation(psiPackage, annotationFQN); + return psiPackage == null ? null : getNullabilityDefault(psiPackage, nullable, placeTargetTypes); } element = element.getContext(); @@ -187,6 +195,37 @@ public class NullableNotNullManager implements PersistentStateComponent return null; } + private static PsiAnnotation getNullabilityDefault(@NotNull PsiModifierListOwner container, boolean nullable, PsiAnnotation.TargetType[] placeTargetTypes) { + PsiModifierList modifierList = container.getModifierList(); + if (modifierList == null) return null; + for (PsiAnnotation annotation : modifierList.getAnnotations()) { + if (isNullabilityDefault(annotation, nullable, placeTargetTypes)) { + return annotation; + } + } + return null; + } + + private static boolean isNullabilityDefault(@NotNull PsiAnnotation annotation, boolean nullable, PsiAnnotation.TargetType[] placeTargetTypes) { + PsiJavaCodeReferenceElement element = annotation.getNameReferenceElement(); + PsiElement declaration = element == null ? null : element.resolve(); + if (!(declaration instanceof PsiClass)) return false; + + if (!AnnotationUtil.isAnnotated((PsiClass)declaration, + nullable ? JAVAX_ANNOTATION_NULLABLE : JAVAX_ANNOTATION_NONNULL, + false, + true)) { + return false; + } + + PsiAnnotation tqDefault = AnnotationUtil.findAnnotation((PsiClass)declaration, true, "javax.annotation.meta.TypeQualifierDefault"); + if (tqDefault == null) return false; + + Set required = AnnotationTargetUtil.extractRequiredAnnotationTargets(tqDefault.findAttributeValue(null)); + if (required == null) return false; + return required.isEmpty() || ContainerUtil.intersects(required, Arrays.asList(placeTargetTypes)); + } + public List getNullables() { return myNullables; } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java index 514087492300..bcf0decb69b7 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java @@ -15,6 +15,7 @@ */ package com.intellij.psi.impl; +import com.intellij.codeInsight.AnnotationTargetUtil; import com.intellij.lang.ASTNode; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; @@ -51,7 +52,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Set; @@ -60,22 +60,6 @@ import static com.intellij.psi.PsiAnnotation.TargetType; public class PsiImplUtil { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.PsiImplUtil"); - private static final Set DEFAULT_TARGETS = Collections.unmodifiableSet(ContainerUtil.newHashSet( - TargetType.PACKAGE, TargetType.TYPE, TargetType.ANNOTATION_TYPE, - TargetType.FIELD, TargetType.METHOD, TargetType.CONSTRUCTOR, - TargetType.PARAMETER, TargetType.LOCAL_VARIABLE)); - - private static final TargetType[] PACKAGE_TARGETS = {TargetType.PACKAGE}; - private static final TargetType[] TYPE_USE_TARGETS = {TargetType.TYPE_USE}; - private static final TargetType[] ANNOTATION_TARGETS = {TargetType.ANNOTATION_TYPE, TargetType.TYPE, TargetType.TYPE_USE}; - private static final TargetType[] TYPE_TARGETS = {TargetType.TYPE, TargetType.TYPE_USE}; - private static final TargetType[] TYPE_PARAMETER_TARGETS = {TargetType.TYPE_PARAMETER, TargetType.TYPE_USE}; - private static final TargetType[] CONSTRUCTOR_TARGETS = {TargetType.CONSTRUCTOR, TargetType.TYPE_USE}; - private static final TargetType[] METHOD_TARGETS = {TargetType.METHOD, TargetType.TYPE_USE}; - private static final TargetType[] FIELD_TARGETS = {TargetType.FIELD, TargetType.TYPE_USE}; - private static final TargetType[] PARAMETER_TARGETS = {TargetType.PARAMETER, TargetType.TYPE_USE}; - private static final TargetType[] LOCAL_VARIABLE_TARGETS ={TargetType.LOCAL_VARIABLE, TargetType.TYPE_USE}; - private PsiImplUtil() { } @NotNull @@ -376,93 +360,14 @@ public class PsiImplUtil { PsiModifierList modifierList = annotationType.getModifierList(); if (modifierList == null) return null; PsiAnnotation target = modifierList.findAnnotation(CommonClassNames.JAVA_LANG_ANNOTATION_TARGET); - if (target == null) return DEFAULT_TARGETS; // if omitted it is applicable to all but Java 8 TYPE_USE/TYPE_PARAMETERS targets + if (target == null) return AnnotationTargetUtil.DEFAULT_TARGETS; // if omitted it is applicable to all but Java 8 TYPE_USE/TYPE_PARAMETERS targets - PsiAnnotationMemberValue value = target.findAttributeValue(null); - if (value instanceof PsiReference) { - TargetType targetType = translateTargetRef((PsiReference)value); - if (targetType != null) { - return Collections.singleton(targetType); - } - } - else if (value instanceof PsiArrayInitializerMemberValue) { - Set targets = ContainerUtil.newHashSet(); - for (PsiAnnotationMemberValue initializer : ((PsiArrayInitializerMemberValue)value).getInitializers()) { - if (initializer instanceof PsiReference) { - TargetType targetType = translateTargetRef((PsiReference)initializer); - if (targetType != null) { - targets.add(targetType); - } - } - } - return targets; - } - - return null; - } - - @Nullable - private static TargetType translateTargetRef(PsiReference reference) { - PsiElement field = reference.resolve(); - if (field instanceof PsiEnumConstant) { - String name = ((PsiEnumConstant)field).getName(); - try { - return TargetType.valueOf(name); - } - catch (IllegalArgumentException e) { - LOG.warn("Unknown target: " + name); - } - } - return null; + return AnnotationTargetUtil.extractRequiredAnnotationTargets(target.findAttributeValue(null)); } @NotNull public static TargetType[] getTargetsForLocation(@Nullable PsiAnnotationOwner owner) { - if (owner == null) { - return TargetType.EMPTY_ARRAY; - } - - if (owner instanceof PsiType || owner instanceof PsiTypeElement) { - return TYPE_USE_TARGETS; - } - - if (owner instanceof PsiTypeParameter) { - return TYPE_PARAMETER_TARGETS; - } - - if (owner instanceof PsiModifierList) { - PsiElement element = ((PsiModifierList)owner).getParent(); - if (element instanceof PsiPackageStatement) { - return PACKAGE_TARGETS; - } - if (element instanceof PsiClass) { - if (((PsiClass)element).isAnnotationType()) { - return ANNOTATION_TARGETS; - } - else { - return TYPE_TARGETS; - } - } - if (element instanceof PsiMethod) { - if (((PsiMethod)element).isConstructor()) { - return CONSTRUCTOR_TARGETS; - } - else { - return METHOD_TARGETS; - } - } - if (element instanceof PsiField) { - return FIELD_TARGETS; - } - if (element instanceof PsiParameter) { - return PARAMETER_TARGETS; - } - if (element instanceof PsiLocalVariable) { - return LOCAL_VARIABLE_TARGETS; - } - } - - return TargetType.EMPTY_ARRAY; + return AnnotationTargetUtil.getTargetsForLocation(owner); } @Nullable diff --git a/java/java-tests/testData/codeInsight/completeStatement/AlreadyCompleteCatch.java b/java/java-tests/testData/codeInsight/completeStatement/AlreadyCompleteCatch.java new file mode 100644 index 000000000000..d8ea6191cef8 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completeStatement/AlreadyCompleteCatch.java @@ -0,0 +1,12 @@ + +class Foo { + { + try + { + + } catch (Exception e) + { + + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completeStatement/AlreadyCompleteCatch_after.java b/java/java-tests/testData/codeInsight/completeStatement/AlreadyCompleteCatch_after.java new file mode 100644 index 000000000000..f4874b45962e --- /dev/null +++ b/java/java-tests/testData/codeInsight/completeStatement/AlreadyCompleteCatch_after.java @@ -0,0 +1,12 @@ + +class Foo { + { + try + { + + } catch (Exception e) + { + + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferFieldsToConstants.java b/java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferFieldsToConstants.java new file mode 100644 index 000000000000..2b47bb58a498 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferFieldsToConstants.java @@ -0,0 +1,17 @@ +public class Foo { + + private LocalDate dateField; + + void foo(LocalDate date) { + + } + + void bar() { + foo() + } +} + +class LocalDate { + public static final LocalDate MAX; + public static final LocalDate MIN; +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/CustomTypeQualifierDefault.java b/java/java-tests/testData/inspection/dataFlow/fixture/CustomTypeQualifierDefault.java new file mode 100644 index 000000000000..e9ec6b1dbe11 --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/CustomTypeQualifierDefault.java @@ -0,0 +1,25 @@ +import foo.*; +import org.jetbrains.annotations.NotNull; + +class Some { + void foo(@NotNull String s) { + NotNullClass.foo(null); + if (NotNullClass.foo(s) == null) {} + + NullableClass.foo(null); + if (NullableClass.foo("a") == null) {} + + AnotherPackageNotNull.foo(null); + if (AnotherPackageNotNull.foo(s) == null) {} + } + +} + +@bar.MethodsAreNotNullByDefault +class NotNullClass { + static native Object foo(String s); + +} +class NullableClass { + static native Object foo(String s); +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java index 2eecdaa9b221..3f199d44ea13 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java @@ -17,9 +17,6 @@ package com.intellij.codeInsight; import com.intellij.JavaTestUtil; import com.intellij.openapi.actionSystem.IdeActions; -import com.intellij.openapi.roots.LanguageLevelProjectExtension; -import com.intellij.pom.java.LanguageLevel; -import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; @@ -54,6 +51,18 @@ public class CompleteStatementTest extends EditorActionTestCase { public void testCompleteCatchLParen() throws Exception { doTest(); } + public void testAlreadyCompleteCatch() throws Exception { + CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()); + int old = settings.BRACE_STYLE; + settings.BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE; + try { + doTest(); + } + finally { + settings.BRACE_STYLE = old; + } + } + public void testCompleteCatchWithExpression() throws Exception { doTest(); } public void testCompleteCatchBody() throws Exception { doTest(); } @@ -171,8 +180,6 @@ public class CompleteStatementTest extends EditorActionTestCase { } public void testSCR36110() throws Exception { - JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject()); - LanguageLevel old = LanguageLevelProjectExtension.getInstance(facade.getProject()).getLanguageLevel(); doTest(); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy index 1d258fe01367..f37b90e21523 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy @@ -160,6 +160,10 @@ public class SmartTypeCompletionOrderingTest extends CompletionSortingTestCase { checkPreferredItems(0, "myVersion", "getVersion", "getSelectedVersion", "calculateVersion"); } + public void testPreferFieldsToConstants() { + checkPreferredItems(0, "dateField", "LocalDate.MAX", "LocalDate.MIN"); + } + public void testPreferParametersToGetters() throws Throwable { checkPreferredItems(0, "a", "I._1", "getLastI", "valueOf"); } diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java index 4cba2ab918a7..2153675e5484 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java @@ -18,6 +18,7 @@ package com.intellij.codeInspection; import com.intellij.JavaTestUtil; import com.intellij.codeInspection.dataFlow.DataFlowInspection; import com.intellij.testFramework.LightProjectDescriptor; +import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; import org.jetbrains.annotations.NotNull; @@ -258,8 +259,8 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase { public void testAccessingSameArrayElements() { doTest(); } public void testParametersAreNonnullByDefault() { - myFixture.addClass("package javax.annotation; public @interface ParametersAreNonnullByDefault {}"); - myFixture.addClass("package javax.annotation; public @interface ParametersAreNullableByDefault {}"); + addJavaxNullabilityAnnotations(myFixture); + addJavaxDefaultNullabilityAnnotations(myFixture); myFixture.addClass("package foo; public class AnotherPackageNotNull { public static void foo(String s) {}}"); myFixture.addFileToProject("foo/package-info.java", "@javax.annotation.ParametersAreNonnullByDefault package foo;"); @@ -267,6 +268,37 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase { doTest(); } + public static void addJavaxDefaultNullabilityAnnotations(final JavaCodeInsightTestFixture fixture) { + fixture.addClass("package javax.annotation;" + + "@javax.annotation.meta.TypeQualifierDefault(java.lang.annotation.ElementType.PARAMETER) @javax.annotation.Nonnull " + + "public @interface ParametersAreNonnullByDefault {}"); + fixture.addClass("package javax.annotation;" + + "@javax.annotation.meta.TypeQualifierDefault(java.lang.annotation.ElementType.PARAMETER) @javax.annotation.Nullable " + + "public @interface ParametersAreNullableByDefault {}"); + } + + public static void addJavaxNullabilityAnnotations(final JavaCodeInsightTestFixture fixture) { + fixture.addClass("package javax.annotation;" + + "public @interface Nonnull {}"); + fixture.addClass("package javax.annotation;" + + "public @interface Nullable {}"); + fixture.addClass("package javax.annotation.meta;" + + "public @interface TypeQualifierDefault { java.lang.annotation.ElementType[] value() default {};}"); + } + + public void testCustomTypeQualifierDefault() { + addJavaxNullabilityAnnotations(myFixture); + myFixture.addClass("package bar;" + + "@javax.annotation.meta.TypeQualifierDefault(java.lang.annotation.ElementType.METHOD) @javax.annotation.Nonnull " + + "public @interface MethodsAreNotNullByDefault {}"); + + myFixture.addClass("package foo; public class AnotherPackageNotNull { public static native Object foo(String s); }"); + myFixture.addFileToProject("foo/package-info.java", "@bar.MethodsAreNotNullByDefault package foo;"); + + myFixture.enableInspections(new DataFlowInspection()); + myFixture.testHighlighting(true, false, true, getTestName(false) + ".java"); + } + public void testTrueOrEqualsSomething() { doTest(); myFixture.launchAction(myFixture.findSingleIntention("Remove redundant assignment")); diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspectionTest.java index e925dd49a8ea..3520ec08d750 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspectionTest.java @@ -40,8 +40,8 @@ public class NullableStuffInspectionTest extends LightCodeInsightFixtureTestCase } public void testHonorSuperParameterDefault() { - myFixture.addClass("package javax.annotation; public @interface ParametersAreNonnullByDefault {}"); - myFixture.addClass("package javax.annotation; public @interface Nullable {}"); + DataFlowInspectionTest.addJavaxNullabilityAnnotations(myFixture); + DataFlowInspectionTest.addJavaxDefaultNullabilityAnnotations(myFixture); myFixture.addFileToProject("foo/package-info.java", "@javax.annotation.ParametersAreNonnullByDefault package foo;"); myFixture.addClass("import javax.annotation.*; package foo; public interface NullableFunction { void fun(@Nullable Object o); }"); @@ -51,7 +51,8 @@ public class NullableStuffInspectionTest extends LightCodeInsightFixtureTestCase } public void testHonorThisParameterDefault() { - myFixture.addClass("package javax.annotation; public @interface ParametersAreNonnullByDefault {}"); + DataFlowInspectionTest.addJavaxNullabilityAnnotations(myFixture); + DataFlowInspectionTest.addJavaxDefaultNullabilityAnnotations(myFixture); myFixture.addFileToProject("foo/package-info.java", "@javax.annotation.ParametersAreNonnullByDefault package foo;"); myFixture.configureFromExistingVirtualFile(myFixture.copyFileToProject(getTestName(false) + ".java", "foo/Classes.java")); @@ -60,8 +61,8 @@ public class NullableStuffInspectionTest extends LightCodeInsightFixtureTestCase } public void testHonorParameterDefaultInSetters() { - myFixture.addClass("package javax.annotation; public @interface ParametersAreNonnullByDefault {}"); - myFixture.addClass("package javax.annotation; public @interface Nullable {}"); + DataFlowInspectionTest.addJavaxNullabilityAnnotations(myFixture); + DataFlowInspectionTest.addJavaxDefaultNullabilityAnnotations(myFixture); myFixture.addFileToProject("foo/package-info.java", "@javax.annotation.ParametersAreNonnullByDefault package foo;"); myFixture.configureFromExistingVirtualFile(myFixture.copyFileToProject(getTestName(false) + ".java", "foo/Classes.java")); diff --git a/java/java-tests/testSrc/com/intellij/navigation/ChooseByNameTest.groovy b/java/java-tests/testSrc/com/intellij/navigation/ChooseByNameTest.groovy index dabe06ba79fa..e4a65647a281 100644 --- a/java/java-tests/testSrc/com/intellij/navigation/ChooseByNameTest.groovy +++ b/java/java-tests/testSrc/com/intellij/navigation/ChooseByNameTest.groovy @@ -197,6 +197,19 @@ class Intf { assert getPopupElements(new GotoClassModel2(project), 'Bar:[2,3]') == [c] } + public void "test dollar"() { + def bar = myFixture.addClass("package foo; class Bar { class Foo {} }") + def foo = bar.innerClasses[0] + myFixture.addClass("package goo; class Goo { }") + assert getPopupElements(new GotoClassModel2(project), 'Bar$Foo') == [foo] + assert getPopupElements(new GotoClassModel2(project), 'foo.Bar$Foo') == [foo] + assert getPopupElements(new GotoClassModel2(project), 'foo.B$F') == [foo] + assert !getPopupElements(new GotoClassModel2(project), 'foo$Foo') + assert !getPopupElements(new GotoClassModel2(project), 'foo$Bar') + assert !getPopupElements(new GotoClassModel2(project), 'foo$Bar$Foo') + assert !getPopupElements(new GotoClassModel2(project), 'foo$Goo') + } + public void "test super method in jdk"() { def ourRun = myFixture.addClass("package foo.bar; class Goo implements Runnable { public void run() {} }").methods[0] def sdkRun diff --git a/java/openapi/src/com/intellij/ui/classFilter/ClassFilter.java b/java/openapi/src/com/intellij/ui/classFilter/ClassFilter.java index 05500e31ebd3..b93deafa1fe8 100644 --- a/java/openapi/src/com/intellij/ui/classFilter/ClassFilter.java +++ b/java/openapi/src/com/intellij/ui/classFilter/ClassFilter.java @@ -17,15 +17,20 @@ package com.intellij.ui.classFilter; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.DefaultJDOMExternalizer; +import com.intellij.openapi.util.InvalidDataException; +import com.intellij.openapi.util.JDOMExternalizable; +import com.intellij.openapi.util.WriteExternalException; import com.intellij.util.xmlb.annotations.Attribute; import com.intellij.util.xmlb.annotations.Tag; import com.intellij.util.xmlb.annotations.Transient; +import org.jdom.Element; import java.util.regex.Matcher; import java.util.regex.Pattern; @Tag("class-filter") -public class ClassFilter implements Cloneable { +public class ClassFilter implements JDOMExternalizable, Cloneable{ private static final Logger LOG = Logger.getInstance("#com.intellij.ui.classFilter.ClassFilter"); public static final ClassFilter[] EMPTY_ARRAY = new ClassFilter[0]; @@ -67,6 +72,16 @@ public class ClassFilter implements Cloneable { return getPattern(); } + @Override + public void readExternal(Element element) throws InvalidDataException { + DefaultJDOMExternalizer.readExternal(this, element); + } + + @Override + public void writeExternal(Element element) throws WriteExternalException { + DefaultJDOMExternalizer.writeExternal(this, element); + } + public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof ClassFilter)) return false; diff --git a/java/testFramework/src/com/intellij/debugger/impl/DescriptorTestCase.java b/java/testFramework/src/com/intellij/debugger/impl/DescriptorTestCase.java index 49db796244dd..7e3c5f9cd55d 100644 --- a/java/testFramework/src/com/intellij/debugger/impl/DescriptorTestCase.java +++ b/java/testFramework/src/com/intellij/debugger/impl/DescriptorTestCase.java @@ -184,23 +184,24 @@ public abstract class DescriptorTestCase extends DebuggerTestCase { for(int i = 0; i < tree.getRowCount(); i++) { final TreeNode treeNode = (TreeNode)tree.getPathForRow(i).getLastPathComponent(); if(tree.isCollapsed(i) && !treeNode.isLeaf()) { + NodeDescriptor nodeDescriptor = null; if (treeNode instanceof DebuggerTreeNodeImpl) { - final NodeDescriptor nodeDescriptor = ((DebuggerTreeNodeImpl)treeNode).getDescriptor(); - boolean shouldExpand = filter == null || filter.shouldExpand(treeNode); - if (shouldExpand) { - // additional checks to prevent infinite expand - if (nodeDescriptor instanceof ValueDescriptor) { - final Value value = ((ValueDescriptor)nodeDescriptor).getValue(); - shouldExpand = !alreadyExpanded.contains(value); - if (shouldExpand) { - alreadyExpanded.add(value); - } + nodeDescriptor = ((DebuggerTreeNodeImpl)treeNode).getDescriptor(); + } + boolean shouldExpand = filter == null || filter.shouldExpand(treeNode); + if (shouldExpand) { + // additional checks to prevent infinite expand + if (nodeDescriptor instanceof ValueDescriptor) { + final Value value = ((ValueDescriptor)nodeDescriptor).getValue(); + shouldExpand = !alreadyExpanded.contains(value); + if (shouldExpand) { + alreadyExpanded.add(value); } } - if (shouldExpand) { - anyCollapsed = true; - tree.expandRow(i); - } + } + if (shouldExpand) { + anyCollapsed = true; + tree.expandRow(i); } } } diff --git a/native/runner/runnerw/.gitignore b/native/runner/runnerw/.gitignore index 998f2ddef2dc..560bd1aaa0c7 100644 --- a/native/runner/runnerw/.gitignore +++ b/native/runner/runnerw/.gitignore @@ -1,5 +1,6 @@ *.aps *.vcxproj.user +Debug Release *.suo *.opensdf diff --git a/native/runner/runnerw/runnerw.cpp b/native/runner/runnerw/runnerw.cpp index 8936b28f53e8..03e975ef81a1 100644 --- a/native/runner/runnerw/runnerw.cpp +++ b/native/runner/runnerw/runnerw.cpp @@ -18,16 +18,25 @@ void PrintUsage() { exit(0); } -void ErrorMessage(char *str) { - +void ErrorMessage(char *operationName) { LPVOID msg; - - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &msg, 0, NULL); - - printf("%s: %s\n", str, msg); - LocalFree(msg); + DWORD lastError = GetLastError(); + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + lastError, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&msg, + 0, + NULL); + if (msg) { + fprintf(stderr, "%s failed with error %d: %s\n", operationName, lastError, msg); + LocalFree(msg); + } + else { + fprintf(stderr, "%s failed with error %d (no message available)\n", operationName, lastError); + } + fflush(stderr); } void CtrlBreak() { @@ -126,6 +135,33 @@ bool hasEnding(std::string const &fullString, std::string const &ending) { } } +BOOL attachChildConsole(PROCESS_INFORMATION const &childProcessInfo) { + if (!FreeConsole()) { + ErrorMessage("FreeConsole"); + return FALSE; + } + int attempts = 20; + for (int i = 0; i < attempts; i++) { + DWORD sleepMillis = i < 5 ? 30 : (i < 10 ? 100 : 500); + // sleep to let child process initialize itself + Sleep(sleepMillis); + if (WaitForSingleObject(childProcessInfo.hProcess, 0) != WAIT_TIMEOUT) { + // child process has been terminated, no console to attach to + return FALSE; + } + if (AttachConsole(childProcessInfo.dwProcessId)) { + return TRUE; + } + // ERROR_GEN_FAILURE means "the specified process does not exist" + // Seems it also means that the console hasn't been fully initialized. + if (GetLastError() != ERROR_GEN_FAILURE) { + break; + } + } + ErrorMessage("AttachConsole"); + return FALSE; +} + int main(int argc, char * argv[]) { if (argc < 2) { PrintUsage(); @@ -195,18 +231,34 @@ int main(int argc, char * argv[]) { char* c_args = new char[args.size() + 1]; strcpy(c_args, args.c_str()); - if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE)) { - ErrorMessage("SetConsoleCtrlHandler"); + DWORD processFlag = CREATE_DEFAULT_ERROR_MODE; + BOOL hasConsoleWindow = GetConsoleWindow() != NULL; + if (hasConsoleWindow) { + processFlag |= CREATE_NO_WINDOW; } - if (!CreateProcess(c_app, // Application name - c_args, // Application arguments - NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &si, &pi)) { + if (!CreateProcess( + c_app, + c_args, + NULL, + NULL, + TRUE, + processFlag, + NULL, + NULL, + &si, + &pi)) { ErrorMessage("CreateProcess"); CloseHandle(newstdin); CloseHandle(write_stdin); exit(0); } + if (hasConsoleWindow) { + attachChildConsole(pi); + } + if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE)) { + ErrorMessage("SetConsoleCtrlHandler"); + } CreateThread(NULL, 0, &scanStdinThread, &write_stdin, 0, NULL); diff --git a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java index 1013565eaba5..b68fa936af23 100644 --- a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java +++ b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java @@ -1154,6 +1154,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { private void balanceWhiteSpaces() { RelativeTokenTypesView wsTokens = new RelativeTokenTypesView(); RelativeTokenTextView tokenTextGetter = new RelativeTokenTextView(); + int lastIndex = 0; for (int i = 1, size = myProduction.size() - 1; i < size; i++) { ProductionMarker item = myProduction.get(i); @@ -1162,7 +1163,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { } int prevProductionLexIndex = myProduction.get(i - 1).myLexemeIndex; - int wsStartIndex = item.myLexemeIndex; + int wsStartIndex = Math.max(item.myLexemeIndex, lastIndex); while (wsStartIndex > prevProductionLexIndex && whitespaceOrComment(myLexTypes[wsStartIndex - 1])) wsStartIndex--; int wsEndIndex = item.myLexemeIndex; while (wsEndIndex < myLexemeCount && whitespaceOrComment(myLexTypes[wsEndIndex])) wsEndIndex++; @@ -1173,6 +1174,11 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { boolean atEnd = wsStartIndex == 0 || wsEndIndex == myLexemeCount; item.myLexemeIndex = wsStartIndex + item.myEdgeTokenBinder.getEdgePosition(wsTokens, atEnd, tokenTextGetter); } + else if (item.myLexemeIndex < wsStartIndex) { + item.myLexemeIndex = wsStartIndex; + } + + lastIndex = item.myLexemeIndex; } } diff --git a/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java index 7b4e9ec210ac..c048204fe482 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java @@ -408,7 +408,7 @@ public class FileManagerImpl implements FileManager { PsiDirectory psiDir = myVFileToPsiDirMap.get(vFile); if (psiDir != null) return psiDir; - if (Registry.is("ide.hide.excluded.files")) { + if (Registry.is("ide.hide.excluded.files", true)) { if (myFileIndex.isExcludedFile(vFile)) return null; } else { diff --git a/platform/lang-api/src/com/intellij/find/FindModel.java b/platform/lang-api/src/com/intellij/find/FindModel.java index a09070c1ed24..8b74a3e0d61a 100644 --- a/platform/lang-api/src/com/intellij/find/FindModel.java +++ b/platform/lang-api/src/com/intellij/find/FindModel.java @@ -96,6 +96,7 @@ public class FindModel extends UserDataHolderBase implements Cloneable { private SearchScope customScope; private boolean isCustomScope = false; private boolean isMultiline = false; + private boolean mySearchInProjectFiles; public boolean isMultiline() { return isMultiline; @@ -215,6 +216,7 @@ public class FindModel extends UserDataHolderBase implements Cloneable { if (myStringToReplace != null ? !myStringToReplace.equals(findModel.myStringToReplace) : findModel.myStringToReplace != null) { return false; } + if (mySearchInProjectFiles != findModel.mySearchInProjectFiles) return false; return true; } @@ -252,6 +254,7 @@ public class FindModel extends UserDataHolderBase implements Cloneable { result = 31 * result + (isCustomScope ? 1 : 0); result = 31 * result + (isMultiline ? 1 : 0); result = 31 * result + (isPreserveCase ? 1 : 0); + result = 31 * result + (mySearchInProjectFiles ? 1 : 0); result = 31 * result + (myPattern != null ? myPattern.hashCode() : 0); return result; } @@ -658,8 +661,8 @@ public class FindModel extends UserDataHolderBase implements Cloneable { } @Override - public Object clone() { - return super.clone(); + public FindModel clone() { + return (FindModel)super.clone(); } @@ -689,6 +692,7 @@ public class FindModel extends UserDataHolderBase implements Cloneable { buffer.append("fileFilter =").append(fileFilter).append("\n"); buffer.append("moduleName =").append(moduleName).append("\n"); buffer.append("customScopeName =").append(customScopeName).append("\n"); + buffer.append("searchInProjectFiles =").append(mySearchInProjectFiles).append("\n"); return buffer.toString(); } @@ -873,6 +877,18 @@ public class FindModel extends UserDataHolderBase implements Cloneable { } } + public boolean isSearchInProjectFiles() { + return mySearchInProjectFiles; + } + + public void setSearchInProjectFiles(boolean searchInProjectFiles) { + boolean changed = mySearchInProjectFiles != searchInProjectFiles; + mySearchInProjectFiles = searchInProjectFiles; + if (changed) { + notifyObservers(); + } + } + private static final Pattern NO_PATTERN = Pattern.compile(""); private Pattern myPattern = NO_PATTERN; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/IndentingBackspaceHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/IndentingBackspaceHandler.java index 345cb80bae69..fe4fc716a5fb 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/IndentingBackspaceHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/IndentingBackspaceHandler.java @@ -23,8 +23,10 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider; import com.intellij.util.text.CharArrayUtil; @@ -37,10 +39,12 @@ public class IndentingBackspaceHandler extends BackspaceHandlerDelegate { private static final Logger LOG = Logger.getInstance(IndentingBackspaceHandler.class); private boolean caretWasAtLineStart; + private int initialCaretOffset; @Override public void beforeCharDeleted(char c, PsiFile file, Editor editor) { caretWasAtLineStart = editor.getCaretModel().getLogicalPosition().column == 0; + initialCaretOffset = editor.getCaretModel().getOffset(); } @Override @@ -68,8 +72,12 @@ public class IndentingBackspaceHandler extends BackspaceHandlerDelegate { return false; } - CodeStyleFacade codeStyleFacade = CodeStyleFacade.getInstance(editor.getProject()); - String indent = codeStyleFacade.getLineIndent(document, lineStartOffset); + Project project = file.getProject(); + CodeStyleFacade codeStyleFacade = CodeStyleFacade.getInstance(project); + PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(project); + // We should calculate indent at line containing the text after caret, cause that text might affect the result (e.g. closing brace in Java) + String indent = codeStyleFacade.getLineIndent(document, caretWasAtLineStart && psiDocumentManager.isUncommited(document) + ? initialCaretOffset : lineStartOffset); if (indent == null) { return false; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ExpressionPostfixTemplateWithChooser.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ChooserExpressionSelector.java similarity index 55% rename from platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ExpressionPostfixTemplateWithChooser.java rename to platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ChooserExpressionSelector.java index f6b0cedae31e..2989f0d0c97c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ExpressionPostfixTemplateWithChooser.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ChooserExpressionSelector.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.template.postfix.templates; + import com.intellij.codeInsight.unwrap.ScopeHighlighter; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; @@ -30,45 +31,43 @@ import org.jetbrains.annotations.NotNull; import java.util.List; /** - * @author ignatov + * See {@link PostfixTemplateExpressionSelector} for description */ -public abstract class ExpressionPostfixTemplateWithChooser extends PostfixTemplate { +public class ChooserExpressionSelector implements PostfixTemplateExpressionSelector { @NotNull - protected final PostfixTemplatePsiInfoBase myInfo; + private final Condition myCondition; - protected ExpressionPostfixTemplateWithChooser(@NotNull String name, @NotNull String example, @NotNull PostfixTemplatePsiInfoBase info) { - super(name, example); - myInfo = info; + public ChooserExpressionSelector(@NotNull Condition condition) { + myCondition = condition; } - protected ExpressionPostfixTemplateWithChooser(@NotNull String name, - @NotNull String key, - @NotNull String example, - @NotNull PostfixTemplatePsiInfoBase info) { - super(name, key, example); - myInfo = info; + + public boolean hasExpression(@NotNull final PostfixTemplateWithExpressionSelector postfixTemplate, + @NotNull PsiElement context, + @NotNull Document copyDocument, + int newOffset) { + return !getExpressions(postfixTemplate, context, copyDocument, newOffset).isEmpty(); } - @Override - public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - return !getExpressions(context, copyDocument, newOffset).isEmpty(); - } - - @Override - public void expand(@NotNull PsiElement context, @NotNull final Editor editor) { - List expressions = getExpressions(context, editor.getDocument(), editor.getCaretModel().getOffset()); + public void expandTemplate(@NotNull final PostfixTemplateWithExpressionSelector postfixTemplate, + @NotNull PsiElement context, + @NotNull final Editor editor) { + List expressions = + getExpressions(postfixTemplate, context, editor.getDocument(), editor.getCaretModel().getOffset()); if (expressions.isEmpty()) { PostfixTemplatesUtils.showErrorHint(context.getProject(), editor); } else if (expressions.size() == 1) { - doIt(editor, expressions.get(0)); + postfixTemplate.expandForChooseExpression(expressions.get(0), editor); } else { if (ApplicationManager.getApplication().isUnitTestMode()) { - doIt(editor, expressions.get(expressions.size() - 1)); + PsiElement item = ContainerUtil.getLastItem(expressions); + assert item != null; + postfixTemplate.expandForChooseExpression(item, editor); return; } @@ -81,22 +80,25 @@ public abstract class ExpressionPostfixTemplateWithChooser extends PostfixTempla public void run() { CommandProcessor.getInstance().executeCommand(e.getProject(), new Runnable() { public void run() { - doIt(editor, e); + postfixTemplate.expandForChooseExpression(e, editor); } }, "Expand postfix template", PostfixLiveTemplate.POSTFIX_TEMPLATE_ID); } }); } }, - myInfo.getRenderer(), + postfixTemplate.getPsiInfo().getRenderer(), "Expressions", 0, ScopeHighlighter.NATURAL_RANGER ); } } @NotNull - protected List getExpressions(@NotNull PsiElement context, @NotNull Document document, final int offset) { - List possibleExpressions = myInfo.getExpressions(context, document, offset); + private List getExpressions(@NotNull PostfixTemplateWithExpressionSelector postfixTemplate, + @NotNull PsiElement context, + @NotNull Document document, + final int offset) { + List possibleExpressions = postfixTemplate.getPsiInfo().getExpressions(context, document, offset); List expressions = ContainerUtil.filter(possibleExpressions, new Condition() { @Override @@ -105,19 +107,13 @@ public abstract class ExpressionPostfixTemplateWithChooser extends PostfixTempla } } ); - return ContainerUtil.filter(expressions.isEmpty() ? maybeTopmostExpression(context) : expressions, getTypeCondition()); + return ContainerUtil + .filter(expressions.isEmpty() ? maybeTopmostExpression(postfixTemplate, context) : expressions, myCondition); } + @NotNull - @SuppressWarnings("unchecked") - protected Condition getTypeCondition() { - return Condition.TRUE; + private static List maybeTopmostExpression(@NotNull PostfixTemplateWithExpressionSelector postfixTemplate, @NotNull PsiElement context) { + return ContainerUtil.createMaybeSingletonList(postfixTemplate.getPsiInfo().getTopmostExpression(context)); } - - @NotNull - private List maybeTopmostExpression(@NotNull PsiElement context) { - return ContainerUtil.createMaybeSingletonList(myInfo.getTopmostExpression(context)); - } - - protected abstract void doIt(@NotNull Editor editor, @NotNull PsiElement expression); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/NotPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/NotPostfixTemplate.java index 9c1d9c66b94d..3944cd930af0 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/NotPostfixTemplate.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/NotPostfixTemplate.java @@ -16,26 +16,34 @@ package com.intellij.codeInsight.template.postfix.templates; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.Condition; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; -public class NotPostfixTemplate extends ExpressionPostfixTemplateWithChooser { +import static com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils.selectorWithChooser; - public NotPostfixTemplate(@NotNull PostfixTemplatePsiInfoBase info) { - super("not", "!expr", info); +public class NotPostfixTemplate extends PostfixTemplateWithExpressionSelector { + + public NotPostfixTemplate(@NotNull PostfixTemplatePsiInfo info, @NotNull Condition typeChecker) { + super("not", "!expr", info, selectorWithChooser(typeChecker)); } + public NotPostfixTemplate(@NotNull PostfixTemplatePsiInfo info) { + super("not", "!expr", info, selectorWithChooser()); + } public NotPostfixTemplate(@NotNull String name, @NotNull String key, @NotNull String example, - @NotNull PostfixTemplatePsiInfoBase info) { - super(name, key, example, info); + @NotNull PostfixTemplatePsiInfo info, + @NotNull Condition typeChecker + ) { + super(name, key, example, info, selectorWithChooser(typeChecker)); } @Override - protected void doIt(@NotNull Editor editor, @NotNull PsiElement expression) { - PsiElement element = myInfo.getNegatedExpression(expression); + protected void expandForChooseExpression(@NotNull PsiElement expression, @NotNull Editor editor) { + PsiElement element = myPsiInfo.getNegatedExpression(expression); expression.replace(element); } } \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedPostfixTemplate.java index 9a5d03a9359c..3f1dd1143348 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedPostfixTemplate.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedPostfixTemplate.java @@ -16,16 +16,25 @@ package com.intellij.codeInsight.template.postfix.templates; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.Condition; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; -public class ParenthesizedPostfixTemplate extends ExpressionPostfixTemplateWithChooser { - public ParenthesizedPostfixTemplate(PostfixTemplatePsiInfoBase psiInfo) { - super("par", "(expr)", psiInfo); +import static com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils.selectorWithChooser; + +public class ParenthesizedPostfixTemplate extends PostfixTemplateWithExpressionSelector { + + public ParenthesizedPostfixTemplate(PostfixTemplatePsiInfo psiInfo, Condition condition) { + super("par", "(expr)", psiInfo, selectorWithChooser(condition)); + } + + + public ParenthesizedPostfixTemplate(PostfixTemplatePsiInfo psiInfo) { + super("par", "(expr)", psiInfo, selectorWithChooser()); } @Override - protected void doIt(@NotNull Editor editor, @NotNull PsiElement expression) { - expression.replace(myInfo.createExpression(expression, "(", ")")); + protected void expandForChooseExpression(@NotNull PsiElement expression, @NotNull Editor editor) { + expression.replace(myPsiInfo.createExpression(expression, "(", ")")); } } \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateExpressionSelector.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateExpressionSelector.java new file mode 100644 index 000000000000..6b5d559da1de --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateExpressionSelector.java @@ -0,0 +1,54 @@ +/* + * 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.template.postfix.templates; + + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; + +/** + * Interface provides method used in {@link com.intellij.codeInsight.template.postfix.templates.PostfixTemplateWithExpressionSelector} + * + * You should implement the interface if you have non-trivial logic how to determine expression for next processing in postfix template + * Otherwise, you can use one of existing simple implementations: + * + * 1) {@link com.intellij.codeInsight.template.postfix.templates.ChooserExpressionSelector} - The selector get all expression + * in the current position and show to user chooser for these expressions. + * + * 2) {@link com.intellij.codeInsight.template.postfix.templates.TopmostExpressionSelector} - The selector pass to postfix template + * top most expression in the current position + * + * + */ +public interface PostfixTemplateExpressionSelector { + + /** + * Check that we can select not-null expression(PsiElement) in current context + */ + boolean hasExpression(@NotNull final PostfixTemplateWithExpressionSelector postfixTemplate, + @NotNull PsiElement context, + @NotNull Document copyDocument, + int newOffset); + + /** + * Select expression(PsiElement) and call postfixTemplate.expandForChooseExpression for selected expression + */ + void expandTemplate(@NotNull final PostfixTemplateWithExpressionSelector postfixTemplate, + @NotNull PsiElement context, + @NotNull final Editor editor); +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfo.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfo.java index 8f4716787453..6664d6404d64 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfo.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfo.java @@ -16,25 +16,42 @@ package com.intellij.codeInsight.template.postfix.templates; +import com.intellij.openapi.editor.Document; import com.intellij.psi.PsiElement; +import com.intellij.util.Function; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public interface PostfixTemplatePsiInfo { +import java.util.List; + +public abstract class PostfixTemplatePsiInfo { @NotNull - PsiElement createStatement(@NotNull PsiElement context, - @NotNull String prefix, - @NotNull String suffix); + public abstract PsiElement createStatement(@NotNull PsiElement context, + @NotNull String prefix, + @NotNull String suffix); @NotNull - PsiElement createExpression(@NotNull PsiElement context, - @NotNull String prefix, - @NotNull String suffix); + public abstract PsiElement createExpression(@NotNull PsiElement context, + @NotNull String prefix, + @NotNull String suffix); @Nullable - PsiElement getTopmostExpression(@NotNull PsiElement element); + public abstract PsiElement getTopmostExpression(@NotNull PsiElement element); @NotNull - PsiElement getNegatedExpression(@NotNull PsiElement element); + public abstract PsiElement getNegatedExpression(@NotNull PsiElement element); + + @NotNull + public abstract List getExpressions(@NotNull PsiElement context, @NotNull Document document, int offset); + + @NotNull + public Function getRenderer() { + return new Function() { + @Override + public String fun(@NotNull PsiElement element) { + return element.getText(); + } + }; + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfoBase.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfoBase.java deleted file mode 100644 index 7254e651ce41..000000000000 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfoBase.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.template.postfix.templates; - -import com.intellij.openapi.editor.Document; -import com.intellij.psi.PsiElement; -import com.intellij.util.Function; -import org.jetbrains.annotations.NotNull; - -import java.util.List; - -public abstract class PostfixTemplatePsiInfoBase implements PostfixTemplatePsiInfo { - - @NotNull - public abstract List getExpressions(@NotNull PsiElement context, @NotNull Document document, int newOffset); - - @NotNull - public Function getRenderer() { - return new Function() { - @Override - public String fun(@NotNull PsiElement element) { - return element.getText(); - } - }; - } -} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateWithExpressionSelector.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateWithExpressionSelector.java new file mode 100644 index 000000000000..d7cfbafdf7a8 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateWithExpressionSelector.java @@ -0,0 +1,83 @@ +/* + * 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.template.postfix.templates; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.Condition; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; + +import static com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils.selectorTopmost; + +public abstract class PostfixTemplateWithExpressionSelector extends PostfixTemplate { + + @NotNull + protected final PostfixTemplatePsiInfo myPsiInfo; + @NotNull + private final PostfixTemplateExpressionSelector mySelector; + + protected PostfixTemplateWithExpressionSelector(@NotNull String name, + @NotNull String key, + @NotNull String example, + @NotNull PostfixTemplatePsiInfo psiInfo, + @NotNull PostfixTemplateExpressionSelector selector) { + super(name, key, example); + myPsiInfo = psiInfo; + mySelector = selector; + } + + + protected PostfixTemplateWithExpressionSelector(@NotNull String name, + @NotNull String example, + @NotNull PostfixTemplatePsiInfo psiInfo, + @NotNull PostfixTemplateExpressionSelector selector) { + super(name, example); + myPsiInfo = psiInfo; + mySelector = selector; + } + + protected PostfixTemplateWithExpressionSelector(@NotNull String name, + @NotNull String example, + @NotNull PostfixTemplatePsiInfo psiInfo, + @NotNull Condition typeChecker) { + this(name, example, psiInfo, selectorTopmost(typeChecker)); + } + + protected PostfixTemplateWithExpressionSelector(@NotNull String name, + @NotNull String example, + @NotNull PostfixTemplatePsiInfo psiInfo) { + this(name, example, psiInfo, selectorTopmost()); + } + + + @Override + public final boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { + return mySelector.hasExpression(this, context, copyDocument, newOffset); + } + + @Override + public final void expand(@NotNull PsiElement context, @NotNull Editor editor) { + mySelector.expandTemplate(this, context, editor); + } + + protected abstract void expandForChooseExpression(@NotNull PsiElement expression, @NotNull Editor editor); + + @NotNull + PostfixTemplatePsiInfo getPsiInfo() { + return myPsiInfo; + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java index 877e10b53490..5ff744e3d72a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java @@ -21,6 +21,8 @@ import com.intellij.lang.surroundWith.Surrounder; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Conditions; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.refactoring.util.CommonRefactoringUtil; @@ -31,6 +33,22 @@ public abstract class PostfixTemplatesUtils { private PostfixTemplatesUtils() { } + public static PostfixTemplateExpressionSelector selectorWithChooser() { + return selectorWithChooser(Conditions.alwaysTrue()); + } + + public static PostfixTemplateExpressionSelector selectorTopmost() { + return selectorTopmost(Conditions.alwaysTrue()); + } + + public static PostfixTemplateExpressionSelector selectorWithChooser(Condition condition) { + return new ChooserExpressionSelector(condition); + } + + public static PostfixTemplateExpressionSelector selectorTopmost(Condition condition) { + return new TopmostExpressionSelector(condition); + } + @Nullable public static TextRange surround(@NotNull Surrounder surrounder, @NotNull Editor editor, diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementWrapPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementWrapPostfixTemplate.java index ed1605d3a9fb..5b5c3624f33b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementWrapPostfixTemplate.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementWrapPostfixTemplate.java @@ -22,7 +22,7 @@ import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; -public abstract class StatementWrapPostfixTemplate extends TypedPostfixTemplate { +public abstract class StatementWrapPostfixTemplate extends PostfixTemplateWithExpressionSelector { @SuppressWarnings("unchecked") protected StatementWrapPostfixTemplate(@NotNull String name, @@ -39,9 +39,7 @@ public abstract class StatementWrapPostfixTemplate extends TypedPostfixTemplate } @Override - public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PsiElement topmostExpression = myPsiInfo.getTopmostExpression(context); - assert topmostExpression != null; + public void expandForChooseExpression(@NotNull PsiElement topmostExpression, @NotNull Editor editor) { PsiElement parent = topmostExpression.getParent(); PsiElement expression = getWrappedExpression(topmostExpression); PsiElement replace = parent.replace(expression); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StringBasedPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StringBasedPostfixTemplate.java index 4d6582f071de..9f19b2011a49 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StringBasedPostfixTemplate.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StringBasedPostfixTemplate.java @@ -26,7 +26,7 @@ import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public abstract class StringBasedPostfixTemplate extends TypedPostfixTemplate { +public abstract class StringBasedPostfixTemplate extends PostfixTemplateWithExpressionSelector { public StringBasedPostfixTemplate(@NotNull String name, @NotNull String example, @@ -36,10 +36,8 @@ public abstract class StringBasedPostfixTemplate extends TypedPostfixTemplate { } @Override - public final void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PsiElement expr = myPsiInfo.getTopmostExpression(context); - assert expr != null; - Project project = context.getProject(); + public final void expandForChooseExpression(@NotNull PsiElement expr, @NotNull Editor editor) { + Project project = expr.getProject(); Document document = editor.getDocument(); PsiElement elementForRemoving = shouldRemoveParent() ? expr.getParent() : expr; document.deleteString(elementForRemoving.getTextRange().getStartOffset(), elementForRemoving.getTextRange().getEndOffset()); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java index 52ad0c4cdde8..77e731fcd06f 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java @@ -40,7 +40,7 @@ public abstract class SurroundPostfixTemplateBase extends StatementWrapPostfixTe @Override - public void expand(@NotNull PsiElement context, @NotNull final Editor editor) { + public final void expandForChooseExpression(@NotNull PsiElement context, @NotNull final Editor editor) { PsiElement topmostExpression = myPsiInfo.getTopmostExpression(context); PsiElement expression = getWrappedExpression(topmostExpression); assert topmostExpression != null; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TopmostExpressionSelector.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TopmostExpressionSelector.java new file mode 100644 index 000000000000..bd6028d2d8d2 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TopmostExpressionSelector.java @@ -0,0 +1,58 @@ +/* + * 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.template.postfix.templates; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.Condition; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; + + +/** + * See {@link PostfixTemplateExpressionSelector} for description + */ +public class TopmostExpressionSelector implements PostfixTemplateExpressionSelector { + + @NotNull + private final Condition myCondition; + + public TopmostExpressionSelector(@NotNull Condition condition) { + + myCondition = condition; + } + + @Override + public boolean hasExpression(@NotNull PostfixTemplateWithExpressionSelector template, + @NotNull PsiElement context, + @NotNull Document copyDocument, + int newOffset) { + PsiElement topmostExpression = template.getPsiInfo().getTopmostExpression(context); + return topmostExpression != null && myCondition.value(topmostExpression); + } + + @Override + public void expandTemplate(@NotNull PostfixTemplateWithExpressionSelector template, + @NotNull PsiElement context, + @NotNull Editor editor) { + PostfixTemplatePsiInfo info = template.getPsiInfo(); + PsiElement expression = info.getTopmostExpression(context); + if (expression == null) { + return; + } + template.expandForChooseExpression(expression, editor); + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TypedPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TypedPostfixTemplate.java deleted file mode 100644 index 0d7d424d99a8..000000000000 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TypedPostfixTemplate.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.template.postfix.templates; - -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.util.Condition; -import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NotNull; - -public abstract class TypedPostfixTemplate extends PostfixTemplate { - - protected final PostfixTemplatePsiInfo myPsiInfo; - protected final Condition myTypeChecker; - - protected TypedPostfixTemplate(@NotNull String name, - @NotNull String example, - @NotNull PostfixTemplatePsiInfo psiInfo, - @NotNull Condition typeChecker) { - super(name, example); - this.myPsiInfo = psiInfo; - this.myTypeChecker = typeChecker; - } - - @Override - public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiElement topmostExpression = myPsiInfo.getTopmostExpression(context); - return topmostExpression != null && myTypeChecker.value(topmostExpression); - } -} diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java index 4cf12e907204..7e9e71d7a94d 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java @@ -19,6 +19,7 @@ import com.google.common.collect.HashMultiset; import com.google.common.collect.Multiset; import com.intellij.find.FindBundle; import com.intellij.find.FindModel; +import com.intellij.find.findInProject.FindInProjectManager; import com.intellij.find.ngrams.TrigramIndex; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ApplicationNamesInfo; @@ -182,7 +183,7 @@ class FindInProjectTask { private void searchInFiles(@NotNull Collection psiFiles, @NotNull FindUsagesProcessPresentation processPresentation, - @NotNull Processor consumer) { + @NotNull final Processor consumer) { int i = 0; long totalFilesSize = 0; int count = 0; @@ -195,7 +196,8 @@ class FindInProjectTask { long fileLength = UsageViewManagerImpl.getFileLength(virtualFile); if (fileLength == -1) continue; // Binary or invalid - if (ProjectCoreUtil.isProjectOrWorkspaceFile(virtualFile) && !Registry.is("find.search.in.project.files")) continue; + final boolean skipProjectFile = ProjectCoreUtil.isProjectOrWorkspaceFile(virtualFile) && !myFindModel.isSearchInProjectFiles(); + if (skipProjectFile && !Registry.is("find.search.in.project.files")) continue; if (fileLength > SINGLE_FILE_SIZE_LIMIT) { myLargeFiles.add(psiFile); @@ -209,7 +211,24 @@ class FindInProjectTask { myProgress.setText(text); myProgress.setText2(FindBundle.message("find.searching.for.string.in.file.occurrences.progress", count)); - int countInFile = FindInProjectUtil.processUsagesInFile(psiFile, myFindModel, consumer); + int countInFile = FindInProjectUtil.processUsagesInFile(psiFile, myFindModel, new Processor() { + @Override + public boolean process(UsageInfo info) { + return skipProjectFile || consumer.process(info); + } + }); + + if (countInFile > 0 && skipProjectFile) { + processPresentation.projectFileUsagesFound(new Runnable() { + @Override + public void run() { + FindModel model = myFindModel.clone(); + model.setSearchInProjectFiles(true); + FindInProjectManager.getInstance(myProject).startFindInProject(model); + } + }); + continue; + } count += countInFile; if (countInFile > 0) { diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java index f9a5934b4e13..3e90f2310884 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java @@ -532,7 +532,7 @@ public abstract class ChooseByNameBase { if (queue instanceof IdeEventQueue) { if (!((IdeEventQueue)queue).wasRootRecentlyClicked(oppositeComponent)) { Component root = SwingUtilities.getRoot(myTextField); - if (root != null) { + if (root != null && root.isShowing()) { root.requestFocus(); myTextField.requestFocus(); return; diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionItemProvider.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionItemProvider.java index a6e6c8fdf658..99d3c9b338ae 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionItemProvider.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionItemProvider.java @@ -26,6 +26,7 @@ import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.impl.ActionManagerImpl; import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; import com.intellij.util.Function; import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; @@ -128,17 +129,19 @@ public class GotoActionItemProvider implements ChooseByNameItemProvider { List actions = ContainerUtil.newArrayList(); if (everywhere) { for (String id : ((ActionManagerImpl)myActionManager).getActionIds()) { + ProgressManager.checkCanceled(); ContainerUtil.addIfNotNull(actions, myActionManager.getAction(id)); } } else { - actions.addAll(myModel.myActionsMap.keySet()); + actions.addAll(myModel.myActionGroups.keySet()); } List actionWrappers = ContainerUtil.newArrayList(); for (AnAction action : actions) { + ProgressManager.checkCanceled(); MatchMode mode = myModel.actionMatches(pattern, action); if (mode != MatchMode.NONE) { - actionWrappers.add(new ActionWrapper(action, myModel.myActionsMap.get(action), mode, dataContext)); + actionWrappers.add(new ActionWrapper(action, myModel.myActionGroups.get(action), mode, dataContext)); } } return processItems(pattern, actionWrappers, consumer); diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java index 88b835613fd6..5120ea000102 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java @@ -68,16 +68,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C private Pattern myCompiledPattern; protected final SearchableOptionsRegistrar myIndex; - protected final Map myActionsMap = new TreeMap(new Comparator() { - @Override - public int compare(@NotNull AnAction o1, @NotNull AnAction o2) { - int compare = Comparing.compare(o1.getTemplatePresentation().getText(), o2.getTemplatePresentation().getText()); - if (compare == 0 && !o1.equals(o2)) { - return o1.hashCode() - o2.hashCode(); - } - return compare; - } - }); + protected final Map myActionGroups = ContainerUtil.newHashMap(); protected final Map myIntentions = new TreeMap(); private final Map myConfigurablesNames = ContainerUtil.newTroveMap(); @@ -90,7 +81,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C myProject = project; myContextComponent = component; final ActionGroup mainMenu = (ActionGroup)myActionManager.getActionOrStub(IdeActions.GROUP_MAIN_MENU); - collectActions(myActionsMap, mainMenu, mainMenu.getTemplatePresentation().getText()); + collectActions(myActionGroups, mainMenu, mainMenu.getTemplatePresentation().getText()); if (project != null && editor != null && file != null) { final ApplyIntentionAction[] children = ApplyIntentionAction.getAvailableIntentions(editor, file); if (children != null) { @@ -463,7 +454,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C LOG.error("Null text for action " + anAction + " of class " + anAction.getClass()); return MatchMode.NONE; } - final String groupName = myActionsMap.get(anAction); + final String groupName = myActionGroups.get(anAction); if (groupName == null) { return matcher.matches(text, compiledPattern) ? MatchMode.NON_MENU : MatchMode.NONE; } @@ -617,7 +608,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C PatternMatcher getMatcher() { return myMatcher.get(); } - + public static class ActionWrapper implements Comparable{ private final AnAction myAction; private final MatchMode myMode; diff --git a/platform/lang-impl/src/com/intellij/internal/DumpLookupElementWeights.java b/platform/lang-impl/src/com/intellij/internal/DumpLookupElementWeights.java index 63d8a6038b6a..6350642c772e 100644 --- a/platform/lang-impl/src/com/intellij/internal/DumpLookupElementWeights.java +++ b/platform/lang-impl/src/com/intellij/internal/DumpLookupElementWeights.java @@ -22,7 +22,6 @@ import com.intellij.codeInsight.lookup.impl.LookupImpl; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; @@ -53,7 +52,12 @@ public class DumpLookupElementWeights extends AnAction implements DumbAware { } public static void dumpLookupElementWeights(final LookupImpl lookup) { - String sb = StringUtil.join(getLookupElementWeights(lookup), "\n"); + LookupElement selected = lookup.getCurrentItem(); + String sb = "selected: " + selected; + if (selected != null) { + sb += "\nprefix: " + lookup.itemPattern(selected); + } + sb += "\nweights:\n" + StringUtil.join(getLookupElementWeights(lookup), "\n"); System.out.println(sb); LOG.info(sb); } diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java index 54406106b976..504496a27716 100644 --- a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java +++ b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java @@ -23,6 +23,7 @@ import com.intellij.ide.highlighter.HighlighterFactory; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.colors.EditorColorsScheme; +import com.intellij.openapi.editor.colors.FontPreferences; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.editor.ex.DisposableIterator; import com.intellij.openapi.editor.ex.MarkupModelEx; @@ -418,7 +419,7 @@ public class TextWithMarkupProcessor extends CopyPastePostProcessor implements UpdatableIndex} diff --git a/platform/lang-impl/testData/editor/indentingBackspace/beforeBrace.java b/platform/lang-impl/testData/editor/indentingBackspace/beforeBrace.java new file mode 100644 index 000000000000..5fd42398e146 --- /dev/null +++ b/platform/lang-impl/testData/editor/indentingBackspace/beforeBrace.java @@ -0,0 +1,5 @@ +class A { + void foo() { + } + +} diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java index 1d4fea4c01de..6ade9b77afc0 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java @@ -36,6 +36,8 @@ public interface IdeActions { @NonNls String ACTION_EDITOR_SELECT_WORD_AT_CARET = "EditorSelectWord"; @NonNls String ACTION_EDITOR_UNSELECT_WORD_AT_CARET = "EditorUnSelectWord"; @NonNls String ACTION_EDITOR_BACKSPACE = "EditorBackSpace"; + @NonNls String ACTION_EDITOR_MOVE_CARET_LEFT_WITH_SELECTION = "EditorLeftWithSelection"; + @NonNls String ACTION_EDITOR_MOVE_CARET_RIGHT_WITH_SELECTION = "EditorRightWithSelection"; @NonNls String ACTION_EDITOR_MOVE_CARET_UP = "EditorUp"; @NonNls String ACTION_EDITOR_MOVE_CARET_LEFT = "EditorLeft"; @NonNls String ACTION_EDITOR_MOVE_CARET_DOWN = "EditorDown"; diff --git a/platform/platform-api/src/com/intellij/ui/table/BaseTableView.java b/platform/platform-api/src/com/intellij/ui/table/BaseTableView.java index a79349b5f6aa..46bce6b3834d 100644 --- a/platform/platform-api/src/com/intellij/ui/table/BaseTableView.java +++ b/platform/platform-api/src/com/intellij/ui/table/BaseTableView.java @@ -17,12 +17,12 @@ package com.intellij.ui.table; import com.intellij.openapi.diagnostic.Logger; import com.intellij.util.config.Storage; -import com.intellij.util.ui.ListTableModel; import org.jetbrains.annotations.NonNls; import javax.swing.*; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; +import javax.swing.table.TableModel; import java.util.ArrayList; import java.util.Arrays; @@ -33,10 +33,14 @@ import java.util.Arrays; public class BaseTableView extends JBTable { private static final Logger LOG = Logger.getInstance("#com.intellij.ui.table.BaseTableView"); - public BaseTableView(final ListTableModel model) { + public BaseTableView(final TableModel model) { super(model); } + public BaseTableView(TableModel model, TableColumnModel columnModel) { + super(model, columnModel); + } + @NonNls private static String orderPropertyName(final int index) { return "Order"+index; diff --git a/platform/platform-api/src/com/intellij/ui/table/JBTable.java b/platform/platform-api/src/com/intellij/ui/table/JBTable.java index e7ff935e57f9..435c4358959f 100644 --- a/platform/platform-api/src/com/intellij/ui/table/JBTable.java +++ b/platform/platform-api/src/com/intellij/ui/table/JBTable.java @@ -62,8 +62,12 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component this(new DefaultTableModel()); } - public JBTable(final TableModel model) { - super(model); + public JBTable(TableModel model) { + this(model, null); + } + + public JBTable(final TableModel model, final TableColumnModel columnModel) { + super(model, columnModel); myEmptyText = new StatusText(this) { @Override diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties index 255d356d5bc0..5ddd24560338 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties @@ -48,6 +48,13 @@ MenuBar.shadow=3c3f41 MenuBar.darcula.borderColor=555555 MenuBar.darcula.borderShadowColor=282828 +CheckBoxMenuItemUI=com.intellij.ide.ui.laf.darcula.ui.DarculaCheckBoxMenuItemUI +CheckBoxMenuItem.borderPainted=false + +RadioButtonMenuItemUI=com.intellij.ide.ui.laf.darcula.ui.DarculaRadioButtonMenuItemUI +RadioButtonMenuItem.borderPainted=false + + TabbedPaneUI=com.intellij.ide.ui.laf.darcula.ui.DarculaTabbedPaneUI TabbedPane.tabInsets=0,4,0,4 TabbedPane.highlight=292b2d diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaCheckBoxMenuItemUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaCheckBoxMenuItemUI.java new file mode 100644 index 000000000000..d9c4ac7895e6 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaCheckBoxMenuItemUI.java @@ -0,0 +1,81 @@ +/* + * 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.ide.ui.laf.darcula.ui; + +import com.intellij.openapi.ui.GraphicsConfig; +import com.intellij.ui.Gray; +import com.intellij.util.ui.UIUtil; +import sun.swing.MenuItemLayoutHelper; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import java.awt.*; + +/** + * @author Konstantin Bulenkov + */ +public class DarculaCheckBoxMenuItemUI extends DarculaMenuItemUIBase { + + @SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"}) + public static ComponentUI createUI(JComponent c) { + return new DarculaCheckBoxMenuItemUI(); + } + + protected String getPropertyPrefix() { + return "CheckBoxMenuItem"; + } + + @Override + public Dimension getPreferredSize(JComponent c) { + return super.getPreferredSize(c); + } + + @Override + protected void paintCheckIcon(Graphics g2, MenuItemLayoutHelper lh, MenuItemLayoutHelper.LayoutResult lr, Color holdc, Color foreground) { + Graphics2D g = (Graphics2D) g2; + final GraphicsConfig config = new GraphicsConfig(g); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT); + + g.translate(lr.getCheckRect().x-2, lr.getCheckRect().y); + + final int sz = 13; + g.setPaint(new GradientPaint(sz / 2, 1, Gray._110, sz / 2, sz, Gray._95)); + g.fillRoundRect(0, 0, sz, sz - 1 , 4, 4); + + g.setPaint(new GradientPaint(sz / 2, 1, Gray._120.withAlpha(0x5a), sz / 2, sz, Gray._105.withAlpha(90))); + g.drawRoundRect(0, (UIUtil.isUnderDarcula() ? 1 : 0), sz, sz - 1, 4, 4); + + g.setPaint(Gray._40.withAlpha(180)); + g.drawRoundRect(0, 0, sz, sz - 1, 4, 4); + + + if (lh.getMenuItem().isSelected()) { + g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); + g.setStroke(new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); + g.setPaint(Gray._30); + g.drawLine(4, 7, 7, 10); + g.drawLine(7, 10, sz, 2); + g.setPaint(Gray._170); + g.drawLine(4, 5, 7, 8); + g.drawLine(7, 8, sz, 0); + } + + g.translate(-lr.getCheckRect().x+2, -lr.getCheckRect().y); + config.restore(); + g.setColor(foreground); + } +} diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaMenuItemUIBase.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaMenuItemUIBase.java new file mode 100644 index 000000000000..cc69d24b6ca3 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaMenuItemUIBase.java @@ -0,0 +1,208 @@ +/* + * 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.ide.ui.laf.darcula.ui; + +import sun.swing.MenuItemLayoutHelper; +import sun.swing.SwingUtilities2; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicMenuItemUI; +import java.awt.*; +import java.awt.event.MouseEvent; + +/** + * @author Konstantin Bulenkov + */ +public class DarculaMenuItemUIBase extends BasicMenuItemUI { + @SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"}) + public static ComponentUI createUI(JComponent c) { + return new DarculaMenuItemUIBase(); + } + + public void processMouseEvent(JMenuItem item, MouseEvent e, MenuElement path[], MenuSelectionManager manager) { + Point p = e.getPoint(); + if (p.x >= 0 && p.x < item.getWidth() && + p.y >= 0 && p.y < item.getHeight()) { + if (e.getID() == MouseEvent.MOUSE_RELEASED) { + manager.clearSelectedPath(); + item.doClick(0); + item.setArmed(false); + } else + manager.setSelectedPath(path); + } else if (item.getModel().isArmed()) { + MenuElement newPath[] = new MenuElement[path.length - 1]; + int i, c; + for (i = 0, c = path.length - 1; i < c; i++) + newPath[i] = path[i]; + manager.setSelectedPath(newPath); + } + } + + protected void paintMenuItem(Graphics g, JComponent c, + Icon checkIcon, Icon arrowIcon, + Color background, Color foreground, + int defaultTextIconGap) { + // Save original graphics font and color + Font holdf = g.getFont(); + Color holdc = g.getColor(); + + JMenuItem mi = (JMenuItem) c; + g.setFont(mi.getFont()); + + Rectangle viewRect = new Rectangle(0, 0, mi.getWidth(), mi.getHeight()); + applyInsets(viewRect, mi.getInsets()); + + MenuItemLayoutHelper lh = new MenuItemLayoutHelper(mi, checkIcon, + arrowIcon, viewRect, defaultTextIconGap, "-", //todo[kb] use protected field BasicMenuItemUI.acceleratorDelimiter when we move to java 1.7 + mi.getComponentOrientation().isLeftToRight(), mi.getFont(), + acceleratorFont, MenuItemLayoutHelper.useCheckAndArrow(menuItem), + getPropertyPrefix()); + MenuItemLayoutHelper.LayoutResult lr = lh.layoutMenuItem(); + + paintBackground(g, mi, background); + paintCheckIcon(g, lh, lr, holdc, foreground); + paintIcon(g, lh, lr, holdc); + g.setColor(foreground); + paintText(g, lh, lr); + paintAccText(g, lh, lr); + paintArrowIcon(g, lh, lr, foreground); + + // Restore original graphics font and color + g.setColor(holdc); + g.setFont(holdf); + } + + protected void paintIcon(Graphics g, MenuItemLayoutHelper lh, + MenuItemLayoutHelper.LayoutResult lr, Color holdc) { + if (lh.getIcon() != null) { + Icon icon; + ButtonModel model = lh.getMenuItem().getModel(); + if (!model.isEnabled()) { + icon = lh.getMenuItem().getDisabledIcon(); + } else if (model.isPressed() && model.isArmed()) { + icon = lh.getMenuItem().getPressedIcon(); + if (icon == null) { + // Use default icon + icon = lh.getMenuItem().getIcon(); + } + } else { + icon = lh.getMenuItem().getIcon(); + } + + if (icon != null) { + icon.paintIcon(lh.getMenuItem(), g, lr.getIconRect().x, + lr.getIconRect().y); + g.setColor(holdc); + } + } + } + + protected void paintCheckIcon(Graphics g, MenuItemLayoutHelper lh, + MenuItemLayoutHelper.LayoutResult lr, + Color holdc, Color foreground) { + if (lh.getCheckIcon() != null) { + ButtonModel model = lh.getMenuItem().getModel(); + if (model.isArmed() || (lh.getMenuItem() instanceof JMenu + && model.isSelected())) { + g.setColor(foreground); + } else { + g.setColor(holdc); + } + if (lh.useCheckAndArrow()) { + lh.getCheckIcon().paintIcon(lh.getMenuItem(), g, + lr.getCheckRect().x, lr.getCheckRect().y); + } + g.setColor(holdc); + } + } + + protected void paintAccText(Graphics g, MenuItemLayoutHelper lh, + MenuItemLayoutHelper.LayoutResult lr) { + if (!lh.getAccText().equals("")) { + ButtonModel model = lh.getMenuItem().getModel(); + g.setFont(lh.getAccFontMetrics().getFont()); + if (!model.isEnabled()) { + // *** paint the accText disabled + if (disabledForeground != null) { + g.setColor(disabledForeground); + SwingUtilities2.drawString(lh.getMenuItem(), g, + lh.getAccText(), lr.getAccRect().x, + lr.getAccRect().y + lh.getAccFontMetrics().getAscent()); + } else { + g.setColor(lh.getMenuItem().getBackground().brighter()); + SwingUtilities2.drawString(lh.getMenuItem(), g, + lh.getAccText(), lr.getAccRect().x, + lr.getAccRect().y + lh.getAccFontMetrics().getAscent()); + g.setColor(lh.getMenuItem().getBackground().darker()); + SwingUtilities2.drawString(lh.getMenuItem(), g, + lh.getAccText(), lr.getAccRect().x - 1, + lr.getAccRect().y + lh.getFontMetrics().getAscent() - 1); + } + } else { + // *** paint the accText normally + if (model.isArmed() + || (lh.getMenuItem() instanceof JMenu + && model.isSelected())) { + g.setColor(acceleratorSelectionForeground); + } else { + g.setColor(acceleratorForeground); + } + SwingUtilities2.drawString(lh.getMenuItem(), g, lh.getAccText(), + lr.getAccRect().x, lr.getAccRect().y + + lh.getAccFontMetrics().getAscent()); + } + } + } + + protected void paintText(Graphics g, MenuItemLayoutHelper lh, + MenuItemLayoutHelper.LayoutResult lr) { + if (!lh.getText().equals("")) { + if (lh.getHtmlView() != null) { + // Text is HTML + lh.getHtmlView().paint(g, lr.getTextRect()); + } else { + // Text isn't HTML + paintText(g, lh.getMenuItem(), lr.getTextRect(), lh.getText()); + } + } + } + + protected void paintArrowIcon(Graphics g, MenuItemLayoutHelper lh, + MenuItemLayoutHelper.LayoutResult lr, + Color foreground) { + if (lh.getArrowIcon() != null) { + ButtonModel model = lh.getMenuItem().getModel(); + if (model.isArmed() || (lh.getMenuItem() instanceof JMenu + && model.isSelected())) { + g.setColor(foreground); + } + if (lh.useCheckAndArrow()) { + lh.getArrowIcon().paintIcon(lh.getMenuItem(), g, + lr.getArrowRect().x, lr.getArrowRect().y); + } + } + } + + protected void applyInsets(Rectangle rect, Insets insets) { + if(insets != null) { + rect.x += insets.left; + rect.y += insets.top; + rect.width -= (insets.right + rect.x); + rect.height -= (insets.bottom + rect.y); + } + } +} diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonMenuItemUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonMenuItemUI.java new file mode 100644 index 000000000000..1048e5d0449b --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonMenuItemUI.java @@ -0,0 +1,85 @@ +/* + * 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.ide.ui.laf.darcula.ui; + +import com.intellij.openapi.ui.GraphicsConfig; +import com.intellij.ui.ColorUtil; +import com.intellij.ui.Gray; +import sun.swing.MenuItemLayoutHelper; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import java.awt.*; + +/** + * @author Konstantin Bulenkov + */ +public class DarculaRadioButtonMenuItemUI extends DarculaMenuItemUIBase { + @SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"}) + public static ComponentUI createUI(JComponent c) { + return new DarculaRadioButtonMenuItemUI(); + } + + protected String getPropertyPrefix() { + return "RadioButtonMenuItem"; + } + + @Override + protected void paintCheckIcon(Graphics g2, MenuItemLayoutHelper lh, MenuItemLayoutHelper.LayoutResult lr, Color holdc, Color foreground) { + Graphics2D g = (Graphics2D) g2; + final GraphicsConfig config = new GraphicsConfig(g); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT); + + g.translate(lr.getCheckRect().x-1, lr.getCheckRect().y-1); + + int rad = 5; + + final int x = 0; + final int y = 0; + final int w = 13; + final int h = 13; + + g.translate(x, y); + + //setup AA for lines + Color bg = lh.getMenuItem().getBackground(); + g.setPaint(new GradientPaint(0, 0, ColorUtil.shift(bg, 1.5), + 0, 16, ColorUtil.shift(bg, 1.2))); + + g.fillOval(0, 1, w - 1, h - 1); + + g.setPaint(new GradientPaint(w / 2, 1, Gray._160.withAlpha(90), w / 2, h, Gray._100.withAlpha(90))); + g.drawOval(0, 2, w - 1, h - 1); + + g.setPaint(Gray._40.withAlpha(200)); + g.drawOval(0, 1, w - 1, h - 1); + + if (lh.getMenuItem().isSelected()) { + final boolean enabled = lh.getMenuItem().isEnabled(); + g.setColor(UIManager.getColor(enabled ? "RadioButton.darcula.selectionEnabledShadowColor" : "RadioButton.darcula.selectionDisabledShadowColor")); + g.fillOval((w - rad)/2 , h/2 , rad, rad); + g.setColor(UIManager.getColor(enabled ? "RadioButton.darcula.selectionEnabledColor" : "RadioButton.darcula.selectionDisabledColor")); + g.fillOval((w - rad)/2 , h/2 - 1, rad, rad); + } + config.restore(); + g.translate(-x, -y); + + + g.translate(-lr.getCheckRect().x+1, -lr.getCheckRect().y+1); + config.restore(); + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretAbove.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretAbove.java index f8b3cf7bc83a..c42cd6533e1c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretAbove.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretAbove.java @@ -15,31 +15,10 @@ */ package com.intellij.openapi.editor.actions; -import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.editor.Caret; -import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.actionSystem.EditorAction; -import com.intellij.openapi.editor.actionSystem.EditorActionHandler; -import org.jetbrains.annotations.NotNull; public class CloneCaretAbove extends EditorAction { public CloneCaretAbove() { - super(new Handler()); - } - - private static class Handler extends EditorActionHandler { - public Handler() { - super(true); - } - - @Override - public void doExecute(Editor editor, @NotNull Caret caret, DataContext dataContext) { - caret.clone(true); - } - - @Override - public boolean isEnabled(Editor editor, DataContext dataContext) { - return editor.getCaretModel().supportsMultipleCarets(); - } + super(new CloneCaretActionHandler(true)); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretActionHandler.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretActionHandler.java new file mode 100644 index 000000000000..5c5528a38153 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretActionHandler.java @@ -0,0 +1,113 @@ +/* + * 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.openapi.editor.actions; + +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.actionSystem.IdeActions; +import com.intellij.openapi.editor.Caret; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.EditorLastActionTracker; +import com.intellij.openapi.editor.ScrollType; +import com.intellij.openapi.editor.actionSystem.EditorActionHandler; +import com.intellij.openapi.util.Key; +import com.intellij.util.containers.HashSet; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +public class CloneCaretActionHandler extends EditorActionHandler { + private static final Key LEVEL = Key.create("CloneCaretActionHandler.level"); + + private static final Set OUR_ACTIONS = new HashSet(Arrays.asList( + IdeActions.ACTION_EDITOR_CLONE_CARET_ABOVE, + IdeActions.ACTION_EDITOR_CLONE_CARET_BELOW, + IdeActions.ACTION_EDITOR_MOVE_CARET_LEFT_WITH_SELECTION, + IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT_WITH_SELECTION + )); + + private final boolean myCloneAbove; + + public CloneCaretActionHandler(boolean above) { + myCloneAbove = above; + } + + @Override + public boolean isEnabled(Editor editor, DataContext dataContext) { + return editor.getCaretModel().supportsMultipleCarets(); + } + + @Override + protected void doExecute(Editor editor, @Nullable Caret targetCaret, DataContext dataContext) { + if (targetCaret != null) { + targetCaret.clone(myCloneAbove); + return; + } + int currentLevel = 0; + List currentCarets = new ArrayList(); + for (Caret caret : editor.getCaretModel().getAllCarets()) { + int level = getLevel(caret); + if (Math.abs(level) > Math.abs(currentLevel)) { + currentLevel = level; + currentCarets.clear(); + } + if (Math.abs(level) == Math.abs(currentLevel)) { + currentCarets.add(caret); + } + } + boolean removeCarets = currentLevel > 0 && myCloneAbove || currentLevel < 0 && !myCloneAbove; + Integer newLevel = myCloneAbove ? currentLevel - 1 : currentLevel + 1; + for (Caret caret : currentCarets) { + if (removeCarets) { + editor.getCaretModel().removeCaret(caret); + } + else { + Caret clone = caret; + do { + Caret original = clone; + clone = clone.clone(myCloneAbove); + if (original != caret) { + editor.getCaretModel().removeCaret(original); + } + } while (clone != null && caret.hasSelection() && !clone.hasSelection()); + if (clone != null) { + clone.putUserData(LEVEL, newLevel); + } + } + } + if (removeCarets) { + editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); + } + } + + private static int getLevel(Caret caret) { + if (isRepeatedActionInvocation()) { + Integer value = caret.getUserData(LEVEL); + return value == null ? 0 : value; + } + else { + caret.putUserData(LEVEL, null); + return 0; + } + } + + private static boolean isRepeatedActionInvocation() { + String lastActionId = EditorLastActionTracker.getInstance().getLastActionId(); + return OUR_ACTIONS.contains(lastActionId); + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretBelow.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretBelow.java index 17d17708b900..974087796e08 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretBelow.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretBelow.java @@ -15,35 +15,10 @@ */ 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.actionSystem.EditorAction; -import com.intellij.openapi.editor.actionSystem.EditorActionHandler; -import org.jetbrains.annotations.NotNull; public class CloneCaretBelow extends EditorAction { public CloneCaretBelow() { - super(new Handler()); - } - - private static class Handler extends EditorActionHandler { - public Handler() { - super(true); - } - - @Override - public void doExecute(Editor editor, @NotNull Caret caret, DataContext dataContext) { - CaretModel caretModel = editor.getCaretModel(); - if (caretModel.supportsMultipleCarets()) { - caret.clone(false); - } - } - - @Override - public boolean isEnabled(Editor editor, DataContext dataContext) { - return editor.getCaretModel().supportsMultipleCarets(); - } + super(new CloneCaretActionHandler(false)); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java index cfd039a5d504..c769f92fff78 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java @@ -62,7 +62,13 @@ public class CaretImpl extends UserDataHolderBase implements Caret { private int myVisualLineEnd; private RangeMarker savedBeforeBulkCaretMarker; private boolean mySkipChangeRequests; + /** + * Initial horizontal caret position during vertical navigation. + * Similar to {@link #myDesiredX}, but represents logical caret position (getLogicalPosition().column) rather than visual. + */ private int myLastColumnNumber = 0; + private int myDesiredSelectionStartColumn = -1; + private int myDesiredSelectionEndColumn = -1; /** * We check that caret is located at the target offset at the end of {@link #moveToOffset(int, boolean)} method. However, * it's possible that the following situation occurs: @@ -82,11 +88,10 @@ public class CaretImpl extends UserDataHolderBase implements Caret { */ private boolean myReportCaretMoves; /** - * There is a possible case that user defined non-monospaced font for editor. That means that various symbols have different - * visual widths. That means that if we move caret vertically it may deviate to the left/right. However, we can try to preserve - * its initial visual position when possible. + * This field holds initial horizontal caret position during vertical navigation. It's used to determine target position when + * moving to the new line. It is stored in pixels, not in columns, to account for non-monospaced fonts as well. *

- * This field holds desired value for visual 'x' caret coordinate (negative value if no coordinate should be preserved). + * Negative value means no coordinate should be preserved. */ private int myDesiredX = -1; @@ -255,10 +260,11 @@ public class CaretImpl extends UserDataHolderBase implements Caret { EditorSettings editorSettings = myEditor.getSettings(); VisualPosition visualCaret = getVisualPosition(); + int lastColumnNumber = myLastColumnNumber; int desiredX = myDesiredX; if (columnShift == 0) { if (myDesiredX < 0) { - desiredX = myEditor.visualPositionToXY(visualCaret).x; + desiredX = getCurrentX(); } } else { @@ -267,15 +273,12 @@ public class CaretImpl extends UserDataHolderBase implements Caret { int newLineNumber = visualCaret.line + lineShift; int newColumnNumber = visualCaret.column + columnShift; - if (desiredX >= 0 && !ApplicationManager.getApplication().isUnitTestMode()) { + if (desiredX >= 0) { newColumnNumber = myEditor.xyToVisualPosition(new Point(desiredX, Math.max(0, newLineNumber) * myEditor.getLineHeight())).column; } Document document = myEditor.getDocument(); - if (!editorSettings.isVirtualSpace() && columnShift == 0 && getLogicalPosition().softWrapLinesOnCurrentLogicalLine <= 0) { - newColumnNumber = supportsMultipleCarets() ? myLastColumnNumber : myEditor.getLastColumnNumber(); - } - else if (!editorSettings.isVirtualSpace() && lineShift == 0 && columnShift == 1) { + if (!editorSettings.isVirtualSpace() && lineShift == 0 && columnShift == 1) { int lastLine = document.getLineCount() - 1; if (lastLine < 0) lastLine = 0; if (EditorModificationUtil.calcAfterLineEnd(myEditor) >= 0 && @@ -303,18 +306,21 @@ public class CaretImpl extends UserDataHolderBase implements Caret { // We want to move caret to the first column if it's already located at the first line and 'Up' is pressed. newColumnNumber = 0; desiredX = -1; + lastColumnNumber = -1; } VisualPosition pos = new VisualPosition(newLineNumber, newColumnNumber); - int lastColumnNumber = newColumnNumber; if (!myEditor.getSoftWrapModel().isInsideSoftWrap(pos)) { LogicalPosition log = myEditor.visualToLogicalPosition(new VisualPosition(newLineNumber, newColumnNumber)); int offset = myEditor.logicalPositionToOffset(log); if (offset >= document.getTextLength()) { int lastOffsetColumn = myEditor.offsetToVisualPosition(document.getTextLength()).column; // We want to move caret to the last column if if it's located at the last line and 'Down' is pressed. - newColumnNumber = lastColumnNumber = Math.max(lastOffsetColumn, newColumnNumber); - desiredX = -1; + if (lastOffsetColumn > newColumnNumber) { + newColumnNumber = lastOffsetColumn; + desiredX = -1; + lastColumnNumber = -1; + } } if (!editorSettings.isCaretInsideTabs()) { CharSequence text = document.getCharsSequence(); @@ -353,7 +359,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { } else { moveToVisualPosition(pos); - if (!editorSettings.isVirtualSpace() && columnShift == 0) { + if (!editorSettings.isVirtualSpace() && columnShift == 0 && lastColumnNumber >=0) { setLastColumnNumber(lastColumnNumber); } } @@ -550,6 +556,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { } setLastColumnNumber(myLogicalCaret.column); + myDesiredSelectionStartColumn = myDesiredSelectionEndColumn = -1; myVisibleCaret = myEditor.logicalToVisualPosition(myLogicalCaret); updateOffsetsFromLogicalPosition(); @@ -705,7 +712,8 @@ public class CaretImpl extends UserDataHolderBase implements Caret { myEditor.getFoldingModel().flushCaretPosition(); - setLastColumnNumber(column); + setLastColumnNumber(myLogicalCaret.column); + myDesiredSelectionStartColumn = myDesiredSelectionEndColumn = -1; myEditor.updateCaretCursor(); requestRepaint(oldInfo); @@ -962,6 +970,8 @@ public class CaretImpl extends UserDataHolderBase implements Caret { clone.myLastColumnNumber = this.myLastColumnNumber; clone.myReportCaretMoves = this.myReportCaretMoves; clone.myDesiredX = this.myDesiredX; + clone.myDesiredSelectionStartColumn = -1; + clone.myDesiredSelectionEndColumn = -1; return clone; } @@ -971,10 +981,10 @@ public class CaretImpl extends UserDataHolderBase implements Caret { assertIsDispatchThread(); int lineShift = above ? -1 : 1; final CaretImpl clone = cloneWithoutSelection(); - final int newSelectionStartOffset, newSelectionEndOffset; + final int newSelectionStartOffset, newSelectionEndOffset, newSelectionStartColumn, newSelectionEndColumn; final VisualPosition newSelectionStartPosition, newSelectionEndPosition; final boolean hasNewSelection; - if (hasSelection()) { + if (hasSelection() || myDesiredSelectionStartColumn >=0 || myDesiredSelectionEndColumn >= 0) { VisualPosition startPosition = getSelectionStartPosition(); VisualPosition endPosition = getSelectionEndPosition(); VisualPosition leadPosition = getLeadSelectionPosition(); @@ -982,8 +992,10 @@ public class CaretImpl extends UserDataHolderBase implements Caret { boolean leadIsEnd = leadPosition.equals(endPosition); LogicalPosition selectionStart = myEditor.visualToLogicalPosition(leadIsStart || leadIsEnd ? leadPosition : startPosition); LogicalPosition selectionEnd = myEditor.visualToLogicalPosition(leadIsEnd ? startPosition : endPosition); - LogicalPosition newSelectionStart = truncate(new LogicalPosition(selectionStart.line + lineShift, selectionStart.column)); - LogicalPosition newSelectionEnd = truncate(new LogicalPosition(selectionEnd.line + lineShift, selectionEnd.column)); + newSelectionStartColumn = myDesiredSelectionStartColumn < 0 ? selectionStart.column : myDesiredSelectionStartColumn; + newSelectionEndColumn = myDesiredSelectionEndColumn < 0 ? selectionEnd.column : myDesiredSelectionEndColumn; + LogicalPosition newSelectionStart = truncate(selectionStart.line + lineShift, newSelectionStartColumn); + LogicalPosition newSelectionEnd = truncate(selectionEnd.line + lineShift, newSelectionEndColumn); newSelectionStartOffset = myEditor.logicalPositionToOffset(newSelectionStart); newSelectionEndOffset = myEditor.logicalPositionToOffset(newSelectionEnd); newSelectionStartPosition = myEditor.logicalToVisualPosition(newSelectionStart); @@ -996,6 +1008,8 @@ public class CaretImpl extends UserDataHolderBase implements Caret { newSelectionStartPosition = null; newSelectionEndPosition = null; hasNewSelection = false; + newSelectionStartColumn = -1; + newSelectionEndColumn = -1; } LogicalPosition oldPosition = getLogicalPosition(); int newLine = oldPosition.line + lineShift; @@ -1003,7 +1017,12 @@ public class CaretImpl extends UserDataHolderBase implements Caret { Disposer.dispose(clone); return null; } - clone.moveToLogicalPosition(new LogicalPosition(newLine, oldPosition.column), false, null, false); + clone.moveToLogicalPosition(new LogicalPosition(newLine, myLastColumnNumber), false, null, false); + clone.myLastColumnNumber = myLastColumnNumber; + clone.myDesiredX = myDesiredX >= 0 ? myDesiredX : getCurrentX(); + clone.myDesiredSelectionStartColumn = newSelectionStartColumn; + clone.myDesiredSelectionEndColumn = newSelectionEndColumn; + if (myEditor.getCaretModel().addCaret(clone)) { if (hasNewSelection) { myEditor.getCaretModel().doWithCaretMerging(new Runnable() { @@ -1025,15 +1044,15 @@ public class CaretImpl extends UserDataHolderBase implements Caret { } } - private LogicalPosition truncate(LogicalPosition position) { - if (position.line < 0) { + private LogicalPosition truncate(int line, int column) { + if (line < 0) { return new LogicalPosition(0, 0); } - else if (position.line >= myEditor.getDocument().getLineCount()) { + else if (line >= myEditor.getDocument().getLineCount()) { return myEditor.offsetToLogicalPosition(myEditor.getDocument().getTextLength()); } else { - return position; + return new LogicalPosition(line, column); } } @@ -1396,9 +1415,8 @@ public class CaretImpl extends UserDataHolderBase implements Caret { } try { - EditorActionHandler handler = EditorActionManager.getInstance().getActionHandler( - IdeActions.ACTION_EDITOR_SELECT_WORD_AT_CARET); - handler.execute(myEditor, myEditor.getDataContext()); + EditorActionHandler handler = EditorActionManager.getInstance().getActionHandler(IdeActions.ACTION_EDITOR_SELECT_WORD_AT_CARET); + handler.execute(myEditor, CaretImpl.this, myEditor.getDataContext()); } finally { if (needOverrideSetting) { @@ -1453,6 +1471,10 @@ public class CaretImpl extends UserDataHolderBase implements Caret { return marker != null && marker.isValid() && isVirtualSelectionEnabled() && myEndVirtualOffset > myStartVirtualOffset; } + private int getCurrentX() { + return myEditor.visualPositionToXY(myVisibleCaret).x; + } + @Override @NotNull public EditorImpl getEditor() { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java index 6f1b9820132b..d8b6697dc8d1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java @@ -303,14 +303,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi if (!isSoftWrappingEnabled()) { return 0; } - int result = 0; - FoldingModel foldingModel = myEditor.getFoldingModel(); - for (SoftWrap softWrap : myStorage.getSoftWraps()) { - if (!foldingModel.isOffsetCollapsed(softWrap.getStart())) { - result++; // Assuming that soft wrap has single line feed all the time - } - } - return result; + return myStorage.getSoftWraps().size(); // Assuming that soft wrap has single line feed all the time } /** diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java index 3519ab6a1af4..14b2afe16345 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java @@ -34,6 +34,7 @@ import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Splitter; +import com.intellij.openapi.ui.ThreeComponentsSplitter; import com.intellij.openapi.util.*; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; @@ -319,6 +320,16 @@ public class EditorWindow { if (disposeIfNeeded && getTabCount() == 0) { removeFromSplitter(); + if (UISettings.getInstance().EDITOR_TAB_PLACEMENT == UISettings.TABS_NONE) { + final EditorsSplitters owner = getOwner(); + if (owner != null) { + final ThreeComponentsSplitter splitter = UIUtil.getParentOfType(ThreeComponentsSplitter.class, owner); + if (splitter != null) { + splitter.revalidate(); + splitter.repaint(); + } + } + } } else { myPanel.revalidate(); diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java index 7b4f5a0371ba..7c65a805ee6c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java @@ -99,8 +99,8 @@ public class KeymapManagerImpl extends KeymapManagerEx implements PersistentStat if (Registry.is("editor.add.carets.on.double.control.arrows")) { ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_CLONE_CARET_ABOVE, KeyEvent.VK_CONTROL, KeyEvent.VK_UP); ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_CLONE_CARET_BELOW, KeyEvent.VK_CONTROL, KeyEvent.VK_DOWN); - ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_MOVE_CARET_LEFT, KeyEvent.VK_CONTROL, KeyEvent.VK_LEFT); - ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT, KeyEvent.VK_CONTROL, KeyEvent.VK_RIGHT); + ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_MOVE_CARET_LEFT_WITH_SELECTION, KeyEvent.VK_CONTROL, KeyEvent.VK_LEFT); + ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT_WITH_SELECTION, KeyEvent.VK_CONTROL, KeyEvent.VK_RIGHT); } ourKeymapManagerInitialized = true; diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java index 7e7505055ad9..13a8aaecb724 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java @@ -17,10 +17,10 @@ package com.intellij.openapi.keymap.impl; import com.intellij.ide.DataManager; import com.intellij.ide.IdeEventQueue; -import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.ActionPlaces; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.ex.ActionManagerEx; import com.intellij.openapi.keymap.KeymapManager; import com.intellij.openapi.util.Clock; import com.intellij.openapi.util.Couple; @@ -196,7 +196,7 @@ public class ModifierKeyDoubleClickHandler { } private void run(KeyEvent event) { - final ActionManager actionManager = ActionManager.getInstance(); + final ActionManagerEx actionManager = ActionManagerEx.getInstanceEx(); final AnAction action = actionManager.getAction(myActionId); final AnActionEvent anActionEvent = new AnActionEvent(event, DataManager.getInstance().getDataContext(IdeFocusManager.findInstance().getFocusOwner()), @@ -204,7 +204,9 @@ public class ModifierKeyDoubleClickHandler { action.getTemplatePresentation(), actionManager, 0); + actionManager.fireBeforeActionPerformed(action, anActionEvent.getDataContext(), anActionEvent); action.actionPerformed(anActionEvent); + actionManager.fireAfterActionPerformed(action, anActionEvent.getDataContext(), anActionEvent); } private boolean isActionBound() { diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java index efaf84d08b8e..98c3884cc993 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java @@ -22,6 +22,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.NotNullLazyValue; +import com.intellij.openapi.util.ShutDownTracker; import com.intellij.openapi.util.io.FileAttributes; import com.intellij.openapi.util.io.FileSystemUtil; import com.intellij.openapi.util.io.FileUtil; @@ -30,6 +31,7 @@ import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VfsBundle; import com.intellij.openapi.vfs.impl.ZipHandler; import com.intellij.openapi.vfs.newvfs.persistent.FSRecords; +import com.intellij.openapi.vfs.newvfs.persistent.FlushingDaemon; import com.intellij.util.io.DataExternalizer; import com.intellij.util.io.EnumeratorStringDescriptor; import com.intellij.util.io.IOUtil; @@ -169,7 +171,6 @@ public class JarHandler extends ZipHandler { info = new CacheLibraryInfo(mirrorFile.getName(), originalAttributes.lastModified, originalAttributes.length); CacheLibraryInfo.ourCachedLibraryInfo.put(path, info); - CacheLibraryInfo.ourCachedLibraryInfo.force(); return mirrorFile; } catch (IOException ex) { @@ -260,6 +261,23 @@ public class JarHandler extends ZipHandler { } assert info != null; ourCachedLibraryInfo = info; + FlushingDaemon.everyFiveSeconds(new Runnable() { + @Override + public void run() { + flushCachedLibraryInfos(); + } + }); + + ShutDownTracker.getInstance().registerShutdownTask(new Runnable() { + @Override + public void run() { + flushCachedLibraryInfos(); + } + }); + } + + private static void flushCachedLibraryInfos() { + if (ourCachedLibraryInfo.isDirty()) ourCachedLibraryInfo.force(); } private CacheLibraryInfo(@NotNull String path, long time, long length) { diff --git a/platform/platform-resources/src/brokenPlugins.txt b/platform/platform-resources/src/brokenPlugins.txt index a202e8f79519..57b863fb916b 100644 --- a/platform/platform-resources/src/brokenPlugins.txt +++ b/platform/platform-resources/src/brokenPlugins.txt @@ -15,5 +15,4 @@ SBT 1.0.0 1.1.0 1.2.0 1.3.0 1.3.1 1.4.0 1.5.0 "JSTestDriver Plugin" 138.21 136.1141 134.1163 134.686 134.31 134.307 134.1039 AngularJS 134.1094 0.1.8 0.1.9 org.jetbrains.plugins.vagrant 0.1 0.2 -org.intellij.clojure 0.2.1.178 -com.jetbrains.chronon 134.1221 134.1414 134.1618 135.476 135.666 \ No newline at end of file +org.intellij.clojure 0.2.1.178 \ No newline at end of file diff --git a/platform/platform-tests/testSrc/com/intellij/lang/PsiBuilderQuickTest.java b/platform/platform-tests/testSrc/com/intellij/lang/PsiBuilderQuickTest.java index 5390ee8eb228..db833c2d8f3e 100644 --- a/platform/platform-tests/testSrc/com/intellij/lang/PsiBuilderQuickTest.java +++ b/platform/platform-tests/testSrc/com/intellij/lang/PsiBuilderQuickTest.java @@ -461,6 +461,27 @@ public class PsiBuilderQuickTest extends LightPlatformLangTestCase { " PsiElement(OTHER)('}')\n"); } + public void testEndMarkersOverlapping() { + doTest("a ", + new Parser() { + @Override + public void parse(PsiBuilder builder) { + PsiBuilder.Marker e1 = builder.mark(); + PsiBuilder.Marker e2 = builder.mark(); + builder.advanceLexer(); + e2.done(OTHER); + e2.setCustomEdgeTokenBinders(null, WhitespacesBinders.GREEDY_RIGHT_BINDER); + e1.done(OTHER); + e1.setCustomEdgeTokenBinders(null, WhitespacesBinders.DEFAULT_RIGHT_BINDER); + assertTrue(builder.eof()); + } + }, + "Element(ROOT)\n" + + " Element(OTHER)\n" + + " Element(OTHER)\n" + + " PsiElement(LETTER)('a')\n" + + " PsiWhiteSpace(' ')\n"); + } private interface Parser { void parse(PsiBuilder builder); diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorCloneCaretAboveBelowTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorCloneCaretAboveBelowTest.java new file mode 100644 index 000000000000..2d73640ff655 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorCloneCaretAboveBelowTest.java @@ -0,0 +1,106 @@ +/* + * 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.openapi.editor.actions; + +import com.intellij.openapi.actionSystem.IdeActions; +import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; + +public class EditorCloneCaretAboveBelowTest extends LightPlatformCodeInsightFixtureTestCase { + public void testStoringDesiredXPosition() { + init("long line\n" + + "line\n" + + "long line\n" + + "very long line"); + cloneCaretBelow(); + checkResult("long line\n" + + "line\n" + + "long line\n" + + "very long line"); + cloneCaretBelow(); + checkResult("long line\n" + + "line\n" + + "long line\n" + + "very long line"); + cloneCaretBelow(); + checkResult("long line\n" + + "line\n" + + "long line\n" + + "very long line"); + } + + public void testCloneAndMove() { + init("long line\n" + + "line\n" + + "long line"); + cloneCaretBelow(); + moveCaretDown(); + checkResult("long line\n" + + "line\n" + + "long line"); + } + + public void testCloneBelowAndAbove() { + init("line\n" + + "line\n" + + "line"); + cloneCaretBelow(); + checkResult("line\n" + + "line\n" + + "line"); + cloneCaretAbove(); + checkResult("line\n" + + "line\n" + + "line"); + cloneCaretAbove(); + checkResult("line\n" + + "line\n" + + "line"); + cloneCaretBelow(); + checkResult("line\n" + + "line\n" + + "line"); + } + + public void testCloneWithSelection() { + init("long line\n" + + "line\n" + + "long line"); + cloneCaretBelow(); + checkResult("long line\n" + + "line\n" + + "long line"); + } + + private void cloneCaretBelow() { + myFixture.performEditorAction(IdeActions.ACTION_EDITOR_CLONE_CARET_BELOW); + } + + private void cloneCaretAbove() { + myFixture.performEditorAction(IdeActions.ACTION_EDITOR_CLONE_CARET_ABOVE); + } + + private void moveCaretDown() { + myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_DOWN); + } + + private void init(String text) { + myFixture.configureByText(getTestName(false) + ".txt", text); + } + + private void checkResult(String text) { + myFixture.checkResult(text); + } +} diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorTest.java index 5dd8bbb8c424..fd774b5e817d 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorTest.java @@ -34,6 +34,7 @@ import java.util.Arrays; import java.util.List; import java.util.Scanner; import java.util.regex.MatchResult; +import java.util.regex.Matcher; import java.util.regex.Pattern; import static org.junit.Assert.assertArrayEquals; @@ -94,6 +95,20 @@ public abstract class AbstractEditorTest extends LightPlatformCodeInsightTestCas )); } + protected static void foldOccurrences(String textToFoldRegexp, final String placeholder) { + final Matcher matcher = Pattern.compile(textToFoldRegexp).matcher(myEditor.getDocument().getCharsSequence()); + myEditor.getFoldingModel().runBatchFoldingOperation(new Runnable() { + @Override + public void run() { + while(matcher.find()) { + FoldRegion foldRegion = myEditor.getFoldingModel().addFoldRegion(matcher.start(), matcher.end(), placeholder); + assertNotNull(foldRegion); + foldRegion.setExpanded(false); + } + } + }); + } + /** * Setups document of the {@link #getEditor() current editor} according to the given text that is expected to contain * information about document lines obtained from the {@link DocumentImpl#dumpState()}. diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java index 5a9d4da33219..ff1256d173d2 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java @@ -16,6 +16,7 @@ package com.intellij.openapi.editor.impl; import com.intellij.codeInsight.folding.CodeFoldingManager; +import com.intellij.openapi.actionSystem.IdeActions; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.VisualPosition; import com.intellij.testFramework.EditorTestUtil; @@ -65,6 +66,20 @@ public class EditorImplTest extends AbstractEditorTest { verifySoftWrapPositions(58, 93); } + public void testCorrectVisibleLineCountCalculation() throws Exception { + init("line containing FOLDED_REGION\n" + + "next line\n" + + "last line"); + foldOccurrences("FOLDED_REGION", "..."); + EditorTestUtil.configureSoftWraps(myEditor, 16); // wrap right at folded region start + verifySoftWrapPositions(16); + + executeAction(IdeActions.ACTION_EDITOR_MOVE_CARET_DOWN); + checkResultByText("line containing FOLDED_REGION\n" + + "next line\n" + + "last line"); + } + private void init(String text) throws IOException { configureFromFileText(getTestName(false) + ".txt", text); } diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java index f12e646a72b9..8ed6e68b1915 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java @@ -20,8 +20,6 @@ import java.util.Map; */ public class ServerConnectionManagerImpl extends ServerConnectionManager { - private static final int POLL_DEPLOYMENTS_DELAY = 2000; - private final Map, ServerConnection> myConnections = new HashMap, ServerConnection>(); private final ServerConnectionEventDispatcher myEventDispatcher = new ServerConnectionEventDispatcher(); @@ -34,29 +32,10 @@ public class ServerConnectionManagerImpl extends ServerConnectionManager { connection = doCreateConnection(server, this); myConnections.put(server, connection); myEventDispatcher.fireConnectionCreated(connection); - pollDeployments(connection); } return connection; } - private void pollDeployments(final ServerConnection connection) { - connection.computeDeployments(new Runnable() { - - @Override - public void run() { - new Alarm().addRequest(new Runnable() { - - @Override - public void run() { - if (connection == getConnection(connection.getServer())) { - pollDeployments(connection); - } - } - }, POLL_DEPLOYMENTS_DELAY, ModalityState.any()); - } - }); - } - @NotNull @Override public ServerConnection createTemporaryConnection(@NotNull RemoteServer server) { diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/ServersToolWindowContent.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/ServersToolWindowContent.java index 7a1f27f3b8ee..8a46887be6cf 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/ServersToolWindowContent.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/ServersToolWindowContent.java @@ -6,6 +6,7 @@ import com.intellij.ide.util.treeView.AbstractTreeNode; import com.intellij.ide.util.treeView.NodeDescriptor; import com.intellij.ide.util.treeView.NodeRenderer; import com.intellij.ide.util.treeView.TreeVisitor; +import com.intellij.openapi.application.ModalityState; import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeStructure; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; @@ -13,7 +14,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Splitter; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.EmptyRunnable; import com.intellij.remoteServer.configuration.RemoteServer; import com.intellij.remoteServer.impl.runtime.log.LoggingHandlerImpl; import com.intellij.remoteServer.impl.runtime.ui.tree.DeploymentNode; @@ -28,6 +28,7 @@ import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.SideBorder; import com.intellij.ui.components.panels.Wrapper; import com.intellij.ui.treeStructure.Tree; +import com.intellij.util.Alarm; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -56,6 +57,8 @@ public class ServersToolWindowContent extends JPanel implements Disposable { private static final String MESSAGE_CARD = "message"; private static final String EMPTY_SELECTION_MESSAGE = "Select a server or deployment in the tree to view details"; + private static final int POLL_DEPLOYMENTS_DELAY = 2000; + private final Tree myTree; private final CardLayout myPropertiesPanelLayout; private final JPanel myPropertiesPanel; @@ -188,6 +191,7 @@ public class ServersToolWindowContent extends JPanel implements Disposable { @Override public void onConnectionCreated(@NotNull ServerConnection connection) { getBuilder().queueUpdate(); + pollDeployments(connection); } @Override @@ -210,6 +214,24 @@ public class ServersToolWindowContent extends JPanel implements Disposable { } } + private static void pollDeployments(final ServerConnection connection) { + connection.computeDeployments(new Runnable() { + + @Override + public void run() { + new Alarm().addRequest(new Runnable() { + + @Override + public void run() { + if (connection == ServerConnectionManager.getInstance().getConnection(connection.getServer())) { + pollDeployments(connection); + } + } + }, POLL_DEPLOYMENTS_DELAY, ModalityState.any()); + } + }); + } + private JComponent createToolbar() { DefaultActionGroup group = new DefaultActionGroup(); group.add(ActionManager.getInstance().getAction(SERVERS_TOOL_WINDOW_TOOLBAR)); diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/Breakpoint.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/Breakpoint.java index 41b6a35b5e8d..f2180d66a069 100755 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/Breakpoint.java +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/Breakpoint.java @@ -24,11 +24,6 @@ public abstract class Breakpoint { @NotNull public abstract BreakpointTarget getTarget(); - /** - * Returns line number of the breakpoint. As source is changed (typically with LiveEdit feature, - * and particularly by calling {@link ScriptManager#setSourceOnRemote}) this value - * may become stale. - */ public abstract int getLine(); /** diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventAdapter.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventAdapter.java index 51cf25e1aefb..10a2444fc834 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventAdapter.java +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventAdapter.java @@ -26,7 +26,7 @@ public abstract class DebugEventAdapter implements DebugEventListener { } @Override - public void scriptContentChanged(Script newScript) { + public void scriptContentChanged(@NotNull Script newScript) { } @Override diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventListener.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventListener.java index 5b73448d39c7..a8038bed8f41 100755 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventListener.java +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventListener.java @@ -50,7 +50,7 @@ public interface DebugEventListener extends EventListener { /** * Reports that script source has been altered in remote VM. */ - void scriptContentChanged(Script newScript); + void scriptContentChanged(@NotNull Script newScript); /** * Reports a navigation event on the target. diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/VmBase.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/VmBase.java index befe4221e011..b2ebd332c623 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/VmBase.java +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/VmBase.java @@ -19,6 +19,7 @@ public abstract class VmBase implements Vm { return evaluateContext; } + @NotNull protected abstract EvaluateContext computeEvaluateContext(); @NotNull diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMapDecoder.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMapDecoder.java index 431a1156ae89..c033a6979f09 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMapDecoder.java +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMapDecoder.java @@ -135,6 +135,10 @@ public final class SourceMapDecoder { } List sources = readSources(sourcesReader, sourceRoot); + if (sources.isEmpty()) { + // empty map, meteor can report such ugly maps + return null; + } @SuppressWarnings("unchecked") List[] reverseMappingsBySourceUrl = new List[sources.size()]; diff --git a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/LazyVariablesGroup.java b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/LazyVariablesGroup.java index e558f4ba91ab..25b8b3e11ee5 100644 --- a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/LazyVariablesGroup.java +++ b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/LazyVariablesGroup.java @@ -21,24 +21,24 @@ public final class LazyVariablesGroup extends XValueGroup { private final ObjectValue value; - private final int start; - private final int end; + private final int startInclusive; + private final int endInclusive; private final VariableContext context; private final ValueType componentType; private final boolean sparse; - public LazyVariablesGroup(@NotNull ObjectValue value, int start, int end, @NotNull VariableContext context) { - this(value, start, end, context, null, true); + public LazyVariablesGroup(@NotNull ObjectValue value, int startInclusive, int endInclusive, @NotNull VariableContext context) { + this(value, startInclusive, endInclusive, context, null, true); } - public LazyVariablesGroup(@NotNull ObjectValue value, int start, int end, @NotNull VariableContext context, @Nullable ValueType componentType, boolean sparse) { - super(String.format("[%,d \u2026 %,d]", start, end)); + public LazyVariablesGroup(@NotNull ObjectValue value, int startInclusive, int endInclusive, @NotNull VariableContext context, @Nullable ValueType componentType, boolean sparse) { + super(String.format("[%,d \u2026 %,d]", startInclusive, endInclusive)); this.value = value; - this.start = start; - this.end = end; + this.startInclusive = startInclusive; + this.endInclusive = endInclusive; this.context = context; @@ -51,18 +51,17 @@ public final class LazyVariablesGroup extends XValueGroup { node.setAlreadySorted(true); int bucketThreshold = XCompositeNode.MAX_CHILDREN_TO_SHOW; - int size = end - start; - if (!sparse && size > bucketThreshold) { - node.addChildren(XValueChildrenList.topGroups(computeNotSparseGroups(value, context, start, end, bucketThreshold)), true); + if (!sparse && (endInclusive - startInclusive) > bucketThreshold) { + node.addChildren(XValueChildrenList.topGroups(computeNotSparseGroups(value, context, startInclusive, endInclusive + 1, bucketThreshold)), true); return; } - value.getIndexedProperties(start, end + 1, bucketThreshold, new VariableView.ObsolescentIndexedVariablesConsumer(node) { + value.getIndexedProperties(startInclusive, endInclusive + 1, bucketThreshold, new VariableView.ObsolescentIndexedVariablesConsumer(node) { @Override public void consumeRanges(@Nullable int[] ranges) { if (ranges == null) { XValueChildrenList groupList = new XValueChildrenList(); - addGroups(value, GROUP_FACTORY, groupList, start, end, XCompositeNode.MAX_CHILDREN_TO_SHOW, context); + addGroups(value, GROUP_FACTORY, groupList, startInclusive, endInclusive, XCompositeNode.MAX_CHILDREN_TO_SHOW, context); node.addChildren(groupList, true); } else { @@ -78,12 +77,12 @@ public final class LazyVariablesGroup extends XValueGroup { } @NotNull - public static List computeNotSparseGroups(@NotNull ObjectValue value, @NotNull VariableContext context, int from, int to, int bucketThreshold) { - int size = to - from; + public static List computeNotSparseGroups(@NotNull ObjectValue value, @NotNull VariableContext context, int fromInclusive, int toExclusive, int bucketThreshold) { + int size = toExclusive - fromInclusive; int bucketSize = (int)Math.pow(bucketThreshold, Math.ceil(Math.log(size) / Math.log(bucketThreshold)) - 1); List groupList = new ArrayList((int)Math.ceil(size / bucketSize)); - for (; from < to; from += bucketSize) { - groupList.add(new LazyVariablesGroup(value, from, from + (Math.min(bucketSize, to - from) - 1), context, ValueType.NUMBER, false)); + for (; fromInclusive < toExclusive; fromInclusive += bucketSize) { + groupList.add(new LazyVariablesGroup(value, fromInclusive, fromInclusive + (Math.min(bucketSize, toExclusive - fromInclusive) - 1), context, ValueType.NUMBER, false)); } return groupList; } diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/BoxableType.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/BoxableType.java index 8c7175962c76..3f4b8ea839ac 100644 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/BoxableType.java +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/BoxableType.java @@ -2,6 +2,7 @@ package org.jetbrains.protocolReader; abstract class BoxableType { static final BoxableType STRING = new StandaloneType(new NamePath("String"), "writeString"); + static final BoxableType ANY_STRING = new StandaloneType(new NamePath("String"), "writeString"); static final BoxableType INT = new StandaloneType(new NamePath("int"), "writeInt"); static final BoxableType LONG = new StandaloneType(new NamePath("long"), "writeLong"); static final BoxableType NUMBER = new StandaloneType(new NamePath("double"), "writeDouble"); diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassScope.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassScope.java index 6b27866492a4..31ba16f3438c 100644 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassScope.java +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassScope.java @@ -20,10 +20,6 @@ abstract class ClassScope { return contextNamespace.getLastComponent(); } - String getFullName() { - return contextNamespace.getFullText(); - } - NamePath getClassContextNamespace() { return contextNamespace; } diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/DomainGenerator.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/DomainGenerator.java index b74c73e28e1a..6798629e835c 100644 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/DomainGenerator.java +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/DomainGenerator.java @@ -153,7 +153,7 @@ class DomainGenerator { } @Override - public QualifiedTypeData resolveType(T typedObject) { + public TypeDescriptor resolveType(T typedObject) { throw new UnsupportedOperationException(); } @@ -162,8 +162,7 @@ class DomainGenerator { throw new UnsupportedOperationException(); } }; - QualifiedTypeData itemTypeData = generator.resolveType(items, resolveAndGenerateScope); - BoxableType itemBoxableType = itemTypeData.getJavaType(); + BoxableType itemBoxableType = generator.resolveType(items, resolveAndGenerateScope).getType(); final BoxableType arrayType = new ListType(itemBoxableType); StandaloneTypeBinding.Target target = new StandaloneTypeBinding.Target() { @@ -178,7 +177,7 @@ class DomainGenerator { }); } - StandaloneTypeBinding createStandaloneObjectInputTypeBinding(final ProtocolMetaModel.StandaloneType type, final List properties) { + StandaloneTypeBinding createStandaloneObjectInputTypeBinding(@NotNull final ProtocolMetaModel.StandaloneType type, @Nullable final List properties) { final String name = type.id(); final NamePath fullTypeName = generator.getNaming().inputValue.getFullName(domain.domain(), name); generator.jsonProtocolParserClassNames.add(fullTypeName.getFullText()); @@ -198,10 +197,12 @@ class DomainGenerator { out.doc(type.description()); } - out.append("@org.chromium.protocolReader.JsonType").newLine(); + out.append("@org.jetbrains.jsonProtocol.JsonType").newLine(); out.append("public interface ").append(className.getLastComponent()).openBlock(); InputClassScope classScope = new InputClassScope(DomainGenerator.this, className); - classScope.generateStandaloneTypeBody(out, properties); + if (properties != null) { + classScope.generateDeclarationBody(out, properties); + } classScope.writeAdditionalMembers(out); out.closeBlock(); fileUpdater.update(); @@ -309,16 +310,18 @@ class DomainGenerator { fileUpdater.update(); } - private void generateJsonProtocolInterface(TextOutput out, String className, String description, List parameters, TextOutConsumer additionalMembersText) throws IOException { + private void generateJsonProtocolInterface(TextOutput out, String className, String description, List parameters, TextOutConsumer additionalMembersText) { if (description != null) { out.doc(description); } - out.append("@org.chromium.protocolReader.JsonType").newLine().append("public interface ").append(className).openBlock(); + out.append("@org.jetbrains.jsonProtocol.JsonType").newLine().append("public interface ").append(className).openBlock(); InputClassScope classScope = new InputClassScope(this, new NamePath(className, new NamePath(ClassNameScheme.getPackageName(generator.getNaming().inputPackage, domain.domain())))); if (additionalMembersText != null) { classScope.addMember(additionalMembersText); } - classScope.generateMainJsonProtocolInterfaceBody(out, parameters); + if (parameters != null) { + classScope.generateDeclarationBody(out, parameters); + } classScope.writeAdditionalMembers(out); out.closeBlock(); } diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.java index e545f0280f81..b02905ad51ad 100644 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.java +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.java @@ -114,92 +114,61 @@ class Generator { fileSet.deleteOtherFiles(); } - QualifiedTypeData resolveType(final ItemDescriptor typedObject, final ResolveAndGenerateScope scope) { - UnqualifiedTypeData unqualifiedType = switchByType(typedObject, new TypeVisitor() { + TypeDescriptor resolveType(@NotNull final ItemDescriptor typedObject, @NotNull final ResolveAndGenerateScope scope) { + final boolean optional = typedObject instanceof ItemDescriptor.Named && ((ItemDescriptor.Named)typedObject).optional(); + return switchByType(typedObject, new TypeVisitor() { @Override - public UnqualifiedTypeData visitRef(String refName) { - return new UnqualifiedTypeData(resolveRefType(scope.getDomainName(), refName, scope.getTypeDirection())); + public TypeDescriptor visitRef(String refName) { + return new TypeDescriptor(resolveRefType(scope.getDomainName(), refName, scope.getTypeDirection()), optional); } @Override - public UnqualifiedTypeData visitBoolean() { - return UnqualifiedTypeData.BOOLEAN; + public TypeDescriptor visitBoolean() { + return new TypeDescriptor(BoxableType.BOOLEAN, optional); } @Override - public UnqualifiedTypeData visitEnum(List enumConstants) { + public TypeDescriptor visitEnum(List enumConstants) { assert scope instanceof MemberScope; - return new UnqualifiedTypeData(((MemberScope)scope).generateEnum(typedObject.description(), enumConstants)); + return new TypeDescriptor(((MemberScope)scope).generateEnum(typedObject.description(), enumConstants), optional); } @Override - public UnqualifiedTypeData visitString() { - return UnqualifiedTypeData.STRING; + public TypeDescriptor visitString() { + return new TypeDescriptor(BoxableType.STRING, optional); } @Override - public UnqualifiedTypeData visitInteger() { - return UnqualifiedTypeData.INT; + public TypeDescriptor visitInteger() { + return new TypeDescriptor(BoxableType.INT, optional); } @Override - public UnqualifiedTypeData visitNumber() { - return UnqualifiedTypeData.NUMBER; + public TypeDescriptor visitNumber() { + return new TypeDescriptor(BoxableType.NUMBER, optional); } @Override - public UnqualifiedTypeData visitMap() { - return UnqualifiedTypeData.MAP; + public TypeDescriptor visitMap() { + return new TypeDescriptor(BoxableType.MAP, optional); } @Override - public UnqualifiedTypeData visitArray(ArrayItemType items) { - return new UnqualifiedTypeData(new ListType(scope.resolveType(items).getJavaType())); + public TypeDescriptor visitArray(ArrayItemType items) { + BoxableType type = scope.resolveType(items).getType(); + return new TypeDescriptor(new ListType(type), optional, false, type == BoxableType.ANY_STRING); } @Override - public UnqualifiedTypeData visitObject(List properties) { - return new UnqualifiedTypeData(scope.generateNestedObject(typedObject.description(), properties), false); + public TypeDescriptor visitObject(List properties) { + return new TypeDescriptor(scope.generateNestedObject(typedObject.description(), properties), optional); } @Override - public UnqualifiedTypeData visitUnknown() { - return UnqualifiedTypeData.ANY; + public TypeDescriptor visitUnknown() { + return new TypeDescriptor(BoxableType.STRING, optional, false, true); } }); - - return unqualifiedType.getQualifiedType(typedObject instanceof ItemDescriptor.Named && ((ItemDescriptor.Named)typedObject).optional()); - } - - private static class UnqualifiedTypeData { - private final BoxableType typeRef; - private final boolean nullable; - private final boolean asRawString; - - UnqualifiedTypeData(BoxableType typeRef) { - this(typeRef, false); - } - - UnqualifiedTypeData(BoxableType typeRef, boolean nullable) { - this(typeRef, nullable, false); - } - - UnqualifiedTypeData(BoxableType typeRef, boolean nullable, boolean asRawString) { - this.typeRef = typeRef; - this.nullable = nullable; - this.asRawString = asRawString; - } - - QualifiedTypeData getQualifiedType(boolean optional) { - return new QualifiedTypeData(typeRef, optional, nullable, asRawString); - } - - static final UnqualifiedTypeData BOOLEAN = new UnqualifiedTypeData(BoxableType.BOOLEAN, false); - static final UnqualifiedTypeData STRING = new UnqualifiedTypeData(BoxableType.STRING, false); - static final UnqualifiedTypeData INT = new UnqualifiedTypeData(BoxableType.INT, false); - static final UnqualifiedTypeData MAP = new UnqualifiedTypeData(BoxableType.MAP, false); - static final UnqualifiedTypeData NUMBER = new UnqualifiedTypeData(BoxableType.NUMBER, false); - static final UnqualifiedTypeData ANY = new UnqualifiedTypeData(BoxableType.STRING, false, true); } private void generateParserInterfaceList() throws IOException { @@ -274,11 +243,11 @@ class Generator { return typeMap.resolve(domainName, shortName, direction); } - static String generateMethodNameSubstitute(String originalName, TextOutput out) { + static String generateMethodNameSubstitute(@NotNull String originalName, @NotNull TextOutput out) { if (!BAD_METHOD_NAMES.contains(originalName)) { return originalName; } - out.append("@org.chromium.protocolReader.JsonField(jsonLiteralName=\"").append(originalName).append("\")").newLine(); + out.append("@org.jetbrains.jsonProtocol.JsonField(jsonLiteralName=\"").append(originalName).append("\")").newLine(); return "get" + Character.toUpperCase(originalName.charAt(0)) + originalName.substring(1); } diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/InputClassScope.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/InputClassScope.java index 9411f4d25db1..99c95d8f5ae3 100644 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/InputClassScope.java +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/InputClassScope.java @@ -1,8 +1,9 @@ package org.jetbrains.protocolReader; -import org.jetbrains.jsonProtocol.ProtocolMetaModel; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jsonProtocol.ItemDescriptor.Named; +import org.jetbrains.jsonProtocol.ProtocolMetaModel.ObjectProperty; -import java.io.IOException; import java.util.List; class InputClassScope extends ClassScope { @@ -10,36 +11,20 @@ class InputClassScope extends ClassScope { super(generator, namePath); } - public void generateMainJsonProtocolInterfaceBody(TextOutput out, List parameters) throws IOException { - if (parameters != null) { - for (ProtocolMetaModel.Parameter parameter : parameters) { - if (parameter.description() != null) { - out.doc(parameter.description()); - } - - String methodName = Generator.generateMethodNameSubstitute(getName(parameter), out); - QualifiedTypeData paramTypeData = newMemberScope(getName(parameter)).resolveType(parameter); - paramTypeData.writeAnnotations(out); - out.append(paramTypeData.getJavaType().getShortText(getClassContextNamespace())).space().append(methodName).append("();").newLine(); + void generateDeclarationBody(@NotNull TextOutput out, @NotNull List list) { + for (int i = 0, n = list.size(); i < n; i++) { + Named named = list.get(i); + if (named.description() != null) { + out.doc(named.description()); } - } - } - void generateStandaloneTypeBody(TextOutput out, List properties) throws IOException { - if (properties != null) { - for (ProtocolMetaModel.ObjectProperty objectProperty : properties) { - String propertyName = getName(objectProperty); - - if (objectProperty.description() != null) { - out.doc(objectProperty.description()); - } - - String methodName = Generator.generateMethodNameSubstitute(propertyName, out); - MemberScope memberScope = newMemberScope(propertyName); - QualifiedTypeData propertyTypeData = memberScope.resolveType(objectProperty); - propertyTypeData.writeAnnotations(out); - - out.append(propertyTypeData.getJavaType().getShortText(getClassContextNamespace()) + ' ' + methodName + "();").newLine(); + String name = getName(named); + String declarationName = Generator.generateMethodNameSubstitute(name, out); + TypeDescriptor typeDescriptor = new InputMemberScope(name).resolveType(named); + typeDescriptor.writeAnnotations(out); + out.append(typeDescriptor.getType().getShortText(getClassContextNamespace())).space().append(declarationName).append("();"); + if (i != (n - 1)) { + out.newLine().newLine(); } } } @@ -49,10 +34,6 @@ class InputClassScope extends ClassScope { return TypeData.Direction.INPUT; } - private MemberScope newMemberScope(String memberName) { - return new InputMemberScope(memberName); - } - class InputMemberScope extends MemberScope { InputMemberScope(String memberName) { super(InputClassScope.this, memberName); @@ -72,28 +53,28 @@ class InputClassScope extends ClassScope { } @Override - public BoxableType generateNestedObject(final String description, final List propertyList) { + public BoxableType generateNestedObject(final String description, final List propertyList) { final String objectName = Generator.capitalizeFirstChar(getMemberName()); addMember(new TextOutConsumer() { @Override public void append(TextOutput out) { out.newLine().doc(description); if (propertyList == null) { - out.append("@org.chromium.protocolReader.JsonType(allowsOtherProperties=true)").newLine(); + out.append("@org.jetbrains.jsonProtocol.JsonType(allowsOtherProperties=true)").newLine(); out.append("public interface ").append(objectName).append(" extends org.jetbrains.jsonProtocol.JsonObjectBased").openBlock(); } else { - out.append("@org.chromium.protocolReader.JsonType").newLine(); + out.append("@org.jetbrains.jsonProtocol.JsonType").newLine(); out.append("public interface ").append(objectName).openBlock(); - for (ProtocolMetaModel.ObjectProperty property : propertyList) { + for (ObjectProperty property : propertyList) { out.doc(property.description()); String methodName = Generator.generateMethodNameSubstitute(getName(property), out); - MemberScope memberScope = newMemberScope(getName(property)); - QualifiedTypeData propertyTypeData = memberScope.resolveType(property); + MemberScope memberScope = new InputMemberScope(getName(property)); + TypeDescriptor propertyTypeData = memberScope.resolveType(property); propertyTypeData.writeAnnotations(out); - out.append(propertyTypeData.getJavaType().getShortText(getClassContextNamespace()) + ' ' + methodName + "();").newLine(); + out.append(propertyTypeData.getType().getShortText(getClassContextNamespace()) + ' ' + methodName + "();").newLine(); } } out.closeBlock(); diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MemberScope.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MemberScope.java index 21de2ca3b228..78a83a9127ca 100644 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MemberScope.java +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MemberScope.java @@ -19,7 +19,7 @@ abstract class MemberScope implements ResolveAndGenerateScope { } @Override - public QualifiedTypeData resolveType(T typedObject) { + public TypeDescriptor resolveType(T typedObject) { return classScope.generator.generator.resolveType(typedObject, this); } diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MyCreateStandaloneTypeBindingVisitorBase.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MyCreateStandaloneTypeBindingVisitorBase.java index e867bf924eaa..90b7068e8cb5 100644 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MyCreateStandaloneTypeBindingVisitorBase.java +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MyCreateStandaloneTypeBindingVisitorBase.java @@ -60,7 +60,7 @@ class MyCreateStandaloneTypeBindingVisitorBase extends CreateStandaloneTypeBindi } @Override - public QualifiedTypeData resolveType(T typedObject) { + public TypeDescriptor resolveType(T typedObject) { throw new UnsupportedOperationException(); } @@ -68,7 +68,7 @@ class MyCreateStandaloneTypeBindingVisitorBase extends CreateStandaloneTypeBindi public BoxableType generateNestedObject(String description, List properties) { return context.generateNestedObject("Item", description, properties); } - }).getJavaType()); + }).getType()); } }, generator.generator.getNaming().outputTypedef, TypeData.Direction.OUTPUT); } diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/OutputClassScope.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/OutputClassScope.java index fa7f4f18740f..f88a55d7a039 100644 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/OutputClassScope.java +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/OutputClassScope.java @@ -19,8 +19,8 @@ class OutputClassScope extends ClassScope { return; } - List

mandatoryParameters = new ArrayList

(); - List

optionalParameters = new ArrayList

(); + List

mandatoryParameters = new ArrayList<>(); + List

optionalParameters = new ArrayList<>(); for (P parameter : parameters) { if (parameter.optional()) { optionalParameters.add(parameter); @@ -34,8 +34,8 @@ class OutputClassScope extends ClassScope { generateConstructor(out, mandatoryParameters, null); if (mandatoryParameters.size() == 1) { P parameter = mandatoryParameters.get(0); - QualifiedTypeData typeData = new OutputMemberScope(getName(parameter)).resolveType(parameter); - if (typeData.getJavaType().getFullText().equals("int[]")) { + TypeDescriptor typeData = new OutputMemberScope(getName(parameter)).resolveType(parameter); + if (typeData.getType().getFullText().equals("int[]")) { BoxableType[] types = new BoxableType[mandatoryParameters.size()]; types[0] = new ListType(BoxableType.INT) { @Override @@ -94,7 +94,7 @@ class OutputClassScope extends ClassScope { out.append("/**").newLine().append(" * @param v ").append(parameter.description()).newLine().append(" */").newLine(); } - CharSequence type = new OutputMemberScope(parameter.name()).resolveType(parameter).getJavaType().getShortText(getClassContextNamespace()); + CharSequence type = new OutputMemberScope(parameter.name()).resolveType(parameter).getType().getShortText(getClassContextNamespace()); if (type.equals(JsonReaderEx.class.getCanonicalName())) { type = "String"; } @@ -131,9 +131,10 @@ class OutputClassScope extends ClassScope { mandatoryParameterTypes = new BoxableType[mandatoryParameters.size()]; } for (int i = 0, length = mandatoryParameterTypes.length; i < length; i++) { + assert mandatoryParameterTypes != null; if (mandatoryParameterTypes[i] == null) { P parameter = mandatoryParameters.get(i); - mandatoryParameterTypes[i] = new OutputMemberScope(parameter.name()).resolveType(parameter).getJavaType(); + mandatoryParameterTypes[i] = new OutputMemberScope(parameter.name()).resolveType(parameter).getType(); } } @@ -144,6 +145,7 @@ class OutputClassScope extends ClassScope { out.comma(); } + assert mandatoryParameterTypes != null; out.append(mandatoryParameterTypes[i].getShortText(getClassContextNamespace())); out.space().append(parameter.name()); needComa = true; @@ -152,6 +154,7 @@ class OutputClassScope extends ClassScope { for (int i = 0, size = mandatoryParameters.size(); i < size; i++) { P parameter = mandatoryParameters.get(i); out.newLine(); + assert mandatoryParameterTypes != null; appendWriteValueInvocation(out, parameter, parameter.name(), mandatoryParameterTypes[i]); } out.closeBlock(); @@ -159,7 +162,7 @@ class OutputClassScope extends ClassScope { private void appendWriteValueInvocation(TextOutput out, ItemDescriptor.Named parameter, String valueRefName, @Nullable BoxableType type) { if (type == null) { - type = new OutputMemberScope(parameter.name()).resolveType(parameter).getJavaType(); + type = new OutputMemberScope(parameter.name()).resolveType(parameter).getType(); } boolean blockOpened = false; @@ -188,7 +191,7 @@ class OutputClassScope extends ClassScope { } // todo CallArgument (we should allow write null as value) out.append(parameter.name().equals("value") && type.getWriteMethodName().equals("writeString") ? "writeNullableString" : type.getWriteMethodName()).append("("); - out.quoute(parameter.name()).comma().append(valueRefName).append(");"); + out.quote(parameter.name()).comma().append(valueRefName).append(");"); if (blockOpened) { out.closeBlock(); } diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ParserRootInterfaceItem.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ParserRootInterfaceItem.java index e3e8049c1b6d..e84c641ff9c3 100644 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ParserRootInterfaceItem.java +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ParserRootInterfaceItem.java @@ -18,7 +18,7 @@ class ParserRootInterfaceItem implements Comparable { } void writeCode(TextOutput out) throws IOException { - out.append("@org.chromium.protocolReader.JsonParseMethod").newLine(); + out.append("@org.jetbrains.jsonProtocol.JsonParseMethod").newLine(); out.append("public abstract ").append(fullName).space(); appendReadMethodName(out); out.append("(").append(Util.JSON_READER_PARAMETER_DEF).append(")").semi().newLine(); diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ResolveAndGenerateScope.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ResolveAndGenerateScope.java index 8f117d02ab95..c43c9ff7deff 100644 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ResolveAndGenerateScope.java +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ResolveAndGenerateScope.java @@ -9,7 +9,7 @@ interface ResolveAndGenerateScope { String getDomainName(); TypeData.Direction getTypeDirection(); - QualifiedTypeData resolveType(T typedObject); + TypeDescriptor resolveType(T typedObject); BoxableType generateNestedObject(String description, List properties); diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeData.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeData.java index 0ab11a07c352..7fbc5f6c2cad 100644 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeData.java +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeData.java @@ -4,6 +4,21 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jsonProtocol.ProtocolMetaModel; class TypeData { + public static final StandaloneTypeBinding ANY = new StandaloneTypeBinding() { + @Override + public BoxableType getJavaType() { + return BoxableType.ANY_STRING; + } + + @Override + public void generate() { + } + + @Override + public Direction getDirection() { + return null; + } + }; private final String name; private Input input; @@ -119,21 +134,7 @@ class TypeData { }; } else if (name.equals("any")) { - return new StandaloneTypeBinding() { - @Override - public BoxableType getJavaType() { - return BoxableType.STRING; - } - - @Override - public void generate() { - } - - @Override - public Direction getDirection() { - return null; - } - }; + return ANY; } throw new RuntimeException(); @@ -164,21 +165,7 @@ class TypeData { }; } else if (name.equals("any")) { - return new StandaloneTypeBinding() { - @Override - public BoxableType getJavaType() { - return BoxableType.STRING; - } - - @Override - public void generate() { - } - - @Override - public Direction getDirection() { - return null; - } - }; + return ANY; } throw new RuntimeException(); diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/QualifiedTypeData.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeDescriptor.java similarity index 52% rename from platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/QualifiedTypeData.java rename to platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeDescriptor.java index a4ccd0b3c49f..d142e8bdf6d5 100644 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/QualifiedTypeData.java +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeDescriptor.java @@ -1,13 +1,19 @@ package org.jetbrains.protocolReader; -class QualifiedTypeData { - private final BoxableType typeRef; +import org.jetbrains.annotations.NotNull; + +class TypeDescriptor { + private final BoxableType type; private final boolean optional; private final boolean nullable; private final boolean asRawString; - QualifiedTypeData(BoxableType typeRef, boolean optional, boolean nullable, boolean asRawString) { - this.typeRef = typeRef; + TypeDescriptor(@NotNull BoxableType type, boolean optional) { + this(type, optional, false, false); + } + + TypeDescriptor(@NotNull BoxableType type, boolean optional, boolean nullable, boolean asRawString) { + this.type = type; this.optional = optional; this.nullable = nullable; this.asRawString = asRawString; @@ -17,13 +23,14 @@ class QualifiedTypeData { return nullable; } - BoxableType getJavaType() { - return typeRef; + @NotNull + BoxableType getType() { + return type; } - void writeAnnotations(TextOutput out) { + void writeAnnotations(@NotNull TextOutput out) { if (optional || asRawString) { - out.append("@org.chromium.protocolReader.JsonField("); + out.append("@org.jetbrains.jsonProtocol.JsonField("); if (optional) { out.append("optional=true"); } @@ -37,7 +44,7 @@ class QualifiedTypeData { } if (isNullable()) { - out.append("@org.chromium.protocolReader.JsonNullable").newLine(); + out.append("@org.jetbrains.jsonProtocol.JsonNullable").newLine(); } } } diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonField.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonField.java similarity index 96% rename from platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonField.java rename to platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonField.java index 5dfa26ca057a..3b960b8636a9 100644 --- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonField.java +++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonField.java @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.protocolReader; +package org.jetbrains.jsonProtocol; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -25,6 +25,7 @@ public @interface JsonField { // read any primitive value as String (true as true, number as string - don't try to parse) boolean allowAnyPrimitiveValue() default false; + boolean allowAnyPrimitiveValueAndMap() default false; boolean optional() default false; diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonNullable.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonNullable.java similarity index 94% rename from platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonNullable.java rename to platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonNullable.java index bbaa82a1b2c5..8e88ab4eb2b4 100644 --- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonNullable.java +++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonNullable.java @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.protocolReader; +package org.jetbrains.jsonProtocol; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonOptionalField.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonOptionalField.java similarity index 94% rename from platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonOptionalField.java rename to platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonOptionalField.java index a2ede4854bf5..92c9cd978700 100644 --- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonOptionalField.java +++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonOptionalField.java @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.protocolReader; +package org.jetbrains.jsonProtocol; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonParseMethod.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonParseMethod.java similarity index 92% rename from platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonParseMethod.java rename to platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonParseMethod.java index c964e8057018..8016b9b59539 100644 --- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonParseMethod.java +++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonParseMethod.java @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.protocolReader; +package org.jetbrains.jsonProtocol; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonReaders.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonReaders.java index aa1d19f1bad2..056e4dc6b78f 100644 --- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonReaders.java +++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonReaders.java @@ -234,7 +234,7 @@ public final class JsonReaders { return list; } - public static List readListOfPrimitive(JsonReaderEx reader) { + public static List readRawStringArray(JsonReaderEx reader) { reader.beginArray(); if (!reader.hasNext()) { reader.endArray(); diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonSubtype.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonSubtype.java similarity index 92% rename from platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonSubtype.java rename to platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonSubtype.java index f104d74943cd..b40d4a1b7687 100644 --- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonSubtype.java +++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonSubtype.java @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.protocolReader; +package org.jetbrains.jsonProtocol; /** * A base interface for JSON subtype interface. This inheritance serves 2 purposes: diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonSubtypeCasting.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonSubtypeCasting.java similarity index 95% rename from platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonSubtypeCasting.java rename to platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonSubtypeCasting.java index 05275511e407..cc59fed74eac 100644 --- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonSubtypeCasting.java +++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonSubtypeCasting.java @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.protocolReader; +package org.jetbrains.jsonProtocol; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonType.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonType.java similarity index 96% rename from platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonType.java rename to platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonType.java index 62e2c8c12118..79dc453ac9fb 100644 --- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonType.java +++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonType.java @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.protocolReader; +package org.jetbrains.jsonProtocol; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/FieldProcessor.java b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/FieldProcessor.java index eabc8d8e4337..111e58caa3a6 100644 --- a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/FieldProcessor.java +++ b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/FieldProcessor.java @@ -1,6 +1,9 @@ package org.jetbrains.protocolReader; -import org.chromium.protocolReader.*; +import org.jetbrains.jsonProtocol.JsonField; +import org.jetbrains.jsonProtocol.JsonNullable; +import org.jetbrains.jsonProtocol.JsonOptionalField; +import org.jetbrains.jsonProtocol.JsonSubtypeCasting; import java.lang.reflect.Method; import java.lang.reflect.Type; diff --git a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/InterfaceReader.java b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/InterfaceReader.java index f80b8c54bb42..cc4e2566f4dd 100644 --- a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/InterfaceReader.java +++ b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/InterfaceReader.java @@ -1,10 +1,10 @@ package org.jetbrains.protocolReader; import gnu.trove.THashSet; -import org.chromium.protocolReader.JsonField; -import org.chromium.protocolReader.JsonSubtype; import org.jetbrains.annotations.Nullable; import org.jetbrains.io.JsonReaderEx; +import org.jetbrains.jsonProtocol.JsonField; +import org.jetbrains.jsonProtocol.JsonSubtype; import org.jetbrains.jsonProtocol.StringIntPair; import java.lang.annotation.RetentionPolicy; @@ -249,7 +249,7 @@ class InterfaceReader { argumentType = wildcard.getUpperBounds()[0]; } } - return new ArrayReader(getFieldTypeParser(argumentType, false, false, null), true, declaredNullable); + return new ArrayReader(getFieldTypeParser(argumentType, false, false, method), true, declaredNullable); } else if (parameterizedType.getRawType() == Map.class) { return declaredNullable ? NULLABLE_MAP_PARSER : MAP_PARSER; diff --git a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ReaderRoot.java b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ReaderRoot.java index a76971dc5da7..7914a5103ac6 100644 --- a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ReaderRoot.java +++ b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ReaderRoot.java @@ -2,7 +2,7 @@ package org.jetbrains.protocolReader; import org.jetbrains.io.JsonReaderEx; import gnu.trove.THashSet; -import org.chromium.protocolReader.JsonParseMethod; +import org.jetbrains.jsonProtocol.JsonParseMethod; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; diff --git a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/TextOutput.java b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/TextOutput.java index cd5afa1c27ff..77d4bd1e275f 100644 --- a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/TextOutput.java +++ b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/TextOutput.java @@ -9,7 +9,7 @@ public class TextOutput { private int identLevel; private final static int indentGranularity = 2; private char[][] indents = {EMPTY_CHARS}; - private boolean justNewlined; + private boolean justNewLined; private final StringBuilder out; public TextOutput(StringBuilder out) { @@ -41,7 +41,7 @@ public class TextOutput { public TextOutput newLine() { out.append('\n'); - justNewlined = true; + justNewLined = true; return this; } @@ -122,14 +122,14 @@ public class TextOutput { return append("/**").newLine().append(" * ").append(description).newLine().append(" */").newLine(); } - public TextOutput quoute(CharSequence s) { + public TextOutput quote(CharSequence s) { return append('"').append(s).append('"'); } public void maybeIndent() { - if (justNewlined) { + if (justNewLined) { out.append(indents[identLevel]); - justNewlined = false; + justNewLined = false; } } } diff --git a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ValueReader.java b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ValueReader.java index 7ef6b3e0fc82..442167687b40 100644 --- a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ValueReader.java +++ b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ValueReader.java @@ -1,7 +1,3 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - package org.jetbrains.protocolReader; import org.jetbrains.annotations.Nullable; @@ -51,7 +47,7 @@ abstract class ValueReader { out.append("name"); } else { - out.quoute(fieldName); + out.quote(fieldName); } } } diff --git a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ItemDescriptor.java b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ItemDescriptor.java index 26dbd72d058e..d6f5afcfbe27 100644 --- a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ItemDescriptor.java +++ b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ItemDescriptor.java @@ -1,7 +1,5 @@ package org.jetbrains.jsonProtocol; -import org.chromium.protocolReader.JsonOptionalField; - import java.util.List; public interface ItemDescriptor { diff --git a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolMetaModel.java b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolMetaModel.java index c08c50c108aa..a4aeeec15d37 100644 --- a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolMetaModel.java +++ b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolMetaModel.java @@ -1,9 +1,5 @@ package org.jetbrains.jsonProtocol; -import org.chromium.protocolReader.JsonField; -import org.chromium.protocolReader.JsonOptionalField; -import org.chromium.protocolReader.JsonType; - import java.util.List; /** diff --git a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolSchemaReader.java b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolSchemaReader.java index 50aeebbbdf1e..aafe735409fd 100644 --- a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolSchemaReader.java +++ b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolSchemaReader.java @@ -5,7 +5,6 @@ package org.jetbrains.jsonProtocol; import org.jetbrains.io.JsonReaderEx; -import org.chromium.protocolReader.JsonParseMethod; import org.jetbrains.jsonProtocol.ProtocolMetaModel.Root; import java.io.IOException; diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java index 3c1f96113532..9e270a0a1f2b 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java @@ -183,6 +183,8 @@ public abstract class LightPlatformCodeInsightTestCase extends LightPlatformTest protected static Editor createEditor(@NotNull VirtualFile file) { Editor editor = FileEditorManager.getInstance(getProject()).openTextEditor(new OpenFileDescriptor(getProject(), file, 0), false); ((EditorImpl)editor).setCaretActive(); + // temporary logging, to investigate blinking tests + System.out.println("Editor created with fonts: " + editor.getColorsScheme().getFontPreferences().getEffectiveFontFamilies()); return editor; } diff --git a/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java b/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java index d608303eec09..2248182a3c5c 100644 --- a/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java +++ b/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java @@ -20,6 +20,7 @@ import com.intellij.openapi.util.Factory; import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.ArrayList; @@ -41,6 +42,7 @@ public class FindUsagesProcessPresentation { private Factory myProgressIndicatorFactory; private Collection myLargeFiles; private boolean myShowFindOptionsPrompt = true; + private Runnable mySearchWithProjectFiles; public FindUsagesProcessPresentation(@NotNull UsageViewPresentation presentation) { myUsageViewPresentation = presentation; @@ -80,6 +82,15 @@ public class FindUsagesProcessPresentation { myProgressIndicatorFactory = progressIndicatorFactory; } + @Nullable + public Runnable searchIncludingProjectFileUsages() { + return mySearchWithProjectFiles; + } + + public void projectFileUsagesFound(@NotNull Runnable searchWithProjectFiles) { + mySearchWithProjectFiles = searchWithProjectFiles; + } + public void setLargeFilesWereNotScanned(@NotNull Collection largeFiles) { myLargeFiles = largeFiles; } diff --git a/platform/usageView/src/com/intellij/usages/impl/SearchForUsagesRunnable.java b/platform/usageView/src/com/intellij/usages/impl/SearchForUsagesRunnable.java index c9124560c740..170d1802eee4 100644 --- a/platform/usageView/src/com/intellij/usages/impl/SearchForUsagesRunnable.java +++ b/platform/usageView/src/com/intellij/usages/impl/SearchForUsagesRunnable.java @@ -19,6 +19,7 @@ import com.intellij.find.FindManager; import com.intellij.icons.AllIcons; import com.intellij.openapi.actionSystem.KeyboardShortcut; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.colors.CodeInsightColors; @@ -71,6 +72,7 @@ class SearchForUsagesRunnable implements Runnable { @NonNls private static final String FIND_OPTIONS_HREF_TARGET = "FindOptions"; @NonNls private static final String SEARCH_IN_PROJECT_HREF_TARGET = "SearchInProject"; @NonNls private static final String LARGE_FILES_HREF_TARGET = "LargeFiles"; + @NonNls private static final String SHOW_PROJECT_FILE_OCCURRENCES_HREF_TARGET = "SHOW_PROJECT_FILE_OCCURRENCES"; private final AtomicInteger myUsageCountWithoutDefinition = new AtomicInteger(0); private final AtomicReference myFirstUsage = new AtomicReference(); @NotNull @@ -135,25 +137,43 @@ class SearchForUsagesRunnable implements Runnable { + UsageViewBundle.message("large.files.were.ignored", largeFiles.size()) + ")"; resultLines.add(shortMessage); - resultListener = new HyperlinkAdapter(){ - @Override - protected void hyperlinkActivated(HyperlinkEvent e) { - if (e.getDescription().equals(LARGE_FILES_HREF_TARGET)) { - String detailedMessage = detailedLargeFilesMessage(largeFiles); - List strings = new ArrayList(lines); - strings.add(detailedMessage); - ToolWindowManager.getInstance(project).notifyByBalloon(ToolWindowId.FIND, info, wrapInHtml(strings), AllIcons.Actions.Find, listener); - } - else if (listener != null) { - listener.hyperlinkUpdate(e); - } + resultListener = addHrefHandling(resultListener, LARGE_FILES_HREF_TARGET, new Runnable() { + public void run() { + String detailedMessage = detailedLargeFilesMessage(largeFiles); + List strings = new ArrayList(lines); + strings.add(detailedMessage); + //noinspection SSBasedInspection + ToolWindowManager.getInstance(project).notifyByBalloon(ToolWindowId.FIND, info, wrapInHtml(strings), AllIcons.Actions.Find, listener); } - }; + }); } + Runnable searchIncludingProjectFileUsages = processPresentation.searchIncludingProjectFileUsages(); + if (searchIncludingProjectFileUsages != null) { + resultLines.add("Occurrences in " + ApplicationNamesInfo.getInstance().getProductName() + " project files are skipped. " + + "Include them"); + resultListener = addHrefHandling(resultListener, SHOW_PROJECT_FILE_OCCURRENCES_HREF_TARGET, searchIncludingProjectFileUsages); + } + + //noinspection SSBasedInspection ToolWindowManager.getInstance(project).notifyByBalloon(ToolWindowId.FIND, info, wrapInHtml(resultLines), AllIcons.Actions.Find, resultListener); } + private static HyperlinkListener addHrefHandling(@Nullable final HyperlinkListener listener, + @NotNull final String hrefTarget, @NotNull final Runnable handler) { + return new HyperlinkAdapter() { + @Override + protected void hyperlinkActivated(HyperlinkEvent e) { + if (e.getDescription().equals(hrefTarget)) { + handler.run(); + } + else if (listener != null) { + listener.hyperlinkUpdate(e); + } + } + }; + } + @NotNull private static String wrapInHtml(@NotNull List strings) { return XmlStringUtil.wrapInHtml(StringUtil.join(strings, "
")); @@ -460,7 +480,9 @@ class SearchForUsagesRunnable implements Runnable { hyperlinkListener = createSearchInProjectListener(); } - if (!myProcessPresentation.getLargeFiles().isEmpty() || myOutOfScopeUsages.get() != 0) { + if (!myProcessPresentation.getLargeFiles().isEmpty() || + myOutOfScopeUsages.get() != 0 || + myProcessPresentation.searchIncludingProjectFileUsages() != null) { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java index 7ef580755585..b9fc77295d62 100644 --- a/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java +++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java @@ -268,7 +268,9 @@ public class UsageViewManagerImpl extends UsageViewManager { return isFileInScope(file, searchScope); } else if(element != null) { - return searchScope instanceof ProjectScopeImpl || searchScope instanceof ProjectAndLibrariesScope; + return searchScope instanceof EverythingGlobalScope || + searchScope instanceof ProjectScopeImpl || + searchScope instanceof ProjectAndLibrariesScope; } return false; } diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java b/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java index 098501af7489..6109e9a41598 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java @@ -164,8 +164,10 @@ public abstract class XDebuggerEvaluator { return text; } + @Deprecated /** * @return delay before showing value tooltip (in ms) + * @deprecated Since IDEA 14 it is a platform setting */ public int getValuePopupDelay() { return XDebuggerSettingsManager.getInstance().getDataViewSettings().getValueLookupDelay(); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ForceStepIntoAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ForceStepIntoAction.java index e7c9cae4db92..e5620e20011b 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ForceStepIntoAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ForceStepIntoAction.java @@ -15,13 +15,14 @@ */ package com.intellij.xdebugger.impl.actions; -import org.jetbrains.annotations.NotNull; import com.intellij.xdebugger.impl.DebuggerSupport; +import org.jetbrains.annotations.NotNull; /** * @author nik */ public class ForceStepIntoAction extends XDebuggerActionBase { + @Override @NotNull protected DebuggerActionHandler getHandler(@NotNull final DebuggerSupport debuggerSupport) { return debuggerSupport.getForceStepIntoHandler(); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XQuickEvaluateHandler.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XQuickEvaluateHandler.java index bf3e0010e6cf..0ccd488e9f9b 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XQuickEvaluateHandler.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XQuickEvaluateHandler.java @@ -100,14 +100,7 @@ public class XQuickEvaluateHandler extends QuickEvaluateHandler { } @Override - public int getValueLookupDelay(final Project project) { - XDebugSession session = XDebuggerManager.getInstance(project).getCurrentSession(); - if (session != null) { - XDebuggerEvaluator evaluator = session.getDebugProcess().getEvaluator(); - if (evaluator != null) { - return evaluator.getValuePopupDelay(); - } - } + public int getValueLookupDelay(Project project) { return XDebuggerSettingsManager.getInstance().getDataViewSettings().getValueLookupDelay(); } } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml index 164c690d4da3..5581810b3f2c 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml @@ -1209,6 +1209,10 @@ key="field.has.setter.but.no.getter.display.name" groupBundle="messages.InspectionsBundle" groupKey="group.names.javabeans.issues" enabledByDefault="false" level="WARNING" implementationClass="com.siyeh.ig.javabeans.FieldHasSetterButNoGetterInspection"/> + #ref #loc class.with.only.private.constructors.display.name=Class with only 'private' constructors should be declared 'final' class.with.only.private.constructors.problem.descriptor=Class #ref with only 'private' constructors should be declared 'final' +property.value.set.to.itself.display.name=Property value set to itself diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javabeans/PropertyValueSetToItselfInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javabeans/PropertyValueSetToItselfInspection.java new file mode 100644 index 000000000000..e4ee7c5956bc --- /dev/null +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javabeans/PropertyValueSetToItselfInspection.java @@ -0,0 +1,102 @@ +/* + * 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.siyeh.ig.javabeans; + +import com.intellij.psi.*; +import com.intellij.psi.util.PropertyUtil; +import com.siyeh.InspectionGadgetsBundle; +import com.siyeh.ig.BaseInspection; +import com.siyeh.ig.BaseInspectionVisitor; +import com.siyeh.ig.psiutils.EquivalenceChecker; +import com.siyeh.ig.psiutils.ParenthesesUtils; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; + +/** + * @author Bas Leijdekkers + */ +public class PropertyValueSetToItselfInspection extends BaseInspection { + + @Nls + @NotNull + @Override + public String getDisplayName() { + return InspectionGadgetsBundle.message("property.value.set.to.itself.display.name"); + } + + @NotNull + @Override + protected String buildErrorString(Object... infos) { + return InspectionGadgetsBundle.message("property.value.set.to.itself.display.name"); + } + + @Override + public BaseInspectionVisitor buildVisitor() { + return new PropertyValueSetToItselfVisitor(); + } + + private static class PropertyValueSetToItselfVisitor extends BaseInspectionVisitor { + + @Override + public void visitMethodCallExpression(PsiMethodCallExpression expression) { + super.visitMethodCallExpression(expression); + final PsiExpressionList argumentList1 = expression.getArgumentList(); + final PsiExpression[] arguments1 = argumentList1.getExpressions(); + if (arguments1.length != 1) { + return; + } + final PsiExpression argument = arguments1[0]; + if (!(argument instanceof PsiMethodCallExpression)) { + return; + } + final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)argument; + final PsiExpressionList argumentList2 = methodCallExpression.getArgumentList(); + final PsiExpression[] arguments2 = argumentList2.getExpressions(); + if (arguments2.length != 0) { + return; + } + final PsiReferenceExpression methodExpression1 = expression.getMethodExpression(); + final PsiExpression qualifierExpression1 = ParenthesesUtils.stripParentheses(methodExpression1.getQualifierExpression()); + final PsiReferenceExpression methodExpression2 = methodCallExpression.getMethodExpression(); + final PsiExpression qualifierExpression2 = ParenthesesUtils.stripParentheses(methodExpression2.getQualifierExpression()); + if (qualifierExpression1 instanceof PsiReferenceExpression && qualifierExpression2 instanceof PsiReferenceExpression) { + if (!EquivalenceChecker.expressionsAreEquivalent(qualifierExpression1, qualifierExpression2)) { + return; + } + } + else if((qualifierExpression1 != null && + !(qualifierExpression1 instanceof PsiThisExpression) && + !(qualifierExpression1 instanceof PsiSuperExpression)) + || + qualifierExpression2 != null && + !(qualifierExpression2 instanceof PsiThisExpression) && + !(qualifierExpression2 instanceof PsiSuperExpression)) { + return; + } + final PsiMethod method1 = expression.resolveMethod(); + final PsiField fieldOfSetter = PropertyUtil.getFieldOfSetter(method1); + if (fieldOfSetter == null) { + return; + } + final PsiMethod method2 = methodCallExpression.resolveMethod(); + final PsiField fieldOfGetter = PropertyUtil.getFieldOfGetter(method2); + if (!fieldOfSetter.equals(fieldOfGetter)) { + return; + } + registerMethodCallError(expression); + } + } +} diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/PropertyValueSetToItself.html b/plugins/InspectionGadgets/src/inspectionDescriptions/PropertyValueSetToItself.html new file mode 100644 index 000000000000..c72e160a9b8c --- /dev/null +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/PropertyValueSetToItself.html @@ -0,0 +1,10 @@ + + +Reports calls on a setter with the value of same objects getter. +For example: bean.setPayerId(bean.getPayerId()); +In regular circumstances this code is a no-op and probably not what was intented.. + +

+ New in 14 + + \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ReturnNull.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ReturnNull.html index 70255c1e9440..c36afbcd8886 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/ReturnNull.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ReturnNull.html @@ -3,14 +3,14 @@ Reports return statements with null values. While occasionally useful, this construct may make the code more prone to failing with a NullPointerException, and often indicates that the -developer doesn't really understand the classes intended semantics. +developer doesn't really understand the class's intended semantics.

-Use the first control below to let this inspection ignore private methods. +Use the first checkbox below to let this inspection ignore private methods.

-Use bottom three controls to specify whether this inspection should report +Use the bottom three checkboxes to specify whether null values on array returns, collection -object returns, plain object returns, or a combination of the three. +object returns, plain object returns, or a combination of the three should be reported.

diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/javabeans/PropertyValueSetToItselfInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/javabeans/PropertyValueSetToItselfInspectionTest.java new file mode 100644 index 000000000000..d17387119ae1 --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/javabeans/PropertyValueSetToItselfInspectionTest.java @@ -0,0 +1,56 @@ +/* + * 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.siyeh.ig.javabeans; + +import com.intellij.codeInspection.InspectionProfileEntry; +import com.siyeh.ig.LightInspectionTestCase; +import org.jetbrains.annotations.Nullable; + +public class PropertyValueSetToItselfInspectionTest extends LightInspectionTestCase { + + public void testSimple() { + doTest("class Bean {\n" + + " private String x;\n" + + " public void setX(String x) {\n" + + " this.x = x;\n" + + " }\n" + + " public String getX() { return x; }\n" + + " void m(Bean b) {\n" + + " (b)./*Property value set to itself*/setX/**/(b.getX());\n" + + " this./*Property value set to itself*/setX/**/(getX());\n" + + " }\n" + + "}"); + } + + public void testNoWarn() { + doTest("class Bean {\n" + + " private String x;\n" + + " public void setX(String x) {\n" + + " this.x = x;\n" + + " }\n" + + " public String getX() { return x; }\n" + + " void m(Bean b, Bean c) {\n" + + " (b).setX(c.getX());\n" + + " }\n" + + "}"); + } + + @Nullable + @Override + protected InspectionProfileEntry getInspection() { + return new PropertyValueSetToItselfInspection(); + } +} \ No newline at end of file diff --git a/plugins/IntelliLang/java-support/resources/javaInjections.xml b/plugins/IntelliLang/java-support/resources/javaInjections.xml index 4b66c8b13713..97ba2e624ac6 100644 --- a/plugins/IntelliLang/java-support/resources/javaInjections.xml +++ b/plugins/IntelliLang/java-support/resources/javaInjections.xml @@ -130,6 +130,13 @@ + + + + + + + diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/annotation/ExpandToNormalAnnotationIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/annotation/ExpandToNormalAnnotationIntentionTest.java index dea52b1d28d3..31a5b061f291 100644 --- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/annotation/ExpandToNormalAnnotationIntentionTest.java +++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/annotation/ExpandToNormalAnnotationIntentionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 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. @@ -17,6 +17,9 @@ package com.siyeh.ipp.annotation; import com.siyeh.ipp.IPPTestCase; +/** + * @see ExpandToNormalAnnotationIntention + */ public class ExpandToNormalAnnotationIntentionTest extends IPPTestCase { public void testOneAttr() throws Exception { doTest(); @@ -32,7 +35,7 @@ public class ExpandToNormalAnnotationIntentionTest extends IPPTestCase { @Override protected String getIntentionName() { - return "Expand to 'value = \"foo\"'"; + return "Add 'value=' to annotation attribute"; } @Override diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/merge/MergeAction.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/merge/MergeAction.java index e76f2f061485..80efbd46f8fa 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/merge/MergeAction.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/merge/MergeAction.java @@ -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. @@ -58,13 +58,13 @@ public class MergeAction extends AnAction { final VcsContext context = CvsContextWrapper.createCachedInstance(e); final VirtualFile[] files = context.getSelectedFiles(); - if (files == null || files.length == 0) return; + if (files.length == 0) return; + final Project project = context.getProject(); final ReadonlyStatusHandler.OperationStatus operationStatus = - ReadonlyStatusHandler.getInstance(context.getProject()).ensureFilesWritable(files); + ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(files); if (operationStatus.hasReadonlyFiles()) { return; } - final Project project = context.getProject(); AbstractVcsHelper.getInstance(project).showMergeDialog(Arrays.asList(files), new CvsMergeProvider()); } catch (Exception e1) { diff --git a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java index 874360a86c5b..9846393b99a8 100644 --- a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java +++ b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java @@ -16,6 +16,7 @@ import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.remoteServer.agent.util.CloudGitApplication; +import com.intellij.remoteServer.agent.util.CloudLoggingHandler; import com.intellij.remoteServer.configuration.deployment.DeploymentSource; import com.intellij.remoteServer.runtime.deployment.DeploymentLogManager; import com.intellij.remoteServer.runtime.deployment.DeploymentTask; @@ -348,6 +349,11 @@ public class CloudGitDeploymentRuntime extends CloudDeploymentRuntime { }; } + @Override + protected CloudLoggingHandler getLoggingHandler() { + return super.getLoggingHandler(); + } + protected void addGitRemote(CloudGitApplication application) throws ServerRuntimeException { doGitRemote(getRemoteName(), application, "add", CloudBundle.getText("failed.add.remote", getRemoteName())); } diff --git a/plugins/groovy/groovy-psi/src/resources/groovyInjections.xml b/plugins/groovy/groovy-psi/src/resources/groovyInjections.xml index dcb426aa135f..910d211476f6 100644 --- a/plugins/groovy/groovy-psi/src/resources/groovyInjections.xml +++ b/plugins/groovy/groovy-psi/src/resources/groovyInjections.xml @@ -50,4 +50,13 @@ RegExp + + Charset Name + + + + + + + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/GroovySdkWizardStepBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/GroovySdkWizardStepBase.java index 0d063527027d..19649574c2bc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/GroovySdkWizardStepBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/GroovySdkWizardStepBase.java @@ -50,7 +50,9 @@ public abstract class GroovySdkWizardStepBase extends ModuleWizardStep { public GroovySdkWizardStepBase(@Nullable final MvcFramework framework, WizardContext wizardContext, String basePath) { myBasePath = basePath; - myLibrariesContainer = LibrariesContainerFactory.createContainer(wizardContext, wizardContext.getModulesProvider()); + myLibrariesContainer = wizardContext.getModulesProvider() == null + ? LibrariesContainerFactory.createContainer(wizardContext.getProject()) + : LibrariesContainerFactory.createContainer(wizardContext, wizardContext.getModulesProvider()); myFramework = framework; }