mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
Binary file not shown.
+13
-8
@@ -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<Method> methods = _refType.methodsByName(myMethodName);
|
||||
for (Method method : methods) {
|
||||
List<Type> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,8 +138,8 @@ public class PreferByKindWeigher extends LookupElementWeigher {
|
||||
qualifiedWithField,
|
||||
qualifiedWithGetter,
|
||||
superMethodParameters,
|
||||
expectedTypeConstant,
|
||||
field,
|
||||
expectedTypeConstant,
|
||||
getter,
|
||||
normal,
|
||||
collectionFactory,
|
||||
|
||||
+1
-4
@@ -36,7 +36,7 @@ public class MissingCatchBodyFixer implements Fixer {
|
||||
final Document doc = editor.getDocument();
|
||||
|
||||
PsiCodeBlock body = catchSection.getCatchBlock();
|
||||
if (body != null && startLine(doc, body) == startLine(doc, catchSection)) return;
|
||||
if (body != null && body.getLBrace() != null && body.getRBrace() != null) return;
|
||||
|
||||
final PsiJavaToken rParenth = catchSection.getRParenth();
|
||||
if (rParenth == null) return;
|
||||
@@ -44,7 +44,4 @@ public class MissingCatchBodyFixer implements Fixer {
|
||||
doc.insertString(rParenth.getTextRange().getEndOffset(), "{}");
|
||||
}
|
||||
|
||||
private static int startLine(Document doc, PsiElement psiElement) {
|
||||
return doc.getLineNumber(psiElement.getTextRange().getStartOffset());
|
||||
}
|
||||
}
|
||||
+16
-4
@@ -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;
|
||||
}
|
||||
|
||||
+4
-4
@@ -187,14 +187,14 @@ public final class FieldFromParameterUtils {
|
||||
modifierList.setModifierProperty(PsiModifier.FINAL, isFinal);
|
||||
|
||||
final NullableNotNullManager manager = NullableNotNullManager.getInstance(project);
|
||||
final String nullable = manager.getNullable(parameter);
|
||||
final PsiAnnotation nullable = manager.getNullableAnnotation(parameter, false);
|
||||
if (nullable != null && !manager.isContainerAnnotation(nullable)) {
|
||||
modifierList.addAfter(factory.createAnnotationFromText("@" + nullable, field), null);
|
||||
modifierList.addAfter(factory.createAnnotationFromText("@" + nullable.getQualifiedName(), field), null);
|
||||
}
|
||||
else if (isFinal) {
|
||||
final String notNull = manager.getNotNull(parameter);
|
||||
final PsiAnnotation notNull = manager.getNotNullAnnotation(parameter, false);
|
||||
if (notNull != null && !manager.isContainerAnnotation(notNull)) {
|
||||
modifierList.addAfter(factory.createAnnotationFromText("@" + notNull, field), null);
|
||||
modifierList.addAfter(factory.createAnnotationFromText("@" + notNull.getQualifiedName(), field), null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-3
@@ -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);
|
||||
}
|
||||
}
|
||||
+7
-3
@@ -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);
|
||||
|
||||
+7
-3
@@ -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();
|
||||
|
||||
-42
@@ -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<PsiElement> getTypeCondition() {
|
||||
return JavaPostfixTemplatesUtils.IS_NON_VOID;
|
||||
}
|
||||
}
|
||||
+3
-13
@@ -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<PsiElement> getTypeCondition() {
|
||||
return JavaPostfixTemplatesUtils.IS_BOOLEAN;
|
||||
super(alias, alias, "!expr", JAVA_PSI_INFO, IS_BOOLEAN);
|
||||
}
|
||||
}
|
||||
+1
-11
@@ -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<PsiElement> getTypeCondition() {
|
||||
return IS_NON_VOID;
|
||||
super(JAVA_PSI_INFO, IS_NON_VOID);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -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
|
||||
|
||||
+14
-1
@@ -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<NavigationItem> 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<PsiClass>() {
|
||||
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());
|
||||
|
||||
@@ -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<PsiAnnotation.TargetType> 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<PsiAnnotation.TargetType> 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 <PsiAnnotation.TargetType> 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;
|
||||
}
|
||||
}
|
||||
@@ -379,14 +379,14 @@ public class AnnotationUtil {
|
||||
@NotNull
|
||||
public static PsiAnnotation[] getAllAnnotations(@NotNull PsiModifierListOwner owner,
|
||||
boolean inHierarchy,
|
||||
Set<PsiModifierListOwner> visited) {
|
||||
@Nullable Set<PsiModifierListOwner> visited) {
|
||||
return getAllAnnotations(owner, inHierarchy, visited, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiAnnotation[] getAllAnnotations(@NotNull PsiModifierListOwner owner,
|
||||
boolean inHierarchy,
|
||||
Set<PsiModifierListOwner> visited, boolean withInferred) {
|
||||
@Nullable Set<PsiModifierListOwner> visited, boolean withInferred) {
|
||||
final PsiModifierList list = owner.getModifierList();
|
||||
PsiAnnotation[] annotations = PsiAnnotation.EMPTY_ARRAY;
|
||||
if (list != null) {
|
||||
|
||||
@@ -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<Element> {
|
||||
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<Element>
|
||||
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<Element>
|
||||
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<Element>
|
||||
}
|
||||
|
||||
@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<Element>
|
||||
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<Element>
|
||||
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<PsiAnnotation.TargetType> required = AnnotationTargetUtil.extractRequiredAnnotationTargets(tqDefault.findAttributeValue(null));
|
||||
if (required == null) return false;
|
||||
return required.isEmpty() || ContainerUtil.intersects(required, Arrays.asList(placeTargetTypes));
|
||||
}
|
||||
|
||||
public List<String> getNullables() {
|
||||
return myNullables;
|
||||
}
|
||||
|
||||
@@ -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<TargetType> 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 <TargetType> 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
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
class Foo {
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
} catch (Ex<caret>ception e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
|
||||
class Foo {
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
} catch (Exception e)
|
||||
{
|
||||
<caret>
|
||||
}
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
public class Foo {
|
||||
|
||||
private LocalDate dateField;
|
||||
|
||||
void foo(LocalDate date) {
|
||||
|
||||
}
|
||||
|
||||
void bar() {
|
||||
foo(<caret>)
|
||||
}
|
||||
}
|
||||
|
||||
class LocalDate {
|
||||
public static final LocalDate MAX;
|
||||
public static final LocalDate MIN;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import foo.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
class Some {
|
||||
void foo(@NotNull String s) {
|
||||
NotNullClass.foo(null);
|
||||
if (<warning descr="Condition 'NotNullClass.foo(s) == null' is always 'false'">NotNullClass.foo(s) == null</warning>) {}
|
||||
|
||||
NullableClass.foo(null);
|
||||
if (NullableClass.foo("a") == null) {}
|
||||
|
||||
AnotherPackageNotNull.foo(null);
|
||||
if (<warning descr="Condition 'AnotherPackageNotNull.foo(s) == null' is always 'false'">AnotherPackageNotNull.foo(s) == null</warning>) {}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@bar.MethodsAreNotNullByDefault
|
||||
class NotNullClass {
|
||||
static native Object foo(String s);
|
||||
|
||||
}
|
||||
class NullableClass {
|
||||
static native Object foo(String s);
|
||||
}
|
||||
@@ -17,9 +17,6 @@ package com.intellij.codeInsight;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.openapi.actionSystem.IdeActions;
|
||||
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
|
||||
@@ -54,6 +51,18 @@ public class CompleteStatementTest extends EditorActionTestCase {
|
||||
|
||||
public void testCompleteCatchLParen() throws Exception { doTest(); }
|
||||
|
||||
public void testAlreadyCompleteCatch() throws Exception {
|
||||
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
|
||||
int old = settings.BRACE_STYLE;
|
||||
settings.BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE;
|
||||
try {
|
||||
doTest();
|
||||
}
|
||||
finally {
|
||||
settings.BRACE_STYLE = old;
|
||||
}
|
||||
}
|
||||
|
||||
public void testCompleteCatchWithExpression() throws Exception { doTest(); }
|
||||
|
||||
public void testCompleteCatchBody() throws Exception { doTest(); }
|
||||
@@ -171,8 +180,6 @@ public class CompleteStatementTest extends EditorActionTestCase {
|
||||
}
|
||||
|
||||
public void testSCR36110() throws Exception {
|
||||
JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject());
|
||||
LanguageLevel old = LanguageLevelProjectExtension.getInstance(facade.getProject()).getLanguageLevel();
|
||||
doTest();
|
||||
}
|
||||
|
||||
|
||||
+4
@@ -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");
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.codeInspection;
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInspection.dataFlow.DataFlowInspection;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture;
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -258,8 +259,8 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase {
|
||||
public void testAccessingSameArrayElements() { doTest(); }
|
||||
|
||||
public void testParametersAreNonnullByDefault() {
|
||||
myFixture.addClass("package javax.annotation; public @interface ParametersAreNonnullByDefault {}");
|
||||
myFixture.addClass("package javax.annotation; public @interface ParametersAreNullableByDefault {}");
|
||||
addJavaxNullabilityAnnotations(myFixture);
|
||||
addJavaxDefaultNullabilityAnnotations(myFixture);
|
||||
|
||||
myFixture.addClass("package foo; public class AnotherPackageNotNull { public static void foo(String s) {}}");
|
||||
myFixture.addFileToProject("foo/package-info.java", "@javax.annotation.ParametersAreNonnullByDefault package foo;");
|
||||
@@ -267,6 +268,37 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public static void addJavaxDefaultNullabilityAnnotations(final JavaCodeInsightTestFixture fixture) {
|
||||
fixture.addClass("package javax.annotation;" +
|
||||
"@javax.annotation.meta.TypeQualifierDefault(java.lang.annotation.ElementType.PARAMETER) @javax.annotation.Nonnull " +
|
||||
"public @interface ParametersAreNonnullByDefault {}");
|
||||
fixture.addClass("package javax.annotation;" +
|
||||
"@javax.annotation.meta.TypeQualifierDefault(java.lang.annotation.ElementType.PARAMETER) @javax.annotation.Nullable " +
|
||||
"public @interface ParametersAreNullableByDefault {}");
|
||||
}
|
||||
|
||||
public static void addJavaxNullabilityAnnotations(final JavaCodeInsightTestFixture fixture) {
|
||||
fixture.addClass("package javax.annotation;" +
|
||||
"public @interface Nonnull {}");
|
||||
fixture.addClass("package javax.annotation;" +
|
||||
"public @interface Nullable {}");
|
||||
fixture.addClass("package javax.annotation.meta;" +
|
||||
"public @interface TypeQualifierDefault { java.lang.annotation.ElementType[] value() default {};}");
|
||||
}
|
||||
|
||||
public void testCustomTypeQualifierDefault() {
|
||||
addJavaxNullabilityAnnotations(myFixture);
|
||||
myFixture.addClass("package bar;" +
|
||||
"@javax.annotation.meta.TypeQualifierDefault(java.lang.annotation.ElementType.METHOD) @javax.annotation.Nonnull " +
|
||||
"public @interface MethodsAreNotNullByDefault {}");
|
||||
|
||||
myFixture.addClass("package foo; public class AnotherPackageNotNull { public static native Object foo(String s); }");
|
||||
myFixture.addFileToProject("foo/package-info.java", "@bar.MethodsAreNotNullByDefault package foo;");
|
||||
|
||||
myFixture.enableInspections(new DataFlowInspection());
|
||||
myFixture.testHighlighting(true, false, true, getTestName(false) + ".java");
|
||||
}
|
||||
|
||||
public void testTrueOrEqualsSomething() {
|
||||
doTest();
|
||||
myFixture.launchAction(myFixture.findSingleIntention("Remove redundant assignment"));
|
||||
|
||||
+6
-5
@@ -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"));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
*.aps
|
||||
*.vcxproj.user
|
||||
Debug
|
||||
Release
|
||||
*.suo
|
||||
*.opensdf
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
+10
-2
@@ -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;
|
||||
}
|
||||
|
||||
+33
-37
@@ -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<PsiElement> myCondition;
|
||||
|
||||
protected ExpressionPostfixTemplateWithChooser(@NotNull String name, @NotNull String example, @NotNull PostfixTemplatePsiInfoBase info) {
|
||||
super(name, example);
|
||||
myInfo = info;
|
||||
public ChooserExpressionSelector(@NotNull Condition<PsiElement> 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<PsiElement> expressions = getExpressions(context, editor.getDocument(), editor.getCaretModel().getOffset());
|
||||
public void expandTemplate(@NotNull final PostfixTemplateWithExpressionSelector postfixTemplate,
|
||||
@NotNull PsiElement context,
|
||||
@NotNull final Editor editor) {
|
||||
List<PsiElement> 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<PsiElement> getExpressions(@NotNull PsiElement context, @NotNull Document document, final int offset) {
|
||||
List<PsiElement> possibleExpressions = myInfo.getExpressions(context, document, offset);
|
||||
private List<PsiElement> getExpressions(@NotNull PostfixTemplateWithExpressionSelector postfixTemplate,
|
||||
@NotNull PsiElement context,
|
||||
@NotNull Document document,
|
||||
final int offset) {
|
||||
List<PsiElement> possibleExpressions = postfixTemplate.getPsiInfo().getExpressions(context, document, offset);
|
||||
List<PsiElement> expressions = ContainerUtil.filter(possibleExpressions,
|
||||
new Condition<PsiElement>() {
|
||||
@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<PsiElement> getTypeCondition() {
|
||||
return Condition.TRUE;
|
||||
private static List<PsiElement> maybeTopmostExpression(@NotNull PostfixTemplateWithExpressionSelector postfixTemplate, @NotNull PsiElement context) {
|
||||
return ContainerUtil.createMaybeSingletonList(postfixTemplate.getPsiInfo().getTopmostExpression(context));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<PsiElement> maybeTopmostExpression(@NotNull PsiElement context) {
|
||||
return ContainerUtil.createMaybeSingletonList(myInfo.getTopmostExpression(context));
|
||||
}
|
||||
|
||||
protected abstract void doIt(@NotNull Editor editor, @NotNull PsiElement expression);
|
||||
}
|
||||
+15
-7
@@ -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<PsiElement> 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<PsiElement> 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);
|
||||
}
|
||||
}
|
||||
+14
-5
@@ -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<PsiElement> 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, "(", ")"));
|
||||
}
|
||||
}
|
||||
+54
@@ -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);
|
||||
}
|
||||
+26
-9
@@ -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<PsiElement> getExpressions(@NotNull PsiElement context, @NotNull Document document, int offset);
|
||||
|
||||
@NotNull
|
||||
public Function<PsiElement, String> getRenderer() {
|
||||
return new Function<PsiElement, String>() {
|
||||
@Override
|
||||
public String fun(@NotNull PsiElement element) {
|
||||
return element.getText();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
-39
@@ -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<PsiElement> getExpressions(@NotNull PsiElement context, @NotNull Document document, int newOffset);
|
||||
|
||||
@NotNull
|
||||
public Function<PsiElement, String> getRenderer() {
|
||||
return new Function<PsiElement, String>() {
|
||||
@Override
|
||||
public String fun(@NotNull PsiElement element) {
|
||||
return element.getText();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+83
@@ -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<PsiElement> 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;
|
||||
}
|
||||
}
|
||||
+18
@@ -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.<PsiElement>alwaysTrue());
|
||||
}
|
||||
|
||||
public static PostfixTemplateExpressionSelector selectorTopmost() {
|
||||
return selectorTopmost(Conditions.<PsiElement>alwaysTrue());
|
||||
}
|
||||
|
||||
public static PostfixTemplateExpressionSelector selectorWithChooser(Condition<PsiElement> condition) {
|
||||
return new ChooserExpressionSelector(condition);
|
||||
}
|
||||
|
||||
public static PostfixTemplateExpressionSelector selectorTopmost(Condition<PsiElement> condition) {
|
||||
return new TopmostExpressionSelector(condition);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static TextRange surround(@NotNull Surrounder surrounder,
|
||||
@NotNull Editor editor,
|
||||
|
||||
+2
-4
@@ -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);
|
||||
|
||||
+3
-5
@@ -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());
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
+58
@@ -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<PsiElement> myCondition;
|
||||
|
||||
public TopmostExpressionSelector(@NotNull Condition<PsiElement> 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);
|
||||
}
|
||||
}
|
||||
-42
@@ -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<PsiElement> myTypeChecker;
|
||||
|
||||
protected TypedPostfixTemplate(@NotNull String name,
|
||||
@NotNull String example,
|
||||
@NotNull PostfixTemplatePsiInfo psiInfo,
|
||||
@NotNull Condition<PsiElement> 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);
|
||||
}
|
||||
}
|
||||
@@ -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<PsiFile> psiFiles,
|
||||
@NotNull FindUsagesProcessPresentation processPresentation,
|
||||
@NotNull Processor<UsageInfo> consumer) {
|
||||
@NotNull final Processor<UsageInfo> 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<UsageInfo>() {
|
||||
@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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<AnAction> 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<ActionWrapper> 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);
|
||||
|
||||
@@ -68,16 +68,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
|
||||
private Pattern myCompiledPattern;
|
||||
|
||||
protected final SearchableOptionsRegistrar myIndex;
|
||||
protected final Map<AnAction, String> myActionsMap = new TreeMap<AnAction, String>(new Comparator<AnAction>() {
|
||||
@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<AnAction, String> myActionGroups = ContainerUtil.newHashMap();
|
||||
|
||||
protected final Map<String, ApplyIntentionAction> myIntentions = new TreeMap<String, ApplyIntentionAction>();
|
||||
private final Map<String, String> myConfigurablesNames = ContainerUtil.newTroveMap();
|
||||
@@ -90,7 +81,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
|
||||
myProject = project;
|
||||
myContextComponent = component;
|
||||
final ActionGroup mainMenu = (ActionGroup)myActionManager.getActionOrStub(IdeActions.GROUP_MAIN_MENU);
|
||||
collectActions(myActionsMap, mainMenu, mainMenu.getTemplatePresentation().getText());
|
||||
collectActions(myActionGroups, mainMenu, mainMenu.getTemplatePresentation().getText());
|
||||
if (project != null && editor != null && file != null) {
|
||||
final ApplyIntentionAction[] children = ApplyIntentionAction.getAvailableIntentions(editor, file);
|
||||
if (children != null) {
|
||||
@@ -463,7 +454,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
|
||||
LOG.error("Null text for action " + anAction + " of class " + anAction.getClass());
|
||||
return MatchMode.NONE;
|
||||
}
|
||||
final String groupName = myActionsMap.get(anAction);
|
||||
final String groupName = myActionGroups.get(anAction);
|
||||
if (groupName == null) {
|
||||
return matcher.matches(text, compiledPattern) ? MatchMode.NON_MENU : MatchMode.NONE;
|
||||
}
|
||||
@@ -617,7 +608,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
|
||||
PatternMatcher getMatcher() {
|
||||
return myMatcher.get();
|
||||
}
|
||||
|
||||
|
||||
public static class ActionWrapper implements Comparable<ActionWrapper>{
|
||||
private final AnAction myAction;
|
||||
private final MatchMode myMode;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+6
-8
@@ -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<RawTextWithM
|
||||
|
||||
private MarkupIterator(@NotNull CharSequence charSequence, @NotNull RangeIterator rangeIterator, @NotNull EditorColorsScheme colorsScheme) {
|
||||
myRangeIterator = rangeIterator;
|
||||
mySegmentIterator = new SegmentIterator(charSequence, colorsScheme.getEditorFontName(), colorsScheme.getEditorFontSize());
|
||||
mySegmentIterator = new SegmentIterator(charSequence, colorsScheme.getFontPreferences());
|
||||
}
|
||||
|
||||
public boolean atEnd() {
|
||||
@@ -812,8 +813,7 @@ public class TextWithMarkupProcessor extends CopyPastePostProcessor<RawTextWithM
|
||||
|
||||
private static class SegmentIterator {
|
||||
private final CharSequence myCharSequence;
|
||||
private final String myDefaultFontFamilyName;
|
||||
private final int myFontSize;
|
||||
private final FontPreferences myFontPreferences;
|
||||
|
||||
private int myCurrentStartOffset;
|
||||
private int myCurrentOffset;
|
||||
@@ -822,10 +822,9 @@ public class TextWithMarkupProcessor extends CopyPastePostProcessor<RawTextWithM
|
||||
private String myCurrentFontFamilyName;
|
||||
private String myNextFontFamilyName;
|
||||
|
||||
private SegmentIterator(CharSequence charSequence, String defaultFontFamilyName, int fontSize) {
|
||||
private SegmentIterator(CharSequence charSequence, FontPreferences fontPreferences) {
|
||||
myCharSequence = charSequence;
|
||||
myDefaultFontFamilyName = defaultFontFamilyName;
|
||||
myFontSize = fontSize;
|
||||
myFontPreferences = fontPreferences;
|
||||
}
|
||||
|
||||
public void reset(int startOffset, int endOffset, int fontStyle) {
|
||||
@@ -843,9 +842,8 @@ public class TextWithMarkupProcessor extends CopyPastePostProcessor<RawTextWithM
|
||||
myCurrentStartOffset = myCurrentOffset;
|
||||
for (; myCurrentOffset < myEndOffset; myCurrentOffset++) {
|
||||
FontInfo fontInfo = ComplementaryFontsRegistry.getFontAbleToDisplay(myCharSequence.charAt(myCurrentOffset),
|
||||
myFontSize,
|
||||
myFontStyle,
|
||||
myDefaultFontFamilyName);
|
||||
myFontPreferences);
|
||||
String fontFamilyName = fontInfo.getFont().getFamily();
|
||||
|
||||
if (myCurrentFontFamilyName == null) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -354,7 +354,7 @@ public class MapReduceIndex<Key, Value, Input> implements UpdatableIndex<Key,Val
|
||||
FileContent fileContent = (FileContent)content;
|
||||
hashId = getHashOfContent(fileContent);
|
||||
if (doReadSavedPersistentData) {
|
||||
if (!myContents.isBusyReading()) { // avoid blocking read, we can calculate index value
|
||||
if (!myContents.isBusyReading() || DebugAssertions.EXTRA_SANITY_CHECKS) { // avoid blocking read, we can calculate index value
|
||||
ByteSequence bytes = myContents.get(hashId);
|
||||
if (bytes != null) {
|
||||
data = deserializeSavedPersistentData(bytes);
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
class A {
|
||||
void foo() {
|
||||
}
|
||||
<caret>}
|
||||
@@ -0,0 +1,5 @@
|
||||
class A {
|
||||
void foo() {
|
||||
}
|
||||
|
||||
<caret>}
|
||||
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -48,6 +48,13 @@ MenuBar.shadow=3c3f41
|
||||
MenuBar.darcula.borderColor=555555
|
||||
MenuBar.darcula.borderShadowColor=282828
|
||||
|
||||
CheckBoxMenuItemUI=com.intellij.ide.ui.laf.darcula.ui.DarculaCheckBoxMenuItemUI
|
||||
CheckBoxMenuItem.borderPainted=false
|
||||
|
||||
RadioButtonMenuItemUI=com.intellij.ide.ui.laf.darcula.ui.DarculaRadioButtonMenuItemUI
|
||||
RadioButtonMenuItem.borderPainted=false
|
||||
|
||||
|
||||
TabbedPaneUI=com.intellij.ide.ui.laf.darcula.ui.DarculaTabbedPaneUI
|
||||
TabbedPane.tabInsets=0,4,0,4
|
||||
TabbedPane.highlight=292b2d
|
||||
|
||||
+81
@@ -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);
|
||||
}
|
||||
}
|
||||
+208
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+85
@@ -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();
|
||||
}
|
||||
}
|
||||
+1
-22
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.editor.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.IdeActions;
|
||||
import com.intellij.openapi.editor.Caret;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.EditorLastActionTracker;
|
||||
import com.intellij.openapi.editor.ScrollType;
|
||||
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class CloneCaretActionHandler extends EditorActionHandler {
|
||||
private static final Key<Integer> LEVEL = Key.create("CloneCaretActionHandler.level");
|
||||
|
||||
private static final Set<String> OUR_ACTIONS = new HashSet<String>(Arrays.asList(
|
||||
IdeActions.ACTION_EDITOR_CLONE_CARET_ABOVE,
|
||||
IdeActions.ACTION_EDITOR_CLONE_CARET_BELOW,
|
||||
IdeActions.ACTION_EDITOR_MOVE_CARET_LEFT_WITH_SELECTION,
|
||||
IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT_WITH_SELECTION
|
||||
));
|
||||
|
||||
private final boolean myCloneAbove;
|
||||
|
||||
public CloneCaretActionHandler(boolean above) {
|
||||
myCloneAbove = above;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(Editor editor, DataContext dataContext) {
|
||||
return editor.getCaretModel().supportsMultipleCarets();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doExecute(Editor editor, @Nullable Caret targetCaret, DataContext dataContext) {
|
||||
if (targetCaret != null) {
|
||||
targetCaret.clone(myCloneAbove);
|
||||
return;
|
||||
}
|
||||
int currentLevel = 0;
|
||||
List<Caret> currentCarets = new ArrayList<Caret>();
|
||||
for (Caret caret : editor.getCaretModel().getAllCarets()) {
|
||||
int level = getLevel(caret);
|
||||
if (Math.abs(level) > Math.abs(currentLevel)) {
|
||||
currentLevel = level;
|
||||
currentCarets.clear();
|
||||
}
|
||||
if (Math.abs(level) == Math.abs(currentLevel)) {
|
||||
currentCarets.add(caret);
|
||||
}
|
||||
}
|
||||
boolean removeCarets = currentLevel > 0 && myCloneAbove || currentLevel < 0 && !myCloneAbove;
|
||||
Integer newLevel = myCloneAbove ? currentLevel - 1 : currentLevel + 1;
|
||||
for (Caret caret : currentCarets) {
|
||||
if (removeCarets) {
|
||||
editor.getCaretModel().removeCaret(caret);
|
||||
}
|
||||
else {
|
||||
Caret clone = caret;
|
||||
do {
|
||||
Caret original = clone;
|
||||
clone = clone.clone(myCloneAbove);
|
||||
if (original != caret) {
|
||||
editor.getCaretModel().removeCaret(original);
|
||||
}
|
||||
} while (clone != null && caret.hasSelection() && !clone.hasSelection());
|
||||
if (clone != null) {
|
||||
clone.putUserData(LEVEL, newLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (removeCarets) {
|
||||
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
|
||||
}
|
||||
}
|
||||
|
||||
private static int getLevel(Caret caret) {
|
||||
if (isRepeatedActionInvocation()) {
|
||||
Integer value = caret.getUserData(LEVEL);
|
||||
return value == null ? 0 : value;
|
||||
}
|
||||
else {
|
||||
caret.putUserData(LEVEL, null);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isRepeatedActionInvocation() {
|
||||
String lastActionId = EditorLastActionTracker.getInstance().getLastActionId();
|
||||
return OUR_ACTIONS.contains(lastActionId);
|
||||
}
|
||||
}
|
||||
+1
-26
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,13 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
|
||||
private int myVisualLineEnd;
|
||||
private RangeMarker savedBeforeBulkCaretMarker;
|
||||
private boolean mySkipChangeRequests;
|
||||
/**
|
||||
* Initial horizontal caret position during vertical navigation.
|
||||
* Similar to {@link #myDesiredX}, but represents logical caret position (<code>getLogicalPosition().column</code>) rather than visual.
|
||||
*/
|
||||
private int myLastColumnNumber = 0;
|
||||
private int myDesiredSelectionStartColumn = -1;
|
||||
private int myDesiredSelectionEndColumn = -1;
|
||||
/**
|
||||
* We check that caret is located at the target offset at the end of {@link #moveToOffset(int, boolean)} method. However,
|
||||
* it's possible that the following situation occurs:
|
||||
@@ -82,11 +88,10 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
|
||||
*/
|
||||
private boolean myReportCaretMoves;
|
||||
/**
|
||||
* There is a possible case that user defined non-monospaced font for editor. That means that various symbols have different
|
||||
* visual widths. That means that if we move caret vertically it may deviate to the left/right. However, we can try to preserve
|
||||
* its initial visual position when possible.
|
||||
* This field holds initial horizontal caret position during vertical navigation. It's used to determine target position when
|
||||
* moving to the new line. It is stored in pixels, not in columns, to account for non-monospaced fonts as well.
|
||||
* <p/>
|
||||
* This field holds desired value for visual <code>'x'</code> caret coordinate (negative value if no coordinate should be preserved).
|
||||
* Negative value means no coordinate should be preserved.
|
||||
*/
|
||||
private int myDesiredX = -1;
|
||||
|
||||
@@ -255,10 +260,11 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
|
||||
EditorSettings editorSettings = myEditor.getSettings();
|
||||
VisualPosition visualCaret = getVisualPosition();
|
||||
|
||||
int lastColumnNumber = myLastColumnNumber;
|
||||
int desiredX = myDesiredX;
|
||||
if (columnShift == 0) {
|
||||
if (myDesiredX < 0) {
|
||||
desiredX = myEditor.visualPositionToXY(visualCaret).x;
|
||||
desiredX = getCurrentX();
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -267,15 +273,12 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
|
||||
|
||||
int newLineNumber = visualCaret.line + lineShift;
|
||||
int newColumnNumber = visualCaret.column + columnShift;
|
||||
if (desiredX >= 0 && !ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
if (desiredX >= 0) {
|
||||
newColumnNumber = myEditor.xyToVisualPosition(new Point(desiredX, Math.max(0, newLineNumber) * myEditor.getLineHeight())).column;
|
||||
}
|
||||
|
||||
Document document = myEditor.getDocument();
|
||||
if (!editorSettings.isVirtualSpace() && columnShift == 0 && getLogicalPosition().softWrapLinesOnCurrentLogicalLine <= 0) {
|
||||
newColumnNumber = supportsMultipleCarets() ? myLastColumnNumber : myEditor.getLastColumnNumber();
|
||||
}
|
||||
else if (!editorSettings.isVirtualSpace() && lineShift == 0 && columnShift == 1) {
|
||||
if (!editorSettings.isVirtualSpace() && lineShift == 0 && columnShift == 1) {
|
||||
int lastLine = document.getLineCount() - 1;
|
||||
if (lastLine < 0) lastLine = 0;
|
||||
if (EditorModificationUtil.calcAfterLineEnd(myEditor) >= 0 &&
|
||||
@@ -303,18 +306,21 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
|
||||
// We want to move caret to the first column if it's already located at the first line and 'Up' is pressed.
|
||||
newColumnNumber = 0;
|
||||
desiredX = -1;
|
||||
lastColumnNumber = -1;
|
||||
}
|
||||
|
||||
VisualPosition pos = new VisualPosition(newLineNumber, newColumnNumber);
|
||||
int lastColumnNumber = newColumnNumber;
|
||||
if (!myEditor.getSoftWrapModel().isInsideSoftWrap(pos)) {
|
||||
LogicalPosition log = myEditor.visualToLogicalPosition(new VisualPosition(newLineNumber, newColumnNumber));
|
||||
int offset = myEditor.logicalPositionToOffset(log);
|
||||
if (offset >= document.getTextLength()) {
|
||||
int lastOffsetColumn = myEditor.offsetToVisualPosition(document.getTextLength()).column;
|
||||
// We want to move caret to the last column if if it's located at the last line and 'Down' is pressed.
|
||||
newColumnNumber = lastColumnNumber = Math.max(lastOffsetColumn, newColumnNumber);
|
||||
desiredX = -1;
|
||||
if (lastOffsetColumn > newColumnNumber) {
|
||||
newColumnNumber = lastOffsetColumn;
|
||||
desiredX = -1;
|
||||
lastColumnNumber = -1;
|
||||
}
|
||||
}
|
||||
if (!editorSettings.isCaretInsideTabs()) {
|
||||
CharSequence text = document.getCharsSequence();
|
||||
@@ -353,7 +359,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
|
||||
}
|
||||
else {
|
||||
moveToVisualPosition(pos);
|
||||
if (!editorSettings.isVirtualSpace() && columnShift == 0) {
|
||||
if (!editorSettings.isVirtualSpace() && columnShift == 0 && lastColumnNumber >=0) {
|
||||
setLastColumnNumber(lastColumnNumber);
|
||||
}
|
||||
}
|
||||
@@ -550,6 +556,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
|
||||
}
|
||||
|
||||
setLastColumnNumber(myLogicalCaret.column);
|
||||
myDesiredSelectionStartColumn = myDesiredSelectionEndColumn = -1;
|
||||
myVisibleCaret = myEditor.logicalToVisualPosition(myLogicalCaret);
|
||||
|
||||
updateOffsetsFromLogicalPosition();
|
||||
@@ -705,7 +712,8 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
|
||||
|
||||
myEditor.getFoldingModel().flushCaretPosition();
|
||||
|
||||
setLastColumnNumber(column);
|
||||
setLastColumnNumber(myLogicalCaret.column);
|
||||
myDesiredSelectionStartColumn = myDesiredSelectionEndColumn = -1;
|
||||
myEditor.updateCaretCursor();
|
||||
requestRepaint(oldInfo);
|
||||
|
||||
@@ -962,6 +970,8 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
|
||||
clone.myLastColumnNumber = this.myLastColumnNumber;
|
||||
clone.myReportCaretMoves = this.myReportCaretMoves;
|
||||
clone.myDesiredX = this.myDesiredX;
|
||||
clone.myDesiredSelectionStartColumn = -1;
|
||||
clone.myDesiredSelectionEndColumn = -1;
|
||||
return clone;
|
||||
}
|
||||
|
||||
@@ -971,10 +981,10 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
|
||||
assertIsDispatchThread();
|
||||
int lineShift = above ? -1 : 1;
|
||||
final CaretImpl clone = cloneWithoutSelection();
|
||||
final int newSelectionStartOffset, newSelectionEndOffset;
|
||||
final int newSelectionStartOffset, newSelectionEndOffset, newSelectionStartColumn, newSelectionEndColumn;
|
||||
final VisualPosition newSelectionStartPosition, newSelectionEndPosition;
|
||||
final boolean hasNewSelection;
|
||||
if (hasSelection()) {
|
||||
if (hasSelection() || myDesiredSelectionStartColumn >=0 || myDesiredSelectionEndColumn >= 0) {
|
||||
VisualPosition startPosition = getSelectionStartPosition();
|
||||
VisualPosition endPosition = getSelectionEndPosition();
|
||||
VisualPosition leadPosition = getLeadSelectionPosition();
|
||||
@@ -982,8 +992,10 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
|
||||
boolean leadIsEnd = leadPosition.equals(endPosition);
|
||||
LogicalPosition selectionStart = myEditor.visualToLogicalPosition(leadIsStart || leadIsEnd ? leadPosition : startPosition);
|
||||
LogicalPosition selectionEnd = myEditor.visualToLogicalPosition(leadIsEnd ? startPosition : endPosition);
|
||||
LogicalPosition newSelectionStart = truncate(new LogicalPosition(selectionStart.line + lineShift, selectionStart.column));
|
||||
LogicalPosition newSelectionEnd = truncate(new LogicalPosition(selectionEnd.line + lineShift, selectionEnd.column));
|
||||
newSelectionStartColumn = myDesiredSelectionStartColumn < 0 ? selectionStart.column : myDesiredSelectionStartColumn;
|
||||
newSelectionEndColumn = myDesiredSelectionEndColumn < 0 ? selectionEnd.column : myDesiredSelectionEndColumn;
|
||||
LogicalPosition newSelectionStart = truncate(selectionStart.line + lineShift, newSelectionStartColumn);
|
||||
LogicalPosition newSelectionEnd = truncate(selectionEnd.line + lineShift, newSelectionEndColumn);
|
||||
newSelectionStartOffset = myEditor.logicalPositionToOffset(newSelectionStart);
|
||||
newSelectionEndOffset = myEditor.logicalPositionToOffset(newSelectionEnd);
|
||||
newSelectionStartPosition = myEditor.logicalToVisualPosition(newSelectionStart);
|
||||
@@ -996,6 +1008,8 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
|
||||
newSelectionStartPosition = null;
|
||||
newSelectionEndPosition = null;
|
||||
hasNewSelection = false;
|
||||
newSelectionStartColumn = -1;
|
||||
newSelectionEndColumn = -1;
|
||||
}
|
||||
LogicalPosition oldPosition = getLogicalPosition();
|
||||
int newLine = oldPosition.line + lineShift;
|
||||
@@ -1003,7 +1017,12 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
|
||||
Disposer.dispose(clone);
|
||||
return null;
|
||||
}
|
||||
clone.moveToLogicalPosition(new LogicalPosition(newLine, oldPosition.column), false, null, false);
|
||||
clone.moveToLogicalPosition(new LogicalPosition(newLine, myLastColumnNumber), false, null, false);
|
||||
clone.myLastColumnNumber = myLastColumnNumber;
|
||||
clone.myDesiredX = myDesiredX >= 0 ? myDesiredX : getCurrentX();
|
||||
clone.myDesiredSelectionStartColumn = newSelectionStartColumn;
|
||||
clone.myDesiredSelectionEndColumn = newSelectionEndColumn;
|
||||
|
||||
if (myEditor.getCaretModel().addCaret(clone)) {
|
||||
if (hasNewSelection) {
|
||||
myEditor.getCaretModel().doWithCaretMerging(new Runnable() {
|
||||
@@ -1025,15 +1044,15 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
|
||||
}
|
||||
}
|
||||
|
||||
private LogicalPosition truncate(LogicalPosition position) {
|
||||
if (position.line < 0) {
|
||||
private LogicalPosition truncate(int line, int column) {
|
||||
if (line < 0) {
|
||||
return new LogicalPosition(0, 0);
|
||||
}
|
||||
else if (position.line >= myEditor.getDocument().getLineCount()) {
|
||||
else if (line >= myEditor.getDocument().getLineCount()) {
|
||||
return myEditor.offsetToLogicalPosition(myEditor.getDocument().getTextLength());
|
||||
}
|
||||
else {
|
||||
return position;
|
||||
return new LogicalPosition(line, column);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1396,9 +1415,8 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
|
||||
}
|
||||
|
||||
try {
|
||||
EditorActionHandler handler = EditorActionManager.getInstance().getActionHandler(
|
||||
IdeActions.ACTION_EDITOR_SELECT_WORD_AT_CARET);
|
||||
handler.execute(myEditor, myEditor.getDataContext());
|
||||
EditorActionHandler handler = EditorActionManager.getInstance().getActionHandler(IdeActions.ACTION_EDITOR_SELECT_WORD_AT_CARET);
|
||||
handler.execute(myEditor, CaretImpl.this, myEditor.getDataContext());
|
||||
}
|
||||
finally {
|
||||
if (needOverrideSetting) {
|
||||
@@ -1453,6 +1471,10 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
|
||||
return marker != null && marker.isValid() && isVirtualSelectionEnabled() && myEndVirtualOffset > myStartVirtualOffset;
|
||||
}
|
||||
|
||||
private int getCurrentX() {
|
||||
return myEditor.visualPositionToXY(myVisibleCaret).x;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public EditorImpl getEditor() {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
+4
-2
@@ -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() {
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.util.NotNullLazyValue;
|
||||
import com.intellij.openapi.util.ShutDownTracker;
|
||||
import com.intellij.openapi.util.io.FileAttributes;
|
||||
import com.intellij.openapi.util.io.FileSystemUtil;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
@@ -30,6 +31,7 @@ import com.intellij.openapi.vfs.JarFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsBundle;
|
||||
import com.intellij.openapi.vfs.impl.ZipHandler;
|
||||
import com.intellij.openapi.vfs.newvfs.persistent.FSRecords;
|
||||
import com.intellij.openapi.vfs.newvfs.persistent.FlushingDaemon;
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import com.intellij.util.io.EnumeratorStringDescriptor;
|
||||
import com.intellij.util.io.IOUtil;
|
||||
@@ -169,7 +171,6 @@ public class JarHandler extends ZipHandler {
|
||||
|
||||
info = new CacheLibraryInfo(mirrorFile.getName(), originalAttributes.lastModified, originalAttributes.length);
|
||||
CacheLibraryInfo.ourCachedLibraryInfo.put(path, info);
|
||||
CacheLibraryInfo.ourCachedLibraryInfo.force();
|
||||
return mirrorFile;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
@@ -260,6 +261,23 @@ public class JarHandler extends ZipHandler {
|
||||
}
|
||||
assert info != null;
|
||||
ourCachedLibraryInfo = info;
|
||||
FlushingDaemon.everyFiveSeconds(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
flushCachedLibraryInfos();
|
||||
}
|
||||
});
|
||||
|
||||
ShutDownTracker.getInstance().registerShutdownTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
flushCachedLibraryInfos();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void flushCachedLibraryInfos() {
|
||||
if (ourCachedLibraryInfo.isDirty()) ourCachedLibraryInfo.force();
|
||||
}
|
||||
|
||||
private CacheLibraryInfo(@NotNull String path, long time, long length) {
|
||||
|
||||
@@ -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
|
||||
org.intellij.clojure 0.2.1.178
|
||||
@@ -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);
|
||||
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.editor.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.IdeActions;
|
||||
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
|
||||
|
||||
public class EditorCloneCaretAboveBelowTest extends LightPlatformCodeInsightFixtureTestCase {
|
||||
public void testStoringDesiredXPosition() {
|
||||
init("long line<caret>\n" +
|
||||
"line\n" +
|
||||
"long line\n" +
|
||||
"very long line");
|
||||
cloneCaretBelow();
|
||||
checkResult("long line<caret>\n" +
|
||||
"line<caret>\n" +
|
||||
"long line\n" +
|
||||
"very long line");
|
||||
cloneCaretBelow();
|
||||
checkResult("long line<caret>\n" +
|
||||
"line<caret>\n" +
|
||||
"long line<caret>\n" +
|
||||
"very long line");
|
||||
cloneCaretBelow();
|
||||
checkResult("long line<caret>\n" +
|
||||
"line<caret>\n" +
|
||||
"long line<caret>\n" +
|
||||
"very long<caret> line");
|
||||
}
|
||||
|
||||
public void testCloneAndMove() {
|
||||
init("long line<caret>\n" +
|
||||
"line\n" +
|
||||
"long line");
|
||||
cloneCaretBelow();
|
||||
moveCaretDown();
|
||||
checkResult("long line\n" +
|
||||
"line<caret>\n" +
|
||||
"long line<caret>");
|
||||
}
|
||||
|
||||
public void testCloneBelowAndAbove() {
|
||||
init("line\n" +
|
||||
"<caret>li<caret>ne\n" +
|
||||
"line");
|
||||
cloneCaretBelow();
|
||||
checkResult("line\n" +
|
||||
"<caret>li<caret>ne\n" +
|
||||
"<caret>li<caret>ne");
|
||||
cloneCaretAbove();
|
||||
checkResult("line\n" +
|
||||
"<caret>li<caret>ne\n" +
|
||||
"line");
|
||||
cloneCaretAbove();
|
||||
checkResult("<caret>li<caret>ne\n" +
|
||||
"<caret>li<caret>ne\n" +
|
||||
"line");
|
||||
cloneCaretBelow();
|
||||
checkResult("line\n" +
|
||||
"<caret>li<caret>ne\n" +
|
||||
"line");
|
||||
}
|
||||
|
||||
public void testCloneWithSelection() {
|
||||
init("long <selection>line<caret></selection>\n" +
|
||||
"line\n" +
|
||||
"long line");
|
||||
cloneCaretBelow();
|
||||
checkResult("long <selection>line<caret></selection>\n" +
|
||||
"line\n" +
|
||||
"long <selection>line<caret></selection>");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
+15
@@ -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()}.
|
||||
|
||||
@@ -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 <caret>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 <caret>line");
|
||||
}
|
||||
|
||||
private void init(String text) throws IOException {
|
||||
configureFromFileText(getTestName(false) + ".txt", text);
|
||||
}
|
||||
|
||||
-21
@@ -20,8 +20,6 @@ import java.util.Map;
|
||||
*/
|
||||
public class ServerConnectionManagerImpl extends ServerConnectionManager {
|
||||
|
||||
private static final int POLL_DEPLOYMENTS_DELAY = 2000;
|
||||
|
||||
private final Map<RemoteServer<?>, ServerConnection> myConnections = new HashMap<RemoteServer<?>, 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 <C extends ServerConfiguration> ServerConnection createTemporaryConnection(@NotNull RemoteServer<C> server) {
|
||||
|
||||
+23
-1
@@ -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));
|
||||
|
||||
@@ -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();
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,7 +26,7 @@ public abstract class DebugEventAdapter implements DebugEventListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scriptContentChanged(Script newScript) {
|
||||
public void scriptContentChanged(@NotNull Script newScript) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -19,6 +19,7 @@ public abstract class VmBase implements Vm {
|
||||
return evaluateContext;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected abstract EvaluateContext computeEvaluateContext();
|
||||
|
||||
@NotNull
|
||||
|
||||
+4
@@ -135,6 +135,10 @@ public final class SourceMapDecoder {
|
||||
}
|
||||
|
||||
List<String> sources = readSources(sourcesReader, sourceRoot);
|
||||
if (sources.isEmpty()) {
|
||||
// empty map, meteor can report such ugly maps
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<MappingEntry>[] reverseMappingsBySourceUrl = new List[sources.size()];
|
||||
|
||||
+16
-17
@@ -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<XValueGroup> computeNotSparseGroups(@NotNull ObjectValue value, @NotNull VariableContext context, int from, int to, int bucketThreshold) {
|
||||
int size = to - from;
|
||||
public static List<XValueGroup> 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<XValueGroup> groupList = new ArrayList<XValueGroup>((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;
|
||||
}
|
||||
|
||||
+1
@@ -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");
|
||||
|
||||
-4
@@ -20,10 +20,6 @@ abstract class ClassScope {
|
||||
return contextNamespace.getLastComponent();
|
||||
}
|
||||
|
||||
String getFullName() {
|
||||
return contextNamespace.getFullText();
|
||||
}
|
||||
|
||||
NamePath getClassContextNamespace() {
|
||||
return contextNamespace;
|
||||
}
|
||||
|
||||
+12
-9
@@ -153,7 +153,7 @@ class DomainGenerator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends ItemDescriptor> QualifiedTypeData resolveType(T typedObject) {
|
||||
public <T extends ItemDescriptor> TypeDescriptor resolveType(T typedObject) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@@ -162,8 +162,7 @@ class DomainGenerator {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
QualifiedTypeData itemTypeData = generator.resolveType(items, resolveAndGenerateScope);
|
||||
BoxableType itemBoxableType = itemTypeData.getJavaType();
|
||||
BoxableType itemBoxableType = generator.resolveType(items, resolveAndGenerateScope).getType();
|
||||
|
||||
final BoxableType arrayType = new ListType(itemBoxableType);
|
||||
StandaloneTypeBinding.Target target = new StandaloneTypeBinding.Target() {
|
||||
@@ -178,7 +177,7 @@ class DomainGenerator {
|
||||
});
|
||||
}
|
||||
|
||||
StandaloneTypeBinding createStandaloneObjectInputTypeBinding(final ProtocolMetaModel.StandaloneType type, final List<ProtocolMetaModel.ObjectProperty> properties) {
|
||||
StandaloneTypeBinding createStandaloneObjectInputTypeBinding(@NotNull final ProtocolMetaModel.StandaloneType type, @Nullable final List<ProtocolMetaModel.ObjectProperty> properties) {
|
||||
final String name = type.id();
|
||||
final NamePath fullTypeName = generator.getNaming().inputValue.getFullName(domain.domain(), name);
|
||||
generator.jsonProtocolParserClassNames.add(fullTypeName.getFullText());
|
||||
@@ -198,10 +197,12 @@ class DomainGenerator {
|
||||
out.doc(type.description());
|
||||
}
|
||||
|
||||
out.append("@org.chromium.protocolReader.JsonType").newLine();
|
||||
out.append("@org.jetbrains.jsonProtocol.JsonType").newLine();
|
||||
out.append("public interface ").append(className.getLastComponent()).openBlock();
|
||||
InputClassScope classScope = new InputClassScope(DomainGenerator.this, className);
|
||||
classScope.generateStandaloneTypeBody(out, properties);
|
||||
if (properties != null) {
|
||||
classScope.generateDeclarationBody(out, properties);
|
||||
}
|
||||
classScope.writeAdditionalMembers(out);
|
||||
out.closeBlock();
|
||||
fileUpdater.update();
|
||||
@@ -309,16 +310,18 @@ class DomainGenerator {
|
||||
fileUpdater.update();
|
||||
}
|
||||
|
||||
private void generateJsonProtocolInterface(TextOutput out, String className, String description, List<ProtocolMetaModel.Parameter> parameters, TextOutConsumer additionalMembersText) throws IOException {
|
||||
private void generateJsonProtocolInterface(TextOutput out, String className, String description, List<ProtocolMetaModel.Parameter> parameters, TextOutConsumer additionalMembersText) {
|
||||
if (description != null) {
|
||||
out.doc(description);
|
||||
}
|
||||
out.append("@org.chromium.protocolReader.JsonType").newLine().append("public interface ").append(className).openBlock();
|
||||
out.append("@org.jetbrains.jsonProtocol.JsonType").newLine().append("public interface ").append(className).openBlock();
|
||||
InputClassScope classScope = new InputClassScope(this, new NamePath(className, new NamePath(ClassNameScheme.getPackageName(generator.getNaming().inputPackage, domain.domain()))));
|
||||
if (additionalMembersText != null) {
|
||||
classScope.addMember(additionalMembersText);
|
||||
}
|
||||
classScope.generateMainJsonProtocolInterfaceBody(out, parameters);
|
||||
if (parameters != null) {
|
||||
classScope.generateDeclarationBody(out, parameters);
|
||||
}
|
||||
classScope.writeAdditionalMembers(out);
|
||||
out.closeBlock();
|
||||
}
|
||||
|
||||
+26
-57
@@ -114,92 +114,61 @@ class Generator {
|
||||
fileSet.deleteOtherFiles();
|
||||
}
|
||||
|
||||
QualifiedTypeData resolveType(final ItemDescriptor typedObject, final ResolveAndGenerateScope scope) {
|
||||
UnqualifiedTypeData unqualifiedType = switchByType(typedObject, new TypeVisitor<UnqualifiedTypeData>() {
|
||||
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<TypeDescriptor>() {
|
||||
@Override
|
||||
public UnqualifiedTypeData visitRef(String refName) {
|
||||
return new UnqualifiedTypeData(resolveRefType(scope.getDomainName(), refName, scope.getTypeDirection()));
|
||||
public TypeDescriptor visitRef(String refName) {
|
||||
return new TypeDescriptor(resolveRefType(scope.getDomainName(), refName, scope.getTypeDirection()), optional);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnqualifiedTypeData visitBoolean() {
|
||||
return UnqualifiedTypeData.BOOLEAN;
|
||||
public TypeDescriptor visitBoolean() {
|
||||
return new TypeDescriptor(BoxableType.BOOLEAN, optional);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnqualifiedTypeData visitEnum(List<String> enumConstants) {
|
||||
public TypeDescriptor visitEnum(List<String> enumConstants) {
|
||||
assert scope instanceof MemberScope;
|
||||
return new UnqualifiedTypeData(((MemberScope)scope).generateEnum(typedObject.description(), enumConstants));
|
||||
return new TypeDescriptor(((MemberScope)scope).generateEnum(typedObject.description(), enumConstants), optional);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnqualifiedTypeData visitString() {
|
||||
return UnqualifiedTypeData.STRING;
|
||||
public TypeDescriptor visitString() {
|
||||
return new TypeDescriptor(BoxableType.STRING, optional);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnqualifiedTypeData visitInteger() {
|
||||
return UnqualifiedTypeData.INT;
|
||||
public TypeDescriptor visitInteger() {
|
||||
return new TypeDescriptor(BoxableType.INT, optional);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnqualifiedTypeData visitNumber() {
|
||||
return UnqualifiedTypeData.NUMBER;
|
||||
public TypeDescriptor visitNumber() {
|
||||
return new TypeDescriptor(BoxableType.NUMBER, optional);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnqualifiedTypeData visitMap() {
|
||||
return UnqualifiedTypeData.MAP;
|
||||
public TypeDescriptor visitMap() {
|
||||
return new TypeDescriptor(BoxableType.MAP, optional);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnqualifiedTypeData visitArray(ArrayItemType items) {
|
||||
return new UnqualifiedTypeData(new ListType(scope.resolveType(items).getJavaType()));
|
||||
public TypeDescriptor visitArray(ArrayItemType items) {
|
||||
BoxableType type = scope.resolveType(items).getType();
|
||||
return new TypeDescriptor(new ListType(type), optional, false, type == BoxableType.ANY_STRING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnqualifiedTypeData visitObject(List<ObjectProperty> properties) {
|
||||
return new UnqualifiedTypeData(scope.generateNestedObject(typedObject.description(), properties), false);
|
||||
public TypeDescriptor visitObject(List<ObjectProperty> properties) {
|
||||
return new TypeDescriptor(scope.generateNestedObject(typedObject.description(), properties), optional);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnqualifiedTypeData visitUnknown() {
|
||||
return UnqualifiedTypeData.ANY;
|
||||
public TypeDescriptor visitUnknown() {
|
||||
return new TypeDescriptor(BoxableType.STRING, optional, false, true);
|
||||
}
|
||||
});
|
||||
|
||||
return unqualifiedType.getQualifiedType(typedObject instanceof ItemDescriptor.Named && ((ItemDescriptor.Named)typedObject).optional());
|
||||
}
|
||||
|
||||
private static class UnqualifiedTypeData {
|
||||
private final BoxableType typeRef;
|
||||
private final boolean nullable;
|
||||
private final boolean asRawString;
|
||||
|
||||
UnqualifiedTypeData(BoxableType typeRef) {
|
||||
this(typeRef, false);
|
||||
}
|
||||
|
||||
UnqualifiedTypeData(BoxableType typeRef, boolean nullable) {
|
||||
this(typeRef, nullable, false);
|
||||
}
|
||||
|
||||
UnqualifiedTypeData(BoxableType typeRef, boolean nullable, boolean asRawString) {
|
||||
this.typeRef = typeRef;
|
||||
this.nullable = nullable;
|
||||
this.asRawString = asRawString;
|
||||
}
|
||||
|
||||
QualifiedTypeData getQualifiedType(boolean optional) {
|
||||
return new QualifiedTypeData(typeRef, optional, nullable, asRawString);
|
||||
}
|
||||
|
||||
static final UnqualifiedTypeData BOOLEAN = new UnqualifiedTypeData(BoxableType.BOOLEAN, false);
|
||||
static final UnqualifiedTypeData STRING = new UnqualifiedTypeData(BoxableType.STRING, false);
|
||||
static final UnqualifiedTypeData INT = new UnqualifiedTypeData(BoxableType.INT, false);
|
||||
static final UnqualifiedTypeData MAP = new UnqualifiedTypeData(BoxableType.MAP, false);
|
||||
static final UnqualifiedTypeData NUMBER = new UnqualifiedTypeData(BoxableType.NUMBER, false);
|
||||
static final UnqualifiedTypeData ANY = new UnqualifiedTypeData(BoxableType.STRING, false, true);
|
||||
}
|
||||
|
||||
private void generateParserInterfaceList() throws IOException {
|
||||
@@ -274,11 +243,11 @@ class Generator {
|
||||
return typeMap.resolve(domainName, shortName, direction);
|
||||
}
|
||||
|
||||
static String generateMethodNameSubstitute(String originalName, TextOutput out) {
|
||||
static String generateMethodNameSubstitute(@NotNull String originalName, @NotNull TextOutput out) {
|
||||
if (!BAD_METHOD_NAMES.contains(originalName)) {
|
||||
return originalName;
|
||||
}
|
||||
out.append("@org.chromium.protocolReader.JsonField(jsonLiteralName=\"").append(originalName).append("\")").newLine();
|
||||
out.append("@org.jetbrains.jsonProtocol.JsonField(jsonLiteralName=\"").append(originalName).append("\")").newLine();
|
||||
return "get" + Character.toUpperCase(originalName.charAt(0)) + originalName.substring(1);
|
||||
}
|
||||
|
||||
|
||||
+22
-41
@@ -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<ProtocolMetaModel.Parameter> parameters) throws IOException {
|
||||
if (parameters != null) {
|
||||
for (ProtocolMetaModel.Parameter parameter : parameters) {
|
||||
if (parameter.description() != null) {
|
||||
out.doc(parameter.description());
|
||||
}
|
||||
|
||||
String methodName = Generator.generateMethodNameSubstitute(getName(parameter), out);
|
||||
QualifiedTypeData paramTypeData = newMemberScope(getName(parameter)).resolveType(parameter);
|
||||
paramTypeData.writeAnnotations(out);
|
||||
out.append(paramTypeData.getJavaType().getShortText(getClassContextNamespace())).space().append(methodName).append("();").newLine();
|
||||
void generateDeclarationBody(@NotNull TextOutput out, @NotNull List<? extends Named> 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<ProtocolMetaModel.ObjectProperty> properties) throws IOException {
|
||||
if (properties != null) {
|
||||
for (ProtocolMetaModel.ObjectProperty objectProperty : properties) {
|
||||
String propertyName = getName(objectProperty);
|
||||
|
||||
if (objectProperty.description() != null) {
|
||||
out.doc(objectProperty.description());
|
||||
}
|
||||
|
||||
String methodName = Generator.generateMethodNameSubstitute(propertyName, out);
|
||||
MemberScope memberScope = newMemberScope(propertyName);
|
||||
QualifiedTypeData propertyTypeData = memberScope.resolveType(objectProperty);
|
||||
propertyTypeData.writeAnnotations(out);
|
||||
|
||||
out.append(propertyTypeData.getJavaType().getShortText(getClassContextNamespace()) + ' ' + methodName + "();").newLine();
|
||||
String name = getName(named);
|
||||
String declarationName = Generator.generateMethodNameSubstitute(name, out);
|
||||
TypeDescriptor typeDescriptor = new InputMemberScope(name).resolveType(named);
|
||||
typeDescriptor.writeAnnotations(out);
|
||||
out.append(typeDescriptor.getType().getShortText(getClassContextNamespace())).space().append(declarationName).append("();");
|
||||
if (i != (n - 1)) {
|
||||
out.newLine().newLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,10 +34,6 @@ class InputClassScope extends ClassScope {
|
||||
return TypeData.Direction.INPUT;
|
||||
}
|
||||
|
||||
private MemberScope newMemberScope(String memberName) {
|
||||
return new InputMemberScope(memberName);
|
||||
}
|
||||
|
||||
class InputMemberScope extends MemberScope {
|
||||
InputMemberScope(String memberName) {
|
||||
super(InputClassScope.this, memberName);
|
||||
@@ -72,28 +53,28 @@ class InputClassScope extends ClassScope {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoxableType generateNestedObject(final String description, final List<ProtocolMetaModel.ObjectProperty> propertyList) {
|
||||
public BoxableType generateNestedObject(final String description, final List<ObjectProperty> propertyList) {
|
||||
final String objectName = Generator.capitalizeFirstChar(getMemberName());
|
||||
addMember(new TextOutConsumer() {
|
||||
@Override
|
||||
public void append(TextOutput out) {
|
||||
out.newLine().doc(description);
|
||||
if (propertyList == null) {
|
||||
out.append("@org.chromium.protocolReader.JsonType(allowsOtherProperties=true)").newLine();
|
||||
out.append("@org.jetbrains.jsonProtocol.JsonType(allowsOtherProperties=true)").newLine();
|
||||
out.append("public interface ").append(objectName).append(" extends org.jetbrains.jsonProtocol.JsonObjectBased").openBlock();
|
||||
}
|
||||
else {
|
||||
out.append("@org.chromium.protocolReader.JsonType").newLine();
|
||||
out.append("@org.jetbrains.jsonProtocol.JsonType").newLine();
|
||||
out.append("public interface ").append(objectName).openBlock();
|
||||
for (ProtocolMetaModel.ObjectProperty property : propertyList) {
|
||||
for (ObjectProperty property : propertyList) {
|
||||
out.doc(property.description());
|
||||
|
||||
String methodName = Generator.generateMethodNameSubstitute(getName(property), out);
|
||||
MemberScope memberScope = newMemberScope(getName(property));
|
||||
QualifiedTypeData propertyTypeData = memberScope.resolveType(property);
|
||||
MemberScope memberScope = new InputMemberScope(getName(property));
|
||||
TypeDescriptor propertyTypeData = memberScope.resolveType(property);
|
||||
propertyTypeData.writeAnnotations(out);
|
||||
|
||||
out.append(propertyTypeData.getJavaType().getShortText(getClassContextNamespace()) + ' ' + methodName + "();").newLine();
|
||||
out.append(propertyTypeData.getType().getShortText(getClassContextNamespace()) + ' ' + methodName + "();").newLine();
|
||||
}
|
||||
}
|
||||
out.closeBlock();
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ abstract class MemberScope implements ResolveAndGenerateScope {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends ItemDescriptor> QualifiedTypeData resolveType(T typedObject) {
|
||||
public <T extends ItemDescriptor> TypeDescriptor resolveType(T typedObject) {
|
||||
return classScope.generator.generator.resolveType(typedObject, this);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -60,7 +60,7 @@ class MyCreateStandaloneTypeBindingVisitorBase extends CreateStandaloneTypeBindi
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends ItemDescriptor> QualifiedTypeData resolveType(T typedObject) {
|
||||
public <T extends ItemDescriptor> TypeDescriptor resolveType(T typedObject) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ class MyCreateStandaloneTypeBindingVisitorBase extends CreateStandaloneTypeBindi
|
||||
public BoxableType generateNestedObject(String description, List<ProtocolMetaModel.ObjectProperty> properties) {
|
||||
return context.generateNestedObject("Item", description, properties);
|
||||
}
|
||||
}).getJavaType());
|
||||
}).getType());
|
||||
}
|
||||
}, generator.generator.getNaming().outputTypedef, TypeData.Direction.OUTPUT);
|
||||
}
|
||||
|
||||
+11
-8
@@ -19,8 +19,8 @@ class OutputClassScope extends ClassScope {
|
||||
return;
|
||||
}
|
||||
|
||||
List<P> mandatoryParameters = new ArrayList<P>();
|
||||
List<P> optionalParameters = new ArrayList<P>();
|
||||
List<P> mandatoryParameters = new ArrayList<>();
|
||||
List<P> optionalParameters = new ArrayList<>();
|
||||
for (P parameter : parameters) {
|
||||
if (parameter.optional()) {
|
||||
optionalParameters.add(parameter);
|
||||
@@ -34,8 +34,8 @@ class OutputClassScope extends ClassScope {
|
||||
generateConstructor(out, mandatoryParameters, null);
|
||||
if (mandatoryParameters.size() == 1) {
|
||||
P parameter = mandatoryParameters.get(0);
|
||||
QualifiedTypeData typeData = new OutputMemberScope(getName(parameter)).resolveType(parameter);
|
||||
if (typeData.getJavaType().getFullText().equals("int[]")) {
|
||||
TypeDescriptor typeData = new OutputMemberScope(getName(parameter)).resolveType(parameter);
|
||||
if (typeData.getType().getFullText().equals("int[]")) {
|
||||
BoxableType[] types = new BoxableType[mandatoryParameters.size()];
|
||||
types[0] = new ListType(BoxableType.INT) {
|
||||
@Override
|
||||
@@ -94,7 +94,7 @@ class OutputClassScope extends ClassScope {
|
||||
out.append("/**").newLine().append(" * @param v ").append(parameter.description()).newLine().append(" */").newLine();
|
||||
}
|
||||
|
||||
CharSequence type = new OutputMemberScope(parameter.name()).resolveType(parameter).getJavaType().getShortText(getClassContextNamespace());
|
||||
CharSequence type = new OutputMemberScope(parameter.name()).resolveType(parameter).getType().getShortText(getClassContextNamespace());
|
||||
if (type.equals(JsonReaderEx.class.getCanonicalName())) {
|
||||
type = "String";
|
||||
}
|
||||
@@ -131,9 +131,10 @@ class OutputClassScope extends ClassScope {
|
||||
mandatoryParameterTypes = new BoxableType[mandatoryParameters.size()];
|
||||
}
|
||||
for (int i = 0, length = mandatoryParameterTypes.length; i < length; i++) {
|
||||
assert mandatoryParameterTypes != null;
|
||||
if (mandatoryParameterTypes[i] == null) {
|
||||
P parameter = mandatoryParameters.get(i);
|
||||
mandatoryParameterTypes[i] = new OutputMemberScope(parameter.name()).resolveType(parameter).getJavaType();
|
||||
mandatoryParameterTypes[i] = new OutputMemberScope(parameter.name()).resolveType(parameter).getType();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,6 +145,7 @@ class OutputClassScope extends ClassScope {
|
||||
out.comma();
|
||||
}
|
||||
|
||||
assert mandatoryParameterTypes != null;
|
||||
out.append(mandatoryParameterTypes[i].getShortText(getClassContextNamespace()));
|
||||
out.space().append(parameter.name());
|
||||
needComa = true;
|
||||
@@ -152,6 +154,7 @@ class OutputClassScope extends ClassScope {
|
||||
for (int i = 0, size = mandatoryParameters.size(); i < size; i++) {
|
||||
P parameter = mandatoryParameters.get(i);
|
||||
out.newLine();
|
||||
assert mandatoryParameterTypes != null;
|
||||
appendWriteValueInvocation(out, parameter, parameter.name(), mandatoryParameterTypes[i]);
|
||||
}
|
||||
out.closeBlock();
|
||||
@@ -159,7 +162,7 @@ class OutputClassScope extends ClassScope {
|
||||
|
||||
private void appendWriteValueInvocation(TextOutput out, ItemDescriptor.Named parameter, String valueRefName, @Nullable BoxableType type) {
|
||||
if (type == null) {
|
||||
type = new OutputMemberScope(parameter.name()).resolveType(parameter).getJavaType();
|
||||
type = new OutputMemberScope(parameter.name()).resolveType(parameter).getType();
|
||||
}
|
||||
|
||||
boolean blockOpened = false;
|
||||
@@ -188,7 +191,7 @@ class OutputClassScope extends ClassScope {
|
||||
}
|
||||
// todo CallArgument (we should allow write null as value)
|
||||
out.append(parameter.name().equals("value") && type.getWriteMethodName().equals("writeString") ? "writeNullableString" : type.getWriteMethodName()).append("(");
|
||||
out.quoute(parameter.name()).comma().append(valueRefName).append(");");
|
||||
out.quote(parameter.name()).comma().append(valueRefName).append(");");
|
||||
if (blockOpened) {
|
||||
out.closeBlock();
|
||||
}
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ class ParserRootInterfaceItem implements Comparable<ParserRootInterfaceItem> {
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ interface ResolveAndGenerateScope {
|
||||
String getDomainName();
|
||||
TypeData.Direction getTypeDirection();
|
||||
|
||||
<T extends ItemDescriptor> QualifiedTypeData resolveType(T typedObject);
|
||||
<T extends ItemDescriptor> TypeDescriptor resolveType(T typedObject);
|
||||
|
||||
BoxableType generateNestedObject(String description,
|
||||
List<ProtocolMetaModel.ObjectProperty> properties);
|
||||
|
||||
+17
-30
@@ -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();
|
||||
|
||||
+16
-9
@@ -1,13 +1,19 @@
|
||||
package org.jetbrains.protocolReader;
|
||||
|
||||
class QualifiedTypeData {
|
||||
private final BoxableType typeRef;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
class TypeDescriptor {
|
||||
private final BoxableType type;
|
||||
private final boolean optional;
|
||||
private final boolean nullable;
|
||||
private final boolean asRawString;
|
||||
|
||||
QualifiedTypeData(BoxableType typeRef, boolean optional, boolean nullable, boolean asRawString) {
|
||||
this.typeRef = typeRef;
|
||||
TypeDescriptor(@NotNull BoxableType type, boolean optional) {
|
||||
this(type, optional, false, false);
|
||||
}
|
||||
|
||||
TypeDescriptor(@NotNull BoxableType type, boolean optional, boolean nullable, boolean asRawString) {
|
||||
this.type = type;
|
||||
this.optional = optional;
|
||||
this.nullable = nullable;
|
||||
this.asRawString = asRawString;
|
||||
@@ -17,13 +23,14 @@ class QualifiedTypeData {
|
||||
return nullable;
|
||||
}
|
||||
|
||||
BoxableType getJavaType() {
|
||||
return typeRef;
|
||||
@NotNull
|
||||
BoxableType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
void writeAnnotations(TextOutput out) {
|
||||
void writeAnnotations(@NotNull TextOutput out) {
|
||||
if (optional || asRawString) {
|
||||
out.append("@org.chromium.protocolReader.JsonField(");
|
||||
out.append("@org.jetbrains.jsonProtocol.JsonField(");
|
||||
if (optional) {
|
||||
out.append("optional=true");
|
||||
}
|
||||
@@ -37,7 +44,7 @@ class QualifiedTypeData {
|
||||
}
|
||||
|
||||
if (isNullable()) {
|
||||
out.append("@org.chromium.protocolReader.JsonNullable").newLine();
|
||||
out.append("@org.jetbrains.jsonProtocol.JsonNullable").newLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package org.chromium.protocolReader;
|
||||
package org.jetbrains.jsonProtocol;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -25,6 +25,7 @@ public @interface JsonField {
|
||||
|
||||
// read any primitive value as String (true as true, number as string - don't try to parse)
|
||||
boolean allowAnyPrimitiveValue() default false;
|
||||
|
||||
boolean allowAnyPrimitiveValueAndMap() default false;
|
||||
|
||||
boolean optional() default false;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user