Merge remote-tracking branch 'origin/master'

This commit is contained in:
Ilya.Kazakevich
2014-07-28 19:59:41 +04:00
134 changed files with 2107 additions and 813 deletions
Binary file not shown.
@@ -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,
@@ -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());
}
}
@@ -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;
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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);
@@ -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();
@@ -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;
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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
@@ -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)
{
}
}
}
@@ -0,0 +1,12 @@
class Foo {
{
try
{
} catch (Exception e)
{
<caret>
}
}
}
@@ -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();
}
@@ -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"));
@@ -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
View File
@@ -1,5 +1,6 @@
*.aps
*.vcxproj.user
Debug
Release
*.suo
*.opensdf
+66 -14
View File
@@ -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;
@@ -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;
}
@@ -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);
}
@@ -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);
}
}
@@ -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, "(", ")"));
}
}
@@ -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);
}
@@ -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();
}
};
}
}
@@ -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();
}
};
}
}
@@ -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;
}
}
@@ -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,
@@ -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);
@@ -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());
@@ -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;
@@ -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);
}
}
@@ -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);
}
@@ -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
@@ -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);
}
}
@@ -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);
}
}
}
@@ -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();
}
}
@@ -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));
}
}
@@ -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);
}
}
@@ -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;
@@ -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);
@@ -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);
}
}
@@ -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);
}
@@ -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) {
@@ -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
@@ -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()];
@@ -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;
}
@@ -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");
@@ -20,10 +20,6 @@ abstract class ClassScope {
return contextNamespace.getLastComponent();
}
String getFullName() {
return contextNamespace.getFullText();
}
NamePath getClassContextNamespace() {
return contextNamespace;
}
@@ -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();
}
@@ -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);
}
@@ -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();
@@ -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);
}
@@ -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);
}
@@ -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();
}
@@ -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();
@@ -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);
@@ -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();
@@ -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,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