Merge remote-tracking branch 'origin/master'

This commit is contained in:
Maxim Kropotov
2017-02-15 14:35:14 +03:00
273 changed files with 3557 additions and 1703 deletions
+5 -2
View File
@@ -80,9 +80,12 @@ sun.java2d.noddraw=true
sun.java2d.d3d=false
#---------------------------------------------------------------------
# Workaround for slow scrolling in JDK6
# Set swing.bufferPerWindow=false to workaround a slow scrolling in JDK6 (see IDEA-35883),
# But this may lead to performance degradation, because it disables a double buffering,
# which is needed to eliminate tearing on blit-accelerated scrolling and to restore
# a frame buffer content without the usual repainting, even when the EDT is blocked.
#---------------------------------------------------------------------
swing.bufferPerWindow=false
swing.bufferPerWindow=true
#---------------------------------------------------------------------
# Removing this property may lead to editor performance degradation under X Window.
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -383,14 +383,15 @@ public class VirtualMachineProxyImpl implements JdiTimer, VirtualMachineProxy {
catch (UnsupportedOperationException e) {
LOG.info(e);
}
if (Patches.JDK_BUG_EVENT_CONTROLLER_LEAK) {
// Memory leak workaround, see IDEA-163334
TargetVM target = ReflectionUtil.getField(myVirtualMachine.getClass(), myVirtualMachine, TargetVM.class, "target");
if (target != null) {
Thread controller = ReflectionUtil.getField(target.getClass(), target, Thread.class, "eventController");
if (controller != null) {
controller.stop();
finally {
if (Patches.JDK_BUG_EVENT_CONTROLLER_LEAK) {
// Memory leak workaround, see IDEA-163334
TargetVM target = ReflectionUtil.getField(myVirtualMachine.getClass(), myVirtualMachine, TargetVM.class, "target");
if (target != null) {
Thread controller = ReflectionUtil.getField(target.getClass(), target, Thread.class, "eventController");
if (controller != null) {
controller.stop();
}
}
}
}
@@ -173,7 +173,7 @@ public class CaptureConfigurable implements SearchableConfigurable {
}
});
try {
JDOMUtil.writeDocument(new Document(rootElement), wrapper.getFile(), "\n");
JDOMUtil.write(rootElement, wrapper.getFile());
}
catch (Exception ex) {
final String msg = ex.getLocalizedMessage();
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -23,7 +23,6 @@ import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.module.ModuleTypeManager;
import com.intellij.openapi.util.ClearableLazyValue;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.platform.ProjectTemplate;
import com.intellij.platform.ProjectTemplatesFactory;
import com.intellij.util.ArrayUtil;
@@ -95,7 +94,7 @@ public class RemoteTemplatesFactory extends ProjectTemplatesFactory {
@NotNull
@TestOnly
public static MultiMap<String, ArchivedProjectTemplate> createFromText(@NotNull String value) throws IOException, JDOMException {
return create(JDOMUtil.loadDocument(value).getRootElement());
return create(JdomKt.loadElement(value));
}
@NotNull
@@ -49,6 +49,9 @@ public class DataFlowRunner {
private Instruction[] myInstructions;
private final MultiMap<PsiElement, DfaMemoryState> myNestedClosures = new MultiMap<>();
// Closures which were registered for previous instruction and can be queried by visitor
// to adjust them somehow
private final List<DfaMemoryState> myStackTopClosures = new ArrayList<>();
@NotNull
private final DfaValueFactory myValueFactory;
private final boolean myShouldCheckLimitTime;
@@ -90,6 +93,10 @@ public class DataFlowRunner {
return Collections.singletonList(createMemoryState());
}
List<DfaMemoryState> getStackTopClosures() {
return new ArrayList<>(myStackTopClosures);
}
@NotNull
public final RunnerResult analyzeMethod(@NotNull PsiElement psiBlock, @NotNull InstructionVisitor visitor) {
Collection<DfaMemoryState> initialStates = createInitialStates(psiBlock, visitor);
@@ -109,6 +116,7 @@ public class DataFlowRunner {
int endOffset = flow.getInstructionCount();
myInstructions = flow.getInstructions();
myNestedClosures.clear();
myStackTopClosures.clear();
Set<Instruction> joinInstructions = ContainerUtil.newHashSet();
for (int index = 0; index < myInstructions.length; index++) {
@@ -270,6 +278,9 @@ public class DataFlowRunner {
@NotNull
protected DfaInstructionState[] acceptInstruction(@NotNull InstructionVisitor visitor, @NotNull DfaInstructionState instructionState) {
Instruction instruction = instructionState.getInstruction();
DfaInstructionState[] states = instruction.accept(this, instructionState.getMemoryState(), visitor);
myStackTopClosures.clear();
PsiElement closure = DfaUtil.getClosureInside(instruction);
if (closure instanceof PsiClass) {
registerNestedClosures(instructionState, (PsiClass)closure);
@@ -277,7 +288,7 @@ public class DataFlowRunner {
registerNestedClosures(instructionState, (PsiLambdaExpression)closure);
}
return instruction.accept(this, instructionState.getMemoryState(), visitor);
return states;
}
private void registerNestedClosures(@NotNull DfaInstructionState instructionState, @NotNull PsiClass nestedClass) {
@@ -285,14 +296,14 @@ public class DataFlowRunner {
for (PsiMethod method : nestedClass.getMethods()) {
PsiCodeBlock body = method.getBody();
if (body != null) {
myNestedClosures.putValue(body, state.createClosureState());
myNestedClosures.putValue(body, createClosureState(state));
}
}
for (PsiClassInitializer initializer : nestedClass.getInitializers()) {
myNestedClosures.putValue(initializer.getBody(), state.createClosureState());
myNestedClosures.putValue(initializer.getBody(), createClosureState(state));
}
for (PsiField field : nestedClass.getFields()) {
myNestedClosures.putValue(field, state.createClosureState());
myNestedClosures.putValue(field, createClosureState(state));
}
}
@@ -300,10 +311,17 @@ public class DataFlowRunner {
DfaMemoryState state = instructionState.getMemoryState();
PsiElement body = expr.getBody();
if (body != null) {
myNestedClosures.putValue(body, state.createClosureState());
myNestedClosures.putValue(body, createClosureState(state));
}
}
@NotNull
private DfaMemoryState createClosureState(DfaMemoryState state) {
DfaMemoryState closureState = state.createClosureState();
myStackTopClosures.add(closureState);
return closureState;
}
@NotNull
protected DfaMemoryState createMemoryState() {
return new DfaMemoryStateImpl(myValueFactory);
@@ -53,8 +53,6 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
// dfa value id -> indices in myEqClasses list of the classes which contain the id (or wrapped)
private final TIntObjectHashMap<int[]> myIdToEqClassesIndices;
private final Stack<DfaValue> myStack;
// Closures which correspond to the stack top (do not track other closures for now)
private final List<DfaMemoryState> myStackTopClosures = new ArrayList<>();
private final TLongHashSet myDistinctClasses;
private final LinkedHashMap<DfaVariableValue,DfaVariableState> myVariableStates;
private final Map<DfaVariableValue,DfaVariableState> myDefaultVariableStates;
@@ -118,14 +116,9 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
copy.flushDependencies(value);
}
copy.emptyStack();
myStackTopClosures.add(copy);
return copy;
}
List<DfaMemoryState> getStackTopClosures() {
return new ArrayList<>(myStackTopClosures);
}
public boolean equals(Object obj) {
if (obj == this) return true;
if (!(obj instanceof DfaMemoryStateImpl)) return false;
@@ -241,7 +234,6 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
@Override
public DfaValue pop() {
myCachedHash = null;
myStackTopClosures.clear();
return myStack.pop();
}
@@ -253,14 +245,12 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
@Override
public void push(@NotNull DfaValue value) {
myCachedHash = null;
myStackTopClosures.clear();
myStack.push(value);
}
@Override
public void emptyStack() {
myCachedHash = null;
myStackTopClosures.clear();
while (!myStack.isEmpty() && !(myStack.peek() instanceof DfaControlTransferValue)) {
myStack.pop();
}
@@ -229,7 +229,7 @@ public class StandardInstructionVisitor extends InstructionVisitor {
if (methodName == null || !OPTIONAL_METHOD_NAMES.contains(methodName)) return Collections.emptyList();
PsiMethod method = call.resolveMethod();
if (method == null || !TypeUtils.isOptional(method.getContainingClass())) return Collections.emptyList();
List<DfaMemoryState> closures = ((DfaMemoryStateImpl)memState).getStackTopClosures();
List<DfaMemoryState> closures = runner.getStackTopClosures();
DfaValue[] argValues = popCallArguments(instruction, runner, memState);
final DfaValue qualifier = popQualifier(instruction, runner, memState);
switch (methodName) {
@@ -890,6 +890,10 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns
.parameterCount(1);
private static final CallMatcher INT_STREAM_RANGE =
CallMatcher.staticCall(CommonClassNames.JAVA_UTIL_STREAM_INT_STREAM, "range").parameterTypes("int", "int");
private static final CallMatcher MIN_INT =
CallMatcher.anyOf(
CallMatcher.staticCall(CommonClassNames.JAVA_LANG_MATH, "min").parameterTypes("int", "int"),
CallMatcher.staticCall(CommonClassNames.JAVA_LANG_INTEGER, "min").parameterTypes("int", "int"));
private final String myName;
@@ -913,8 +917,10 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns
public PsiElement simplify(PsiMethodCallExpression mapToObjCall) {
Project project = mapToObjCall.getProject();
PsiExpression mapper = ArrayUtil.getFirstElement(mapToObjCall.getArgumentList().getExpressions());
IndexedContainer container = extractContainer(getQualifierMethodCall(mapToObjCall), mapper);
if (container == null) return null;
LimitedContainer limitedContainer = extractContainer(getQualifierMethodCall(mapToObjCall), mapper);
if (limitedContainer == null) return null;
IndexedContainer container = limitedContainer.myContainer;
PsiExpression limit = limitedContainer.myLimit;
PsiExpression containerQualifier = container.getQualifier();
PsiType type = containerQualifier.getType();
PsiType elementType = container.getElementType();
@@ -929,6 +935,9 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns
}
PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
CommentTracker ct = new CommentTracker();
if (limit != null) {
replacement += ".limit(" + ct.text(limit) + ")";
}
if (mapper instanceof PsiMethodReferenceExpression) {
mapper = LambdaRefactoringUtil.convertMethodReferenceToLambda((PsiMethodReferenceExpression)mapper, false, true);
}
@@ -975,22 +984,39 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns
static CallHandler<CallChainSimplification> handler() {
return CallHandler.of(INT_STREAM_MAP, call -> {
PsiExpression mapper = call.getArgumentList().getExpressions()[0];
IndexedContainer container = extractContainer(getQualifierMethodCall(call), mapper);
if (container == null) return null;
return new ReplaceWithElementIterationFix(container, call.getMethodExpression().getReferenceName());
LimitedContainer limitedContainer = extractContainer(getQualifierMethodCall(call), mapper);
if (limitedContainer == null) return null;
return new ReplaceWithElementIterationFix(limitedContainer.myContainer, call.getMethodExpression().getReferenceName());
});
}
@Contract("null, _ -> null")
private static IndexedContainer extractContainer(PsiMethodCallExpression qualifierCall, PsiExpression mapper) {
private static LimitedContainer extractContainer(PsiMethodCallExpression qualifierCall, PsiExpression mapper) {
if (!INT_STREAM_RANGE.test(qualifierCall)) return null;
PsiExpression[] rangeArgs = qualifierCall.getArgumentList().getExpressions();
if (!ExpressionUtils.isZero(rangeArgs[0])) return null;
PsiExpression bound = rangeArgs[1];
PsiExpression bound = ExpressionUtils.resolveExpression(rangeArgs[1]);
IndexedContainer container = IndexedContainer.fromLengthExpression(bound);
if (container == null || !StreamApiUtil.isSupportedStreamElement(container.getElementType())) return null;
PsiExpression limit = null;
if (container == null) {
if(bound instanceof PsiMethodCallExpression && MIN_INT.test((PsiMethodCallExpression)bound)) {
PsiExpression[] args = ((PsiMethodCallExpression)bound).getArgumentList().getExpressions();
container = IndexedContainer.fromLengthExpression(args[0]);
if(container != null) {
limit = args[1];
} else {
container = IndexedContainer.fromLengthExpression(args[1]);
if(container != null) {
limit = args[0];
}
}
}
if(container == null) return null;
}
if (!StreamApiUtil.isSupportedStreamElement(container.getElementType())) return null;
LimitedContainer limitedContainer = new LimitedContainer(container, limit);
if (mapper instanceof PsiMethodReferenceExpression && container.isGetMethodReference((PsiMethodReferenceExpression)mapper)) {
return container;
return limitedContainer;
}
if (mapper instanceof PsiLambdaExpression) {
PsiLambdaExpression lambda = (PsiLambdaExpression)mapper;
@@ -1001,12 +1027,23 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns
if (body == null) return null;
Collection<PsiReference> refs = ReferencesSearch.search(indexParameter, new LocalSearchScope(body)).findAll();
if (!refs.isEmpty() &&
refs.stream().allMatch(ref -> container.extractGetExpressionFromIndex(tryCast(ref, PsiExpression.class)) != null)) {
return container;
refs.stream()
.allMatch(ref -> limitedContainer.myContainer.extractGetExpressionFromIndex(tryCast(ref, PsiExpression.class)) != null)) {
return limitedContainer;
}
}
return null;
}
static class LimitedContainer {
@NotNull final IndexedContainer myContainer;
@Nullable final PsiExpression myLimit;
LimitedContainer(@NotNull IndexedContainer container, @Nullable PsiExpression limit) {
myContainer = container;
myLimit = limit;
}
}
}
private static class RemoveBooleanIdentityFix implements CallChainSimplification {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -46,9 +46,7 @@ import com.intellij.psi.util.PsiTreeUtil
import com.sun.tools.doclint.DocLint
import java.io.File
class JavadocHtmlLintAnnotator() :
ExternalAnnotator<JavadocHtmlLintAnnotator.Info, JavadocHtmlLintAnnotator.Result>() {
class JavadocHtmlLintAnnotator : ExternalAnnotator<JavadocHtmlLintAnnotator.Info, JavadocHtmlLintAnnotator.Result>() {
data class Info(val file: PsiFile)
data class Anno(val row: Int, val col: Int, val error: Boolean, val message: String)
data class Result(val annotations: List<Anno>)
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -25,5 +25,5 @@ class JavadocHtmlLintInspection : LocalInspectionTool(), ExternalAnnotatorBatchI
val SHORT_NAME = "JavadocHtmlLint"
}
override fun getBatchSuppressActions(element: PsiElement?) = SuppressQuickFix.EMPTY_ARRAY
override fun getBatchSuppressActions(element: PsiElement?): Array<out SuppressQuickFix> = SuppressQuickFix.EMPTY_ARRAY
}
@@ -45,6 +45,8 @@ import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.*;
import com.intellij.slicer.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.indexing.FileBasedIndex;
@@ -325,42 +327,60 @@ public class MagicConstantInspection extends BaseJavaLocalInspectionTool {
private static AllowedValues getAllowedValuesFromMagic(@NotNull PsiType type,
@NotNull PsiAnnotation magic,
@NotNull PsiManager manager) {
PsiAnnotationMemberValue[] allowedValues;
final boolean canBeOred;
PsiAnnotationMemberValue[] allowedValues = PsiAnnotationMemberValue.EMPTY_ARRAY;
boolean values = false, flags = false;
if (TypeConversionUtil.getTypeRank(type) <= TypeConversionUtil.LONG_RANK) {
PsiAnnotationMemberValue intValues = magic.findAttributeValue("intValues");
allowedValues = intValues instanceof PsiArrayInitializerMemberValue ? ((PsiArrayInitializerMemberValue)intValues).getInitializers() : PsiAnnotationMemberValue.EMPTY_ARRAY;
if (allowedValues.length == 0) {
PsiAnnotationMemberValue orValue = magic.findAttributeValue("flags");
allowedValues = orValue instanceof PsiArrayInitializerMemberValue ? ((PsiArrayInitializerMemberValue)orValue).getInitializers() : PsiAnnotationMemberValue.EMPTY_ARRAY;
canBeOred = true;
if (intValues instanceof PsiArrayInitializerMemberValue) {
final PsiAnnotationMemberValue[] initializers = ((PsiArrayInitializerMemberValue)intValues).getInitializers();
if (initializers.length != 0) {
allowedValues = initializers;
values = true;
}
}
else {
canBeOred = false;
if (!values) {
PsiAnnotationMemberValue orValue = magic.findAttributeValue("flags");
if (orValue instanceof PsiArrayInitializerMemberValue) {
final PsiAnnotationMemberValue[] initializers = ((PsiArrayInitializerMemberValue)orValue).getInitializers();
if (initializers.length != 0) {
allowedValues = initializers;
flags = true;
}
}
}
}
else if (type.equals(PsiType.getJavaLangString(manager, GlobalSearchScope.allScope(manager.getProject())))) {
PsiAnnotationMemberValue strValuesAttr = magic.findAttributeValue("stringValues");
allowedValues = strValuesAttr instanceof PsiArrayInitializerMemberValue ? ((PsiArrayInitializerMemberValue)strValuesAttr).getInitializers() : PsiAnnotationMemberValue.EMPTY_ARRAY;
canBeOred = false;
if (strValuesAttr instanceof PsiArrayInitializerMemberValue) {
final PsiAnnotationMemberValue[] initializers = ((PsiArrayInitializerMemberValue)strValuesAttr).getInitializers();
if (initializers.length != 0) {
allowedValues = initializers;
values = true;
}
}
}
else {
return null; //other types not supported
}
if (allowedValues.length != 0) {
return new AllowedValues(allowedValues, canBeOred);
PsiAnnotationMemberValue[] valuesFromClass = readFromClass("valuesFromClass", magic, type, manager);
if (valuesFromClass != null) {
allowedValues = ArrayUtil.mergeArrays(allowedValues, valuesFromClass, PsiAnnotationMemberValue.ARRAY_FACTORY);
values = true;
}
// last resort: try valuesFromClass
PsiAnnotationMemberValue[] values = readFromClass("valuesFromClass", magic, type, manager);
boolean ored = false;
if (values == null) {
values = readFromClass("flagsFromClass", magic, type, manager);
ored = true;
PsiAnnotationMemberValue[] flagsFromClass = readFromClass("flagsFromClass", magic, type, manager);
if (flagsFromClass != null) {
allowedValues = ArrayUtil.mergeArrays(allowedValues, flagsFromClass, PsiAnnotationMemberValue.ARRAY_FACTORY);
flags = true;
}
if (values == null) return null;
return new AllowedValues(values, ored);
if (allowedValues.length == 0) {
return null;
}
if (values && flags) {
throw new IncorrectOperationException(
"Misconfiguration of @MagicConstant annotation: 'flags' and 'values' shouldn't be used at the same time");
}
return new AllowedValues(allowedValues, flags);
}
private static PsiAnnotationMemberValue[] readFromClass(@NonNls @NotNull String attributeName,
@@ -106,7 +106,8 @@ class CollectMigration extends BaseStreamApiMigration {
return initializerClass != null &&
varClass != null &&
CommonClassNames.JAVA_UTIL_HASH_MAP.equals(initializerClass.getQualifiedName()) &&
CommonClassNames.JAVA_UTIL_MAP.equals(varClass.getQualifiedName());
CommonClassNames.JAVA_UTIL_MAP.equals(varClass.getQualifiedName()) &&
!ConstructionUtils.isCustomizedEmptyCollectionInitializer(initializer);
}
@Nullable
@@ -315,13 +316,14 @@ class CollectMigration extends BaseStreamApiMigration {
PsiClassType rawVarType = type instanceof PsiClassType ? ((PsiClassType)type).rawType() : null;
if (rawType != null && rawVarType != null &&
rawType.equalsToText(CommonClassNames.JAVA_UTIL_ARRAY_LIST) &&
(rawVarType.equalsToText(CommonClassNames.JAVA_UTIL_LIST) || rawVarType.equalsToText(CommonClassNames.JAVA_UTIL_COLLECTION))) {
(rawVarType.equalsToText(CommonClassNames.JAVA_UTIL_LIST) || rawVarType.equalsToText(CommonClassNames.JAVA_UTIL_COLLECTION)) &&
!ConstructionUtils.isCustomizedEmptyCollectionInitializer(initializer)) {
collector = "toList()";
}
else if (rawType != null && rawVarType != null &&
rawType.equalsToText(CommonClassNames.JAVA_UTIL_HASH_SET) &&
(rawVarType.equalsToText(CommonClassNames.JAVA_UTIL_SET) ||
rawVarType.equalsToText(CommonClassNames.JAVA_UTIL_COLLECTION))) {
(rawVarType.equalsToText(CommonClassNames.JAVA_UTIL_SET) || rawVarType.equalsToText(CommonClassNames.JAVA_UTIL_COLLECTION)) &&
!ConstructionUtils.isCustomizedEmptyCollectionInitializer(initializer)) {
collector = "toSet()";
}
else {
@@ -331,7 +333,7 @@ class CollectMigration extends BaseStreamApiMigration {
PsiExpressionList argumentList = ((PsiNewExpression)copy).getArgumentList();
if (argumentList != null) {
PsiExpression arg = ArrayUtil.getFirstElement(argumentList.getExpressions());
if (arg != null) {
if (arg != null && !(arg.getType() instanceof PsiPrimitiveType)) {
arg.delete();
}
}
@@ -1,13 +1,27 @@
/*
* Copyright 2000-2017 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.jarFinder;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.JdomKt;
import com.intellij.util.io.HttpRequests;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -52,14 +66,14 @@ public abstract class SourceSearcher {
}
@NotNull
protected static Document readDocumentCancelable(final ProgressIndicator indicator, String url) throws IOException {
protected static Element readDocumentCancelable(final ProgressIndicator indicator, String url) throws IOException {
return HttpRequests.request(url)
.accept("application/xml")
.connect(new HttpRequests.RequestProcessor<Document>() {
.connect(new HttpRequests.RequestProcessor<Element>() {
@Override
public Document process(@NotNull HttpRequests.Request request) throws IOException {
public Element process(@NotNull HttpRequests.Request request) throws IOException {
try {
return JDOMUtil.loadDocument(request.getReader(indicator));
return JdomKt.loadElement(request.getReader(indicator));
}
catch (JDOMException e) {
throw new IOException(e);
@@ -18,8 +18,8 @@ package com.intellij.psi.impl.source.resolve.reference.impl;
import com.intellij.codeInsight.completion.InsertHandler;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.completion.JavaLookupElementBuilder;
import com.intellij.codeInsight.completion.PrioritizedLookupElement;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilCore;
@@ -29,6 +29,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Comparator;
import static com.intellij.psi.impl.source.resolve.reference.impl.JavaReflectionReferenceUtil.*;
@@ -71,7 +72,7 @@ public class JavaLangClassMemberReference extends PsiReferenceBase<PsiLiteralExp
case DECLARED_FIELD: {
PsiField field = psiClass.findFieldByName(name, false);
return isReachable(field, psiClass) ? field : null;
return isPotentiallyAccessible(field, psiClass) ? field : null;
}
case METHOD: {
@@ -85,7 +86,7 @@ public class JavaLangClassMemberReference extends PsiReferenceBase<PsiLiteralExp
case DECLARED_METHOD: {
final PsiMethod[] methods = psiClass.findMethodsByName(name, false);
return ContainerUtil.find(methods, method -> isRegularMethod(method) && isReachable(method, psiClass));
return ContainerUtil.find(methods, method -> isRegularMethod(method) && isPotentiallyAccessible(method, psiClass));
}
}
}
@@ -115,21 +116,30 @@ public class JavaLangClassMemberReference extends PsiReferenceBase<PsiLiteralExp
switch (type) {
case DECLARED_FIELD:
return psiClass.getFields();
return Arrays.stream(psiClass.getFields())
.sorted(Comparator.comparing(PsiField::getName))
.map(field -> lookupField(field))
.toArray();
case FIELD:
return ContainerUtil.filter(psiClass.getAllFields(), field -> isReachable(field, psiClass)).toArray();
return Arrays.stream(psiClass.getAllFields())
.filter(field -> isPotentiallyAccessible(field, psiClass))
.sorted(Comparator.comparingInt((PsiField field) -> isPublic(field) ? 0 : 1).thenComparing(PsiField::getName))
.map(field -> withPriority(lookupField(field), isPublic(field)))
.toArray();
case DECLARED_METHOD:
return Arrays.stream(psiClass.getMethods())
.filter(method -> isRegularMethod(method))
.map(this::lookupMethod)
.sorted(Comparator.comparing(PsiMethod::getName))
.map(method -> lookupMethod(method))
.toArray();
case METHOD:
return Arrays.stream(psiClass.getAllMethods())
.filter(method -> isRegularMethod(method) && isReachable(method, psiClass) && !isJavaLangObject(method.getContainingClass()))
.map(this::lookupMethod)
.filter(method -> isRegularMethod(method) && isPotentiallyAccessible(method, psiClass))
.sorted(Comparator.comparingInt((PsiMethod method) -> getMethodSortOrder(method)).thenComparing(PsiMethod::getName))
.map(method -> PrioritizedLookupElement.withPriority(lookupMethod(method), -getMethodSortOrder(method)))
.toArray();
}
}
@@ -137,8 +147,17 @@ public class JavaLangClassMemberReference extends PsiReferenceBase<PsiLiteralExp
return EMPTY_ARRAY;
}
private static int getMethodSortOrder(PsiMethod method) {
return isJavaLangObject(method.getContainingClass()) ? 1 : isPublic(method) ? -1 : 0;
}
@NotNull
private LookupElementBuilder lookupMethod(PsiMethod method) {
private static LookupElement lookupField(PsiField field) {
return JavaLookupElementBuilder.forField(field);
}
@NotNull
private LookupElement lookupMethod(PsiMethod method) {
return JavaLookupElementBuilder.forMethod(method, PsiSubstitutor.EMPTY).withInsertHandler(this);
}
@@ -27,11 +27,11 @@ import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.ProcessingContext;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.Set;
import java.util.function.BiConsumer;
import static com.intellij.codeInsight.completion.JavaCompletionContributor.isInJavaContext;
import static com.intellij.patterns.PsiJavaPatterns.*;
@@ -42,18 +42,27 @@ import static com.intellij.psi.impl.source.resolve.reference.impl.JavaReflection
* @author Pavel.Dolgov
*/
public class JavaReflectionCompletionContributor extends CompletionContributor {
private static final String CONSTRUCTOR = "getConstructor";
private static final String DECLARED_CONSTRUCTOR = "getDeclaredConstructor";
private static final String ANNOTATION = "getAnnotation";
private static final String DECLARED_ANNOTATION = "getDeclaredAnnotation";
private static final String ANNOTATIONS_BY_TYPE = "getAnnotationsByType";
private static final String DECLARED_ANNOTATIONS_BY_TYPE = "getDeclaredAnnotationsByType";
private static final String ANNOTATED_ELEMENT = "java.lang.reflect.AnnotatedElement";
private static final Set<String> DECLARED_NAMES =
ContainerUtil.immutableSet(DECLARED_CONSTRUCTOR, DECLARED_ANNOTATION, DECLARED_ANNOTATIONS_BY_TYPE);
private static final ElementPattern<? extends PsiElement> CONSTRUCTOR_ARGUMENTS = psiElement(PsiExpressionList.class)
.withParent(psiExpression().methodCall(
psiMethod()
.withName("getConstructor", "getDeclaredConstructor")
.withName(CONSTRUCTOR, DECLARED_CONSTRUCTOR)
.definedInClass(CommonClassNames.JAVA_LANG_CLASS)));
private static final ElementPattern<? extends PsiElement> ANNOTATION_ARGUMENTS = psiElement(PsiExpressionList.class)
.withParent(psiExpression().methodCall(
psiMethod()
.withName("getAnnotation", "getDeclaredAnnotation", "getAnnotationsByType", "getDeclaredAnnotationsByType")
.with(new MethodDefinedInInterfacePatternCondition("java.lang.reflect.AnnotatedElement"))));
.withName(ANNOTATION, DECLARED_ANNOTATION, ANNOTATIONS_BY_TYPE, DECLARED_ANNOTATIONS_BY_TYPE)
.with(new MethodDefinedInInterfacePatternCondition(ANNOTATED_ELEMENT))));
private static final ElementPattern<PsiElement> BEGINNING_OF_CONSTRUCTOR_ARGUMENTS = beginningOfArguments(CONSTRUCTOR_ARGUMENTS);
@@ -79,28 +88,32 @@ public class JavaReflectionCompletionContributor extends CompletionContributor {
}
if (BEGINNING_OF_ANNOTATION_ARGUMENTS.accepts(position)) {
PsiClass psiClass = getQualifierClass(position);
if (psiClass != null) {
addAnnotationClasses(psiClass, result);
}
addVariants(position, (psiClass, isDeclared) -> addAnnotationClasses(psiClass, isDeclared, result));
//TODO handle annotations on fields and methods
}
if (BEGINNING_OF_CONSTRUCTOR_ARGUMENTS.accepts(position)) {
PsiClass psiClass = getQualifierClass(position);
else if (BEGINNING_OF_CONSTRUCTOR_ARGUMENTS.accepts(position)) {
addVariants(position, (psiClass, isDeclared) -> addConstructorParameterTypes(psiClass, isDeclared, result));
}
}
private static void addVariants(PsiElement position, BiConsumer<PsiClass, Boolean> variantAdder) {
PsiMethodCallExpression methodCall = PsiTreeUtil.getParentOfType(position, PsiMethodCallExpression.class);
if (methodCall != null) {
PsiClass psiClass = getReflectiveClass(methodCall.getMethodExpression().getQualifierExpression());
if (psiClass != null) {
addConstructorParameterTypes(psiClass, result);
String methodName = methodCall.getMethodExpression().getReferenceName();
if (methodName != null) {
variantAdder.accept(psiClass, DECLARED_NAMES.contains(methodName));
}
}
}
}
@Nullable
private static PsiClass getQualifierClass(@Nullable PsiElement position) {
PsiMethodCallExpression methodCall = PsiTreeUtil.getParentOfType(position, PsiMethodCallExpression.class);
return methodCall != null ? getReflectiveClass(methodCall.getMethodExpression().getQualifierExpression()) : null;
}
private static void addAnnotationClasses(@NotNull PsiClass psiClass, boolean isDeclared, @NotNull CompletionResultSet result) {
Set<PsiAnnotation> declaredAnnotations =
isDeclared ? ContainerUtil.set(AnnotationUtil.getAllAnnotations(psiClass, false, null, false)) : null;
private static void addAnnotationClasses(@NotNull PsiModifierListOwner annotationsOwner, @NotNull CompletionResultSet result) {
PsiAnnotation[] annotations = AnnotationUtil.getAllAnnotations(annotationsOwner, true, null);
PsiAnnotation[] annotations = AnnotationUtil.getAllAnnotations(psiClass, true, null, false);
for (PsiAnnotation annotation : annotations) {
PsiJavaCodeReferenceElement referenceElement = annotation.getNameReferenceElement();
if (referenceElement != null) {
@@ -112,6 +125,9 @@ public class JavaReflectionCompletionContributor extends CompletionContributor {
LookupElement lookupElement = LookupElementBuilder.createWithIcon(annotationClass)
.withPresentableText(className + ".class")
.withInsertHandler(JavaReflectionCompletionContributor::handleAnnotationClassInsertion);
if (isDeclared) {
lookupElement = withPriority(lookupElement, declaredAnnotations.contains(annotation));
}
result.addElement(lookupElement);
}
}
@@ -119,26 +135,22 @@ public class JavaReflectionCompletionContributor extends CompletionContributor {
}
}
private static void addConstructorParameterTypes(@NotNull PsiClass psiClass, @NotNull CompletionResultSet result) {
private static void addConstructorParameterTypes(@NotNull PsiClass psiClass, boolean isDeclared, @NotNull CompletionResultSet result) {
PsiMethod[] constructors = psiClass.getConstructors();
if (constructors.length != 0) {
for (PsiMethod constructor : constructors) {
String parameterTypesText = Arrays.stream(constructor.getParameterList().getParameters())
.map(p -> p.getType().getCanonicalText())
.collect(Collectors.joining(",", constructor.getName() + "(", ")"));
LookupElement lookupElement = LookupElementBuilder.createWithIcon(constructor)
.withPresentableText(parameterTypesText)
.withInsertHandler(JavaReflectionCompletionContributor::handleConstructorSignatureInsertion);
result.addElement(lookupElement);
for (PsiMethod constructor : constructors) {
LookupElement lookupElement = JavaLookupElementBuilder.forMethod(constructor, PsiSubstitutor.EMPTY)
.withInsertHandler(JavaReflectionCompletionContributor::handleConstructorSignatureInsertion);
if (isDeclared) {
lookupElement = withPriority(lookupElement, isPublic(constructor));
}
result.addElement(lookupElement);
}
}
private static void handleAnnotationClassInsertion(@NotNull InsertionContext context, @NotNull LookupElement item) {
Object object = item.getObject();
if (object instanceof PsiClass) {
String className = ((PsiClass)object).getName();
String className = ((PsiClass)object).getQualifiedName();
if (className != null) {
handleParametersInsertion(context, className + ".class");
}
@@ -16,6 +16,8 @@
package com.intellij.psi.impl.source.resolve.reference.impl;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.completion.PrioritizedLookupElement;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.RecursionGuard;
import com.intellij.openapi.util.RecursionManager;
@@ -151,7 +153,7 @@ class JavaReflectionReferenceUtil {
* Non-public members of superclass/superinterface can't be obtained via reflection, they need to be filtered out.
*/
@Contract("null, _ -> false")
static boolean isReachable(PsiMember member, PsiClass psiClass) {
static boolean isPotentiallyAccessible(PsiMember member, PsiClass psiClass) {
return member != null && (member.getContainingClass() == psiClass || isPublic(member));
}
@@ -175,4 +177,9 @@ class JavaReflectionReferenceUtil {
JavaCodeStyleManager.getInstance(context.getProject()).shortenClassReferences(methodCall.getArgumentList());
}
}
@NotNull
static LookupElement withPriority(LookupElement lookupElement, boolean hasPriority) {
return PrioritizedLookupElement.withPriority(lookupElement, hasPriority ? 1 : -1);
}
}
@@ -62,10 +62,9 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
final PsiClass baseClass = parameters.getClassToProcess();
assert parameters.isCheckInheritance();
SearchScope useScope = ReadAction.compute(baseClass::getUseScope);
final Project project = PsiUtilCore.getProjectInReadAction(baseClass);
if (JavaClassInheritorsSearcher.isJavaLangObject(baseClass)) {
SearchScope useScope = ReadAction.compute(baseClass::getUseScope);
return AllClassesSearch.search(useScope, project).forEach(psiClass -> {
ProgressManager.checkCanceled();
if (psiClass.isInterface()) {
@@ -76,13 +75,17 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
});
}
SearchScope scope = parameters.getScope();
CompilerDirectHierarchyInfo info = performSearchUsingCompilerIndices(parameters, scope, project);
if (info != null) {
SearchScope scope;
SearchScope useScope;
CompilerDirectHierarchyInfo info = performSearchUsingCompilerIndices(parameters, parameters.getScope(), project);
if (info == null) {
scope = parameters.getScope();
useScope = ReadAction.compute(baseClass::getUseScope);
}
else {
if (!processInheritorCandidates(info.getHierarchyChildren(), consumer, parameters.includeAnonymous())) return false;
scope = scope.intersectWith(info.getDirtyScope());
useScope = useScope.intersectWith(info.getDirtyScope());
scope = ReadAction.compute(() -> parameters.getScope().intersectWith(info.getDirtyScope()));
useScope = ReadAction.compute(() -> baseClass.getUseScope().intersectWith(info.getDirtyScope()));
}
PsiClass[] cache = getOrCalculateDirectSubClasses(project, baseClass, useScope);
@@ -35,13 +35,14 @@ public interface PsiModifier {
String VOLATILE = "volatile";
String DEFAULT = "default";
String OPEN = "open";
String TRANSITIVE = "transitive";
String[] MODIFIERS = {
PUBLIC, PROTECTED, PRIVATE, STATIC, ABSTRACT, FINAL, NATIVE, SYNCHRONIZED, STRICTFP, TRANSIENT, VOLATILE, DEFAULT, OPEN
PUBLIC, PROTECTED, PRIVATE, STATIC, ABSTRACT, FINAL, NATIVE, SYNCHRONIZED, STRICTFP, TRANSIENT, VOLATILE, DEFAULT, OPEN, TRANSITIVE
};
@MagicConstant(stringValues = {
PUBLIC, PROTECTED, PRIVATE, STATIC, ABSTRACT, FINAL, NATIVE, SYNCHRONIZED, STRICTFP, TRANSIENT, VOLATILE, DEFAULT, OPEN, PACKAGE_LOCAL
PUBLIC, PROTECTED, PRIVATE, STATIC, ABSTRACT, FINAL, NATIVE, SYNCHRONIZED, STRICTFP, TRANSIENT, VOLATILE, DEFAULT, OPEN, TRANSITIVE, PACKAGE_LOCAL
})
@interface ModifierConstant { }
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -22,7 +22,7 @@ import org.jetbrains.annotations.Nullable;
*
* @since 2016.3
*/
public interface PsiRequiresStatement extends PsiElement {
public interface PsiRequiresStatement extends PsiModifierListOwner {
PsiRequiresStatement[] EMPTY_ARRAY = new PsiRequiresStatement[0];
@Nullable PsiJavaModuleReferenceElement getReferenceElement();
@@ -42,6 +42,7 @@ public final class ModifierFlags {
public static final int STRICTFP_MASK = 0x0800;
public static final int PACKAGE_LOCAL_MASK = 0x1000;
public static final int OPEN_MASK = 0x2000;
public static final int TRANSITIVE_MASK = 0x4000;
public static final TObjectIntHashMap<String> NAME_TO_MODIFIER_FLAG_MAP = new TObjectIntHashMap<String>();
public static final TIntObjectHashMap<String> MODIFIER_FLAG_TO_NAME_MAP = new TIntObjectHashMap<String>();
@@ -61,6 +62,7 @@ public final class ModifierFlags {
NAME_TO_MODIFIER_FLAG_MAP.put(PsiModifier.STRICTFP, STRICTFP_MASK);
NAME_TO_MODIFIER_FLAG_MAP.put(PsiModifier.PACKAGE_LOCAL, PACKAGE_LOCAL_MASK);
NAME_TO_MODIFIER_FLAG_MAP.put(PsiModifier.OPEN, OPEN_MASK);
NAME_TO_MODIFIER_FLAG_MAP.put(PsiModifier.TRANSITIVE, TRANSITIVE_MASK);
for (Object name : NAME_TO_MODIFIER_FLAG_MAP.keys()) {
MODIFIER_FLAG_TO_NAME_MAP.put(NAME_TO_MODIFIER_FLAG_MAP.get((String)name), (String)name);
@@ -79,6 +81,7 @@ public final class ModifierFlags {
KEYWORD_TO_MODIFIER_FLAG_MAP.put(JavaTokenType.ABSTRACT_KEYWORD, ABSTRACT_MASK);
KEYWORD_TO_MODIFIER_FLAG_MAP.put(JavaTokenType.STRICTFP_KEYWORD, STRICTFP_MASK);
KEYWORD_TO_MODIFIER_FLAG_MAP.put(JavaTokenType.OPEN_KEYWORD, OPEN_MASK);
KEYWORD_TO_MODIFIER_FLAG_MAP.put(JavaTokenType.TRANSITIVE_KEYWORD, TRANSITIVE_MASK);
}
public static boolean hasModifierProperty(String name, int mask) {
@@ -34,6 +34,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import static com.intellij.util.containers.ContainerUtil.newArrayList;
import static java.util.Arrays.asList;
public class ClsJavaModuleImpl extends ClsRepositoryPsiElement<PsiJavaModuleStub> implements PsiJavaModule {
private PsiJavaModuleReferenceElement myReference;
@@ -93,16 +94,16 @@ public class ClsJavaModuleImpl extends ClsRepositoryPsiElement<PsiJavaModuleStub
@Override
public void setMirror(@NotNull TreeElement element) throws InvalidMirrorException {
setMirrorCheckingType(element, JavaElementType.MODULE);
PsiJavaModule mirror = SourceTreeToPsiMap.treeToPsiNotNull(element);
setMirrorCheckingType(element, JavaElementType.MODULE);
setMirror(getNameIdentifier(), mirror.getNameIdentifier());
setMirror(getModifierList(), mirror.getModifierList());
//setMirror(getModifierList(), mirror.getModifierList());
setMirrors(newArrayList(getStub().getChildrenByType(JavaElementType.REQUIRES_STATEMENT, PsiRequiresStatement.EMPTY_ARRAY)),
setMirrors(asList(getStub().getChildrenByType(JavaElementType.REQUIRES_STATEMENT, PsiRequiresStatement.EMPTY_ARRAY)),
newArrayList(mirror.getRequires()));
setMirrors(newArrayList(getStub().getChildrenByType(JavaElementType.EXPORTS_STATEMENT, PsiPackageAccessibilityStatement.EMPTY_ARRAY)),
setMirrors(asList(getStub().getChildrenByType(JavaElementType.EXPORTS_STATEMENT, PsiPackageAccessibilityStatement.EMPTY_ARRAY)),
newArrayList(mirror.getExports()));
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -24,12 +24,10 @@ import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.impl.source.tree.TreeElement;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("ForLoopReplaceableByForEach")
public class ClsModifierListImpl extends ClsRepositoryPsiElement<PsiModifierListStub> implements PsiModifierList {
public ClsModifierListImpl(final PsiModifierListStub stub) {
public ClsModifierListImpl(PsiModifierListStub stub) {
super(stub);
}
@@ -78,29 +76,29 @@ public class ClsModifierListImpl extends ClsRepositoryPsiElement<PsiModifierList
@Override
@NotNull
public PsiAnnotation addAnnotation(@NotNull @NonNls String qualifiedName) {
public PsiAnnotation addAnnotation(@NotNull String qualifiedName) {
throw cannotModifyException(this);
}
@Override
public void appendMirrorText(int indentLevel, @NotNull StringBuilder buffer) {
final PsiElement parent = getParent();
final PsiAnnotation[] annotations = getAnnotations();
final boolean separateAnnotations = parent instanceof PsiClass || parent instanceof PsiMethod || parent instanceof PsiField;
PsiElement parent = getParent();
PsiAnnotation[] annotations = getAnnotations();
boolean separateAnnotations = parent instanceof PsiClass || parent instanceof PsiMethod || parent instanceof PsiField;
for (int i = 0; i < annotations.length; i++) {
appendText(annotations[i], indentLevel, buffer, separateAnnotations ? NEXT_LINE : " ");
for (PsiAnnotation annotation : annotations) {
appendText(annotation, indentLevel, buffer, separateAnnotations ? NEXT_LINE : " ");
}
final boolean isClass = parent instanceof PsiClass;
final boolean isInterface = isClass && ((PsiClass)parent).isInterface();
final boolean isEnum = isClass && ((PsiClass)parent).isEnum();
final boolean isInterfaceClass = isClass && parent.getParent() instanceof PsiClass && ((PsiClass)parent.getParent()).isInterface();
final boolean isMethod = parent instanceof PsiMethod;
final boolean isInterfaceMethod = isMethod && parent.getParent() instanceof PsiClass && ((PsiClass)parent.getParent()).isInterface();
final boolean isField = parent instanceof PsiField;
final boolean isInterfaceField = isField && parent.getParent() instanceof PsiClass && ((PsiClass)parent.getParent()).isInterface();
final boolean isEnumConstant = parent instanceof PsiEnumConstant;
boolean isClass = parent instanceof PsiClass;
boolean isInterface = isClass && ((PsiClass)parent).isInterface();
boolean isEnum = isClass && ((PsiClass)parent).isEnum();
boolean isInterfaceClass = isClass && parent.getParent() instanceof PsiClass && ((PsiClass)parent.getParent()).isInterface();
boolean isMethod = parent instanceof PsiMethod;
boolean isInterfaceMethod = isMethod && parent.getParent() instanceof PsiClass && ((PsiClass)parent.getParent()).isInterface();
boolean isField = parent instanceof PsiField;
boolean isInterfaceField = isField && parent.getParent() instanceof PsiClass && ((PsiClass)parent.getParent()).isInterface();
boolean isEnumConstant = parent instanceof PsiEnumConstant;
if (hasModifierProperty(PsiModifier.PUBLIC) && !isInterfaceMethod && !isInterfaceField && !isInterfaceClass && !isEnumConstant) {
buffer.append(PsiModifier.PUBLIC).append(' ');
@@ -160,4 +158,4 @@ public class ClsModifierListImpl extends ClsRepositoryPsiElement<PsiModifierList
public String toString() {
return "PsiModifierList";
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -19,10 +19,14 @@ import com.intellij.openapi.util.AtomicNotNullLazyValue;
import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiJavaModuleReferenceElement;
import com.intellij.psi.PsiModifierList;
import com.intellij.psi.PsiRequiresStatement;
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
import com.intellij.psi.impl.java.stubs.PsiRequiresStatementStub;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.impl.source.tree.TreeElement;
import com.intellij.psi.stubs.StubElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -70,6 +74,19 @@ public class ClsRequiresStatementImpl extends ClsRepositoryPsiElement<PsiRequire
@Override
public void setMirror(@NotNull TreeElement element) throws InvalidMirrorException {
setMirrorCheckingType(element, JavaElementType.REQUIRES_STATEMENT);
//setMirror(getModifierList(), SourceTreeToPsiMap.<PsiRequiresStatement>treeToPsiNotNull(element).getModifierList());
}
@Override
public PsiModifierList getModifierList() {
StubElement<PsiModifierList> childStub = getStub().findChildStubByType(JavaStubElementTypes.MODIFIER_LIST);
return childStub != null ? childStub.getPsi() : null;
}
@Override
public boolean hasModifierProperty(@NotNull String name) {
PsiModifierList modifierList = getModifierList();
return modifierList != null && modifierList.hasModifierProperty(name);
}
@Override
@@ -18,7 +18,7 @@ package com.intellij.psi.impl.java.stubs;
import com.intellij.psi.*;
import com.intellij.psi.impl.compiled.*;
/*
/**
* @author max
*/
public class ClsStubPsiFactory extends StubPsiFactory {
@@ -13,16 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* @author max
*/
package com.intellij.psi.impl.java.stubs;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.*;
import com.intellij.psi.impl.source.tree.java.*;
/**
* @author max
*/
public class SourceStubPsiFactory extends StubPsiFactory {
public static final SourceStubPsiFactory INSTANCE = new SourceStubPsiFactory();
@@ -17,7 +17,7 @@ package com.intellij.psi.impl.java.stubs;
import com.intellij.psi.*;
/*
/**
* @author max
*/
public abstract class StubPsiFactory {
@@ -61,6 +61,7 @@ public class PsiModifierListImpl extends JavaStubPsiElement<PsiModifierListStub>
NAME_TO_KEYWORD_TYPE_MAP.put(VOLATILE, JavaTokenType.VOLATILE_KEYWORD);
NAME_TO_KEYWORD_TYPE_MAP.put(DEFAULT, JavaTokenType.DEFAULT_KEYWORD);
NAME_TO_KEYWORD_TYPE_MAP.put(OPEN, JavaTokenType.OPEN_KEYWORD);
NAME_TO_KEYWORD_TYPE_MAP.put(TRANSITIVE, JavaTokenType.TRANSITIVE_KEYWORD);
KEYWORD_TYPE_TO_NAME_MAP = ContainerUtil.newTroveMap();
for (String name : NAME_TO_KEYWORD_TYPE_MAP.keySet()) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -67,6 +67,17 @@ public class PsiRequiresStatementImpl extends JavaStubPsiElement<PsiRequiresStat
}
}
@Override
public PsiModifierList getModifierList() {
return getStubOrPsiChild(JavaStubElementTypes.MODIFIER_LIST);
}
@Override
public boolean hasModifierProperty(@NotNull String name) {
PsiModifierList modifierList = getModifierList();
return modifierList != null && modifierList.hasModifierProperty(name);
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof JavaElementVisitor) {
@@ -35,7 +35,8 @@ public interface ElementType extends JavaTokenType, JavaDocTokenType, JavaElemen
PRIVATE_KEYWORD, PROTECTED_KEYWORD, PUBLIC_KEYWORD, RETURN_KEYWORD, SHORT_KEYWORD, SUPER_KEYWORD, STATIC_KEYWORD, STRICTFP_KEYWORD,
SWITCH_KEYWORD, SYNCHRONIZED_KEYWORD, THIS_KEYWORD, THROW_KEYWORD, THROWS_KEYWORD, TRANSIENT_KEYWORD, TRY_KEYWORD, VOID_KEYWORD,
VOLATILE_KEYWORD, WHILE_KEYWORD,
OPEN_KEYWORD, MODULE_KEYWORD, REQUIRES_KEYWORD, EXPORTS_KEYWORD, OPENS_KEYWORD, USES_KEYWORD, PROVIDES_KEYWORD, TO_KEYWORD, WITH_KEYWORD);
OPEN_KEYWORD, MODULE_KEYWORD, REQUIRES_KEYWORD, EXPORTS_KEYWORD, OPENS_KEYWORD, USES_KEYWORD, PROVIDES_KEYWORD,
TRANSITIVE_KEYWORD, TO_KEYWORD, WITH_KEYWORD);
TokenSet LITERAL_BIT_SET = TokenSet.create(TRUE_KEYWORD, FALSE_KEYWORD, NULL_KEYWORD);
@@ -70,7 +71,8 @@ public interface ElementType extends JavaTokenType, JavaDocTokenType, JavaElemen
WHILE_STATEMENT, FOR_STATEMENT, FOREACH_STATEMENT, DO_WHILE_STATEMENT, SWITCH_STATEMENT, SWITCH_LABEL_STATEMENT, BREAK_STATEMENT,
CONTINUE_STATEMENT, RETURN_STATEMENT, THROW_STATEMENT, SYNCHRONIZED_STATEMENT, TRY_STATEMENT, LABELED_STATEMENT, ASSERT_STATEMENT);
TokenSet JAVA_MODULE_STATEMENT_BIT_SET = TokenSet.create(REQUIRES_STATEMENT, EXPORTS_STATEMENT, OPENS_STATEMENT, USES_STATEMENT, PROVIDES_STATEMENT);
TokenSet JAVA_MODULE_STATEMENT_BIT_SET = TokenSet.create(
REQUIRES_STATEMENT, EXPORTS_STATEMENT, OPENS_STATEMENT, USES_STATEMENT, PROVIDES_STATEMENT);
TokenSet IMPORT_STATEMENT_BASE_BIT_SET = TokenSet.create(IMPORT_STATEMENT, IMPORT_STATIC_STATEMENT);
TokenSet CLASS_KEYWORD_BIT_SET = TokenSet.create(CLASS_KEYWORD, INTERFACE_KEYWORD, ENUM_KEYWORD);
@@ -22,5 +22,5 @@ class DeclaredField {
class Test {
public int num;
public int num2;
int num3;
int num1;
}
@@ -22,5 +22,5 @@ class DeclaredField {
class Test {
public int num;
public int num2;
int num3;
int num1;
}
@@ -22,7 +22,7 @@ class DecalredMethod {
class Test {
public void method(){}
public void method2(A a, B b){}
public void method3(){}
void method1(){}
}
class A {}
@@ -22,7 +22,7 @@ class DecalredMethod2 {
class Test {
void method(){}
void method2(A a, B b){}
void method3(){}
void method1(){}
}
class A {}
@@ -15,14 +15,14 @@
*/
class DecalredMethod2 {
void foo() {
Test.class.getDeclaredMethod("method3");
Test.class.getDeclaredMethod("method1");
}
}
class Test {
void method(){}
void method2(A a, B b){}
void method3(){}
void method1(){}
}
class A {}
@@ -22,7 +22,7 @@ class DecalredMethod {
class Test {
public void method(){}
public void method2(A a, B b){}
public void method3(){}
void method1(){}
}
class A {}
@@ -22,5 +22,5 @@ class ForNameDeclaredField {
class Test {
public int num;
public int num2;
int num3;
int num1;
}
@@ -15,12 +15,12 @@
*/
class ForNameDeclaredField {
void foo() {
Class.forName("Test").getDeclaredField("num3");
Class.forName("Test").getDeclaredField("num1");
}
}
class Test {
public int num;
public int num2;
int num3;
int num1;
}
@@ -22,7 +22,7 @@ class ForNameDeclaredMethod {
class Test {
public void method(){}
public void method2(A a, B b){}
void method3(){}
void method1(){}
}
class A {}
@@ -22,7 +22,7 @@ class ForNameDeclaredMethod {
class Test {
public void method(){}
public void method2(A a, B b){}
void method3(){}
void method1(){}
}
class A {}
@@ -0,0 +1,17 @@
class HasConstructor {
void foo() {
Test.class.getMethod("<caret>");
}
}
class Test {
public Test() {}
Test(int n) {}
public void method(){}
public void method2(A a, B b){}
void method1(){}
}
class A {}
class B {}
class C {}
@@ -0,0 +1,17 @@
class HasConstructor {
void foo() {
Test.class.getMethod("method1");
}
}
class Test {
public Test() {}
Test(int n) {}
public void method(){}
public void method2(A a, B b){}
void method1(){}
}
class A {}
class B {}
class C {}
@@ -0,0 +1,9 @@
class Main {
void foo() {
Test.class.getMethod("<caret>");
}
}
class Test {
public void method(){}
}
@@ -0,0 +1,9 @@
class Main {
void foo() {
Test.class.getMethod("notifyAll");
}
}
class Test {
public void method(){}
}
@@ -0,0 +1,5 @@
class Main {
void foo() {
Object.class.getMethod("<caret>");
}
}
@@ -0,0 +1,5 @@
class Main {
void foo() {
Object.class.getMethod("wait", long.class);
}
}
@@ -0,0 +1,17 @@
class Main {
void foo() {
Test.class.getMethod("<caret>");
}
}
class Test {
public Test() {}
Test(int n) {}
public void method(){}
void method(A a, B b){}
public void method(C c){}
}
class A {}
class B {}
class C {}
@@ -0,0 +1,17 @@
class Main {
void foo() {
Test.class.getMethod("method", A.class, B.class);
}
}
class Test {
public Test() {}
Test(int n) {}
public void method(){}
void method(A a, B b){}
public void method(C c){}
}
class A {}
class B {}
class C {}
@@ -1,7 +1,6 @@
import foo.bar.*;
class Main {
void foo() throws ReflectiveOperationException {
Class<Annotation> aType = Baz.class;
Test.class.getAnnotation(<caret>);
}
}
@@ -1,7 +1,6 @@
import foo.bar.*;
class Main {
void foo() throws ReflectiveOperationException {
Class<Annotation> aType = Baz.class;
Test.class.getAnnotation(Bar.class);
}
}
@@ -1,6 +1,6 @@
import foo.bar.*;
class Main {
void foo() throws ReflectiveOperationException {
Test.class.getDeclaredAnnotation(Bar.class);
Test.class.getDeclaredAnnotation(Foo.class);
}
}
@@ -0,0 +1,6 @@
import foo.bar.*;
class Main {
void foo() throws ReflectiveOperationException {
More.class.getAnnotation(<caret>);
}
}
@@ -0,0 +1,8 @@
import foo.bar.*;
import foo.baz.Baz;
class Main {
void foo() throws ReflectiveOperationException {
More.class.getAnnotation(Baz.class);
}
}
@@ -1,7 +1,6 @@
import foo.bar.*;
class Main {
void foo() throws ReflectiveOperationException {
Class<Annotation> aType = Baz.class;
Test.class.getAnnotation(<caret>);
}
}
@@ -1,7 +1,6 @@
import foo.bar.*;
class Main {
void foo() throws ReflectiveOperationException {
Class<Annotation> aType = Baz.class;
Test.class.getAnnotation(Foo.class);
}
}
@@ -1,6 +1,6 @@
import foo.bar.*;
class Main {
void foo() throws ReflectiveOperationException {
Test.class.getDeclaredAnnotation(Foo.class);
Test.class.getDeclaredAnnotation(Bar.class);
}
}
@@ -0,0 +1,8 @@
import foo.bar.*;
import foo.baz.Baz;
class Main {
void foo() throws ReflectiveOperationException {
Class<Annotation> aType = Baz.class;
Test.class.getAnnotation(<caret>);
}
}
@@ -0,0 +1,8 @@
import foo.bar.*;
import foo.baz.Baz;
class Main {
void foo() throws ReflectiveOperationException {
Class<Annotation> aType = Baz.class;
Test.class.getAnnotation(aType);
}
}
@@ -0,0 +1,52 @@
// "Fix all 'Loop can be collapsed with Stream API' problems in file" "true"
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
public class Test {
void testList(List<String> input) {
List<String> result = input.stream().filter(s -> !s.isEmpty()).collect(Collectors.toCollection(() -> new ArrayList<>(10)));
System.out.println(result);
ArrayList<String> result2 = input.stream().filter(s -> !s.isEmpty()).collect(Collectors.toCollection(() -> new ArrayList<>(20)));
System.out.println(result2);
// Non-empty
ArrayList<String> result3 = new ArrayList<>(input);
input.stream().filter(s -> !s.isEmpty()).forEach(result3::add);
System.out.println(result3);
}
void testSet(List<String> input) {
Set<String> result = input.stream().filter(s -> !s.isEmpty()).collect(Collectors.toCollection(() -> new HashSet<>(10)));
System.out.println(result);
Collection<String> result2 = input.stream().filter(s -> !s.isEmpty()).collect(Collectors.toCollection(() -> new LinkedHashSet<>(20, 0.8f)));
System.out.println(result2);
// Non-empty
AbstractSet<String> result3 = new HashSet<>(input);
input.stream().filter(s -> !s.isEmpty()).forEach(result3::add);
System.out.println(result3);
Collection<TimeUnit> result4 = input.stream().filter(s -> !s.isEmpty()).map(TimeUnit::valueOf).collect(Collectors.toCollection(() -> EnumSet.noneOf(TimeUnit.class)));
System.out.println(result4);
}
void testMap(List<String> input) {
Map<Integer, String> result = input.stream().filter(s -> !s.isEmpty()).collect(Collectors.toMap(String::length, s -> s, (a, b) -> b, () -> new HashMap<>(10)));
System.out.println(result);
Map<Integer, String> result2 = input.stream().filter(s -> !s.isEmpty()).collect(Collectors.toMap(String::length, s -> s, (a, b) -> b, () -> new HashMap<>(10, 0.8f)));
System.out.println(result2);
EnumMap<TimeUnit, String> result3 = input.stream().filter(s -> !s.isEmpty()).collect(Collectors.toMap(TimeUnit::valueOf, s -> s, (a, b) -> b, () -> new EnumMap<>(TimeUnit.class)));
System.out.println(result3);
// Non-empty
EnumMap<TimeUnit, String> result4 = new EnumMap<>(result3);
input.stream().filter(s -> !s.isEmpty()).forEach(s -> result4.put(TimeUnit.valueOf(s), s));
System.out.println(result4);
}
}
@@ -0,0 +1,14 @@
// "Replace with collect" "true"
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Test {
public List<String> test(String[] data) {
int top = Math.min(10, data.length);
List<String> result = Arrays.stream(data).limit(10).map(String::trim).filter(item -> !item.isEmpty()).collect(Collectors.toList());
return result;
}
}
@@ -0,0 +1,103 @@
// "Fix all 'Loop can be collapsed with Stream API' problems in file" "true"
import java.util.*;
import java.util.concurrent.TimeUnit;
public class Test {
void testList(List<String> input) {
List<String> result = new ArrayList<>(10);
for (String s : in<caret>put) {
if (!s.isEmpty()) {
result.add(s);
}
}
System.out.println(result);
ArrayList<String> result2 = new ArrayList<>(20);
for (String s : input) {
if (!s.isEmpty()) {
result2.add(s);
}
}
System.out.println(result2);
// Non-empty
ArrayList<String> result3 = new ArrayList<>(input);
for (String s : input) {
if (!s.isEmpty()) {
result3.add(s);
}
}
System.out.println(result3);
}
void testSet(List<String> input) {
Set<String> result = new HashSet<>(10);
for (String s : input) {
if (!s.isEmpty()) {
result.add(s);
}
}
System.out.println(result);
Collection<String> result2 = new LinkedHashSet<>(20, 0.8f);
for (String s : input) {
if (!s.isEmpty()) {
result2.add(s);
}
}
System.out.println(result2);
// Non-empty
AbstractSet<String> result3 = new HashSet<>(input);
for (String s : input) {
if (!s.isEmpty()) {
result3.add(s);
}
}
System.out.println(result3);
Collection<TimeUnit> result4 = EnumSet.noneOf(TimeUnit.class);
for (String s : input) {
if (!s.isEmpty()) {
result4.add(TimeUnit.valueOf(s));
}
}
System.out.println(result4);
}
void testMap(List<String> input) {
Map<Integer, String> result = new HashMap<>(10);
for (String s : input) {
if (!s.isEmpty()) {
result.put(s.length(), s);
}
}
System.out.println(result);
Map<Integer, String> result2 = new HashMap<>(10, 0.8f);
for (String s : input) {
if (!s.isEmpty()) {
result2.put(s.length(), s);
}
}
System.out.println(result2);
EnumMap<TimeUnit, String> result3 = new EnumMap<>(TimeUnit.class);
for (String s : input) {
if (!s.isEmpty()) {
result3.put(TimeUnit.valueOf(s), s);
}
}
System.out.println(result3);
// Non-empty
EnumMap<TimeUnit, String> result4 = new EnumMap<>(result3);
for (String s : input) {
if (!s.isEmpty()) {
result4.put(TimeUnit.valueOf(s), s);
}
}
System.out.println(result4);
}
}
@@ -0,0 +1,18 @@
// "Replace with collect" "true"
import java.util.ArrayList;
import java.util.List;
public class Test {
public List<String> test(String[] data) {
int top = Math.min(10, data.length);
List<String> result = new ArrayList<>();
for(int<caret> i=0; i<top; i++) {
String item = data[i].trim();
if(!item.isEmpty()) {
result.add(item);
}
}
return result;
}
}
@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
<problem>
<file>X.java</file>
<line>31</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
<description>Should be one of: Const1.X, Const2.I</description>
</problem>
<problem>
<file>X.java</file>
<line>32</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
<description>Should be one of: Const1.X, Const2.I</description>
</problem>
<problem>
<file>X.java</file>
<line>33</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
<description>Should be one of: Const1.X, Const2.I</description>
</problem>
<problem>
<file>X.java</file>
<line>44</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
<description>Should be one of: Const2.I, Const1.X</description>
</problem>
<problem>
<file>X.java</file>
<line>45</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
<description>Should be one of: Const2.I, Const1.X</description>
</problem>
<problem>
<file>X.java</file>
<line>46</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
<description>Should be one of: Const2.I, Const1.X</description>
</problem>
<problem>
<file>X.java</file>
<line>57</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
<description>Should be one of: Const1.X, Const2.I or their combination</description>
</problem>
<problem>
<file>X.java</file>
<line>58</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
<description>Should be one of: Const1.X, Const2.I or their combination</description>
</problem>
<problem>
<file>X.java</file>
<line>59</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
<description>Should be one of: Const1.X, Const2.I</description>
</problem>
<problem>
<file>X.java</file>
<line>61</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
<description>Should be one of: Const1.X, Const2.I or their combination</description>
</problem>
<problem>
<file>X.java</file>
<line>72</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
<description>Should be one of: Const2.I, Const1.X or their combination</description>
</problem>
<problem>
<file>X.java</file>
<line>73</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
<description>Should be one of: Const2.I, Const1.X or their combination</description>
</problem>
</problems>
@@ -0,0 +1,82 @@
/*
* Copyright 2000-2011 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.
*/
import org.intellij.lang.annotations.MagicConstant;
class Const1 {
public static final int X = 1;
}
class Const2 {
public static final int I = 4;
}
public class X {
void f(@MagicConstant(intValues = {Const1.X, Const2.I}) int x) {
/////////// BAD
f(0);
f(1);
f(Const1.X | Const2.I);
////////////// GOOD
f(Const1.X);
f(Const2.I);
f2(x);
}
void f2(@MagicConstant(valuesFromClass = Const1.class, intValues = {Const2.I}) int x) {
/////////// BAD
f2(0);
f2(1);
f2(Const1.X | Const2.I);
////////////// GOOD
f2(Const1.X);
f2(Const2.I);
f(x);
}
void f3(@MagicConstant(flags = {Const1.X, Const2.I}) int x) {
/////////// BAD
f3(2);
f3(1);
f(Const1.X | Const2.I);
int i = Const1.X | 4;
f3(i);
////////////// GOOD
f3(Const1.X);
f3(Const2.I);
f4(x);
}
void f4(@MagicConstant(flagsFromClass = Const1.class, flags = {Const2.I}) int x) {
/////////// BAD
f4(-3);
f4(1);
////////////// GOOD
f4(Const1.X);
f4(Const2.I);
f4(Const1.X | Const2.I);
f3(x);
}
}
@@ -0,0 +1,53 @@
/*
* Copyright 2000-2017 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.completion
import com.intellij.JavaTestUtil
/**
* @author Pavel.Dolgov
*/
class JavaReflectionCompletionOverloadTest : LightFixtureCompletionTestCase() {
override fun getBasePath() = JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInsight/completion/reflectionOverload/"
fun testOverloadMethods() = doTest(2, "method()", "method(C c)", "method(A a,B b)")
fun testJavaLangObjectMethods() = doTest(6,
"method()",
"equals(java.lang.Object obj)", "hashCode()", "toString()",
"getClass()", "notify()", "notifyAll()",
"wait()", "wait(long timeout)", "wait(long timeout,int nanos)"
)
fun testJavaLangObjectOwnMethods() = doTest(9,
"clone()", "equals(java.lang.Object obj)", "hashCode()",
"toString()", "finalize()", "getClass()",
"notify()", "notifyAll()",
"wait()", "wait(long timeout)", "wait(long timeout,int nanos)",
"registerNatives()")
private fun doTest(index: Int, vararg expected: String) {
configureByFile(getTestName(false) + ".java")
val lookupItems = lookup.items
val texts = lookupItemTexts(lookupItems, expected.size)
assertOrderedEquals(texts, *expected)
if (index >= 0) selectItem(lookupItems[index])
myFixture.checkResultByFile(getTestName(false) + "_after.java")
}
}
@@ -34,15 +34,15 @@ public class JavaReflectionCompletionTest extends LightFixtureCompletionTestCase
}
public void testDeclaredField() throws Exception {
doTest(1, "num", "num2", "num3");
doTest(2, "num", "num1", "num2");
}
public void testDeclaredMethod() throws Exception {
doTest(1, "method", "method2", "method3");
doTest(2, "method", "method1", "method2");
}
public void testDeclaredMethod2() throws Exception {
doTest(2, "method", "method2", "method3");
doTest(1, "method", "method1", "method2");
}
public void testMethod() throws Exception {
@@ -50,7 +50,7 @@ public class JavaReflectionCompletionTest extends LightFixtureCompletionTestCase
}
public void testForNameDeclaredMethod() throws Exception {
doTest(1, "method", "method2", "method3");
doTest(2, "method", "method1", "method2");
}
public void testForNameMethod() throws Exception {
@@ -62,7 +62,7 @@ public class JavaReflectionCompletionTest extends LightFixtureCompletionTestCase
}
public void testForNameDeclaredField() throws Exception {
doTest(2, "num", "num2", "num3");
doTest(1, "num", "num1", "num2");
}
public void testVarargMethod() throws Exception {
@@ -135,7 +135,7 @@ public class JavaReflectionCompletionTest extends LightFixtureCompletionTestCase
}
public void testConstantGetClassField() throws Exception {
doTest(1, "num", "num2", "num3");
doTest(2, "num", "num3", "num2");
}
public void testExpressionGetClassField() throws Exception {
@@ -165,9 +165,14 @@ public class JavaReflectionCompletionTest extends LightFixtureCompletionTestCase
doTest(0, "PublicClass");
}
public void testHasConstructor() {
doTest(2, "method", "method2", "method1");
}
private void doTest(int index, String... expected) {
configureByFile(getTestName(false) + ".java");
assertStringItems(expected);
assertFirstStringItems(expected);
if (index >= 0) selectItem(getLookup().getItems().get(index));
myFixture.checkResultByFile(getTestName(false) + "_after.java");
}
@@ -31,7 +31,9 @@
package com.intellij.codeInsight.completion
import com.intellij.JavaTestUtil
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.codeInsight.lookup.LookupElementPresentation
import com.intellij.psi.PsiMethod
import com.intellij.testFramework.LightProjectDescriptor
/**
@@ -42,26 +44,36 @@ class JavaReflectionParametersCompletionTest : LightFixtureCompletionTestCase()
override fun getProjectDescriptor(): LightProjectDescriptor = com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase.JAVA_8
fun testAnnotation() = doTest(0, "Bar.class", "Foo.class", "aType")
fun testAnnotation() = doTest(0, "Bar.class", "Foo.class")
fun testInheritedAnnotation() = doTest(1, "Bar.class", "Foo.class", "aType")
fun testInheritedAnnotation() = doTest(1, "Bar.class", "Foo.class")
fun testDeclaredAnnotation() = doTest(0, "Bar.class", "Foo.class")
fun testDeclaredAnnotation() = doTest(0, "Foo.class", "Bar.class")
fun testInheritedDeclaredAnnotation() = doTest(1, "Bar.class", "Foo.class")
fun testInheritedDeclaredAnnotation() = doTest(1, "Foo.class", "Bar.class")
fun testAnnotationsByType() = doTest(0, "Bar.class", "Foo.class")
fun testDeclaredAnnotationsByType() = doTest(1, "Bar.class", "Foo.class")
fun testDeclaredAnnotationsByType() = doTest(0, "Foo.class", "Bar.class")
fun testConstructor() {
addConstructors()
doTest(2, "Construct()", "Construct(int)", "Construct(int,java.lang.String)", "Construct(java.lang.String)")
doTest(3, "Construct()", "Construct(int n)", "Construct(java.lang.String s)", "Construct(int n,java.lang.String s)")
}
fun testDeclaredConstructor() {
addConstructors()
doTest(0, "Construct()", "Construct(int)", "Construct(int,java.lang.String)", "Construct(java.lang.String)")
doTest(0, "Construct()", "Construct(int n,java.lang.String s)", "Construct(int n)", "Construct(java.lang.String s)")
}
fun testImports() {
addMoreClasses()
doTest(1, "Bar.class", "Baz.class")
}
fun testVariable() {
addMoreClasses()
doTest(2, "Bar.class", "Foo.class", "aType")
}
private fun doTest(index: Int, vararg expected: String) {
@@ -69,11 +81,7 @@ class JavaReflectionParametersCompletionTest : LightFixtureCompletionTestCase()
configureByFile(getTestName(false) + ".java")
val lookupItems = lookup.items
val texts = lookupItems.subList(0, Math.min(lookupItems.size, expected.size)).map {
val presentation = LookupElementPresentation()
it?.renderElement(presentation)
presentation.itemText ?: ""
}
val texts = lookupItemTexts(lookupItems, expected.size)
assertOrderedEquals(texts, *expected)
selectItem(lookupItems[index])
myFixture.checkResultByFile(getTestName(false) + "_after.java")
@@ -82,9 +90,13 @@ class JavaReflectionParametersCompletionTest : LightFixtureCompletionTestCase()
private fun addClasses() {
myFixture.addClass("package foo.bar; public @interface Foo {}")
myFixture.addClass("package foo.bar; public @interface Bar {}")
myFixture.addClass("package foo.bar; public @interface Baz {}")
myFixture.addClass("package foo.bar; @Foo class Parent {}")
myFixture.addClass("package foo.bar; @Bar class Test extends Parent {}")
myFixture.addClass("package foo.bar; @Bar class Parent {}")
myFixture.addClass("package foo.bar; @Foo class Test extends Parent {}")
}
private fun addMoreClasses() {
myFixture.addClass("package foo.baz; public @interface Baz {}")
myFixture.addClass("package foo.bar; @foo.baz.Baz class More extends Parent {}")
}
private fun addConstructors() {
@@ -96,4 +108,20 @@ public class Construct {
public Construct() {}
}""")
}
}
fun lookupItemTexts(lookupItems: List<LookupElement?>, maxSize: Int): List<String> =
lookupItems.subList(0, Math.min(lookupItems.size, maxSize)).map {
val obj = it?.`object`
when (obj) {
is PsiMethod -> {
obj.name + obj.parameterList.parameters.map { it.type.canonicalText + " " + it.name }
.joinToString(",", prefix = "(", postfix = ")")
}
else -> {
val presentation = LookupElementPresentation()
it?.renderElement(presentation)
presentation.itemText ?: ""
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -15,11 +15,11 @@
*/
package com.intellij.codeInsight.javadoc
import com.intellij.openapi.util.JDOMUtil
import com.intellij.psi.PsiJavaFile
import com.intellij.testFramework.assertions.Assertions.assertThat
import com.intellij.testFramework.LightProjectDescriptor
import com.intellij.testFramework.assertions.Assertions.assertThat
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import com.intellij.util.loadElement
class LightJavadocGeneratorTest : LightCodeInsightFixtureTestCase() {
override fun getProjectDescriptor(): LightProjectDescriptor = JAVA_9
@@ -45,7 +45,7 @@ class LightJavadocGeneratorTest : LightCodeInsightFixtureTestCase() {
val file = myFixture.configureByText("module-info.java", text)
val module = (file as PsiJavaFile).moduleDeclaration!!
val docInfo = JavaDocInfoGeneratorFactory.create(project, module).generateDocInfo(null)!!
val body = JDOMUtil.loadDocument(docInfo).rootElement.getChild("body")
val body = loadElement(docInfo).getChild("body")
assertThat(body).isEqualTo(expected)
}
}
@@ -35,6 +35,7 @@ import com.intellij.psi.codeStyle.CommonCodeStyleSettings
import com.intellij.testFramework.LightPlatformCodeInsightTestCase
import com.intellij.testFramework.fixtures.CodeInsightTestUtil
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import com.intellij.util.JdomKt
import com.intellij.util.containers.ContainerUtil
import com.intellij.util.ui.UIUtil
import org.jdom.Element
@@ -658,11 +659,11 @@ class Outer {
}
void testDontSaveDefaultContexts() {
def defElement = JDOMUtil.loadDocument('''\
def defElement = JdomKt.loadElement('''\
<context>
<option name="JAVA_STATEMENT" value="false"/>
<option name="JAVA_CODE" value="true"/>
</context>''').rootElement
</context>''')
def defContext = new TemplateContext()
defContext.readTemplateContext(defElement)
@@ -695,10 +696,10 @@ class Outer {
}
void "test adding new context to Other"() {
def defElement = JDOMUtil.loadDocument('''\
def defElement = JdomKt.loadElement('''\
<context>
<option name="OTHER" value="true"/>
</context>''').rootElement
</context>''')
def context = new TemplateContext()
context.readTemplateContext(defElement)
@@ -92,6 +92,8 @@ public class MagicConstantInspectionTest extends InspectionTestCase {
}
public void testSimple() throws Exception { doTest(); }
public void testManyConstantSources() throws Exception { doTest(); }
// test that the optimisation for not loading AST works
public void testWithLibrary() throws Exception { doTest(); }
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -117,7 +117,7 @@ public class InspectionProfileTest extends LightIdeaTestCase {
}
public void testConvertOldProfile() throws Exception {
Element element = JDOMUtil.loadDocument("<inspections version=\"1.0\">\n" +
Element element = JdomKt.loadElement("<inspections version=\"1.0\">\n" +
" <option name=\"myName\" value=\"ToConvert\" />\n" +
" <inspection_tool class=\"JavaDoc\" enabled=\"false\" level=\"WARNING\" enabled_by_default=\"false\">\n" +
" <option name=\"TOP_LEVEL_CLASS_OPTIONS\">\n" +
@@ -149,7 +149,7 @@ public class InspectionProfileTest extends LightIdeaTestCase {
" <option name=\"IGNORE_POINT_TO_ITSELF\" value=\"false\" />\n" +
" <option name=\"myAdditionalJavadocTags\" value=\"tag1,tag2 \" />\n" +
" </inspection_tool>\n" +
"</inspections>").getRootElement();
"</inspections>");
InspectionProfileImpl profile = createProfile();
profile.readExternal(element);
profile.getModifiableModel().commit();
@@ -296,7 +296,7 @@ public class InspectionProfileTest extends LightIdeaTestCase {
InspectionToolsConfigurable.importInspectionProfile(toImportElement, getApplicationProfileManager(), getProject(), null);
//check merged
Element mergedElement = JDOMUtil.loadDocument(mergedText).getRootElement();
Element mergedElement = JdomKt.loadElement(mergedText);
profile = createProfile(new InspectionProfileImpl("foo"));
profile.readExternal(mergedElement);
profile.getModifiableModel().commit();
@@ -307,7 +307,7 @@ public class InspectionProfileTest extends LightIdeaTestCase {
public void testStoredMemberVisibility() throws Exception {
InspectionProfileImpl profile = createProfile(new InspectionProfileImpl("foo"));
profile.readExternal(JDOMUtil.loadDocument("<profile version=\"1.0\">\n" +
profile.readExternal(JdomKt.loadElement("<profile version=\"1.0\">\n" +
" <inspection_tool class=\"unused\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n" +
" <option name=\"LOCAL_VARIABLE\" value=\"true\" />\n" +
" <option name=\"FIELD\" value=\"true\" />\n" +
@@ -320,7 +320,7 @@ public class InspectionProfileTest extends LightIdeaTestCase {
" <option name=\"ADD_SERVLET_TO_ENTRIES\" value=\"true\" />\n" +
" <option name=\"ADD_NONJAVA_TO_ENTRIES\" value=\"false\" />\n" +
" </inspection_tool>\n" +
"</profile>").getRootElement());
"</profile>"));
profile.modifyProfile(it -> {
InspectionToolWrapper toolWrapper = it.getInspectionTool("unused", getProject());
UnusedDeclarationInspectionBase tool = (UnusedDeclarationInspectionBase)toolWrapper.getTool();
@@ -481,7 +481,7 @@ public class InspectionProfileTest extends LightIdeaTestCase {
}
private static void checkMergedNoChanges(String initialText) throws Exception {
final Element element = JDOMUtil.loadDocument(initialText).getRootElement();
final Element element = JdomKt.loadElement(initialText);
InspectionProfileImpl profile = createProfile(new InspectionProfileImpl("foo"));
profile.readExternal(element);
profile.getModifiableModel().commit();
@@ -615,13 +615,13 @@ public class InspectionProfileTest extends LightIdeaTestCase {
public void testInspectionInitializationForSerialization() throws Exception {
InspectionProfileImpl foo = new InspectionProfileImpl("foo");
foo.readExternal(JDOMUtil.loadDocument("<profile version=\"1.0\">\n" +
foo.readExternal(JdomKt.loadElement("<profile version=\"1.0\">\n" +
" <option name=\"myName\" value=\"idea.default\" />\n" +
" <inspection_tool class=\"AbstractMethodCallInConstructor\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n" +
" <inspection_tool class=\"AssignmentToForLoopParameter\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n" +
" <option name=\"m_checkForeachParameters\" value=\"false\" />\n" +
" </inspection_tool>\n" +
"</profile>").getRootElement());
"</profile>"));
foo.initInspectionTools(getProject());
assertEquals(1, countInitializedTools(foo));
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -21,11 +21,11 @@ import com.intellij.execution.configurations.UnknownConfigurationType;
import com.intellij.execution.junit.JUnitConfigurationType;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.Trinity;
import com.intellij.testFramework.LightIdeaTestCase;
import com.intellij.ui.RowsDnDSupport;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.JdomKt;
import org.jdom.Element;
import javax.swing.tree.DefaultMutableTreeNode;
@@ -66,7 +66,7 @@ public class RunConfigurableTest extends LightIdeaTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
myConfigurable = new MockRunConfigurable(createRunManager(JDOMUtil.loadDocument(FOLDERS_CONFIGURATION).getRootElement()));
myConfigurable = new MockRunConfigurable(createRunManager(JdomKt.loadElement(FOLDERS_CONFIGURATION)));
myTree = myConfigurable.myTree;
myRoot = myConfigurable.myRoot;
myModel = myConfigurable.myTreeModel;
@@ -282,6 +282,18 @@ public class GotoImplementationHandlerTest extends JavaCodeInsightFixtureTestCas
assertEquals(1, impls.length);
}
public void testPrivateClassInheritors() {
PsiFile file = myFixture.addFileToProject("Foo.java",
"class C {\n" +
" private static class Pr<caret>ivate {}\n" +
" public static class Public extends Private {}" +
"}");
myFixture.addClass("class Inheritor extends C.Public {}");
myFixture.configureFromExistingVirtualFile(file.getVirtualFile());
assertSize(2, getTargets(file));
}
private PsiElement[] getTargets(PsiFile file) {
GotoTargetHandler.GotoData gotoData = CodeInsightTestUtil.gotoImplementation(myFixture.getEditor(), file);
assertNotNull(gotoData);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -16,10 +16,10 @@
package com.intellij.openapi.wm.impl;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.wm.ToolWindowEP;
import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.usageView.impl.UsageViewManagerImpl;
import com.intellij.util.JdomKt;
import java.util.Arrays;
@@ -41,7 +41,7 @@ public class HiddenSidebarButtonTest extends ToolWindowManagerTestCase {
public void testHiddenButton() throws Exception {
DesktopLayout layout = myManager.getLayout();
layout.readExternal(JDOMUtil.loadDocument(LAYOUT).getRootElement());
layout.readExternal(JdomKt.loadElement(LAYOUT));
for (String ID : IDS) {
assertFalse(layout.isToolWindowRegistered(ID));
assertTrue(layout.isToolWindowUnregistered(ID));
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -206,6 +206,8 @@ public class ClsMirrorBuildingTest extends LightIdeaTestCase {
}
assertEquals(expected, ClsFileImpl.decompile(file).toString());
((ClsFileImpl)getPsiManager().findFile(file)).getMirror();
}
private static boolean isInner(String name) throws IOException {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -16,8 +16,8 @@
package com.intellij.run
import com.intellij.application.options.PathMacrosCollector
import com.intellij.openapi.util.JDOMUtil
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import com.intellij.util.JdomKt
class JavaPathMacroCollectorTest extends LightCodeInsightFixtureTestCase {
void testJunitConfiguration() {
@@ -56,8 +56,7 @@ class JavaPathMacroCollectorTest extends LightCodeInsightFixtureTestCase {
</recent_temporary>
</component>
'''
def element = JDOMUtil.loadDocument(text).rootElement
assert PathMacrosCollector.getMacroNames(element).empty
assert PathMacrosCollector.getMacroNames(JdomKt.loadElement(text)).empty
}
}
@@ -1,9 +1,11 @@
package com.jetbrains.jsonSchema;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.components.*;
import com.intellij.openapi.fileTypes.ex.FileTypeManagerEx;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.xmlb.annotations.Transient;
import org.jetbrains.annotations.NotNull;
@@ -74,7 +76,7 @@ public class JsonSchemaMappingsProjectConfiguration extends JsonSchemaMappingsCo
private void recalculateSchemaFiles() {
ApplicationManager.getApplication().invokeLater(() -> {
ApplicationManager.getApplication().runWriteAction(() -> FileTypeManagerEx.getInstanceEx().fireFileTypesChanged());
}, o -> !myProject.isDisposed());
}, ModalityState.NON_MODAL, myProject == null ? Condition.FALSE : myProject.getDisposed());
mySchemaFiles.clear();
if (myProject == null || myProject.getBaseDir() == null) return;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,17 +20,19 @@ import com.intellij.codeInspection.ex.InspectionProfileImpl;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.profile.codeInspection.InspectionProfileManager;
import com.intellij.util.JdomKt;
import com.intellij.util.io.PathKt;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
@@ -93,20 +95,19 @@ public class InspectionProfileConvertor {
}
private static void renameOldDefaultsProfile() {
String directoryPath = PathManager.getConfigPath() + File.separator + InspectionProfileManager.INSPECTION_DIR;
File profileDirectory = new File(directoryPath);
if (!profileDirectory.exists()) {
Path directoryPath = Paths.get(PathManager.getConfigPath(), InspectionProfileManager.INSPECTION_DIR);
if (!PathKt.exists(directoryPath)) {
return;
}
File[] files = profileDirectory.listFiles(pathname -> pathname.getPath().endsWith(File.separator + DEFAULT_XML));
File[] files = directoryPath.toFile().listFiles(pathname -> pathname.getPath().endsWith(File.separator + DEFAULT_XML));
if (files == null || files.length != 1 || !files[0].isFile() || files[0].length() == 0) {
return;
}
try {
Element root = JDOMUtil.load(files[0]);
Element root = JdomKt.loadElement(files[0].toPath());
if (root.getAttributeValue(VERSION_ATT) == null){
JDOMUtil.writeParent(root, new FileOutputStream(new File(profileDirectory, OLD_DEFAUL_PROFILE + XML_EXTENSION)), "\n");
JdomKt.write(root, directoryPath.resolve(OLD_DEFAUL_PROFILE + XML_EXTENSION));
FileUtil.delete(files[0]);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -18,8 +18,8 @@ package com.intellij.profile.codeInspection;
import com.intellij.codeInspection.ex.InspectionProfileImpl;
import com.intellij.codeInspection.ex.InspectionToolRegistrar;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.JdomKt;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jetbrains.annotations.NotNull;
@@ -46,7 +46,7 @@ public class InspectionProfileLoadUtil {
public static InspectionProfileImpl load(@NotNull File file,
@NotNull InspectionToolRegistrar registrar,
@NotNull InspectionProfileManager profileManager) throws JDOMException, IOException, InvalidDataException {
Element element = JDOMUtil.load(file);
Element element = JdomKt.loadElement(file.getPath());
InspectionProfileImpl profile = new InspectionProfileImpl(getProfileName(file, element), registrar,
(BaseInspectionProfileManager)profileManager);
final Element profileElement = element.getChild("profile");
@@ -50,7 +50,6 @@ public class BootstrapClassLoaderUtil extends ClassUtilCore {
@NotNull
public static ClassLoader initClassLoader(boolean updatePlugins) throws MalformedURLException {
PathManager.loadProperties();
PathManager.patchProperties();
Collection<URL> classpath = new LinkedHashSet<URL>();
addParentClasspath(classpath, false);
@@ -18,6 +18,7 @@ package org.jetbrains.intellij.build.impl
import com.intellij.openapi.util.MultiValuesMap
import com.intellij.openapi.util.io.FileUtil
import org.apache.tools.ant.types.FileSet
import org.apache.tools.ant.types.resources.FileProvider
import org.jetbrains.intellij.build.BuildContext
import org.jetbrains.intellij.build.BuildOptions
import org.jetbrains.intellij.build.BuildTasks
@@ -32,7 +33,7 @@ import org.jetbrains.jps.util.JpsPathUtil
/**
* Assembles output of modules to platform JARs (in {@link org.jetbrains.intellij.build.BuildPaths#distAll distAll}/lib directory),
* bunlded plugins' JARs (in {@link org.jetbrains.intellij.build.BuildPaths#distAll distAll}/plugins directory) and zip archives with
* bundled plugins' JARs (in {@link org.jetbrains.intellij.build.BuildPaths#distAll distAll}/plugins directory) and zip archives with
* non-bundled plugins (in {@link org.jetbrains.intellij.build.BuildPaths#artifacts artifacts}/plugins directory).
*
* @author nik
@@ -293,27 +294,31 @@ class DistributionJARsBuilder {
def enabledModulesSet = buildContext.productProperties.productLayout.enabledPluginModules
pluginsToInclude.each { plugin ->
def actualModuleJars = plugin.getActualModules(enabledModulesSet)
checkOutputOfPluginModules(plugin.mainModule, actualModuleJars.values())
checkOutputOfPluginModules(plugin.mainModule, actualModuleJars.values(), plugin.moduleExcludes)
buildByLayout(layoutBuilder, plugin, "$targetDirectory/$plugin.directoryName", actualModuleJars)
}
}
private void checkOutputOfPluginModules(String mainPluginModule, Collection<String> moduleNames) {
def modulesWithPluginXml = moduleNames.findAll { containsFileInOutput(it, "META-INF/plugin.xml") }
private void checkOutputOfPluginModules(String mainPluginModule, Collection<String> moduleNames, MultiValuesMap<String, String> moduleExcludes) {
def modulesWithPluginXml = moduleNames.findAll { containsFileInOutput(it, "META-INF/plugin.xml", moduleExcludes.get(it)) }
if (modulesWithPluginXml.size() > 1) {
buildContext.messages.error("Multiple modules (${modulesWithPluginXml.join(", ")}) from '$mainPluginModule' plugin contain plugin.xml files so the plugin won't work properly")
}
moduleNames.each {
if (containsFileInOutput(it, "com/intellij/uiDesigner/core/GridLayoutManager.class")) {
if (containsFileInOutput(it, "com/intellij/uiDesigner/core/GridLayoutManager.class", moduleExcludes.get(it))) {
buildContext.messages.error("Runtime classes of GUI designer must not be packaged to '$mainPluginModule' plugin, because they are included into a platform JAR. " +
"Make sure that 'Automatically copy form runtime classes to the output directory' is disabled in Settings | Editor | GUI Designer.")
}
}
}
private boolean containsFileInOutput(String moduleName, String filePath) {
return new File(buildContext.projectBuilder.getModuleOutput(buildContext.findRequiredModule(moduleName), false), filePath).exists()
private boolean containsFileInOutput(String moduleName, String filePath, Collection<String> excludes) {
def moduleOutput = new File(buildContext.projectBuilder.getModuleOutput(buildContext.findRequiredModule(moduleName), false))
def fileInOutput = new File(moduleOutput, filePath)
return fileInOutput.exists() && (excludes == null || excludes.every {
createFileSet(it, moduleOutput).iterator().every { !(it instanceof FileProvider && FileUtil.filesEqual(it.file, fileInOutput))}
})
}
private void buildByLayout(LayoutBuilder layoutBuilder, BaseLayout layout, String targetDirectory, MultiValuesMap<String, String> moduleJars) {
@@ -419,22 +424,26 @@ class DistributionJARsBuilder {
moduleExcludes.entrySet().each { entry ->
String module = entry.key
entry.value.each { pattern ->
def fileSet = new FileSet()
fileSet.setProject(buildContext.ant.antProject)
def moduleOutput = new File(buildContext.projectBuilder.getModuleOutput(buildContext.findRequiredModule(module), false))
if (!moduleOutput.exists()) {
buildContext.messages.error("There are excludes defined for module '$module', but the module wasn't compiled; " +
"most probably it means that '$module' isn't include into the product distribution so it makes no sense to define excludes for it.")
}
fileSet.setDir(moduleOutput)
fileSet.createInclude().setName(pattern)
if (fileSet.size() == 0) {
if (createFileSet(pattern, moduleOutput).size() == 0) {
buildContext.messages.error("Incorrect exludes for module '$module': nothing matches to $pattern in the module output")
}
}
}
}
private FileSet createFileSet(String pattern, File baseDir) {
def fileSet = new FileSet()
fileSet.setProject(buildContext.ant.antProject)
fileSet.setDir(baseDir)
fileSet.createInclude().setName(pattern)
return fileSet
}
static String basePath(BuildContext buildContext, String moduleName) {
JpsPathUtil.urlToPath(buildContext.findRequiredModule(moduleName).contentRootsList.urls.first())
}
@@ -132,7 +132,8 @@ open class FileBasedStorage(file: Path,
else {
val charBuffer = StandardCharsets.UTF_8.decode(ByteBuffer.wrap(file.contentsToByteArray()))
lineSeparator = detectLineSeparators(charBuffer, if (isUseXmlProlog) null else LineSeparator.LF)
return JDOMUtil.loadDocument(charBuffer).detachRootElement()
@Suppress("DEPRECATION")
return loadElement(charBuffer)
}
return null
}
@@ -242,7 +243,7 @@ private fun doWrite(requestor: Any, file: VirtualFile, content: Any, lineSeparat
out.write(lineSeparator.separatorBytes)
}
if (content is Element) {
JDOMUtil.writeParent(content, out, lineSeparator.separatorString)
JDOMUtil.write(content, out, lineSeparator.separatorString)
}
else {
(content as BufferExposingByteArrayOutputStream).writeTo(out)
@@ -253,7 +254,7 @@ private fun doWrite(requestor: Any, file: VirtualFile, content: Any, lineSeparat
internal fun Parent.toBufferExposingByteArray(lineSeparator: String = "\n"): BufferExposingByteArrayOutputStream {
val out = BufferExposingByteArrayOutputStream(512)
JDOMUtil.writeParent(this, out, lineSeparator)
JDOMUtil.write(this, out, lineSeparator)
return out
}
@@ -129,7 +129,7 @@ abstract class ProjectStoreBase(override final val project: ProjectImpl) : Compo
wrapper.addContent(profile)
val path = Paths.get(storageManager.expandMacro(PROJECT_CONFIG_DIR), if (isInspection) "inspectionProfiles" else "copyright",
"${FileUtil.sanitizeFileName(schemeName, true)}.xml")
JDOMUtil.writeParent(wrapper, path.outputStream(), "\n")
JDOMUtil.write(wrapper, path.outputStream(), "\n")
}
}
@@ -58,7 +58,7 @@ fun getNewByteIfDiffers(key: String, newState: Any, oldState: ByteArray): ByteAr
val logChangedComponents = SystemProperties.getBooleanProperty("idea.log.changed.components", false)
if (ApplicationManager.getApplication().isUnitTestMode || logChangedComponents ) {
fun stateToString(state: Any) = JDOMUtil.writeParent(state as? Element ?: unarchiveState(state as ByteArray), "\n")
fun stateToString(state: Any) = JDOMUtil.write(state as? Element ?: unarchiveState(state as ByteArray), "\n")
val before = stateToString(oldState)
val after = stateToString(newState)
@@ -634,7 +634,7 @@ internal class XmlSerializerTest {
private fun checkSmartSerialization(bean: Bean2, serialized: String) {
val serializer = SmartSerializer()
serializer.readExternal(bean, JDOMUtil.loadDocument(serialized).rootElement)
serializer.readExternal(bean, JDOMUtil.load(serialized))
val serializedState = Element("Bean2")
serializer.writeExternal(bean, serializedState)
assertThat(JDOMUtil.writeElement(serializedState)).isEqualTo(serialized)
@@ -164,14 +164,14 @@ public class DocumentCommitThread implements Runnable, Disposable, DocumentCommi
PsiDocumentManager.getInstance(project).getLastCommittedText(document));
}
@NotNull
private CommitTask doQueue(@NotNull Project project,
private void doQueue(@NotNull Project project,
@NotNull Document document,
@NotNull List<Pair<PsiFileImpl, FileASTNode>> oldFileNodes,
@NotNull Object reason,
@NotNull ModalityState currentModalityState,
@NotNull CharSequence lastCommittedText) {
synchronized (lock) {
if (!project.isInitialized()) return; // check the project is disposed under lock.
CommitTask newTask = createNewTaskAndCancelSimilar(project, document, oldFileNodes, reason, currentModalityState,
lastCommittedText);
@@ -179,7 +179,6 @@ public class DocumentCommitThread implements Runnable, Disposable, DocumentCommi
log(project, "Queued", newTask, reason);
wakeUpQueue();
return newTask;
}
}
@@ -556,10 +555,8 @@ public class DocumentCommitThread implements Runnable, Disposable, DocumentCommi
if (task.reason.equals(SYNC_COMMIT_REASON)) {
throw new PsiInvalidElementAccessException(file, "File " + file + " invalidated during sync commit");
}
else {
commitAsynchronously(project, document, "File " + file + " invalidated during background commit; task: "+task,
task.myCreationModalityState);
}
commitAsynchronously(project, document, "File " + file + " invalidated during background commit; task: "+task,
task.myCreationModalityState);
}
}
}
@@ -204,6 +204,7 @@ public class TextMergeViewer implements MergeTool.MergeViewer {
myTextDiffProvider = new TextDiffProviderBase(getTextSettings(),
myInnerDiffWorker::onSettingsChanged,
this,
ar(IgnorePolicy.DEFAULT),
ar(HighlightPolicy.BY_LINE, HighlightPolicy.BY_WORD));
@@ -122,7 +122,7 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
myEditorSettingsAction = new SetEditorSettingsAction(getTextSettings(), getEditors());
myEditorSettingsAction.applyDefaults();
myTextDiffProvider = DiffUtil.createNoIgnoreTextDiffProvider(getProject(), getRequest(), getTextSettings(), this::rediff);
myTextDiffProvider = DiffUtil.createNoIgnoreTextDiffProvider(getProject(), getRequest(), getTextSettings(), this::rediff, this);
new MyOpenInEditorWithMouseAction().install(getEditors());
@@ -80,7 +80,7 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
myModifierProvider = new ModifierProvider();
myTextDiffProvider = DiffUtil.createTextDiffProvider(getProject(), getRequest(), getTextSettings(), this::rediff);
myTextDiffProvider = DiffUtil.createTextDiffProvider(getProject(), getRequest(), getTextSettings(), this::rediff, this);
DiffUtil.registerAction(new ReplaceSelectedChangesAction(Side.LEFT, true), myPanel);
DiffUtil.registerAction(new AppendSelectedChangesAction(Side.LEFT, true), myPanel);
@@ -56,7 +56,7 @@ public class SimpleOnesideDiffViewer extends OnesideTextDiffViewer {
public SimpleOnesideDiffViewer(@NotNull DiffContext context, @NotNull DiffRequest request) {
super(context, (ContentDiffRequest)request);
myTextDiffProvider = DiffUtil.createTextDiffProvider(getProject(), getRequest(), getTextSettings(), this::rediff);
myTextDiffProvider = DiffUtil.createTextDiffProvider(getProject(), getRequest(), getTextSettings(), this::rediff, this);
}
@Override
@@ -49,7 +49,7 @@ public class SimpleThreesideDiffViewer extends ThreesideTextDiffViewerEx {
public SimpleThreesideDiffViewer(@NotNull DiffContext context, @NotNull DiffRequest request) {
super(context, (ContentDiffRequest)request);
myTextDiffProvider = new SimpleThreesideTextDiffProvider(getTextSettings(), this::rediff);
myTextDiffProvider = new SimpleThreesideTextDiffProvider(getTextSettings(), this::rediff, this);
}
@NotNull
@@ -17,12 +17,15 @@ package com.intellij.diff.tools.util.base
import com.intellij.diff.util.DiffPlaces
import com.intellij.diff.util.DiffUtil
import com.intellij.openapi.Disposable
import com.intellij.openapi.components.PersistentStateComponent
import com.intellij.openapi.components.State
import com.intellij.openapi.components.Storage
import com.intellij.openapi.components.service
import com.intellij.openapi.util.Key
import com.intellij.util.EventDispatcher
import com.intellij.util.xmlb.annotations.MapAnnotation
import com.intellij.util.xmlb.annotations.Transient
import java.util.*
@State(
@@ -61,12 +64,19 @@ class TextDiffSettingsHolder : PersistentStateComponent<TextDiffSettingsHolder.S
// Fragments settings
var EXPAND_BY_DEFAULT: Boolean = true
)
) {
@Transient
val eventDispatcher: EventDispatcher<TextDiffSettings.Listener> = EventDispatcher.create(TextDiffSettings.Listener::class.java)
}
class TextDiffSettings internal constructor(private val SHARED_SETTINGS: SharedSettings,
private val PLACE_SETTINGS: PlaceSettings) {
constructor() : this(SharedSettings(), PlaceSettings())
fun addListener(listener: Listener, disposable: Disposable) {
PLACE_SETTINGS.eventDispatcher.addListener(listener, disposable)
}
// Presentation settings
var isEnableSyncScroll: Boolean
@@ -77,11 +87,13 @@ class TextDiffSettingsHolder : PersistentStateComponent<TextDiffSettingsHolder.S
var highlightPolicy: HighlightPolicy
get() = PLACE_SETTINGS.HIGHLIGHT_POLICY
set(value) { PLACE_SETTINGS.HIGHLIGHT_POLICY = value }
set(value) { PLACE_SETTINGS.HIGHLIGHT_POLICY = value
PLACE_SETTINGS.eventDispatcher.multicaster.highlightPolicyChanged() }
var ignorePolicy: IgnorePolicy
get() = PLACE_SETTINGS.IGNORE_POLICY
set(value) { PLACE_SETTINGS.IGNORE_POLICY = value }
set(value) { PLACE_SETTINGS.IGNORE_POLICY = value
PLACE_SETTINGS.eventDispatcher.multicaster.ignorePolicyChanged() }
//
// Merge
@@ -139,6 +151,11 @@ class TextDiffSettingsHolder : PersistentStateComponent<TextDiffSettingsHolder.S
@JvmStatic fun getSettings(): TextDiffSettings = getSettings(null)
@JvmStatic fun getSettings(place: String?): TextDiffSettings = service<TextDiffSettingsHolder>().getSettings(place)
}
interface Listener : EventListener {
fun highlightPolicyChanged() {}
fun ignorePolicyChanged() {}
}
}
fun getSettings(place: String?): TextDiffSettings {
@@ -261,14 +261,11 @@ public class TextDiffViewerUtil {
public static class HighlightPolicySettingAction extends EnumPolicySettingAction<HighlightPolicy> {
@NotNull protected final TextDiffSettings mySettings;
@NotNull private final Runnable myRediffRunnable;
public HighlightPolicySettingAction(@NotNull TextDiffSettings settings,
@NotNull Runnable rediff,
@NotNull HighlightPolicy... policies) {
super(policies);
mySettings = settings;
myRediffRunnable = rediff;
}
@Override
@@ -276,7 +273,6 @@ public class TextDiffViewerUtil {
if (getValue() == option) return;
UsageTrigger.trigger("diff.TextDiffSettings.HighlightPolicy." + option.name());
mySettings.setHighlightPolicy(option);
myRediffRunnable.run();
}
@NotNull
@@ -306,14 +302,11 @@ public class TextDiffViewerUtil {
public static class IgnorePolicySettingAction extends EnumPolicySettingAction<IgnorePolicy> {
@NotNull protected final TextDiffSettings mySettings;
@NotNull private final Runnable myRediffRunnable;
public IgnorePolicySettingAction(@NotNull TextDiffSettings settings,
@NotNull Runnable rediff,
@NotNull IgnorePolicy... policies) {
super(policies);
mySettings = settings;
myRediffRunnable = rediff;
}
@Override
@@ -321,7 +314,6 @@ public class TextDiffViewerUtil {
if (getValue() == option) return;
UsageTrigger.trigger("diff.TextDiffSettings.IgnorePolicy." + option.name());
mySettings.setIgnorePolicy(option);
myRediffRunnable.run();
}
@NotNull
@@ -21,7 +21,8 @@ import com.intellij.diff.fragments.LineFragment;
import com.intellij.diff.tools.util.base.HighlightPolicy;
import com.intellij.diff.tools.util.base.IgnorePolicy;
import com.intellij.diff.tools.util.base.TextDiffSettingsHolder.TextDiffSettings;
import com.intellij.diff.util.DiffUserDataKeysEx;
import com.intellij.diff.util.DiffUserDataKeysEx.DiffComputer;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
@@ -32,7 +33,7 @@ import static com.intellij.diff.tools.util.base.HighlightPolicy.*;
import static com.intellij.diff.tools.util.base.IgnorePolicy.*;
public class SimpleTextDiffProvider extends TwosideTextDiffProviderBase implements TwosideTextDiffProvider {
static final DiffUserDataKeysEx.DiffComputer DEFAULT_COMPUTER = (text1, text2, policy, innerChanges, indicator) -> {
static final DiffComputer DEFAULT_COMPUTER = (text1, text2, policy, innerChanges, indicator) -> {
if (innerChanges) {
return ComparisonManager.getInstance().compareLinesInner(text1, text2, policy, indicator);
}
@@ -44,25 +45,28 @@ public class SimpleTextDiffProvider extends TwosideTextDiffProviderBase implemen
private static final IgnorePolicy[] IGNORE_POLICIES = {DEFAULT, TRIM_WHITESPACES, IGNORE_WHITESPACES, IGNORE_WHITESPACES_CHUNKS};
private static final HighlightPolicy[] HIGHLIGHT_POLICIES = {BY_LINE, BY_WORD, BY_WORD_SPLIT, DO_NOT_HIGHLIGHT};
@NotNull private final DiffUserDataKeysEx.DiffComputer myDiffComputer;
@NotNull private final DiffComputer myDiffComputer;
public SimpleTextDiffProvider(@NotNull TextDiffSettings settings,
@NotNull Runnable rediff) {
this(settings, rediff, DEFAULT_COMPUTER);
@NotNull Runnable rediff,
@NotNull Disposable disposable) {
this(settings, rediff, disposable, DEFAULT_COMPUTER);
}
public SimpleTextDiffProvider(@NotNull TextDiffSettings settings,
@NotNull Runnable rediff,
@NotNull DiffUserDataKeysEx.DiffComputer diffComputer) {
this(settings, rediff, diffComputer, IGNORE_POLICIES, HIGHLIGHT_POLICIES);
@NotNull Disposable disposable,
@NotNull DiffComputer diffComputer) {
this(settings, rediff, disposable, diffComputer, IGNORE_POLICIES, HIGHLIGHT_POLICIES);
}
private SimpleTextDiffProvider(@NotNull TextDiffSettings settings,
@NotNull Runnable rediff,
@NotNull DiffUserDataKeysEx.DiffComputer diffComputer,
@NotNull Disposable disposable,
@NotNull DiffComputer diffComputer,
@NotNull IgnorePolicy[] ignorePolicies,
@NotNull HighlightPolicy[] highlightPolicies) {
super(settings, rediff, ignorePolicies, highlightPolicies);
super(settings, rediff, disposable, ignorePolicies, highlightPolicies);
myDiffComputer = diffComputer;
}
@@ -79,12 +83,12 @@ public class SimpleTextDiffProvider extends TwosideTextDiffProviderBase implemen
public static class NoIgnore extends SimpleTextDiffProvider implements TwosideTextDiffProvider.NoIgnore {
public NoIgnore(@NotNull TextDiffSettings settings, @NotNull Runnable rediff) {
this(settings, rediff, DEFAULT_COMPUTER);
public NoIgnore(@NotNull TextDiffSettings settings, @NotNull Runnable rediff, @NotNull Disposable disposable) {
this(settings, rediff, disposable, DEFAULT_COMPUTER);
}
public NoIgnore(@NotNull TextDiffSettings settings, @NotNull Runnable rediff, @NotNull DiffUserDataKeysEx.DiffComputer diffComputer) {
super(settings, rediff, diffComputer, IGNORE_POLICIES, ArrayUtil.remove(HIGHLIGHT_POLICIES, DO_NOT_HIGHLIGHT));
public NoIgnore(@NotNull TextDiffSettings settings, @NotNull Runnable rediff, @NotNull Disposable disposable, @NotNull DiffComputer diffComputer) {
super(settings, rediff, disposable, diffComputer, IGNORE_POLICIES, ArrayUtil.remove(HIGHLIGHT_POLICIES, DO_NOT_HIGHLIGHT));
}
@NotNull
@@ -24,6 +24,7 @@ import com.intellij.diff.tools.util.base.TextDiffSettingsHolder.TextDiffSettings
import com.intellij.diff.util.DiffUtil;
import com.intellij.diff.util.MergeConflictType;
import com.intellij.diff.util.ThreeSide;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
@@ -40,8 +41,9 @@ public class SimpleThreesideTextDiffProvider extends TextDiffProviderBase {
private static final HighlightPolicy[] HIGHLIGHT_POLICIES = {BY_LINE, BY_WORD};
public SimpleThreesideTextDiffProvider(@NotNull TextDiffSettings settings,
@NotNull Runnable rediff) {
super(settings, rediff, IGNORE_POLICIES, HIGHLIGHT_POLICIES);
@NotNull Runnable rediff,
@NotNull Disposable disposable) {
super(settings, rediff, disposable, IGNORE_POLICIES, HIGHLIGHT_POLICIES);
}
@NotNull
@@ -25,6 +25,7 @@ import com.intellij.diff.tools.util.base.HighlightPolicy;
import com.intellij.diff.tools.util.base.IgnorePolicy;
import com.intellij.diff.tools.util.base.TextDiffSettingsHolder.TextDiffSettings;
import com.intellij.diff.util.Side;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
@@ -51,24 +52,26 @@ public class SmartTextDiffProvider extends TwosideTextDiffProviderBase implement
public static TwosideTextDiffProvider create(@Nullable Project project,
@NotNull ContentDiffRequest request,
@NotNull TextDiffSettings settings,
@NotNull Runnable rediff) {
@NotNull Runnable rediff,
@NotNull Disposable disposable) {
DiffContent content1 = Side.LEFT.select(request.getContents());
DiffContent content2 = Side.RIGHT.select(request.getContents());
DiffIgnoredRangeProvider ignoredRangeProvider = getIgnoredRangeProvider(project, content1, content2);
if (ignoredRangeProvider == null) return null;
return new SmartTextDiffProvider(project, content1, content2, settings, rediff, ignoredRangeProvider);
return new SmartTextDiffProvider(project, content1, content2, settings, rediff, disposable, ignoredRangeProvider);
}
@Nullable
public static TwosideTextDiffProvider.NoIgnore createNoIgnore(@Nullable Project project,
@NotNull ContentDiffRequest request,
@NotNull TextDiffSettings settings,
@NotNull Runnable rediff) {
@NotNull Runnable rediff,
@NotNull Disposable disposable) {
DiffContent content1 = Side.LEFT.select(request.getContents());
DiffContent content2 = Side.RIGHT.select(request.getContents());
DiffIgnoredRangeProvider ignoredRangeProvider = getIgnoredRangeProvider(project, content1, content2);
if (ignoredRangeProvider == null) return null;
return new SmartTextDiffProvider.NoIgnore(project, content1, content2, settings, rediff, ignoredRangeProvider);
return new SmartTextDiffProvider.NoIgnore(project, content1, content2, settings, rediff, disposable, ignoredRangeProvider);
}
private SmartTextDiffProvider(@Nullable Project project,
@@ -76,8 +79,9 @@ public class SmartTextDiffProvider extends TwosideTextDiffProviderBase implement
@NotNull DiffContent content2,
@NotNull TextDiffSettings settings,
@NotNull Runnable rediff,
@NotNull Disposable disposable,
@NotNull DiffIgnoredRangeProvider ignoredRangeProvider) {
this(project, content1, content2, settings, rediff, ignoredRangeProvider, IGNORE_POLICIES, HIGHLIGHT_POLICIES);
this(project, content1, content2, settings, rediff, disposable, ignoredRangeProvider, IGNORE_POLICIES, HIGHLIGHT_POLICIES);
}
private SmartTextDiffProvider(@Nullable Project project,
@@ -85,10 +89,11 @@ public class SmartTextDiffProvider extends TwosideTextDiffProviderBase implement
@NotNull DiffContent content2,
@NotNull TextDiffSettings settings,
@NotNull Runnable rediff,
@NotNull Disposable disposable,
@NotNull DiffIgnoredRangeProvider ignoredRangeProvider,
@NotNull IgnorePolicy[] ignorePolicies,
@NotNull HighlightPolicy[] highlightPolicies) {
super(settings, rediff, ignorePolicies, highlightPolicies);
super(settings, rediff, disposable, ignorePolicies, highlightPolicies);
myProject = project;
myContent1 = content1;
myContent2 = content2;
@@ -151,8 +156,9 @@ public class SmartTextDiffProvider extends TwosideTextDiffProviderBase implement
@NotNull DiffContent content2,
@NotNull TextDiffSettings settings,
@NotNull Runnable rediff,
@NotNull Disposable disposable,
@NotNull DiffIgnoredRangeProvider ignoredRangeProvider) {
super(project, content1, content2, settings, rediff, ignoredRangeProvider,
super(project, content1, content2, settings, rediff, disposable, ignoredRangeProvider,
IGNORE_POLICIES, ArrayUtil.remove(HIGHLIGHT_POLICIES, DO_NOT_HIGHLIGHT));
}
@@ -20,6 +20,7 @@ import com.intellij.diff.tools.util.base.IgnorePolicy;
import com.intellij.diff.tools.util.base.TextDiffSettingsHolder.TextDiffSettings;
import com.intellij.diff.tools.util.base.TextDiffViewerUtil.HighlightPolicySettingAction;
import com.intellij.diff.tools.util.base.TextDiffViewerUtil.IgnorePolicySettingAction;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.Separator;
import org.jetbrains.annotations.NotNull;
@@ -36,10 +37,12 @@ public class TextDiffProviderBase implements TextDiffProvider {
public TextDiffProviderBase(@NotNull TextDiffSettings settings,
@NotNull Runnable rediff,
@NotNull Disposable disposable,
@NotNull IgnorePolicy[] ignorePolicies,
@NotNull HighlightPolicy[] highlightPolicies) {
myIgnorePolicySettingAction = new MyIgnorePolicySettingAction(settings, rediff, ignorePolicies);
myHighlightPolicySettingAction = new MyHighlightPolicySettingAction(settings, rediff, highlightPolicies);
myIgnorePolicySettingAction = new MyIgnorePolicySettingAction(settings, ignorePolicies);
myHighlightPolicySettingAction = new MyHighlightPolicySettingAction(settings, highlightPolicies);
settings.addListener(new MyListener(rediff), disposable);
}
@NotNull
@@ -86,9 +89,8 @@ public class TextDiffProviderBase implements TextDiffProvider {
private class MyIgnorePolicySettingAction extends IgnorePolicySettingAction {
public MyIgnorePolicySettingAction(@NotNull TextDiffSettings settings,
@NotNull Runnable rediff,
@NotNull IgnorePolicy[] ignorePolicies) {
super(settings, rediff, ignorePolicies);
super(settings, ignorePolicies);
}
@NotNull
@@ -100,9 +102,8 @@ public class TextDiffProviderBase implements TextDiffProvider {
private class MyHighlightPolicySettingAction extends HighlightPolicySettingAction {
public MyHighlightPolicySettingAction(@NotNull TextDiffSettings settings,
@NotNull Runnable rediff,
@NotNull HighlightPolicy[] highlightPolicies) {
super(settings, rediff, highlightPolicies);
super(settings, highlightPolicies);
}
@NotNull
@@ -111,4 +112,22 @@ public class TextDiffProviderBase implements TextDiffProvider {
return notNullize(TextDiffProviderBase.this.getText(option), super.getText(option));
}
}
private static class MyListener implements TextDiffSettings.Listener {
@NotNull private final Runnable myRediff;
public MyListener(@NotNull Runnable rediff) {
myRediff = rediff;
}
@Override
public void highlightPolicyChanged() {
myRediff.run();
}
@Override
public void ignorePolicyChanged() {
myRediff.run();
}
}
}
@@ -21,6 +21,7 @@ import com.intellij.diff.fragments.LineFragment;
import com.intellij.diff.tools.util.base.HighlightPolicy;
import com.intellij.diff.tools.util.base.IgnorePolicy;
import com.intellij.diff.tools.util.base.TextDiffSettingsHolder.TextDiffSettings;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.progress.ProgressIndicator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -30,9 +31,10 @@ import java.util.List;
abstract class TwosideTextDiffProviderBase extends TextDiffProviderBase implements TwosideTextDiffProvider {
protected TwosideTextDiffProviderBase(@NotNull TextDiffSettings settings,
@NotNull Runnable rediff,
@NotNull Disposable disposable,
@NotNull IgnorePolicy[] ignorePolicies,
@NotNull HighlightPolicy[] highlightPolicies) {
super(settings, rediff, ignorePolicies, highlightPolicies);
super(settings, rediff, disposable, ignorePolicies, highlightPolicies);
}
@Nullable
@@ -600,28 +600,30 @@ public class DiffUtil {
public static TwosideTextDiffProvider createTextDiffProvider(@Nullable Project project,
@NotNull ContentDiffRequest request,
@NotNull TextDiffSettings settings,
@NotNull Runnable rediff) {
@NotNull Runnable rediff,
@NotNull Disposable disposable) {
DiffUserDataKeysEx.DiffComputer diffComputer = request.getUserData(DiffUserDataKeysEx.CUSTOM_DIFF_COMPUTER);
if (diffComputer != null) return new SimpleTextDiffProvider(settings, rediff, diffComputer);
if (diffComputer != null) return new SimpleTextDiffProvider(settings, rediff, disposable, diffComputer);
TwosideTextDiffProvider smartProvider = SmartTextDiffProvider.create(project, request, settings, rediff);
TwosideTextDiffProvider smartProvider = SmartTextDiffProvider.create(project, request, settings, rediff, disposable);
if (smartProvider != null) return smartProvider;
return new SimpleTextDiffProvider(settings, rediff);
return new SimpleTextDiffProvider(settings, rediff, disposable);
}
@NotNull
public static TwosideTextDiffProvider.NoIgnore createNoIgnoreTextDiffProvider(@Nullable Project project,
@NotNull ContentDiffRequest request,
@NotNull TextDiffSettings settings,
@NotNull Runnable rediff) {
@NotNull Runnable rediff,
@NotNull Disposable disposable) {
DiffUserDataKeysEx.DiffComputer diffComputer = request.getUserData(DiffUserDataKeysEx.CUSTOM_DIFF_COMPUTER);
if (diffComputer != null) return new SimpleTextDiffProvider.NoIgnore(settings, rediff, diffComputer);
if (diffComputer != null) return new SimpleTextDiffProvider.NoIgnore(settings, rediff, disposable, diffComputer);
TwosideTextDiffProvider.NoIgnore smartProvider = SmartTextDiffProvider.createNoIgnore(project, request, settings, rediff);
TwosideTextDiffProvider.NoIgnore smartProvider = SmartTextDiffProvider.createNoIgnore(project, request, settings, rediff, disposable);
if (smartProvider != null) return smartProvider;
return new SimpleTextDiffProvider.NoIgnore(settings, rediff);
return new SimpleTextDiffProvider.NoIgnore(settings, rediff, disposable);
}
@Nullable
@@ -17,83 +17,365 @@ package com.intellij.diff.tools.fragmented
import com.intellij.diff.DiffTestCase
import com.intellij.diff.comparison.ComparisonPolicy
import com.intellij.diff.comparison.iterables.DiffIterable
import com.intellij.diff.comparison.iterables.DiffIterableUtil
import com.intellij.diff.fragments.LineFragment
import com.intellij.diff.fragments.LineFragmentImpl
import com.intellij.diff.util.LineRange
import com.intellij.diff.util.Range
import com.intellij.diff.util.Side
import com.intellij.openapi.editor.impl.DocumentImpl
import com.intellij.openapi.progress.DumbProgressIndicator
import junit.framework.TestCase
import java.util.*
class UnifiedFragmentBuilderTest : DiffTestCase() {
fun testEquals() {
val builder = createBuilder("A\nB\nC", "A\nB\nC", Side.LEFT)
fun testSimple() {
Test("", "",
".",
" ")
.run()
assertTrue(builder.isEqual)
assertEquals(builder.text.toString(), "A\nB\nC\n")
assertEmpty(builder.changedLines)
assertEmpty(builder.blocks)
Test("A_B_C", "A_B_C",
"A_B_C",
" _ _ ")
.run()
// empty document has one line, so it's "modified" case (and not "deleted")
Test("A", "",
"A_.",
"L_R")
.run()
Test("", "A",
"._A",
"L_R")
.run()
Test("A_", "",
"A_.",
"L_ ")
.run()
Test("A_", "B",
"A_._B",
"L_L_R")
.run()
Test("B_", "B",
"B_.",
" _L")
.run()
Test("_B", "B",
"._B",
"L_ ")
.run()
Test("A_A", "B",
"A_A_B",
"L_L_R")
.run()
Test("A_B_C_D", "A_D",
"A_B_C_D",
" _L_L_ ")
.run()
Test("X_B_C", "A_B_C",
"X_A_B_C",
"L_R_ _ ")
.run()
Test("A_B_C", "A_B_Y",
"A_B_C_Y",
" _ _L_R")
.run()
Test("A_B_C_D_E_F", "A_X_C_D_Y_F",
"A_B_X_C_D_E_Y_F",
" _L_R_ _ _L_R_ ")
.run()
Test("A_B_C_D_E_F", "A_B_X_C_D_F",
"A_B_X_C_D_E_F",
" _ _R_ _ _L_ ")
.run()
Test("A_B_C_D_E_F", "A_B_X_Y_E_F",
"A_B_C_D_X_Y_E_F",
" _ _L_L_R_R_ _ ")
.run()
Test("", "",
".",
" ")
.changes()
.run()
Test("A", "B",
"A_B",
"L_R")
.changes(mod(0, 0, 1, 1))
.runLeft()
Test("A", "B",
"A",
" ")
.changes()
.runLeft()
Test("A", "B",
"B",
" ")
.changes()
.runRight()
}
fun testWrongEndLineTypoBug() {
val builder = createBuilder("A\nB\nC\nD", "A\nD", Side.RIGHT)
fun testNonFair() {
Test("A_B", "",
"A_B",
" _ ")
.changes()
.runLeft()
assertFalse(builder.isEqual)
assertEquals(builder.text.toString(), "A\nB\nC\nD\n")
assertEquals(builder.changedLines, listOf(LineRange(1, 3)))
Test("A_B", "",
".",
" ")
.changes()
.runRight()
assertEquals(builder.blocks.size, 1)
val block = builder.blocks[0]
assertEquals(block.line1, 1)
assertEquals(block.line2, 3)
assertEquals(block.range1.start, 1)
assertEquals(block.range1.end, 3)
assertEquals(block.range2.start, 3)
assertEquals(block.range2.end, 3)
Test("A_B", "A_._B",
"A_B",
" _ ")
.changes()
.runLeft()
Test("A_B", "A_._B",
"A_._B",
" _ _ ")
.changes()
.runRight()
Test("_._A_._", "X",
"._._A_X_._.",
" _ _L_R_ _ ")
.changes(mod(2, 0, 1, 1))
.runLeft()
Test("_._A_._", "X",
"A_X",
"L_R")
.changes(mod(2, 0, 1, 1))
.runRight()
Test("A_B_C_D", "X_BC_Y",
"A_X_BC_D_Y",
"L_R_ _L_R")
.changes(mod(0, 0, 1, 1), mod(3, 2, 1, 1))
.runRight()
Test("A_B_C_D", "A_BC_Y",
"A_BC_D_Y",
" _ _L_R")
.changes(mod(3, 2, 1, 1))
.runRight()
Test("AB_C_DE", "A_B_D_E",
"AB_C_DE",
" _L_ ")
.changes(del(1, 2, 1))
.runLeft()
Test("AB_C_DE", "A_B_D_E",
"A_B_C_D_E",
" _ _L_ _ ")
.changes(del(1, 2, 1))
.runRight()
Test("AB_DE", "A_B_C_D_E",
"AB_C_DE",
" _R_ ")
.changes(ins(1, 2, 1))
.runLeft()
Test("AB_DE", "A_B_C_D_E",
"A_B_C_D_E",
" _ _R_ _ ")
.changes(ins(1, 2, 1))
.runRight()
}
fun testFirstLineChange() {
val builder = createBuilder("X\nB\nC", "A\nB\nC", Side.RIGHT)
private inner class Test(val input1: String, val input2: String,
val result: String,
val lineMapping: String) {
private var customFragments: List<LineFragment>? = null
assertFalse(builder.isEqual)
assertEquals(builder.text.toString(), "X\nA\nB\nC\n")
assertEquals(builder.changedLines, listOf(LineRange(0, 1), LineRange(1, 2)))
fun runLeft() {
doRun(Side.LEFT)
}
assertEquals(builder.blocks.size, 1)
val block = builder.blocks[0]
assertEquals(block.line1, 0)
assertEquals(block.line2, 2)
assertEquals(block.range1.start, 0)
assertEquals(block.range1.end, 1)
assertEquals(block.range2.start, 1)
assertEquals(block.range2.end, 2)
fun runRight() {
doRun(Side.RIGHT)
}
fun run() {
doRun(Side.LEFT, Side.RIGHT)
}
private fun doRun(vararg sides: Side) {
sides.forEach { side ->
assert(result.length == lineMapping.length)
val text1 = processText(input1)
val text2 = processText(input2)
val fragments = if (customFragments != null) customFragments!!
else MANAGER.compareLines(text1, text2, ComparisonPolicy.DEFAULT, INDICATOR)
val builder = UnifiedFragmentBuilder(fragments, DocumentImpl(text1), DocumentImpl(text2), side)
builder.exec()
val lineCount1 = input1.count({ it == '_' }) + 1
val lineCount2 = input2.count({ it == '_' }) + 1
val resultLineCount = result.count({ it == '_' }) + 1
val lineIterable = DiffIterableUtil.create(fragments.map { Range(it.startLine1, it.endLine1, it.startLine2, it.endLine2) },
lineCount1, lineCount2)
val expectedText = processText(result)
val actualText = processActualText(builder)
val expectedMapping = processExpectedLineMapping(lineMapping)
val actualMapping = processActualLineMapping(builder.blocks, resultLineCount)
val expectedChangedLines = processExpectedChangedLines(lineMapping)
val actualChangedLines = processActualChangedLines(builder.changedLines)
val expectedMappedLines1 = processExpectedMappedLines(lineIterable, Side.LEFT)
val expectedMappedLines2 = processExpectedMappedLines(lineIterable, Side.RIGHT)
val actualMappedLines1 = processActualMappedLines(builder.convertor1, resultLineCount)
val actualMappedLines2 = processActualMappedLines(builder.convertor2, resultLineCount)
assertEquals(expectedText, actualText)
assertEquals(expectedMapping, actualMapping)
assertEquals(expectedChangedLines, actualChangedLines)
if (customFragments == null) {
assertEquals(expectedMappedLines1, actualMappedLines1)
assertEquals(expectedMappedLines2, actualMappedLines2)
}
}
}
fun changes(vararg ranges: Range): Test {
customFragments = ranges.map {
LineFragmentImpl(it.start1, it.end1, it.start2, it.end2,
-1, -1, -1, -1)
}
return this
}
private fun processText(text: String): String {
return text.filterNot { it == '.' }.replace('_', '\n')
}
private fun processActualText(builder: UnifiedFragmentBuilder): String {
return builder.text.toString().removeSuffix("\n")
}
private fun processExpectedLineMapping(lineMapping: String): LineMapping {
val leftSet = BitSet()
val rightSet = BitSet()
val unchangedSet = BitSet()
lineMapping.split('_').forEachIndexed { index, line ->
if (!line.isEmpty()) {
val left = line.all { it == 'L' }
val right = line.all { it == 'R' }
val unchanged = line.all { it == ' ' }
if (left) leftSet.set(index)
else if (right) rightSet.set(index)
else if (unchanged) unchangedSet.set(index)
else TestCase.fail()
}
}
return LineMapping(leftSet, rightSet, unchangedSet)
}
private fun processActualLineMapping(blocks: List<ChangedBlock>, lineCount: Int): LineMapping {
val leftSet = BitSet()
val rightSet = BitSet()
val unchangedSet = BitSet()
blocks.forEach {
leftSet.set(it.range1.start, it.range1.end)
rightSet.set(it.range2.start, it.range2.end)
}
unchangedSet.set(0, lineCount)
unchangedSet.andNot(leftSet)
unchangedSet.andNot(rightSet)
return LineMapping(leftSet, rightSet, unchangedSet)
}
private fun processExpectedChangedLines(lineMapping: String): BitSet {
val expectedMapping = processExpectedLineMapping(lineMapping)
val result = BitSet()
result.or(expectedMapping.left)
result.or(expectedMapping.right)
return result
}
private fun processActualChangedLines(changedRanges: List<LineRange>): BitSet {
val result = BitSet()
changedRanges.forEach {
result.set(it.start, it.end)
}
return result
}
private fun processExpectedMappedLines(iterable: DiffIterable, side: Side): BitSet {
val result = BitSet()
DiffIterableUtil.iterateAll(iterable).forEach { pair ->
val range = pair.first
val start = side.select(range.start1, range.start2)
val end = side.select(range.end1, range.end2)
result.set(start, end)
}
return result
}
private fun processActualMappedLines(convertor: LineNumberConvertor, lineCount: Int): BitSet {
val result = BitSet()
for (i in -5..lineCount + 5) {
val line = convertor.convert(i)
if (line != -1) {
if (result[line]) TestCase.fail()
result.set(line)
}
}
return result
}
}
fun testDeletion() {
val builder = createBuilder("A\n", "", Side.LEFT)
assertFalse(builder.isEqual)
assertEquals(builder.text.toString(), "A\n\n")
assertEquals(builder.changedLines, listOf(LineRange(0, 1)))
assertEquals(builder.blocks.size, 1)
val block = builder.blocks[0]
assertEquals(block.line1, 0)
assertEquals(block.line2, 1)
assertEquals(block.range1.start, 0)
assertEquals(block.range1.end, 1)
assertEquals(block.range2.start, 1)
assertEquals(block.range2.end, 1)
private fun mod(line1: Int, line2: Int, count1: Int, count2: Int): Range {
assert(count1 != 0)
assert(count2 != 0)
return Range(line1, line1 + count1, line2, line2 + count2)
}
private fun createBuilder(text1: String, text2: String, side: Side): UnifiedFragmentBuilder {
val document1 = DocumentImpl(text1)
val document2 = DocumentImpl(text2)
val fragments = MANAGER.compareLinesInner(document1.charsSequence, document2.charsSequence,
ComparisonPolicy.DEFAULT, DumbProgressIndicator.INSTANCE)
val builder = UnifiedFragmentBuilder(fragments, document1, document2, side)
builder.exec()
return builder
private fun del(line1: Int, line2: Int, count1: Int): Range {
assert(count1 != 0)
return Range(line1, line1 + count1, line2, line2)
}
private fun ins(line1: Int, line2: Int, count2: Int): Range {
assert(count2 != 0)
return Range(line1, line1, line2, line2 + count2)
}
private data class LineMapping(val left: BitSet, val right: BitSet, val unchanged: BitSet)
}
@@ -59,7 +59,7 @@ public interface PrePushHandler {
String getPresentableName();
/**
* Check synchronously if the push operation should be performed or canceled for specified {@link PushDetail}s
* Check synchronously if the push operation should be performed or canceled for specified {@link PushInfo}s
* <p>
* Note: it is permissible for a handler to show it's own modal dialogs with specifying
* the supplied {@code indicator}'s {@link ProgressIndicator#getModalityState() modality} state.
@@ -70,6 +70,6 @@ public interface PrePushHandler {
*/
@CalledInAny
@NotNull
Result handle(@NotNull List<PushDetail> pushDetails, @NotNull ProgressIndicator indicator);
Result handle(@NotNull List<PushInfo> pushDetails, @NotNull ProgressIndicator indicator);
}

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