From e19eb64ee35b8ad22941997f876c39f40cc18963 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Sat, 26 Jul 2014 00:12:45 +0200 Subject: [PATCH 01/60] fix IPP test --- .../annotation/ExpandToNormalAnnotationIntentionTest.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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 From 6b251e6701887fc9486c5410ce19d8207a904816 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Sat, 26 Jul 2014 11:59:06 +0200 Subject: [PATCH 02/60] IDEA-127812 ([Very trivial] Spelling mistake in 'return of null' inspection description) --- .../src/inspectionDescriptions/ReturnNull.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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.

From e7ce04bbf5f011267762bd8801a2fd7784ac5036 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Sat, 26 Jul 2014 20:58:30 +0200 Subject: [PATCH 03/60] IDEA-15622 (Warn about bean-like getters/setters assigning a property to itself) --- .../src/META-INF/InspectionGadgets.xml | 4 + .../siyeh/InspectionGadgetsBundle.properties | 1 + .../PropertyValueSetToItselfInspection.java | 102 ++++++++++++++++++ .../PropertyValueSetToItself.html | 10 ++ ...ropertyValueSetToItselfInspectionTest.java | 56 ++++++++++ 5 files changed, 173 insertions(+) create mode 100644 plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javabeans/PropertyValueSetToItselfInspection.java create mode 100644 plugins/InspectionGadgets/src/inspectionDescriptions/PropertyValueSetToItself.html create mode 100644 plugins/InspectionGadgets/testsrc/com/siyeh/ig/javabeans/PropertyValueSetToItselfInspectionTest.java 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/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 From 49f68b13ef35918176059795d89887fd3ec0a9ca Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Sun, 27 Jul 2014 12:57:29 +0200 Subject: [PATCH 04/60] get rid of UnqualifiedTypeData --- .../jetbrains/protocolReader/BoxableType.java | 1 + .../jetbrains/protocolReader/Generator.java | 78 ++++++------------- .../protocolReader/OutputClassScope.java | 7 +- .../protocolReader/QualifiedTypeData.java | 8 +- .../jetbrains/protocolReader/TypeData.java | 47 ++++------- .../chromium/protocolReader/JsonField.java | 1 + .../jetbrains/protocolReader/ValueReader.java | 4 - 7 files changed, 54 insertions(+), 92 deletions(-) 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/Generator.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.java index e545f0280f81..90cc08c07c3c 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 @@ -115,91 +115,59 @@ class Generator { } QualifiedTypeData resolveType(final ItemDescriptor typedObject, final ResolveAndGenerateScope scope) { - UnqualifiedTypeData unqualifiedType = switchByType(typedObject, new TypeVisitor() { + 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 QualifiedTypeData visitRef(String refName) { + return new QualifiedTypeData(resolveRefType(scope.getDomainName(), refName, scope.getTypeDirection()), optional); } @Override - public UnqualifiedTypeData visitBoolean() { - return UnqualifiedTypeData.BOOLEAN; + public QualifiedTypeData visitBoolean() { + return new QualifiedTypeData(BoxableType.BOOLEAN, optional); } @Override - public UnqualifiedTypeData visitEnum(List enumConstants) { + public QualifiedTypeData visitEnum(List enumConstants) { assert scope instanceof MemberScope; - return new UnqualifiedTypeData(((MemberScope)scope).generateEnum(typedObject.description(), enumConstants)); + return new QualifiedTypeData(((MemberScope)scope).generateEnum(typedObject.description(), enumConstants), optional); } @Override - public UnqualifiedTypeData visitString() { - return UnqualifiedTypeData.STRING; + public QualifiedTypeData visitString() { + return new QualifiedTypeData(BoxableType.STRING, optional); } @Override - public UnqualifiedTypeData visitInteger() { - return UnqualifiedTypeData.INT; + public QualifiedTypeData visitInteger() { + return new QualifiedTypeData(BoxableType.INT, optional); } @Override - public UnqualifiedTypeData visitNumber() { - return UnqualifiedTypeData.NUMBER; + public QualifiedTypeData visitNumber() { + return new QualifiedTypeData(BoxableType.NUMBER, optional); } @Override - public UnqualifiedTypeData visitMap() { - return UnqualifiedTypeData.MAP; + public QualifiedTypeData visitMap() { + return new QualifiedTypeData(BoxableType.MAP, optional); } @Override - public UnqualifiedTypeData visitArray(ArrayItemType items) { - return new UnqualifiedTypeData(new ListType(scope.resolveType(items).getJavaType())); + public QualifiedTypeData visitArray(ArrayItemType items) { + return new QualifiedTypeData(new ListType(scope.resolveType(items).getJavaType()), optional); } @Override - public UnqualifiedTypeData visitObject(List properties) { - return new UnqualifiedTypeData(scope.generateNestedObject(typedObject.description(), properties), false); + public QualifiedTypeData visitObject(List properties) { + return new QualifiedTypeData(scope.generateNestedObject(typedObject.description(), properties), optional); } @Override - public UnqualifiedTypeData visitUnknown() { - return UnqualifiedTypeData.ANY; + public QualifiedTypeData visitUnknown() { + return new QualifiedTypeData(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,7 +242,7 @@ 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; } 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..8181d326e366 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); @@ -131,6 +131,7 @@ 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(); @@ -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(); 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/QualifiedTypeData.java index a4ccd0b3c49f..7fe090efa3f4 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/QualifiedTypeData.java @@ -1,11 +1,17 @@ package org.jetbrains.protocolReader; +import org.jetbrains.annotations.NotNull; + class QualifiedTypeData { private final BoxableType typeRef; private final boolean optional; private final boolean nullable; private final boolean asRawString; + QualifiedTypeData(BoxableType typeRef, boolean optional) { + this(typeRef, optional, false, false); + } + QualifiedTypeData(BoxableType typeRef, boolean optional, boolean nullable, boolean asRawString) { this.typeRef = typeRef; this.optional = optional; @@ -21,7 +27,7 @@ class QualifiedTypeData { return typeRef; } - void writeAnnotations(TextOutput out) { + void writeAnnotations(@NotNull TextOutput out) { if (optional || asRawString) { out.append("@org.chromium.protocolReader.JsonField("); if (optional) { 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-reader-runtime/src/org/chromium/protocolReader/JsonField.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonField.java index 5dfa26ca057a..88f57a616a3f 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/chromium/protocolReader/JsonField.java @@ -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/src/org/jetbrains/protocolReader/ValueReader.java b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ValueReader.java index 7ef6b3e0fc82..8e41d479a61b 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; From f9502aae50caadeec3a4349bba55324c65c9a389 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Sun, 27 Jul 2014 13:00:39 +0200 Subject: [PATCH 05/60] cleanup --- .../jetbrains/protocolReader/DomainGenerator.java | 2 +- .../org/jetbrains/protocolReader/Generator.java | 2 +- .../jetbrains/protocolReader/InputClassScope.java | 6 +++--- .../MyCreateStandaloneTypeBindingVisitorBase.java | 2 +- .../protocolReader/OutputClassScope.java | 10 +++++----- .../protocolReader/QualifiedTypeData.java | 15 ++++++++------- .../org/jetbrains/protocolReader/TextOutput.java | 10 +++++----- .../org/jetbrains/protocolReader/ValueReader.java | 2 +- 8 files changed, 25 insertions(+), 24 deletions(-) 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..4d0107640631 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 @@ -163,7 +163,7 @@ class DomainGenerator { } }; QualifiedTypeData itemTypeData = generator.resolveType(items, resolveAndGenerateScope); - BoxableType itemBoxableType = itemTypeData.getJavaType(); + BoxableType itemBoxableType = itemTypeData.getType(); final BoxableType arrayType = new ListType(itemBoxableType); StandaloneTypeBinding.Target target = new StandaloneTypeBinding.Target() { 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 90cc08c07c3c..c91dcf9239c9 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 @@ -155,7 +155,7 @@ class Generator { @Override public QualifiedTypeData visitArray(ArrayItemType items) { - return new QualifiedTypeData(new ListType(scope.resolveType(items).getJavaType()), optional); + return new QualifiedTypeData(new ListType(scope.resolveType(items).getType()), optional); } @Override 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..6287b1107dd5 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 @@ -20,7 +20,7 @@ class InputClassScope extends ClassScope { 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(); + out.append(paramTypeData.getType().getShortText(getClassContextNamespace())).space().append(methodName).append("();").newLine(); } } } @@ -39,7 +39,7 @@ class InputClassScope extends ClassScope { QualifiedTypeData propertyTypeData = memberScope.resolveType(objectProperty); propertyTypeData.writeAnnotations(out); - out.append(propertyTypeData.getJavaType().getShortText(getClassContextNamespace()) + ' ' + methodName + "();").newLine(); + out.append(propertyTypeData.getType().getShortText(getClassContextNamespace()) + ' ' + methodName + "();").newLine(); } } } @@ -93,7 +93,7 @@ class InputClassScope extends ClassScope { QualifiedTypeData 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/MyCreateStandaloneTypeBindingVisitorBase.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MyCreateStandaloneTypeBindingVisitorBase.java index e867bf924eaa..05fd1017e083 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 @@ -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 8181d326e366..faed3bba8f49 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 @@ -35,7 +35,7 @@ class OutputClassScope extends ClassScope { if (mandatoryParameters.size() == 1) { P parameter = mandatoryParameters.get(0); QualifiedTypeData typeData = new OutputMemberScope(getName(parameter)).resolveType(parameter); - if (typeData.getJavaType().getFullText().equals("int[]")) { + 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"; } @@ -134,7 +134,7 @@ class OutputClassScope extends ClassScope { 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(); } } @@ -162,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; @@ -191,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/QualifiedTypeData.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/QualifiedTypeData.java index 7fe090efa3f4..8d63defdda9c 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/QualifiedTypeData.java @@ -3,17 +3,17 @@ package org.jetbrains.protocolReader; import org.jetbrains.annotations.NotNull; class QualifiedTypeData { - private final BoxableType typeRef; + private final BoxableType type; private final boolean optional; private final boolean nullable; private final boolean asRawString; - QualifiedTypeData(BoxableType typeRef, boolean optional) { - this(typeRef, optional, false, false); + QualifiedTypeData(@NotNull BoxableType type, boolean optional) { + this(type, optional, false, false); } - QualifiedTypeData(BoxableType typeRef, boolean optional, boolean nullable, boolean asRawString) { - this.typeRef = typeRef; + QualifiedTypeData(@NotNull BoxableType type, boolean optional, boolean nullable, boolean asRawString) { + this.type = type; this.optional = optional; this.nullable = nullable; this.asRawString = asRawString; @@ -23,8 +23,9 @@ class QualifiedTypeData { return nullable; } - BoxableType getJavaType() { - return typeRef; + @NotNull + BoxableType getType() { + return type; } void writeAnnotations(@NotNull TextOutput out) { 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 8e41d479a61b..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 @@ -47,7 +47,7 @@ abstract class ValueReader { out.append("name"); } else { - out.quoute(fieldName); + out.quote(fieldName); } } } From d10677705663ef085a96f7d14dee747ed6f6dc16 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Sun, 27 Jul 2014 13:03:27 +0200 Subject: [PATCH 06/60] cleanup --- .../protocolReader/DomainGenerator.java | 4 +- .../jetbrains/protocolReader/Generator.java | 44 +++++++++---------- .../protocolReader/InputClassScope.java | 6 +-- .../jetbrains/protocolReader/MemberScope.java | 2 +- ...reateStandaloneTypeBindingVisitorBase.java | 2 +- .../protocolReader/OutputClassScope.java | 2 +- .../ResolveAndGenerateScope.java | 2 +- ...ifiedTypeData.java => TypeDescriptor.java} | 6 +-- 8 files changed, 34 insertions(+), 34 deletions(-) rename platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/{QualifiedTypeData.java => TypeDescriptor.java} (83%) 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 4d0107640631..b3906dc22987 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,7 +162,7 @@ class DomainGenerator { throw new UnsupportedOperationException(); } }; - QualifiedTypeData itemTypeData = generator.resolveType(items, resolveAndGenerateScope); + TypeDescriptor itemTypeData = generator.resolveType(items, resolveAndGenerateScope); BoxableType itemBoxableType = itemTypeData.getType(); final BoxableType arrayType = new ListType(itemBoxableType); 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 c91dcf9239c9..d42734a3e051 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,58 +114,58 @@ class Generator { fileSet.deleteOtherFiles(); } - QualifiedTypeData resolveType(final ItemDescriptor typedObject, final ResolveAndGenerateScope scope) { + TypeDescriptor resolveType(final ItemDescriptor typedObject, final ResolveAndGenerateScope scope) { final boolean optional = typedObject instanceof ItemDescriptor.Named && ((ItemDescriptor.Named)typedObject).optional(); - return switchByType(typedObject, new TypeVisitor() { + return switchByType(typedObject, new TypeVisitor() { @Override - public QualifiedTypeData visitRef(String refName) { - return new QualifiedTypeData(resolveRefType(scope.getDomainName(), refName, scope.getTypeDirection()), optional); + public TypeDescriptor visitRef(String refName) { + return new TypeDescriptor(resolveRefType(scope.getDomainName(), refName, scope.getTypeDirection()), optional); } @Override - public QualifiedTypeData visitBoolean() { - return new QualifiedTypeData(BoxableType.BOOLEAN, optional); + public TypeDescriptor visitBoolean() { + return new TypeDescriptor(BoxableType.BOOLEAN, optional); } @Override - public QualifiedTypeData visitEnum(List enumConstants) { + public TypeDescriptor visitEnum(List enumConstants) { assert scope instanceof MemberScope; - return new QualifiedTypeData(((MemberScope)scope).generateEnum(typedObject.description(), enumConstants), optional); + return new TypeDescriptor(((MemberScope)scope).generateEnum(typedObject.description(), enumConstants), optional); } @Override - public QualifiedTypeData visitString() { - return new QualifiedTypeData(BoxableType.STRING, optional); + public TypeDescriptor visitString() { + return new TypeDescriptor(BoxableType.STRING, optional); } @Override - public QualifiedTypeData visitInteger() { - return new QualifiedTypeData(BoxableType.INT, optional); + public TypeDescriptor visitInteger() { + return new TypeDescriptor(BoxableType.INT, optional); } @Override - public QualifiedTypeData visitNumber() { - return new QualifiedTypeData(BoxableType.NUMBER, optional); + public TypeDescriptor visitNumber() { + return new TypeDescriptor(BoxableType.NUMBER, optional); } @Override - public QualifiedTypeData visitMap() { - return new QualifiedTypeData(BoxableType.MAP, optional); + public TypeDescriptor visitMap() { + return new TypeDescriptor(BoxableType.MAP, optional); } @Override - public QualifiedTypeData visitArray(ArrayItemType items) { - return new QualifiedTypeData(new ListType(scope.resolveType(items).getType()), optional); + public TypeDescriptor visitArray(ArrayItemType items) { + return new TypeDescriptor(new ListType(scope.resolveType(items).getType()), optional); } @Override - public QualifiedTypeData visitObject(List properties) { - return new QualifiedTypeData(scope.generateNestedObject(typedObject.description(), properties), optional); + public TypeDescriptor visitObject(List properties) { + return new TypeDescriptor(scope.generateNestedObject(typedObject.description(), properties), optional); } @Override - public QualifiedTypeData visitUnknown() { - return new QualifiedTypeData(BoxableType.STRING, optional, false, true); + public TypeDescriptor visitUnknown() { + return new TypeDescriptor(BoxableType.STRING, optional, false, true); } }); } 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 6287b1107dd5..d34cb38772b8 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 @@ -18,7 +18,7 @@ class InputClassScope extends ClassScope { } String methodName = Generator.generateMethodNameSubstitute(getName(parameter), out); - QualifiedTypeData paramTypeData = newMemberScope(getName(parameter)).resolveType(parameter); + TypeDescriptor paramTypeData = newMemberScope(getName(parameter)).resolveType(parameter); paramTypeData.writeAnnotations(out); out.append(paramTypeData.getType().getShortText(getClassContextNamespace())).space().append(methodName).append("();").newLine(); } @@ -36,7 +36,7 @@ class InputClassScope extends ClassScope { String methodName = Generator.generateMethodNameSubstitute(propertyName, out); MemberScope memberScope = newMemberScope(propertyName); - QualifiedTypeData propertyTypeData = memberScope.resolveType(objectProperty); + TypeDescriptor propertyTypeData = memberScope.resolveType(objectProperty); propertyTypeData.writeAnnotations(out); out.append(propertyTypeData.getType().getShortText(getClassContextNamespace()) + ' ' + methodName + "();").newLine(); @@ -90,7 +90,7 @@ class InputClassScope extends ClassScope { String methodName = Generator.generateMethodNameSubstitute(getName(property), out); MemberScope memberScope = newMemberScope(getName(property)); - QualifiedTypeData propertyTypeData = memberScope.resolveType(property); + TypeDescriptor propertyTypeData = memberScope.resolveType(property); propertyTypeData.writeAnnotations(out); out.append(propertyTypeData.getType().getShortText(getClassContextNamespace()) + ' ' + methodName + "();").newLine(); 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 05fd1017e083..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(); } 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 faed3bba8f49..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 @@ -34,7 +34,7 @@ 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); + 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) { 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/QualifiedTypeData.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeDescriptor.java similarity index 83% 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 8d63defdda9c..4fd37530e460 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 @@ -2,17 +2,17 @@ package org.jetbrains.protocolReader; import org.jetbrains.annotations.NotNull; -class QualifiedTypeData { +class TypeDescriptor { private final BoxableType type; private final boolean optional; private final boolean nullable; private final boolean asRawString; - QualifiedTypeData(@NotNull BoxableType type, boolean optional) { + TypeDescriptor(@NotNull BoxableType type, boolean optional) { this(type, optional, false, false); } - QualifiedTypeData(@NotNull BoxableType type, boolean optional, boolean nullable, boolean asRawString) { + TypeDescriptor(@NotNull BoxableType type, boolean optional, boolean nullable, boolean asRawString) { this.type = type; this.optional = optional; this.nullable = nullable; From 135b809660794c496a52adfb6af7fa9d0e19131e Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Sun, 27 Jul 2014 13:08:24 +0200 Subject: [PATCH 07/60] cleanup --- .../src/org/jetbrains/protocolReader/DomainGenerator.java | 4 ++-- .../src/org/jetbrains/protocolReader/Generator.java | 2 +- .../src/org/jetbrains/protocolReader/InputClassScope.java | 4 ++-- .../jetbrains/protocolReader/ParserRootInterfaceItem.java | 2 +- .../src/org/jetbrains/protocolReader/TypeDescriptor.java | 4 ++-- .../protocolReader => jetbrains/jsonProtocol}/JsonField.java | 2 +- .../jsonProtocol}/JsonNullable.java | 2 +- .../jsonProtocol}/JsonOptionalField.java | 2 +- .../jsonProtocol}/JsonParseMethod.java | 2 +- .../jsonProtocol}/JsonSubtype.java | 2 +- .../jsonProtocol}/JsonSubtypeCasting.java | 2 +- .../protocolReader => jetbrains/jsonProtocol}/JsonType.java | 2 +- .../src/org/jetbrains/protocolReader/FieldProcessor.java | 5 ++++- .../src/org/jetbrains/protocolReader/InterfaceReader.java | 4 ++-- .../src/org/jetbrains/protocolReader/ReaderRoot.java | 2 +- .../src/org/jetbrains/jsonProtocol/ItemDescriptor.java | 2 -- .../src/org/jetbrains/jsonProtocol/ProtocolMetaModel.java | 4 ---- .../src/org/jetbrains/jsonProtocol/ProtocolSchemaReader.java | 1 - 18 files changed, 22 insertions(+), 26 deletions(-) rename platform/script-debugger/protocol/protocol-reader-runtime/src/org/{chromium/protocolReader => jetbrains/jsonProtocol}/JsonField.java (96%) rename platform/script-debugger/protocol/protocol-reader-runtime/src/org/{chromium/protocolReader => jetbrains/jsonProtocol}/JsonNullable.java (94%) rename platform/script-debugger/protocol/protocol-reader-runtime/src/org/{chromium/protocolReader => jetbrains/jsonProtocol}/JsonOptionalField.java (94%) rename platform/script-debugger/protocol/protocol-reader-runtime/src/org/{chromium/protocolReader => jetbrains/jsonProtocol}/JsonParseMethod.java (92%) rename platform/script-debugger/protocol/protocol-reader-runtime/src/org/{chromium/protocolReader => jetbrains/jsonProtocol}/JsonSubtype.java (92%) rename platform/script-debugger/protocol/protocol-reader-runtime/src/org/{chromium/protocolReader => jetbrains/jsonProtocol}/JsonSubtypeCasting.java (95%) rename platform/script-debugger/protocol/protocol-reader-runtime/src/org/{chromium/protocolReader => jetbrains/jsonProtocol}/JsonType.java (96%) 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 b3906dc22987..e4ece226e0a0 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 @@ -198,7 +198,7 @@ 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); @@ -313,7 +313,7 @@ class DomainGenerator { 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); 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 d42734a3e051..30e910468f75 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 @@ -246,7 +246,7 @@ class Generator { 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 d34cb38772b8..371c2a8b9458 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 @@ -79,11 +79,11 @@ class InputClassScope extends ClassScope { 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) { out.doc(property.description()); 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/TypeDescriptor.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeDescriptor.java index 4fd37530e460..d142e8bdf6d5 100644 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeDescriptor.java +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeDescriptor.java @@ -30,7 +30,7 @@ class TypeDescriptor { 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"); } @@ -44,7 +44,7 @@ class TypeDescriptor { } 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 88f57a616a3f..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; 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/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..5b75e48d2bc7 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,8 +1,8 @@ package org.jetbrains.protocolReader; import gnu.trove.THashSet; -import org.chromium.protocolReader.JsonField; -import org.chromium.protocolReader.JsonSubtype; +import org.jetbrains.jsonProtocol.JsonField; +import org.jetbrains.jsonProtocol.JsonSubtype; import org.jetbrains.annotations.Nullable; import org.jetbrains.io.JsonReaderEx; import org.jetbrains.jsonProtocol.StringIntPair; 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/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; From 49edb7d103c7d7c9d41be1cf49fb271402811a33 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Sun, 27 Jul 2014 13:41:18 +0200 Subject: [PATCH 08/60] fix read GetIndexedPropertiesResult --- .../jetbrains/protocolReader/ClassScope.java | 4 -- .../protocolReader/DomainGenerator.java | 15 +++-- .../jetbrains/protocolReader/Generator.java | 5 +- .../protocolReader/InputClassScope.java | 55 ++++++------------- .../jetbrains/jsonProtocol/JsonReaders.java | 2 +- .../protocolReader/InterfaceReader.java | 6 +- 6 files changed, 34 insertions(+), 53 deletions(-) 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 e4ece226e0a0..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 @@ -162,8 +162,7 @@ class DomainGenerator { throw new UnsupportedOperationException(); } }; - TypeDescriptor itemTypeData = generator.resolveType(items, resolveAndGenerateScope); - BoxableType itemBoxableType = itemTypeData.getType(); + 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()); @@ -201,7 +200,9 @@ class DomainGenerator { 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,7 +310,7 @@ 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); } @@ -318,7 +319,9 @@ class DomainGenerator { 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 30e910468f75..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,7 +114,7 @@ class Generator { fileSet.deleteOtherFiles(); } - TypeDescriptor resolveType(final ItemDescriptor typedObject, final ResolveAndGenerateScope scope) { + 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 @@ -155,7 +155,8 @@ class Generator { @Override public TypeDescriptor visitArray(ArrayItemType items) { - return new TypeDescriptor(new ListType(scope.resolveType(items).getType()), optional); + BoxableType type = scope.resolveType(items).getType(); + return new TypeDescriptor(new ListType(type), optional, false, type == BoxableType.ANY_STRING); } @Override 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 371c2a8b9458..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); - TypeDescriptor paramTypeData = newMemberScope(getName(parameter)).resolveType(parameter); - paramTypeData.writeAnnotations(out); - out.append(paramTypeData.getType().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); - TypeDescriptor propertyTypeData = memberScope.resolveType(objectProperty); - propertyTypeData.writeAnnotations(out); - - out.append(propertyTypeData.getType().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,7 +53,7 @@ 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 @@ -85,11 +66,11 @@ class InputClassScope extends ClassScope { else { 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)); + MemberScope memberScope = new InputMemberScope(getName(property)); TypeDescriptor propertyTypeData = memberScope.resolveType(property); propertyTypeData.writeAnnotations(out); 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/src/org/jetbrains/protocolReader/InterfaceReader.java b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/InterfaceReader.java index 5b75e48d2bc7..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.jetbrains.jsonProtocol.JsonField; -import org.jetbrains.jsonProtocol.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; From 7c21900dbb0c7c9163bea275e7bcc431c33f1a28 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Sun, 27 Jul 2014 18:06:38 +0400 Subject: [PATCH 09/60] Allow database element usages in everything-global scopes --- .../src/com/intellij/usages/impl/UsageViewManagerImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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; } From 9126db1856868a6d936813900b5485d1dc28aa35 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Sun, 27 Jul 2014 16:34:06 +0200 Subject: [PATCH 10/60] do not perform "recommended" if "restart required" detected it is general solution, ideal solution is complex --- .../backend/src/org/jetbrains/debugger/Breakpoint.java | 5 ----- .../src/org/jetbrains/debugger/DebugEventAdapter.java | 2 +- .../src/org/jetbrains/debugger/DebugEventListener.java | 2 +- 3 files changed, 2 insertions(+), 7 deletions(-) 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. From 68ebb6243aed22b1a26b309d08c81bb9e9de1f5b Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 28 Jul 2014 10:10:07 +0200 Subject: [PATCH 11/60] enable BytecodeAnalysisIndex by default --- .../bytecodeAnalysis/BytecodeAnalysisIndex.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisIndex.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisIndex.java index 297b2b694c62..22c35f9b0ed0 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisIndex.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisIndex.java @@ -16,8 +16,6 @@ package com.intellij.codeInspection.bytecodeAnalysis; import com.intellij.ide.highlighter.JavaClassFileType; -import com.intellij.openapi.application.Application; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.SystemProperties; import com.intellij.util.indexing.*; @@ -42,12 +40,7 @@ public class BytecodeAnalysisIndex extends FileBasedIndexExtension Date: Mon, 28 Jul 2014 10:10:19 +0200 Subject: [PATCH 12/60] dump more info in addition to lookup element weights --- .../com/intellij/internal/DumpLookupElementWeights.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) 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); } From 7ded3487fa1f171de707878750f304c24f625a0b Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 28 Jul 2014 10:10:57 +0200 Subject: [PATCH 13/60] don't lose actions while sorting goto action model (IDEA-127636) --- .../gotoByName/GotoActionItemProvider.java | 7 ++-- .../ide/util/gotoByName/GotoActionModel.java | 35 +++++++------------ 2 files changed, 17 insertions(+), 25 deletions(-) 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..985a30bcf3cf 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 @@ -24,7 +24,6 @@ import com.intellij.ide.ui.search.SearchableOptionsRegistrar; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.ActionUtil; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.keymap.KeymapManager; import com.intellij.openapi.keymap.KeymapUtil; @@ -57,7 +56,6 @@ import static com.intellij.ui.SimpleTextAttributes.STYLE_PLAIN; import static com.intellij.ui.SimpleTextAttributes.STYLE_SEARCH_MATCH; public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, Comparator, EdtSortingModel { - private static final Logger LOG = Logger.getInstance("#com.intellij.ide.util.gotoByName.GotoActionModel"); @Nullable private final Project myProject; private final Component myContextComponent; @@ -68,16 +66,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 +79,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) { @@ -459,15 +448,11 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C else if (description != null && !description.equals(text) && matcher.matches(description, compiledPattern)) { return MatchMode.DESCRIPTION; } - if (text == null) { - 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; + return text != null && matcher.matches(text, compiledPattern) ? MatchMode.NON_MENU : MatchMode.NONE; } - return matcher.matches(groupName + " " + text, compiledPattern) ? MatchMode.GROUP : MatchMode.NONE; + return text != null && matcher.matches(groupName + " " + text, compiledPattern) ? MatchMode.GROUP : MatchMode.NONE; } @Nullable @@ -643,9 +628,13 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C @Override public int compareTo(@NotNull ActionWrapper o) { int compared = myMode.compareTo(o.getMode()); - return compared != 0 - ? compared - : StringUtil.compare(myAction.getTemplatePresentation().getText(), o.getAction().getTemplatePresentation().getText(), true); + if (compared == 0) { + compared = StringUtil.compare(myAction.getTemplatePresentation().getText(), o.getAction().getTemplatePresentation().getText(), true); + } + if (compared == 0) { + compared = myAction.getClass().getName().compareTo(o.getAction().getClass().getName()); + } + return compared; } private boolean isAvailable() { From 4d8d3b072147d240b1e8b6e673722fdec3db2a55 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 28 Jul 2014 10:11:19 +0200 Subject: [PATCH 14/60] IDEA-127406 charset name completion: provide completion for a few more APIs --- .../java-support/resources/javaInjections.xml | 7 +++++++ .../groovy/groovy-psi/src/resources/groovyInjections.xml | 9 +++++++++ 2 files changed, 16 insertions(+) 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/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 + + + + + + + From a24e62f28d6e057dee797232e6c51272770e01e9 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 28 Jul 2014 10:11:37 +0200 Subject: [PATCH 15/60] IDEA-127512 Ctrl+Shift+Enter produces invalid code for catch statements --- .../smartEnter/MissingCatchBodyFixer.java | 2 +- .../smartEnter/PlainEnterProcessor.java | 20 +++++++++++++++---- .../AlreadyCompleteCatch.java | 12 +++++++++++ .../AlreadyCompleteCatch_after.java | 12 +++++++++++ .../codeInsight/CompleteStatementTest.java | 15 +++++++++++--- 5 files changed, 53 insertions(+), 8 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completeStatement/AlreadyCompleteCatch.java create mode 100644 java/java-tests/testData/codeInsight/completeStatement/AlreadyCompleteCatch_after.java 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..006ea6c2f3d0 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; 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-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/testSrc/com/intellij/codeInsight/CompleteStatementTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java index 2eecdaa9b221..b88876e28d9d 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java @@ -17,8 +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; @@ -54,6 +52,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(); } @@ -172,7 +182,6 @@ public class CompleteStatementTest extends EditorActionTestCase { public void testSCR36110() throws Exception { JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject()); - LanguageLevel old = LanguageLevelProjectExtension.getInstance(facade.getProject()).getLanguageLevel(); doTest(); } From 7594dc6033005af7056b3377cd5622e1d32147b5 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 28 Jul 2014 10:12:04 +0200 Subject: [PATCH 16/60] IDEA-127668 Smart type completion prefers constants to fields, normal completion prefers fields to constants --- .../completion/PreferByKindWeigher.java | 2 +- .../PreferFieldsToConstants.java | 17 +++++++++++++++++ .../SmartTypeCompletionOrderingTest.groovy | 4 ++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferFieldsToConstants.java 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-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/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"); } From 51a92208c29789119b53317acf789537c1220ce4 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 28 Jul 2014 10:12:27 +0200 Subject: [PATCH 17/60] support dollars in goto class patterns (IDEA-122889) --- .../DefaultClassNavigationContributor.java | 15 ++++++++++++++- .../intellij/navigation/ChooseByNameTest.groovy | 13 +++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) 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-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 From 6f8c9cd291e8ddf6569dfa8a98532bf7dc456baf Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 28 Jul 2014 10:13:19 +0200 Subject: [PATCH 18/60] IDEA-125281 Support @TypeQualifierDefault for nullable/notnull warnings --- .../impl/FieldFromParameterUtils.java | 4 +- .../codeInsight/AnnotationTargetUtil.java | 136 ++++++++++++++++++ .../intellij/codeInsight/AnnotationUtil.java | 4 +- .../codeInsight/NullableNotNullManager.java | 75 +++++++--- .../com/intellij/psi/impl/PsiImplUtil.java | 103 +------------ .../fixture/CustomTypeQualifierDefault.java | 25 ++++ .../DataFlowInspectionTest.java | 32 ++++- 7 files changed, 256 insertions(+), 123 deletions(-) create mode 100644 java/java-psi-api/src/com/intellij/codeInsight/AnnotationTargetUtil.java create mode 100644 java/java-tests/testData/inspection/dataFlow/fixture/CustomTypeQualifierDefault.java 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..c98b002ae664 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,12 +187,12 @@ 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); } 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); } 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/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/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java index 4cba2ab918a7..3bdcae2b9093 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java @@ -258,8 +258,14 @@ 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.addClass("package javax.annotation;" + + "@javax.annotation.meta.TypeQualifierDefault(java.lang.annotation.ElementType.PARAMETER) @javax.annotation.Nonnull " + + "public @interface ParametersAreNonnullByDefault {}"); + myFixture.addClass("package javax.annotation;" + + "@javax.annotation.meta.TypeQualifierDefault(java.lang.annotation.ElementType.PARAMETER) @javax.annotation.Nullable " + + "public @interface ParametersAreNullableByDefault {}"); 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 +273,28 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase { doTest(); } + private void addJavaxNullabilityAnnotations() { + myFixture.addClass("package javax.annotation;" + + "public @interface Nonnull {}"); + myFixture.addClass("package javax.annotation.meta;" + + "public @interface TypeQualifier {}"); + myFixture.addClass("package javax.annotation.meta;" + + "public @interface TypeQualifierDefault { java.lang.annotation.ElementType[] value() default {};}"); + } + + public void testCustomTypeQualifierDefault() { + addJavaxNullabilityAnnotations(); + 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")); From 998b2755cdc1f991858eae79e2bfe1f4408c3afb Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 28 Jul 2014 10:18:02 +0200 Subject: [PATCH 19/60] restore after faulty merge: log.error when encountering actions with null text (goto action, CR-IC-5843) --- .../ide/util/gotoByName/GotoActionModel.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) 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 985a30bcf3cf..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 @@ -24,6 +24,7 @@ import com.intellij.ide.ui.search.SearchableOptionsRegistrar; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.ActionUtil; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.keymap.KeymapManager; import com.intellij.openapi.keymap.KeymapUtil; @@ -56,6 +57,7 @@ import static com.intellij.ui.SimpleTextAttributes.STYLE_PLAIN; import static com.intellij.ui.SimpleTextAttributes.STYLE_SEARCH_MATCH; public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, Comparator, EdtSortingModel { + private static final Logger LOG = Logger.getInstance("#com.intellij.ide.util.gotoByName.GotoActionModel"); @Nullable private final Project myProject; private final Component myContextComponent; @@ -448,11 +450,15 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C else if (description != null && !description.equals(text) && matcher.matches(description, compiledPattern)) { return MatchMode.DESCRIPTION; } + if (text == null) { + LOG.error("Null text for action " + anAction + " of class " + anAction.getClass()); + return MatchMode.NONE; + } final String groupName = myActionGroups.get(anAction); if (groupName == null) { - return text != null && matcher.matches(text, compiledPattern) ? MatchMode.NON_MENU : MatchMode.NONE; + return matcher.matches(text, compiledPattern) ? MatchMode.NON_MENU : MatchMode.NONE; } - return text != null && matcher.matches(groupName + " " + text, compiledPattern) ? MatchMode.GROUP : MatchMode.NONE; + return matcher.matches(groupName + " " + text, compiledPattern) ? MatchMode.GROUP : MatchMode.NONE; } @Nullable @@ -602,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; @@ -628,13 +634,9 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C @Override public int compareTo(@NotNull ActionWrapper o) { int compared = myMode.compareTo(o.getMode()); - if (compared == 0) { - compared = StringUtil.compare(myAction.getTemplatePresentation().getText(), o.getAction().getTemplatePresentation().getText(), true); - } - if (compared == 0) { - compared = myAction.getClass().getName().compareTo(o.getAction().getClass().getName()); - } - return compared; + return compared != 0 + ? compared + : StringUtil.compare(myAction.getTemplatePresentation().getText(), o.getAction().getTemplatePresentation().getText(), true); } private boolean isAvailable() { From d57d9896e000b7ece4de1f4cea20936e05cc7001 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Thu, 24 Jul 2014 13:44:52 +0400 Subject: [PATCH 20/60] Complete fix for IDEA-62908, works now when virtual space is disabled as well. --- .../intellij/openapi/editor/impl/CaretImpl.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) 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..ea3f206285fc 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 @@ -82,11 +82,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; @@ -272,10 +271,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { } 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 && @@ -313,8 +309,10 @@ public class CaretImpl extends UserDataHolderBase implements Caret { 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. + if (lastOffsetColumn > newColumnNumber) { + desiredX = -1; + } newColumnNumber = lastColumnNumber = Math.max(lastOffsetColumn, newColumnNumber); - desiredX = -1; } if (!editorSettings.isCaretInsideTabs()) { CharSequence text = document.getCharsSequence(); From 9325dd0669e5741709e34fed1d4eabd36f8ca2a7 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Thu, 24 Jul 2014 15:32:04 +0400 Subject: [PATCH 21/60] IDEA-122811 Add caret below, add caret above creates duplicates when carets are at different positions. --- .../openapi/editor/impl/CaretImpl.java | 26 +++++-- .../EditorCloneCaretAboveBelowTest.java | 67 +++++++++++++++++++ 2 files changed, 86 insertions(+), 7 deletions(-) create mode 100644 platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorCloneCaretAboveBelowTest.java 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 ea3f206285fc..c2060abe4bd4 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,6 +62,10 @@ 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; /** * We check that caret is located at the target offset at the end of {@link #moveToOffset(int, boolean)} method. However, @@ -254,10 +258,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 { @@ -266,7 +271,7 @@ 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; } @@ -299,10 +304,10 @@ 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); @@ -310,9 +315,10 @@ public class CaretImpl extends UserDataHolderBase implements Caret { 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. if (lastOffsetColumn > newColumnNumber) { + newColumnNumber = lastOffsetColumn; desiredX = -1; + lastColumnNumber = -1; } - newColumnNumber = lastColumnNumber = Math.max(lastOffsetColumn, newColumnNumber); } if (!editorSettings.isCaretInsideTabs()) { CharSequence text = document.getCharsSequence(); @@ -351,7 +357,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); } } @@ -703,7 +709,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { myEditor.getFoldingModel().flushCaretPosition(); - setLastColumnNumber(column); + setLastColumnNumber(myLogicalCaret.column); myEditor.updateCaretCursor(); requestRepaint(oldInfo); @@ -1001,7 +1007,9 @@ 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(); if (myEditor.getCaretModel().addCaret(clone)) { if (hasNewSelection) { myEditor.getCaretModel().doWithCaretMerging(new Runnable() { @@ -1451,6 +1459,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-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..a75dd28aa38f --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorCloneCaretAboveBelowTest.java @@ -0,0 +1,67 @@ +/* + * 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.openapi.editor.impl.AbstractEditorTest; +import com.intellij.testFramework.TestFileType; + +import java.io.IOException; + +public class EditorCloneCaretAboveBelowTest extends AbstractEditorTest { + public void testStoringDesiredXPosition() throws IOException { + init("long line\n" + + "line\n" + + "long line\n" + + "very long line", + TestFileType.TEXT); + cloneCaretBelow(); + checkResultByText("long line\n" + + "line\n" + + "long line\n" + + "very long line"); + cloneCaretBelow(); + checkResultByText("long line\n" + + "line\n" + + "long line\n" + + "very long line"); + cloneCaretBelow(); + checkResultByText("long line\n" + + "line\n" + + "long line\n" + + "very long line"); + } + + public void testCloneAndMove() throws IOException { + init("long line\n" + + "line\n" + + "long line", + TestFileType.TEXT); + cloneCaretBelow(); + moveCaretDown(); + checkResultByText("long line\n" + + "line\n" + + "long line"); + } + + private static void cloneCaretBelow() { + executeAction(IdeActions.ACTION_EDITOR_CLONE_CARET_BELOW); + } + + private static void moveCaretDown() { + executeAction(IdeActions.ACTION_EDITOR_MOVE_CARET_DOWN); + } +} From f2100ad0a812ace013543e431cd113d9bdd0414f Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Thu, 24 Jul 2014 15:37:03 +0400 Subject: [PATCH 22/60] avoid deprecated method usage --- .../src/com/intellij/openapi/editor/impl/CaretImpl.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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 c2060abe4bd4..35c740b8cbfb 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 @@ -1402,9 +1402,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) { From 502805082c954b469c9ce0ffb9a362862c0c0e12 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Thu, 24 Jul 2014 18:58:49 +0400 Subject: [PATCH 23/60] make 'clone caret' actions remove carets if invoked in opposite direction --- .../editor/actions/CloneCaretAbove.java | 23 +--- .../actions/CloneCaretActionHandler.java | 106 ++++++++++++++++++ .../editor/actions/CloneCaretBelow.java | 27 +---- .../impl/ModifierKeyDoubleClickHandler.java | 6 +- .../EditorCloneCaretAboveBelowTest.java | 83 +++++++++----- 5 files changed, 169 insertions(+), 76 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretActionHandler.java 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..74122a978817 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretActionHandler.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.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, + IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT + )); + + 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.clone(myCloneAbove); + 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, 0); + 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/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-tests/testSrc/com/intellij/openapi/editor/actions/EditorCloneCaretAboveBelowTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorCloneCaretAboveBelowTest.java index a75dd28aa38f..1ae88e273f7a 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorCloneCaretAboveBelowTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorCloneCaretAboveBelowTest.java @@ -16,52 +16,83 @@ package com.intellij.openapi.editor.actions; import com.intellij.openapi.actionSystem.IdeActions; -import com.intellij.openapi.editor.impl.AbstractEditorTest; -import com.intellij.testFramework.TestFileType; +import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; import java.io.IOException; -public class EditorCloneCaretAboveBelowTest extends AbstractEditorTest { +public class EditorCloneCaretAboveBelowTest extends LightPlatformCodeInsightFixtureTestCase { public void testStoringDesiredXPosition() throws IOException { init("long line\n" + "line\n" + "long line\n" + - "very long line", - TestFileType.TEXT); + "very long line"); cloneCaretBelow(); - checkResultByText("long line\n" + - "line\n" + - "long line\n" + - "very long line"); + checkResult("long line\n" + + "line\n" + + "long line\n" + + "very long line"); cloneCaretBelow(); - checkResultByText("long line\n" + - "line\n" + - "long line\n" + - "very long line"); + checkResult("long line\n" + + "line\n" + + "long line\n" + + "very long line"); cloneCaretBelow(); - checkResultByText("long line\n" + - "line\n" + - "long line\n" + - "very long line"); + checkResult("long line\n" + + "line\n" + + "long line\n" + + "very long line"); } public void testCloneAndMove() throws IOException { init("long line\n" + "line\n" + - "long line", - TestFileType.TEXT); + "long line"); cloneCaretBelow(); moveCaretDown(); - checkResultByText("long line\n" + - "line\n" + - "long line"); + checkResult("long line\n" + + "line\n" + + "long line"); } - private static void cloneCaretBelow() { - executeAction(IdeActions.ACTION_EDITOR_CLONE_CARET_BELOW); + public void testCloneBelowAndAbove() throws IOException { + 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"); } - private static void moveCaretDown() { - executeAction(IdeActions.ACTION_EDITOR_MOVE_CARET_DOWN); + 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); } } From 466b1b009e57ff325629028aede5471076638a17 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Fri, 25 Jul 2014 11:56:48 +0400 Subject: [PATCH 24/60] remember original selection on cloning carets --- .../openapi/actionSystem/IdeActions.java | 2 ++ .../actions/CloneCaretActionHandler.java | 15 +++++++++---- .../openapi/editor/impl/CaretImpl.java | 21 +++++++++++++++---- .../keymap/impl/KeymapManagerImpl.java | 4 ++-- .../EditorCloneCaretAboveBelowTest.java | 18 +++++++++++----- 5 files changed, 45 insertions(+), 15 deletions(-) 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-impl/src/com/intellij/openapi/editor/actions/CloneCaretActionHandler.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretActionHandler.java index 74122a978817..5c5528a38153 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretActionHandler.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretActionHandler.java @@ -37,8 +37,8 @@ public class CloneCaretActionHandler extends EditorActionHandler { 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, - IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT + IdeActions.ACTION_EDITOR_MOVE_CARET_LEFT_WITH_SELECTION, + IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT_WITH_SELECTION )); private final boolean myCloneAbove; @@ -77,7 +77,14 @@ public class CloneCaretActionHandler extends EditorActionHandler { editor.getCaretModel().removeCaret(caret); } else { - Caret clone = caret.clone(myCloneAbove); + 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); } @@ -94,7 +101,7 @@ public class CloneCaretActionHandler extends EditorActionHandler { return value == null ? 0 : value; } else { - caret.putUserData(LEVEL, 0); + caret.putUserData(LEVEL, null); return 0; } } 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 35c740b8cbfb..01891f5dad23 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 @@ -67,6 +67,8 @@ public class CaretImpl extends UserDataHolderBase implements Caret { * 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: @@ -554,6 +556,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { } setLastColumnNumber(myLogicalCaret.column); + myDesiredSelectionStartColumn = myDesiredSelectionEndColumn = -1; myVisibleCaret = myEditor.logicalToVisualPosition(myLogicalCaret); updateOffsetsFromLogicalPosition(); @@ -710,6 +713,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { myEditor.getFoldingModel().flushCaretPosition(); setLastColumnNumber(myLogicalCaret.column); + myDesiredSelectionStartColumn = myDesiredSelectionEndColumn = -1; myEditor.updateCaretCursor(); requestRepaint(oldInfo); @@ -966,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; } @@ -975,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(); @@ -986,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(new LogicalPosition(selectionStart.line + lineShift, newSelectionStartColumn)); + LogicalPosition newSelectionEnd = truncate(new LogicalPosition(selectionEnd.line + lineShift, newSelectionEndColumn)); newSelectionStartOffset = myEditor.logicalPositionToOffset(newSelectionStart); newSelectionEndOffset = myEditor.logicalPositionToOffset(newSelectionEnd); newSelectionStartPosition = myEditor.logicalToVisualPosition(newSelectionStart); @@ -1000,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; @@ -1010,6 +1020,9 @@ public class CaretImpl extends UserDataHolderBase implements Caret { 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() { 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-tests/testSrc/com/intellij/openapi/editor/actions/EditorCloneCaretAboveBelowTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorCloneCaretAboveBelowTest.java index 1ae88e273f7a..2d73640ff655 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorCloneCaretAboveBelowTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorCloneCaretAboveBelowTest.java @@ -18,10 +18,8 @@ package com.intellij.openapi.editor.actions; import com.intellij.openapi.actionSystem.IdeActions; import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; -import java.io.IOException; - public class EditorCloneCaretAboveBelowTest extends LightPlatformCodeInsightFixtureTestCase { - public void testStoringDesiredXPosition() throws IOException { + public void testStoringDesiredXPosition() { init("long line\n" + "line\n" + "long line\n" + @@ -43,7 +41,7 @@ public class EditorCloneCaretAboveBelowTest extends LightPlatformCodeInsightFixt "very long line"); } - public void testCloneAndMove() throws IOException { + public void testCloneAndMove() { init("long line\n" + "line\n" + "long line"); @@ -54,7 +52,7 @@ public class EditorCloneCaretAboveBelowTest extends LightPlatformCodeInsightFixt "long line"); } - public void testCloneBelowAndAbove() throws IOException { + public void testCloneBelowAndAbove() { init("line\n" + "line\n" + "line"); @@ -76,6 +74,16 @@ public class EditorCloneCaretAboveBelowTest extends LightPlatformCodeInsightFixt "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); } From 2475b5a2e5caf2ea48ff3fdc9fa5a5cb56c9ad97 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Fri, 25 Jul 2014 12:02:06 +0400 Subject: [PATCH 25/60] fix exception at cloning carets --- .../com/intellij/openapi/editor/impl/CaretImpl.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) 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 01891f5dad23..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 @@ -994,8 +994,8 @@ public class CaretImpl extends UserDataHolderBase implements Caret { LogicalPosition selectionEnd = myEditor.visualToLogicalPosition(leadIsEnd ? startPosition : endPosition); newSelectionStartColumn = myDesiredSelectionStartColumn < 0 ? selectionStart.column : myDesiredSelectionStartColumn; newSelectionEndColumn = myDesiredSelectionEndColumn < 0 ? selectionEnd.column : myDesiredSelectionEndColumn; - LogicalPosition newSelectionStart = truncate(new LogicalPosition(selectionStart.line + lineShift, newSelectionStartColumn)); - LogicalPosition newSelectionEnd = truncate(new LogicalPosition(selectionEnd.line + lineShift, newSelectionEndColumn)); + 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); @@ -1044,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); } } From 39715123472c4642fd8e75fd0f13817796e4bea8 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Fri, 25 Jul 2014 14:45:26 +0400 Subject: [PATCH 26/60] make 'rich copy' functionality use exactly the same fonts as editor does for painting --- .../editor/richcopy/TextWithMarkupProcessor.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) 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 Date: Fri, 25 Jul 2014 18:11:48 +0400 Subject: [PATCH 27/60] fix inability to move caret to document trailing region using mouse or keyboard when soft wraps are enabled --- .../openapi/editor/impl/SoftWrapModelImpl.java | 9 +-------- .../openapi/editor/impl/AbstractEditorTest.java | 15 +++++++++++++++ .../openapi/editor/impl/EditorImplTest.java | 15 +++++++++++++++ 3 files changed, 31 insertions(+), 8 deletions(-) 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-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); } From 27c4a581ad868fa4e9f37a0211497e405d99e856 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Fri, 25 Jul 2014 19:28:29 +0400 Subject: [PATCH 28/60] IDEA-127198 New smart backspace feature is not good for deletion of blank line before --- .../editorActions/IndentingBackspaceHandler.java | 12 ++++++++++-- .../editor/indentingBackspace/beforeBrace-after.java | 4 ++++ .../editor/indentingBackspace/beforeBrace.java | 5 +++++ 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 platform/lang-impl/testData/editor/indentingBackspace/beforeBrace-after.java create mode 100644 platform/lang-impl/testData/editor/indentingBackspace/beforeBrace.java 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/testData/editor/indentingBackspace/beforeBrace-after.java b/platform/lang-impl/testData/editor/indentingBackspace/beforeBrace-after.java new file mode 100644 index 000000000000..f1733f5e6d06 --- /dev/null +++ b/platform/lang-impl/testData/editor/indentingBackspace/beforeBrace-after.java @@ -0,0 +1,4 @@ +class A { + void foo() { + } +} 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() { + } + +} From 1b9eacd43aaf8e37df35d9074bb1e2a6746d7f21 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Mon, 28 Jul 2014 12:19:42 +0400 Subject: [PATCH 29/60] temporary logging to investigate blinking tests --- .../testFramework/LightPlatformCodeInsightTestCase.java | 2 ++ 1 file changed, 2 insertions(+) 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; } From 695e05cd2277f6e1ad331c70f1ec1c8eb92f3264 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Mon, 28 Jul 2014 12:55:42 +0400 Subject: [PATCH 30/60] fixed DebuggerTreeTest.testUpdateDescriptors --- .../debugger/impl/DescriptorTestCase.java | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) 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); } } } From 97ed10bd9ff068690f0e887ba50c2be7d354ba9e Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 28 Jul 2014 10:16:12 +0200 Subject: [PATCH 31/60] cleanup --- .../intellij/xdebugger/impl/actions/ForceStepIntoAction.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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(); From eb1df96105c439c39e9e668d849fe0b03c0e7607 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Mon, 28 Jul 2014 13:23:48 +0400 Subject: [PATCH 32/60] fixed --- .../jetbrains/plugins/groovy/mvc/GroovySdkWizardStepBase.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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; } From d3b89163aa5343fe4752aebe39c0976b3a6a1c1a Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 28 Jul 2014 11:29:17 +0200 Subject: [PATCH 33/60] Always read previous indexed data from file when EXTRA_SANITY_CHECKS is set. This is needed to make index assertions to appear every time --- .../src/com/intellij/util/indexing/DebugAssertions.java | 2 +- .../src/com/intellij/util/indexing/MapReduceIndex.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/util/indexing/DebugAssertions.java b/platform/lang-impl/src/com/intellij/util/indexing/DebugAssertions.java index 6c866ad2283f..09aeea33b71e 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/DebugAssertions.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/DebugAssertions.java @@ -31,7 +31,7 @@ public class DebugAssertions { public static final boolean EXTRA_SANITY_CHECKS = SystemProperties.getBooleanProperty( "intellij.idea.indices.debug.extra.sanity", - true + DEBUG ); public static void assertTrue(boolean value) { diff --git a/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java index ebb7911e82be..89c531ec4bc5 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java @@ -354,7 +354,7 @@ public class MapReduceIndex implements UpdatableIndex Date: Mon, 28 Jul 2014 11:31:53 +0200 Subject: [PATCH 34/60] Prevent markers from overlapping after whitespace balancing (WEB-12693) [a=Roman Shevchenko, r=Maxim.Mossienko] --- .../intellij/lang/impl/PsiBuilderImpl.java | 8 ++++++- .../intellij/lang/PsiBuilderQuickTest.java | 21 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) 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/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); From c0df46cd5fb92a66d2e28cc5f367d9a25e529c42 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 28 Jul 2014 12:24:10 +0200 Subject: [PATCH 35/60] flush cached library info in async way via flushing daemon --- .../src/com/intellij/openapi/vfs/impl/jar/JarHandler.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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..06676b213831 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 @@ -30,6 +30,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 +170,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 +260,12 @@ public class JarHandler extends ZipHandler { } assert info != null; ourCachedLibraryInfo = info; + FlushingDaemon.everyFiveSeconds(new Runnable() { + @Override + public void run() { + if (ourCachedLibraryInfo.isDirty()) ourCachedLibraryInfo.force(); + } + }); } private CacheLibraryInfo(@NotNull String path, long time, long length) { From 642b8702d321d25d6cc5d70f9c7a459f49702e45 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 28 Jul 2014 12:38:03 +0200 Subject: [PATCH 36/60] disable bytecode analysis index as it leads to OOM during indexing teamcity (as Yann says) --- .../bytecodeAnalysis/BytecodeAnalysisIndex.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisIndex.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisIndex.java index 22c35f9b0ed0..297b2b694c62 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisIndex.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisIndex.java @@ -16,6 +16,8 @@ package com.intellij.codeInspection.bytecodeAnalysis; import com.intellij.ide.highlighter.JavaClassFileType; +import com.intellij.openapi.application.Application; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.SystemProperties; import com.intellij.util.indexing.*; @@ -40,7 +42,12 @@ public class BytecodeAnalysisIndex extends FileBasedIndexExtension Date: Mon, 28 Jul 2014 12:48:05 +0200 Subject: [PATCH 37/60] find in path to ignore .idea on the first pass, but allow to see the results there if needed (IDEA-123559, IDEA-127419) --- .../src/com/intellij/find/FindModel.java | 20 +++++++- .../intellij/find/impl/FindInProjectTask.java | 25 ++++++++-- .../usages/FindUsagesProcessPresentation.java | 11 ++++ .../usages/impl/SearchForUsagesRunnable.java | 50 +++++++++++++------ 4 files changed, 87 insertions(+), 19 deletions(-) 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/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/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() { From be5b5124b29a651098517726b9eafbcbc3a1c475 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 28 Jul 2014 12:49:52 +0200 Subject: [PATCH 38/60] CR-IC-5839#CFR-87746 "Now it makes no sense to override this method so why not mark is as deprecated?" --- .../xdebugger/evaluation/XDebuggerEvaluator.java | 2 ++ .../impl/evaluate/quick/XQuickEvaluateHandler.java | 9 +-------- 2 files changed, 3 insertions(+), 8 deletions(-) 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/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(); } } From be928c0ef69bb848786b8299501e2ee4a12d5344 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 28 Jul 2014 13:09:07 +0200 Subject: [PATCH 39/60] IDEA-127930 IDE doesn't repaint if close last editor --- .../openapi/fileEditor/impl/EditorWindow.java | 11 +++++++++++ 1 file changed, 11 insertions(+) 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(); From 19edaa4e475c9fc740f49c1c981013e68cbeade9 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 28 Jul 2014 13:17:39 +0200 Subject: [PATCH 40/60] CR-IC-5835#CFR-87684 restore ClassFilter API --- .../intellij/ui/classFilter/ClassFilter.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) 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; From 6342e6e8618a1f70019e329634933d81d33346df Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 28 Jul 2014 13:37:52 +0200 Subject: [PATCH 41/60] WEB-11049 Chrome insists to download javascript source map files, despite disabled setting, when started from IntelliJ IDEA --- .../backend/src/org/jetbrains/debugger/VmBase.java | 1 + 1 file changed, 1 insertion(+) 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 From d609d2d7889d2738ee133e8bbe3374727ec621e9 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 28 Jul 2014 14:01:45 +0200 Subject: [PATCH 42/60] temporary fix for popups which stay forever --- .../src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; From ade2c2127349332a6d49543ee03f7e13120ea688 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 28 Jul 2014 14:12:27 +0200 Subject: [PATCH 43/60] flush cached libraries info upon shutdown --- .../intellij/openapi/vfs/impl/jar/JarHandler.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) 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 06676b213831..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; @@ -263,9 +264,20 @@ public class JarHandler extends ZipHandler { FlushingDaemon.everyFiveSeconds(new Runnable() { @Override public void run() { - if (ourCachedLibraryInfo.isDirty()) ourCachedLibraryInfo.force(); + 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) { From 499960f802b8c4c5e6c4f209b8879f42cb07b954 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 28 Jul 2014 15:00:49 +0200 Subject: [PATCH 44/60] + Darcula checkbox menu item --- .../ide/ui/laf/darcula/darcula.properties | 3 + .../darcula/ui/DarculaCheckBoxMenuItemUI.java | 81 +++++++ .../laf/darcula/ui/DarculaMenuItemUIBase.java | 208 ++++++++++++++++++ 3 files changed, 292 insertions(+) create mode 100644 platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaCheckBoxMenuItemUI.java create mode 100644 platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaMenuItemUIBase.java 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..abbb299e6aad 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,9 @@ MenuBar.shadow=3c3f41 MenuBar.darcula.borderColor=555555 MenuBar.darcula.borderShadowColor=282828 +CheckBoxMenuItemUI=com.intellij.ide.ui.laf.darcula.ui.DarculaCheckBoxMenuItemUI +CheckBoxMenuItem.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); + } + } +} From 27a3d4f9a35ea6fe1a5005051be9e85770beaebb Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 28 Jul 2014 15:11:20 +0200 Subject: [PATCH 45/60] + Darcula menu item radio buttons --- .../ide/ui/laf/darcula/darcula.properties | 4 + .../ui/DarculaRadioButtonMenuItemUI.java | 85 +++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonMenuItemUI.java 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 abbb299e6aad..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 @@ -51,6 +51,10 @@ 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/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(); + } +} From b5b2244e6b2486907f5b8f028061c23b41e1d1fe Mon Sep 17 00:00:00 2001 From: Michael Golubev Date: Mon, 28 Jul 2014 14:49:17 +0200 Subject: [PATCH 46/60] IDEA-127377 - IAE at com.intellij.remoteServer.util.CloudGitDeploymentRuntime$6.onLineAvailable --- .../remoteServer/util/CloudGitDeploymentRuntime.java | 6 ++++++ 1 file changed, 6 insertions(+) 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())); } From 586c2d49f995de7dde2dae32d6b06a0c75c0c69a Mon Sep 17 00:00:00 2001 From: Michael Golubev Date: Mon, 28 Jul 2014 14:51:04 +0200 Subject: [PATCH 47/60] CR-IC-5700 - move polling to ui --- .../runtime/ServerConnectionManagerImpl.java | 21 ---------------- .../runtime/ui/ServersToolWindowContent.java | 24 ++++++++++++++++++- 2 files changed, 23 insertions(+), 22 deletions(-) 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)); From 8208134548dd0afe4fe82ad3775656e386e95757 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 28 Jul 2014 14:19:01 +0200 Subject: [PATCH 48/60] complete catch clause cleanup --- .../editorActions/smartEnter/MissingCatchBodyFixer.java | 3 --- .../com/intellij/codeInsight/CompleteStatementTest.java | 2 -- 2 files changed, 5 deletions(-) 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 006ea6c2f3d0..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 @@ -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-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java index b88876e28d9d..3f199d44ea13 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java @@ -17,7 +17,6 @@ package com.intellij.codeInsight; import com.intellij.JavaTestUtil; import com.intellij.openapi.actionSystem.IdeActions; -import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; @@ -181,7 +180,6 @@ public class CompleteStatementTest extends EditorActionTestCase { } public void testSCR36110() throws Exception { - JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject()); doTest(); } From a6e027610104efd6b962bfdd20f775152e4bf377 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 28 Jul 2014 15:32:16 +0200 Subject: [PATCH 49/60] fix javax nullable/notnull tests (IDEA-125281) --- .../impl/FieldFromParameterUtils.java | 4 +-- .../DataFlowInspectionTest.java | 36 ++++++++++--------- .../NullableStuffInspectionTest.java | 11 +++--- 3 files changed, 28 insertions(+), 23 deletions(-) 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 c98b002ae664..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 @@ -189,12 +189,12 @@ public final class FieldFromParameterUtils { final NullableNotNullManager manager = NullableNotNullManager.getInstance(project); 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 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-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java index 3bdcae2b9093..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,14 +259,8 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase { public void testAccessingSameArrayElements() { doTest(); } public void testParametersAreNonnullByDefault() { - addJavaxNullabilityAnnotations(); - - myFixture.addClass("package javax.annotation;" + - "@javax.annotation.meta.TypeQualifierDefault(java.lang.annotation.ElementType.PARAMETER) @javax.annotation.Nonnull " + - "public @interface ParametersAreNonnullByDefault {}"); - myFixture.addClass("package javax.annotation;" + - "@javax.annotation.meta.TypeQualifierDefault(java.lang.annotation.ElementType.PARAMETER) @javax.annotation.Nullable " + - "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;"); @@ -273,17 +268,26 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase { doTest(); } - private void addJavaxNullabilityAnnotations() { - myFixture.addClass("package javax.annotation;" + - "public @interface Nonnull {}"); - myFixture.addClass("package javax.annotation.meta;" + - "public @interface TypeQualifier {}"); - myFixture.addClass("package javax.annotation.meta;" + - "public @interface TypeQualifierDefault { java.lang.annotation.ElementType[] value() default {};}"); + 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(); + addJavaxNullabilityAnnotations(myFixture); myFixture.addClass("package bar;" + "@javax.annotation.meta.TypeQualifierDefault(java.lang.annotation.ElementType.METHOD) @javax.annotation.Nonnull " + "public @interface MethodsAreNotNullByDefault {}"); 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")); From 34aca9371d5ee323e3384752aa3ab916e028ecac Mon Sep 17 00:00:00 2001 From: nik Date: Mon, 28 Jul 2014 17:37:03 +0400 Subject: [PATCH 50/60] added default value to Registry.is call to fix MissingResourceException from Kotlin --- .../src/com/intellij/psi/impl/file/impl/FileManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 { From 9af31244e72b25e2b9ca2bf4bef39eba324cfab8 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Mon, 28 Jul 2014 15:44:30 +0200 Subject: [PATCH 51/60] avoid unnecessary and time-consuming type resolution for method parameters --- .../expression/MethodEvaluator.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) 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; + } } } } From bc9ff879e6a24078ea44c593d7dfb7268f75454e Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 28 Jul 2014 16:24:46 +0200 Subject: [PATCH 52/60] skip empty map --- .../org/jetbrains/debugger/sourcemap/SourceMapDecoder.java | 4 ++++ 1 file changed, 4 insertions(+) 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()]; From dcc8675a4730a514cbecf5654811e21dbb447306 Mon Sep 17 00:00:00 2001 From: Sergey Simonchik Date: Mon, 28 Jul 2014 18:31:30 +0400 Subject: [PATCH 53/60] WEB-12852 Windows: IDE exits when stopping Node.js app --- native/runner/runnerw/runnerw.cpp | 80 +++++++++++++++++++++++++------ 1 file changed, 66 insertions(+), 14 deletions(-) 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); From e467bf59c2693f5be40f5a4aa99e07b7ab41e44d Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 28 Jul 2014 16:53:30 +0200 Subject: [PATCH 54/60] =?UTF-8?q?fix=20computeNotSparseGroups=20=E2=80=94?= =?UTF-8?q?=20expected=20exclusive=20"to",=20so,=20we=20should=20pass=20"e?= =?UTF-8?q?ndInclusive=20+=201"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../debugger/LazyVariablesGroup.java | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) 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; } From d45730191b5eae798cff87a1074ded9e49ea2464 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 28 Jul 2014 17:00:44 +0200 Subject: [PATCH 55/60] getSelectedFiles is NotNull --- .../com/intellij/cvsSupport2/actions/merge/MergeAction.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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..75533ea2c08f 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,7 +58,7 @@ 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 ReadonlyStatusHandler.OperationStatus operationStatus = ReadonlyStatusHandler.getInstance(context.getProject()).ensureFilesWritable(files); if (operationStatus.hasReadonlyFiles()) { From 321e884332e99d01c01edfadfe42b266022c74a8 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 28 Jul 2014 17:02:06 +0200 Subject: [PATCH 56/60] ensureFilesWriteable may show dialog --- .../com/intellij/cvsSupport2/actions/merge/MergeAction.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 75533ea2c08f..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 @@ -59,12 +59,12 @@ public class MergeAction extends AnAction { final VcsContext context = CvsContextWrapper.createCachedInstance(e); final VirtualFile[] files = context.getSelectedFiles(); 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) { From c7ea4a1d5c2c2a8904ea1fc8e059420cef7f77e8 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Mon, 28 Jul 2014 16:41:53 +0400 Subject: [PATCH 57/60] incompatible api changes reverted, chronon plugin works again --- platform/platform-resources/src/brokenPlugins.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 From c2cd5cdfa0141191654a0a93f4b1b38e591c2c74 Mon Sep 17 00:00:00 2001 From: Andrey Starovoyt Date: Mon, 28 Jul 2014 19:19:21 +0400 Subject: [PATCH 58/60] export expression chooser to separate class --- .../CastExpressionPostfixTemplate.java | 10 ++- .../IntroduceFieldPostfixTemplate.java | 10 ++- .../IntroduceVariablePostfixTemplate.java | 10 ++- .../JavaPostfixTemplateWithChooser.java | 42 ---------- .../NotExpressionPostfixTemplate.java | 16 +--- ...arenthesizedExpressionPostfixTemplate.java | 12 +-- .../util/JavaPostfixTemplatesUtils.java | 4 +- ...er.java => ChooserExpressionSelector.java} | 70 ++++++++-------- .../postfix/templates/NotPostfixTemplate.java | 22 +++-- .../ParenthesizedPostfixTemplate.java | 19 +++-- .../PostfixTemplateExpressionSelector.java | 54 ++++++++++++ .../templates/PostfixTemplatePsiInfo.java | 35 ++++++-- .../templates/PostfixTemplatePsiInfoBase.java | 39 --------- ...PostfixTemplateWithExpressionSelector.java | 83 +++++++++++++++++++ .../templates/PostfixTemplatesUtils.java | 18 ++++ .../StatementWrapPostfixTemplate.java | 6 +- .../templates/StringBasedPostfixTemplate.java | 8 +- .../SurroundPostfixTemplateBase.java | 2 +- .../templates/TopmostExpressionSelector.java | 58 +++++++++++++ .../templates/TypedPostfixTemplate.java | 42 ---------- 20 files changed, 334 insertions(+), 226 deletions(-) delete mode 100644 java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateWithChooser.java rename platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/{ExpressionPostfixTemplateWithChooser.java => ChooserExpressionSelector.java} (55%) create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateExpressionSelector.java delete mode 100644 platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfoBase.java create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateWithExpressionSelector.java create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TopmostExpressionSelector.java delete mode 100644 platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TypedPostfixTemplate.java 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/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); - } -} From 9b6ad0c968ac8d8626deea1a5fba53c503df0872 Mon Sep 17 00:00:00 2001 From: Sergey Savenko Date: Wed, 23 Jul 2014 17:55:24 +0400 Subject: [PATCH 59/60] add constructors to JTable successors --- .../src/com/intellij/ui/table/BaseTableView.java | 8 ++++++-- .../platform-api/src/com/intellij/ui/table/JBTable.java | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) 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 From a586ea72f9999a3d5c313de99498e9f3a6c36d05 Mon Sep 17 00:00:00 2001 From: Sergey Simonchik Date: Mon, 28 Jul 2014 19:47:13 +0400 Subject: [PATCH 60/60] update runnerw.exe after WEB-12852 --- bin/win/runnerw.exe | Bin 106088 -> 99840 bytes native/runner/runnerw/.gitignore | 1 + 2 files changed, 1 insertion(+) diff --git a/bin/win/runnerw.exe b/bin/win/runnerw.exe index 5c5f103adca8894cd7b1a6441f61462c0ba660ea..29c5d336d08c8a4bd97407506e888f6f82177974 100644 GIT binary patch delta 32511 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 ME+0`Fto_!%0d-cnbN~PV delta 38857 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