Merge remote-tracking branch 'origin/master'
@@ -62,7 +62,7 @@ class CompilerReferenceReader {
|
||||
}
|
||||
else {
|
||||
LightRef.LightClassHierarchyElementDef hierarchyElement = ((LightRef.LightMember)ref).getOwner();
|
||||
hierarchy = getWholeHierarchy(hierarchyElement, checkBaseClassAmbiguity, -1);
|
||||
hierarchy = getHierarchy(hierarchyElement, checkBaseClassAmbiguity, false, -1);
|
||||
}
|
||||
if (hierarchy == null) return null;
|
||||
TIntHashSet set = new TIntHashSet();
|
||||
@@ -222,25 +222,28 @@ class CompilerReferenceReader {
|
||||
}
|
||||
|
||||
@Nullable("return null if the class hierarchy contains ambiguous qualified names")
|
||||
LightRef.NamedLightRef[] getWholeHierarchy(LightRef.LightClassHierarchyElementDef hierarchyElement, boolean checkBaseClassAmbiguity, int interruptNumber) {
|
||||
LightRef.LightClassHierarchyElementDef[] getHierarchy(LightRef.LightClassHierarchyElementDef hierarchyElement,
|
||||
boolean checkBaseClassAmbiguity,
|
||||
boolean includeAnonymous,
|
||||
int interruptNumber) {
|
||||
try {
|
||||
Set<LightRef.NamedLightRef> result = new THashSet<>();
|
||||
Queue<LightRef.NamedLightRef> q = new Queue<>(10);
|
||||
Set<LightRef.LightClassHierarchyElementDef> result = new THashSet<>();
|
||||
Queue<LightRef.LightClassHierarchyElementDef> q = new Queue<>(10);
|
||||
q.addLast(hierarchyElement);
|
||||
while (!q.isEmpty()) {
|
||||
LightRef.NamedLightRef curClass = q.pullFirst();
|
||||
LightRef.LightClassHierarchyElementDef curClass = q.pullFirst();
|
||||
if (interruptNumber != -1 && result.size() > interruptNumber) {
|
||||
break;
|
||||
}
|
||||
if (result.add(curClass)) {
|
||||
if (checkBaseClassAmbiguity || curClass != hierarchyElement) {
|
||||
if (!(curClass instanceof LightRef.LightAnonymousClassDef) && (checkBaseClassAmbiguity || curClass != hierarchyElement)) {
|
||||
if (hasMultipleDefinitions(curClass)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
myIndex.get(CompilerIndices.BACK_HIERARCHY).getData(curClass).forEach((id, children) -> {
|
||||
for (LightRef child : children) {
|
||||
if (child instanceof LightRef.LightClassHierarchyElementDef && !(child instanceof LightRef.LightAnonymousClassDef)) {
|
||||
if (child instanceof LightRef.LightClassHierarchyElementDef && (includeAnonymous || !(child instanceof LightRef.LightAnonymousClassDef))) {
|
||||
q.addLast((LightRef.LightClassHierarchyElementDef)child);
|
||||
}
|
||||
}
|
||||
@@ -248,13 +251,27 @@ class CompilerReferenceReader {
|
||||
});
|
||||
}
|
||||
}
|
||||
return result.toArray(LightRef.NamedLightRef.EMPTY_ARRAY);
|
||||
return result.toArray(LightRef.LightClassHierarchyElementDef.EMPTY_ARRAY);
|
||||
}
|
||||
catch (StorageException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
LightRef.LightClassHierarchyElementDef[] getDirectInheritors(LightRef.LightClassHierarchyElementDef hierarchyElement) throws StorageException {
|
||||
Set<LightRef.LightClassHierarchyElementDef> result = new THashSet<>();
|
||||
myIndex.get(CompilerIndices.BACK_HIERARCHY).getData(hierarchyElement).forEach((id, children) -> {
|
||||
for (LightRef child : children) {
|
||||
if (child instanceof LightRef.LightClassHierarchyElementDef && !(child instanceof LightRef.LightAnonymousClassDef)) {
|
||||
result.add((LightRef.LightClassHierarchyElementDef)child);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return result.toArray(LightRef.LightClassHierarchyElementDef.EMPTY_ARRAY);
|
||||
}
|
||||
|
||||
private enum DefCount { NONE, ONE, MANY}
|
||||
private boolean hasMultipleDefinitions(LightRef.NamedLightRef def) throws StorageException {
|
||||
DefCount[] result = new DefCount[]{DefCount.NONE};
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.jetbrains.jps.backwardRefs.SignatureData;
|
||||
import java.util.SortedSet;
|
||||
|
||||
/**
|
||||
* The service is used for java relevant chain completion
|
||||
* The service is used for java relevant chain completion / frequently used superclass inspection
|
||||
*/
|
||||
public abstract class CompilerReferenceServiceEx extends CompilerReferenceService {
|
||||
protected CompilerReferenceServiceEx(Project project) {
|
||||
@@ -43,4 +43,11 @@ public abstract class CompilerReferenceServiceEx extends CompilerReferenceServic
|
||||
@NotNull
|
||||
public abstract String getName(int idx)
|
||||
throws ReferenceIndexUnavailableException;
|
||||
|
||||
public abstract int getNameId(@NotNull String name) throws ReferenceIndexUnavailableException;
|
||||
|
||||
@NotNull
|
||||
public abstract LightRef.LightClassHierarchyElementDef[] getDirectInheritors(LightRef.LightClassHierarchyElementDef baseClass) throws ReferenceIndexUnavailableException;
|
||||
|
||||
public abstract int getInheritorCount(LightRef.LightClassHierarchyElementDef baseClass) throws ReferenceIndexUnavailableException;
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.ConcurrentFactoryMap;
|
||||
import com.intellij.util.indexing.FileBasedIndex;
|
||||
import com.intellij.util.indexing.StorageException;
|
||||
@@ -235,7 +236,7 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceServiceEx imp
|
||||
.filter(r -> r instanceof LightRef.JavaLightMethodRef)
|
||||
.map(r -> (LightRef.JavaLightMethodRef) r)
|
||||
.flatMap(r -> {
|
||||
LightRef.NamedLightRef[] hierarchy = myReader.getWholeHierarchy(r.getOwner(), false, ChainSearchMagicConstants.MAX_HIERARCHY_SIZE);
|
||||
LightRef.NamedLightRef[] hierarchy = myReader.getHierarchy(r.getOwner(), false, false, ChainSearchMagicConstants.MAX_HIERARCHY_SIZE);
|
||||
return hierarchy == null ? Stream.empty() : Arrays.stream(hierarchy).map(c -> r.override(c.getName()));
|
||||
})
|
||||
.distinct()
|
||||
@@ -278,7 +279,7 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceServiceEx imp
|
||||
return false;
|
||||
}
|
||||
catch (Exception e) {
|
||||
onException(e, "correlation");
|
||||
onException(e, "conditional probability");
|
||||
return false;
|
||||
}
|
||||
} finally {
|
||||
@@ -293,6 +294,58 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceServiceEx imp
|
||||
try {
|
||||
if (myReader == null) throw new ReferenceIndexUnavailableException();
|
||||
return myReader.getNameEnumerator().getName(idx);
|
||||
} catch (Exception e) {
|
||||
onException(e, "find methods");
|
||||
throw new ReferenceIndexUnavailableException();
|
||||
} finally {
|
||||
myReadDataLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNameId(@NotNull String name) throws ReferenceIndexUnavailableException {
|
||||
myReadDataLock.lock();
|
||||
try {
|
||||
if (myReader == null) throw new ReferenceIndexUnavailableException();
|
||||
int id;
|
||||
try {
|
||||
id = myReader.getNameEnumerator().tryEnumerate(name);
|
||||
}
|
||||
catch (Exception e) {
|
||||
onException(e, "get name-id");
|
||||
throw new ReferenceIndexUnavailableException();
|
||||
}
|
||||
return id;
|
||||
} finally {
|
||||
myReadDataLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public LightRef.LightClassHierarchyElementDef[] getDirectInheritors(@NotNull LightRef.LightClassHierarchyElementDef baseClass) throws ReferenceIndexUnavailableException {
|
||||
myReadDataLock.lock();
|
||||
try {
|
||||
if (myReader == null) throw new ReferenceIndexUnavailableException();
|
||||
return myReader.getDirectInheritors(baseClass);
|
||||
} catch (Exception e) {
|
||||
onException(e, "find methods");
|
||||
throw new ReferenceIndexUnavailableException();
|
||||
} finally {
|
||||
myReadDataLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInheritorCount(@NotNull LightRef.LightClassHierarchyElementDef baseClass) throws ReferenceIndexUnavailableException {
|
||||
myReadDataLock.lock();
|
||||
try {
|
||||
if (myReader == null) throw new ReferenceIndexUnavailableException();
|
||||
LightRef.NamedLightRef[] hierarchy = ObjectUtils.notNull(myReader.getHierarchy(baseClass, false, true, -1));
|
||||
return hierarchy.length;
|
||||
} catch (Exception e) {
|
||||
onException(e, "inheritor count");
|
||||
throw new ReferenceIndexUnavailableException();
|
||||
} finally {
|
||||
myReadDataLock.unlock();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 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.
|
||||
@@ -13,34 +13,37 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.codeInspection.inheritance;
|
||||
package com.intellij.compiler.inspection;
|
||||
|
||||
import com.intellij.codeInsight.daemon.GroupNames;
|
||||
import com.intellij.codeInsight.intention.LowPriorityAction;
|
||||
import com.intellij.codeInsight.intention.HighPriorityAction;
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
public class ChangeSuperClassFix implements LocalQuickFix {
|
||||
public class ChangeSuperClassFix implements LocalQuickFix, HighPriorityAction {
|
||||
@NotNull
|
||||
private final SmartPsiElementPointer<PsiClass> myNewSuperClass;
|
||||
@NotNull
|
||||
private final SmartPsiElementPointer<PsiClass> myOldSuperClass;
|
||||
private final int myPercent;
|
||||
private final int myInheritorCount;
|
||||
@NotNull
|
||||
private final String myNewSuperName;
|
||||
private final boolean myNewSuperIsInterface;
|
||||
|
||||
public ChangeSuperClassFix(@NotNull final PsiClass newSuperClass, final int percent, @NotNull final PsiClass oldSuperClass) {
|
||||
final SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(newSuperClass.getProject());
|
||||
myNewSuperName = ObjectUtils.notNull(newSuperClass.getQualifiedName());
|
||||
myNewSuperIsInterface = newSuperClass.isInterface();
|
||||
myNewSuperClass = smartPointerManager.createSmartPsiElementPointer(newSuperClass);
|
||||
myOldSuperClass = smartPointerManager.createSmartPsiElementPointer(oldSuperClass);
|
||||
myPercent = percent;
|
||||
myInheritorCount = percent;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -50,14 +53,14 @@ public class ChangeSuperClassFix implements LocalQuickFix {
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
public int getPercent() {
|
||||
return myPercent;
|
||||
public int getInheritorCount() {
|
||||
return myInheritorCount;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return String.format("Make extends '%s' - %s%%", myNewSuperName, myPercent);
|
||||
return String.format("Make " + (myNewSuperIsInterface ? "implements" : "extends") + " '%s'", myNewSuperName);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -83,42 +86,38 @@ public class ChangeSuperClassFix implements LocalQuickFix {
|
||||
private static void changeSuperClass(@NotNull final PsiClass aClass,
|
||||
@NotNull final PsiClass oldSuperClass,
|
||||
@NotNull final PsiClass newSuperClass) {
|
||||
PsiElementFactory factory = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory();
|
||||
JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(aClass.getProject());
|
||||
PsiElementFactory factory = psiFacade.getElementFactory();
|
||||
if (aClass instanceof PsiAnonymousClass) {
|
||||
((PsiAnonymousClass)aClass).getBaseClassReference().replace(factory.createClassReferenceElement(newSuperClass));
|
||||
return;
|
||||
}
|
||||
else if (oldSuperClass.isInterface()) {
|
||||
final PsiReferenceList interfaceList = aClass.getImplementsList();
|
||||
if (interfaceList != null) {
|
||||
for (final PsiJavaCodeReferenceElement interfaceRef : interfaceList.getReferenceElements()) {
|
||||
final PsiElement aInterface = interfaceRef.resolve();
|
||||
if (aInterface != null && aInterface.isEquivalentTo(oldSuperClass)) {
|
||||
interfaceRef.delete();
|
||||
}
|
||||
}
|
||||
PsiReferenceList extendsList = ObjectUtils.notNull(aClass.getExtendsList());
|
||||
PsiJavaCodeReferenceElement[] refElements =
|
||||
ArrayUtil.mergeArrays(getReferences(extendsList), getReferences(aClass.getImplementsList()));
|
||||
for (PsiJavaCodeReferenceElement refElement : refElements) {
|
||||
if (refElement.isReferenceTo(oldSuperClass)) {
|
||||
refElement.delete();
|
||||
}
|
||||
}
|
||||
|
||||
final PsiReferenceList extendsList = aClass.getExtendsList();
|
||||
if (extendsList != null) {
|
||||
final PsiJavaCodeReferenceElement newClassReference = factory.createClassReferenceElement(newSuperClass);
|
||||
if (extendsList.getReferenceElements().length == 0) {
|
||||
extendsList.add(newClassReference);
|
||||
}
|
||||
}
|
||||
PsiReferenceList list;
|
||||
if (newSuperClass.isInterface()) {
|
||||
list = aClass.getImplementsList();
|
||||
}
|
||||
else {
|
||||
final PsiReferenceList extendsList = aClass.getExtendsList();
|
||||
if (extendsList != null && extendsList.getReferenceElements().length == 1) {
|
||||
extendsList.getReferenceElements()[0].delete();
|
||||
PsiElement ref = extendsList.add(factory.createClassReferenceElement(newSuperClass));
|
||||
JavaCodeStyleManager.getInstance(aClass.getProject()).shortenClassReferences(ref);
|
||||
list = extendsList;
|
||||
PsiJavaCodeReferenceElement[] elements = list.getReferenceElements();
|
||||
if (elements.length == 1 &&
|
||||
elements[0].isReferenceTo(psiFacade.findClass(CommonClassNames.JAVA_LANG_OBJECT, aClass.getResolveScope()))) {
|
||||
elements[0].delete();
|
||||
}
|
||||
}
|
||||
PsiElement ref = list.add(factory.createClassReferenceElement(newSuperClass));
|
||||
JavaCodeStyleManager.getInstance(aClass.getProject()).shortenClassReferences(ref);
|
||||
}
|
||||
|
||||
public static class LowPriority extends ChangeSuperClassFix implements LowPriorityAction {
|
||||
public LowPriority(@NotNull final PsiClass newSuperClass, final int percent, @NotNull final PsiClass oldSuperClass) {
|
||||
super(newSuperClass, percent, oldSuperClass);
|
||||
}
|
||||
private static PsiJavaCodeReferenceElement[] getReferences(PsiReferenceList list) {
|
||||
return list == null ? PsiJavaCodeReferenceElement.EMPTY_ARRAY : list.getReferenceElements();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* 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.compiler.inspection;
|
||||
|
||||
import com.intellij.codeInspection.*;
|
||||
import com.intellij.compiler.CompilerReferenceService;
|
||||
import com.intellij.compiler.backwardRefs.CompilerReferenceServiceEx;
|
||||
import com.intellij.compiler.backwardRefs.ReferenceIndexUnavailableException;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.java.stubs.index.JavaFullClassNameIndex;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import one.util.streamex.MoreCollectors;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.backwardRefs.LightRef;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class FrequentlyUsedInheritorInspection extends BaseJavaLocalInspectionTool {
|
||||
private static final Logger LOG = Logger.getInstance(FrequentlyUsedInheritorInspection.class);
|
||||
|
||||
public static final byte MAX_RESULT = 3;
|
||||
private static final int PERCENT_THRESHOLD = 20;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ProblemDescriptor[] checkClass(@NotNull final PsiClass aClass,
|
||||
@NotNull final InspectionManager manager,
|
||||
final boolean isOnTheFly) {
|
||||
if (aClass.isInterface() || aClass instanceof PsiTypeParameter) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final PsiClass superClass = getSuperIfOnlyOne(aClass);
|
||||
if (superClass == null) return null;
|
||||
|
||||
long ms = System.currentTimeMillis();
|
||||
final List<ClassAndInheritorCount> topInheritors = getTopInheritorsUsingCompilerIndices(superClass, aClass.getResolveScope(), aClass);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("search for inheritance structure of " + superClass.getQualifiedName() + " in " + (System.currentTimeMillis() - ms) + " ms");
|
||||
}
|
||||
if (topInheritors.isEmpty()) return null;
|
||||
|
||||
final Collection<LocalQuickFix> topInheritorsQuickFix = new ArrayList<>(topInheritors.size());
|
||||
for (final ClassAndInheritorCount searchResult : topInheritors) {
|
||||
final LocalQuickFix quickFix = new ChangeSuperClassFix(searchResult.psi, searchResult.number, superClass);
|
||||
topInheritorsQuickFix.add(quickFix);
|
||||
if (topInheritorsQuickFix.size() >= MAX_RESULT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new ProblemDescriptor[]{manager
|
||||
.createProblemDescriptor(aClass, "Class can have more common super class", isOnTheFly,
|
||||
topInheritorsQuickFix.toArray(LocalQuickFix.EMPTY_ARRAY),
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING)};
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiClass getSuperIfOnlyOne(@NotNull final PsiClass aClass) {
|
||||
PsiClass superClass = aClass.getSuperClass();
|
||||
if (superClass != null && !CommonClassNames.JAVA_LANG_OBJECT.equals(superClass.getQualifiedName())) {
|
||||
return isInSourceContent(aClass) ? superClass : null;
|
||||
}
|
||||
|
||||
return Arrays
|
||||
.stream(aClass.getInterfaces())
|
||||
.filter(c -> !CommonClassNames.JAVA_LANG_OBJECT.equals(c.getQualifiedName()))
|
||||
.filter(c -> isInSourceContent(c))
|
||||
.collect(MoreCollectors.onlyOne())
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<ClassAndInheritorCount> getTopInheritorsUsingCompilerIndices(@NotNull PsiClass aClass,
|
||||
@NotNull GlobalSearchScope searchScope,
|
||||
@NotNull PsiElement place) {
|
||||
String qName = aClass.getQualifiedName();
|
||||
if (qName == null) return Collections.emptyList();
|
||||
|
||||
final Project project = aClass.getProject();
|
||||
final CompilerReferenceServiceEx compilerRefService = (CompilerReferenceServiceEx)CompilerReferenceService.getInstance(project);
|
||||
try {
|
||||
int id = compilerRefService.getNameId(qName);
|
||||
if (id == 0) return Collections.emptyList();
|
||||
return findInheritors(aClass, new LightRef.JavaLightClassRef(id), searchScope, place, -1, project, compilerRefService);
|
||||
}
|
||||
catch (ReferenceIndexUnavailableException e) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
private static List<ClassAndInheritorCount> findInheritors(@NotNull PsiClass aClass,
|
||||
@NotNull LightRef.JavaLightClassRef classAsLightRef,
|
||||
@NotNull GlobalSearchScope searchScope,
|
||||
@NotNull PsiElement place,
|
||||
int hierarchyCardinality,
|
||||
@NotNull Project project,
|
||||
@NotNull CompilerReferenceServiceEx compilerRefService) {
|
||||
LightRef.LightClassHierarchyElementDef[] directInheritors = compilerRefService.getDirectInheritors(classAsLightRef);
|
||||
|
||||
if (hierarchyCardinality == -1) {
|
||||
hierarchyCardinality = compilerRefService.getInheritorCount(classAsLightRef);
|
||||
}
|
||||
int finalHierarchyCardinality = hierarchyCardinality;
|
||||
|
||||
List<ClassAndInheritorCount> directInheritorStats = Stream
|
||||
.of(directInheritors)
|
||||
.filter(inheritor -> !(inheritor instanceof LightRef.LightAnonymousClassDef))
|
||||
.map(inheritor -> {
|
||||
int count = compilerRefService.getInheritorCount(inheritor);
|
||||
if (count * 100 > finalHierarchyCardinality * PERCENT_THRESHOLD) {
|
||||
return new Object() {
|
||||
final LightRef.LightClassHierarchyElementDef myDef = inheritor;
|
||||
final int inheritorCount = count;
|
||||
};
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.map(defAndCount -> {
|
||||
String name = compilerRefService.getName(defAndCount.myDef.getName());
|
||||
PsiClass inheritor =
|
||||
JavaFullClassNameIndex.getInstance().get(name.hashCode(), project, searchScope).stream()
|
||||
.filter(cls -> name.equals(cls.getQualifiedName()))
|
||||
.collect(MoreCollectors.onlyOne())
|
||||
.orElse(null);
|
||||
|
||||
if (inheritor == null || !inheritor.isInheritor(aClass, false)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ClassAndInheritorCount(inheritor, defAndCount.myDef, defAndCount.inheritorCount);
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
PsiResolveHelper resolveHelper = PsiResolveHelper.SERVICE.getInstance(project);
|
||||
return directInheritorStats
|
||||
.stream()
|
||||
.filter(c -> resolveHelper.isAccessible(c.psi, place, null))
|
||||
.flatMap(c -> Stream.concat(Stream.of(c), getClassesIfInterface(c, finalHierarchyCardinality, searchScope, place, project, compilerRefService).stream()))
|
||||
.sorted()
|
||||
.limit(MAX_RESULT)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static List<ClassAndInheritorCount> getClassesIfInterface(@NotNull ClassAndInheritorCount classAndInheritorCount,
|
||||
int hierarchyCardinality,
|
||||
GlobalSearchScope searchScope,
|
||||
PsiElement place,
|
||||
Project project,
|
||||
CompilerReferenceServiceEx compilerRefService) {
|
||||
if (classAndInheritorCount.psi.isInterface()) {
|
||||
return findInheritors(classAndInheritorCount.psi,
|
||||
(LightRef.JavaLightClassRef)classAndInheritorCount.descriptor,
|
||||
searchScope,
|
||||
place,
|
||||
hierarchyCardinality,
|
||||
project,
|
||||
compilerRefService);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private static boolean isInSourceContent(@NotNull PsiElement e) {
|
||||
final VirtualFile file = e.getContainingFile().getVirtualFile();
|
||||
if (file == null) return false;
|
||||
final ProjectFileIndex index = ProjectRootManager.getInstance(e.getProject()).getFileIndex();
|
||||
return index.isInContent(file);
|
||||
}
|
||||
|
||||
private static class ClassAndInheritorCount implements Comparable<ClassAndInheritorCount> {
|
||||
private final PsiClass psi;
|
||||
private final LightRef.LightClassHierarchyElementDef descriptor;
|
||||
private final int number;
|
||||
|
||||
private ClassAndInheritorCount(PsiClass psi,
|
||||
LightRef.LightClassHierarchyElementDef descriptor,
|
||||
int number) {
|
||||
this.psi = psi;
|
||||
this.descriptor = descriptor;
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull ClassAndInheritorCount o) {
|
||||
return - number + o.number;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,6 +47,7 @@ import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.EditorNotifications;
|
||||
import com.intellij.ui.content.Content;
|
||||
@@ -357,7 +358,7 @@ public class JavaDebugProcess extends XDebugProcess {
|
||||
}
|
||||
|
||||
private void registerMemoryViewPanel(@NotNull RunnerLayoutUi ui) {
|
||||
if (!MemoryViewManager.getInstance().isEnabled()) return;
|
||||
if (!Registry.get("debugger.enable.memory.view").asBoolean()) return;
|
||||
final XDebugSession session = getSession();
|
||||
final DebugProcessImpl process = myJavaSession.getProcess();
|
||||
final InstancesTracker tracker = InstancesTracker.getInstance(myJavaSession.getProject());
|
||||
|
||||
@@ -87,10 +87,6 @@ public class MemoryViewManager implements ApplicationComponent, PersistentStateC
|
||||
return myState.isShowTrackedOnly;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return Registry.get("debugger.enable.memory.view").asBoolean();
|
||||
}
|
||||
|
||||
public void addMemoryViewManagerListener(MemoryViewManagerListener listener, @NotNull Disposable parentDisposable) {
|
||||
myDispatcher.addListener(listener, parentDisposable);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import org.jetbrains.uast.UDeclaration
|
||||
/**
|
||||
* Extension Point provides language-abstracted code modifications for JVM-based languages.
|
||||
*
|
||||
* Each method should return nullable code modification (preferable [IntentionAction] as most generic).
|
||||
* Each method should return nullable code modification ([IntentionAction]).
|
||||
* If method returns `null` this means that operation on given elements is not supported or not yet implemented for a language.
|
||||
*
|
||||
* Every new added method should return `null` by default and then be overridden in implementations for each language if it is possible.
|
||||
@@ -34,12 +34,12 @@ import org.jetbrains.uast.UDeclaration
|
||||
* @since 2017.2
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
abstract class JvmCommonCodeModifications {
|
||||
abstract class JvmCommonIntentionActionsFactory {
|
||||
|
||||
open fun createChangeModifierAction(declaration: UDeclaration, @PsiModifier.ModifierConstant @NonNls modifier: String, shouldPresent: Boolean): IntentionAction? = null
|
||||
|
||||
open fun createAddMethodAction(u: UClass, methodName: String, returnType: PsiType, vararg arguments: PsiType): IntentionAction? = null
|
||||
open fun createAddMethodAction(u: UClass, methodName: String, returnType: PsiType, vararg parameters: PsiType): IntentionAction? = null
|
||||
|
||||
companion object : LanguageExtension<JvmCommonCodeModifications>("com.intellij.codeInsight.intention.jvmCommonCodeModifications")
|
||||
companion object : LanguageExtension<JvmCommonIntentionActionsFactory>("com.intellij.codeInsight.intention.jvmCommonIntentionActionsFactory")
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ public class AnonymousHasLambdaAlternativeInspection extends BaseJavaBatchLocalI
|
||||
new AnonymousLambdaAlternative("java.lang.ThreadLocal", "initialValue", "java.lang.ThreadLocal.withInitial($lambda$)",
|
||||
"ThreadLocal.withInitial()"),
|
||||
new AnonymousLambdaAlternative("java.lang.Thread", "run", "new java.lang.Thread($lambda$)",
|
||||
"new Thread() with lambda argument")
|
||||
"new Thread(() -> {…})")
|
||||
};
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -17,7 +17,7 @@ package com.intellij.codeInspection.inheritance
|
||||
|
||||
import com.intellij.CommonBundle
|
||||
import com.intellij.codeInsight.daemon.QuickFixBundle
|
||||
import com.intellij.codeInsight.intention.JvmCommonCodeModifications
|
||||
import com.intellij.codeInsight.intention.JvmCommonIntentionActionsFactory
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.codeInspection.*
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
@@ -58,13 +58,13 @@ class ImplicitSubclassInspection : AbstractBaseUastLocalInspectionTool() {
|
||||
|
||||
val smartPointerManager = SmartPointerManager.getInstance(aClass.project)
|
||||
|
||||
val commonModifications = JvmCommonCodeModifications.forLanguage(aClass.language)
|
||||
val actionsFactory = JvmCommonIntentionActionsFactory.forLanguage(aClass.language)
|
||||
|
||||
for ((method, description) in methodsToOverride) {
|
||||
if (method.isFinal || method.isStatic || method.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
methodsToAttachToClassFix?.add(smartPointerManager.createSmartPsiElementPointer(method, method.containingFile))
|
||||
|
||||
val methodFixes = createFixesIfApplicable(commonModifications, method, method.name)
|
||||
val methodFixes = createFixesIfApplicable(actionsFactory, method, method.name)
|
||||
problemTargets(method, methodHighlightableModifiersSet).forEach {
|
||||
problems.add(manager.createProblemDescriptor(
|
||||
it, description, isOnTheFly,
|
||||
@@ -81,7 +81,7 @@ class ImplicitSubclassInspection : AbstractBaseUastLocalInspectionTool() {
|
||||
problems.add(manager.createProblemDescriptor(
|
||||
it, classReasonToBeSubclassed ?: InspectionsBundle.message("inspection.implicit.subclass.display.forClass", aClass.name),
|
||||
isOnTheFly,
|
||||
createFixesIfApplicable(commonModifications, aClass, aClass.name ?: "class", methodsToAttachToClassFix ?: emptyList()),
|
||||
createFixesIfApplicable(actionsFactory, aClass, aClass.name ?: "class", methodsToAttachToClassFix ?: emptyList()),
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING)
|
||||
)
|
||||
}
|
||||
@@ -91,12 +91,12 @@ class ImplicitSubclassInspection : AbstractBaseUastLocalInspectionTool() {
|
||||
return problems.toTypedArray()
|
||||
}
|
||||
|
||||
private fun createFixesIfApplicable(commonModifications: JvmCommonCodeModifications?,
|
||||
private fun createFixesIfApplicable(actionsFactory: JvmCommonIntentionActionsFactory?,
|
||||
aClass: UDeclaration,
|
||||
hintTargetName: String,
|
||||
methodsToAttachToClassFix: List<SmartPsiElementPointer<UDeclaration>> = emptyList()): Array<LocalQuickFix> {
|
||||
if (commonModifications == null) return emptyArray()
|
||||
val fix = MakeExtendableFix(aClass, hintTargetName, commonModifications, methodsToAttachToClassFix)
|
||||
if (actionsFactory == null) return emptyArray()
|
||||
val fix = MakeExtendableFix(aClass, hintTargetName, actionsFactory, methodsToAttachToClassFix)
|
||||
if (!fix.hasActionsToPerform) return emptyArray()
|
||||
return arrayOf(fix)
|
||||
}
|
||||
@@ -120,7 +120,7 @@ class ImplicitSubclassInspection : AbstractBaseUastLocalInspectionTool() {
|
||||
|
||||
private class MakeExtendableFix(uDeclaration: UDeclaration,
|
||||
hintTargetName: String,
|
||||
val changeModifiers: JvmCommonCodeModifications,
|
||||
val actionsFactory: JvmCommonIntentionActionsFactory,
|
||||
val siblings: List<SmartPsiElementPointer<UDeclaration>> = emptyList())
|
||||
: LocalQuickFixOnPsiElement(uDeclaration) {
|
||||
|
||||
@@ -185,7 +185,7 @@ class ImplicitSubclassInspection : AbstractBaseUastLocalInspectionTool() {
|
||||
shouldPresent: Boolean,
|
||||
actionsList: SmartList<IntentionAction>) {
|
||||
if (declaration.modifierList?.hasModifierProperty(name) != shouldPresent) {
|
||||
(changeModifiers.createChangeModifierAction(declaration, name, shouldPresent))?.let {
|
||||
(actionsFactory.createChangeModifierAction(declaration, name, shouldPresent))?.let {
|
||||
actionsList.add(it)
|
||||
}
|
||||
}
|
||||
@@ -196,7 +196,7 @@ class ImplicitSubclassInspection : AbstractBaseUastLocalInspectionTool() {
|
||||
private val text = when (uDeclaration) {
|
||||
is UClass ->
|
||||
if (actionsToPerform.size <= MAX_MESSAGES_TO_COMBINE)
|
||||
actionsToPerform.map { it.text }.joinToString()
|
||||
actionsToPerform.joinToString { it.text }
|
||||
else InspectionsBundle.message("inspection.implicit.subclass.make.class.extendable",
|
||||
hintTargetName,
|
||||
siblings.size,
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
package com.intellij.codeInspection.inheritance;
|
||||
|
||||
import com.intellij.codeInsight.daemon.GroupNames;
|
||||
import com.intellij.codeInspection.*;
|
||||
import com.intellij.codeInspection.inheritance.search.InheritorsStatisticalDataSearch;
|
||||
import com.intellij.codeInspection.inheritance.search.InheritorsStatisticsSearchResult;
|
||||
import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class SuperClassHasFrequentlyUsedInheritorsInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
private static final int MIN_PERCENT_RATIO = 5;
|
||||
public static final int MAX_QUICK_FIX_COUNTS = 4;
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.INHERITANCE_GROUP_NAME;
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return "Class may extend a commonly used base class instead of implementing interface or extending abstract class";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledByDefault() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ProblemDescriptor[] checkClass(@NotNull final PsiClass aClass,
|
||||
@NotNull final InspectionManager manager,
|
||||
final boolean isOnTheFly) {
|
||||
if (aClass.isInterface() ||
|
||||
aClass.isEnum() ||
|
||||
aClass instanceof PsiTypeParameter ||
|
||||
aClass.getMethods().length != 0 ||
|
||||
aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final PsiClass superClass = getSuperIfUnique(aClass);
|
||||
if (superClass == null) return null;
|
||||
|
||||
final List<InheritorsStatisticsSearchResult> topInheritors =
|
||||
InheritorsStatisticalDataSearch.search(superClass, aClass, aClass.getResolveScope(), MIN_PERCENT_RATIO);
|
||||
|
||||
if (topInheritors.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Collection<LocalQuickFix> topInheritorsQuickFix = new ArrayList<>(topInheritors.size());
|
||||
|
||||
boolean isFirst = true;
|
||||
for (final InheritorsStatisticsSearchResult searchResult : topInheritors) {
|
||||
final LocalQuickFix quickFix;
|
||||
if (isFirst) {
|
||||
quickFix = new ChangeSuperClassFix(searchResult.getPsiClass(), searchResult.getPercent(), superClass);
|
||||
isFirst = false;
|
||||
} else {
|
||||
quickFix = new ChangeSuperClassFix.LowPriority(searchResult.getPsiClass(), searchResult.getPercent(), superClass);
|
||||
}
|
||||
topInheritorsQuickFix.add(quickFix);
|
||||
if (topInheritorsQuickFix.size() >= MAX_QUICK_FIX_COUNTS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new ProblemDescriptor[]{
|
||||
manager.createProblemDescriptor(aClass, getDisplayName(), false, ProblemHighlightType.INFORMATION, false,
|
||||
topInheritorsQuickFix.toArray(new LocalQuickFix[topInheritorsQuickFix.size()]))};
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiClass getSuperIfUnique(@NotNull final PsiClass aClass) {
|
||||
if (aClass instanceof PsiAnonymousClass) {
|
||||
final PsiClass returnClass = (PsiClass)((PsiAnonymousClass)aClass).getBaseClassReference().resolve();
|
||||
if (returnClass != null && CommonClassNames.JAVA_LANG_OBJECT.equals(returnClass.getQualifiedName())) return null;
|
||||
return returnClass;
|
||||
}
|
||||
final PsiReferenceList extendsList = aClass.getExtendsList();
|
||||
if (extendsList != null) {
|
||||
final PsiJavaCodeReferenceElement[] referenceElements = extendsList.getReferenceElements();
|
||||
if (referenceElements.length == 1) {
|
||||
final PsiElement resolved = referenceElements[0].resolve();
|
||||
if (resolved instanceof PsiClass) {
|
||||
PsiClass returnClass = (PsiClass)resolved;
|
||||
if (!CommonClassNames.JAVA_LANG_OBJECT.equals(returnClass.getQualifiedName()) && !returnClass.isInterface()) {
|
||||
return returnClass;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final PsiReferenceList implementsList = aClass.getImplementsList();
|
||||
if (implementsList != null) {
|
||||
final PsiJavaCodeReferenceElement[] referenceElements = implementsList.getReferenceElements();
|
||||
if (referenceElements.length == 1) {
|
||||
PsiClass returnClass = (PsiClass)referenceElements[0].resolve();
|
||||
if (returnClass != null && returnClass.isInterface()) {
|
||||
return returnClass;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package com.intellij.codeInspection.inheritance.search;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
class InheritorsCountData implements Comparable<InheritorsCountData> {
|
||||
@NotNull
|
||||
private final PsiClass myPsiClass;
|
||||
private final int myInheritorsCount;
|
||||
|
||||
public InheritorsCountData(@NotNull final PsiClass psiClass, final int inheritorsCount) {
|
||||
myPsiClass = psiClass;
|
||||
myInheritorsCount = inheritorsCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || !(o instanceof InheritorsCountData)) return false;
|
||||
|
||||
final InheritorsCountData data = (InheritorsCountData)o;
|
||||
return myInheritorsCount == data.myInheritorsCount && myPsiClass.equals(data.myPsiClass);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiClass getPsiClass() {
|
||||
return myPsiClass;
|
||||
}
|
||||
|
||||
public int getInheritorsCount() {
|
||||
return myInheritorsCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final String name = myPsiClass.getName();
|
||||
int result = name != null ? name.hashCode() : 0;
|
||||
return 31 * result + myInheritorsCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull final InheritorsCountData that) {
|
||||
final int sub = -this.myInheritorsCount + that.myInheritorsCount;
|
||||
if (sub != 0) return sub;
|
||||
return String.CASE_INSENSITIVE_ORDER.compare(this.myPsiClass.getName(), that.myPsiClass.getName());
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.format("%s:%d", myPsiClass, myInheritorsCount);
|
||||
}
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.codeInspection.inheritance.search;
|
||||
|
||||
import com.intellij.openapi.util.Couple;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class InheritorsStatisticalDataSearch {
|
||||
|
||||
/**
|
||||
* search for most used inheritors of superClass in scope
|
||||
*
|
||||
* @param aClass - class that excluded from inheritors of superClass
|
||||
* @param minPercentRatio - head volume
|
||||
* @return - search results in relevant ordering (frequency descent)
|
||||
*/
|
||||
public static List<InheritorsStatisticsSearchResult> search(final @NotNull PsiClass superClass,
|
||||
final @NotNull PsiClass aClass,
|
||||
final @NotNull GlobalSearchScope scope,
|
||||
final int minPercentRatio) {
|
||||
final String superClassName = superClass.getName();
|
||||
final String aClassName = aClass.getName();
|
||||
final Set<String> disabledNames = new HashSet<>();
|
||||
disabledNames.add(aClassName);
|
||||
disabledNames.add(superClassName);
|
||||
final Set<InheritorsCountData> collector = new TreeSet<>();
|
||||
final Couple<Integer> collectingResult = collectInheritorsInfo(superClass, collector, disabledNames);
|
||||
final int allAnonymousInheritors = collectingResult.getSecond();
|
||||
final int allInheritors = collectingResult.getFirst() + allAnonymousInheritors - 1;
|
||||
|
||||
final List<InheritorsStatisticsSearchResult> result = new ArrayList<>();
|
||||
|
||||
Integer firstPercent = null;
|
||||
for (final InheritorsCountData data : collector) {
|
||||
final int inheritorsCount = data.getInheritorsCount();
|
||||
if (inheritorsCount < allAnonymousInheritors) {
|
||||
break;
|
||||
}
|
||||
final int percent = (inheritorsCount * 100) / allInheritors;
|
||||
if (percent < 1) {
|
||||
break;
|
||||
}
|
||||
if (firstPercent == null) {
|
||||
firstPercent = percent;
|
||||
}
|
||||
else if (percent * minPercentRatio < firstPercent) {
|
||||
break;
|
||||
}
|
||||
|
||||
final PsiClass psiClass = data.getPsiClass();
|
||||
final VirtualFile file = psiClass.getContainingFile().getVirtualFile();
|
||||
if (file != null && scope.contains(file)) {
|
||||
result.add(new InheritorsStatisticsSearchResult(psiClass, percent));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Couple<Integer> collectInheritorsInfo(final PsiClass superClass,
|
||||
final Set<InheritorsCountData> collector,
|
||||
final Set<String> disabledNames) {
|
||||
return collectInheritorsInfo(superClass, collector, disabledNames, new HashSet<>(), new HashSet<>());
|
||||
}
|
||||
|
||||
private static Couple<Integer> collectInheritorsInfo(final PsiClass aClass,
|
||||
final Set<InheritorsCountData> collector,
|
||||
final Set<String> disabledNames,
|
||||
final Set<String> processedElements,
|
||||
final Set<String> allNotAnonymousInheritors) {
|
||||
final String className = aClass.getName();
|
||||
if (!processedElements.add(className)) return Couple.of(0, 0);
|
||||
|
||||
final MyInheritorsInfoProcessor processor = new MyInheritorsInfoProcessor(collector, disabledNames, processedElements);
|
||||
DirectClassInheritorsSearch.search(aClass).forEach(processor);
|
||||
|
||||
allNotAnonymousInheritors.addAll(processor.getAllNotAnonymousInheritors());
|
||||
|
||||
final int allInheritorsCount = processor.getAllNotAnonymousInheritors().size() + processor.getAnonymousInheritorsCount();
|
||||
if (!aClass.isInterface() && allInheritorsCount != 0 && !disabledNames.contains(className)) {
|
||||
collector.add(new InheritorsCountData(aClass, allInheritorsCount));
|
||||
}
|
||||
return Couple.of(allNotAnonymousInheritors.size(), processor.getAnonymousInheritorsCount());
|
||||
}
|
||||
|
||||
private static class MyInheritorsInfoProcessor implements Processor<PsiClass> {
|
||||
private final Set<InheritorsCountData> myCollector;
|
||||
private final Set<String> myDisabledNames;
|
||||
private final Set<String> myProcessedElements;
|
||||
private final Set<String> myAllNotAnonymousInheritors;
|
||||
|
||||
private MyInheritorsInfoProcessor(Set<InheritorsCountData> collector, Set<String> disabledNames, Set<String> processedElements) {
|
||||
myCollector = collector;
|
||||
myDisabledNames = disabledNames;
|
||||
myProcessedElements = processedElements;
|
||||
myAllNotAnonymousInheritors = new HashSet<>();
|
||||
}
|
||||
|
||||
private int myAnonymousInheritorsCount;
|
||||
|
||||
private Set<String> getAllNotAnonymousInheritors() {
|
||||
return myAllNotAnonymousInheritors;
|
||||
}
|
||||
|
||||
private int getAnonymousInheritorsCount() {
|
||||
return myAnonymousInheritorsCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean process(final PsiClass psiClass) {
|
||||
final String inheritorName = psiClass.getName();
|
||||
if (inheritorName == null) {
|
||||
myAnonymousInheritorsCount++;
|
||||
}
|
||||
else {
|
||||
final Couple<Integer> res = collectInheritorsInfo(psiClass,
|
||||
myCollector,
|
||||
myDisabledNames,
|
||||
myProcessedElements,
|
||||
myAllNotAnonymousInheritors);
|
||||
myAnonymousInheritorsCount += res.getSecond();
|
||||
if (!psiClass.isInterface()) {
|
||||
myAllNotAnonymousInheritors.add(inheritorName);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package com.intellij.codeInspection.inheritance.search;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class InheritorsStatisticsSearchResult {
|
||||
|
||||
@NotNull
|
||||
private final PsiClass myClass;
|
||||
private final int myPercent;
|
||||
|
||||
InheritorsStatisticsSearchResult(final @NotNull PsiClass aClass, final int percent) {
|
||||
myClass = aClass;
|
||||
myPercent = percent;
|
||||
}
|
||||
|
||||
public PsiClass getPsiClass() {
|
||||
return myClass;
|
||||
}
|
||||
|
||||
public int getPercent() {
|
||||
return myPercent;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,7 +21,7 @@ import com.intellij.codeInsight.lookup.VariableLookupItem;
|
||||
import com.intellij.featureStatistics.FeatureUsageTracker;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -53,6 +53,10 @@ public class JavaStaticMemberProcessor extends StaticMemberProcessor {
|
||||
protected LookupElement createLookupElement(@NotNull PsiMember member, @NotNull final PsiClass containingClass, boolean shouldImport) {
|
||||
shouldImport |= myOriginalPosition != null && PsiTreeUtil.isAncestor(containingClass, myOriginalPosition, false);
|
||||
|
||||
if (!PsiNameHelper.getInstance(member.getProject()).isIdentifier(member.getName(), PsiUtil.getLanguageLevel(getPosition()))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PsiReference ref = createReferenceToMemberName(member);
|
||||
if (ref == null) return null;
|
||||
|
||||
@@ -74,13 +78,8 @@ public class JavaStaticMemberProcessor extends StaticMemberProcessor {
|
||||
}
|
||||
|
||||
private PsiReference createReferenceToMemberName(@NotNull PsiMember member) {
|
||||
try {
|
||||
String exprText = member.getName() + (member instanceof PsiMethod ? "()" : "");
|
||||
return JavaPsiFacade.getElementFactory(member.getProject()).createExpressionFromText(exprText, myOriginalPosition).findReferenceAt(0);
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
return null;
|
||||
}
|
||||
String exprText = member.getName() + (member instanceof PsiMethod ? "()" : "");
|
||||
return JavaPsiFacade.getElementFactory(member.getProject()).createExpressionFromText(exprText, myOriginalPosition).findReferenceAt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -278,7 +278,7 @@ public class PreferByKindWeigher extends LookupElementWeigher {
|
||||
return psiElement().inside(PsiReferenceParameterList.class).accepts(position);
|
||||
}
|
||||
|
||||
private static boolean isOnTopLevelInVoidMethod(PsiStatement statement) {
|
||||
private static boolean isOnTopLevelInVoidMethod(@NotNull PsiStatement statement) {
|
||||
if (!(statement.getParent() instanceof PsiCodeBlock)) return false;
|
||||
|
||||
PsiElement parent = statement.getParent().getParent();
|
||||
@@ -302,7 +302,10 @@ public class PreferByKindWeigher extends LookupElementWeigher {
|
||||
}
|
||||
|
||||
private static boolean isLastStatement(PsiStatement statement) {
|
||||
if (statement == null || !(statement.getParent() instanceof PsiCodeBlock)) {
|
||||
if (statement == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(statement.getParent() instanceof PsiCodeBlock)) {
|
||||
return true;
|
||||
}
|
||||
PsiStatement[] siblings = ((PsiCodeBlock)statement.getParent()).getStatements();
|
||||
|
||||
@@ -132,6 +132,10 @@ public abstract class StaticMemberProcessor {
|
||||
return member.hasModifierProperty(PsiModifier.STATIC) && isAccessible(member) && !StaticImportMemberFix.isExcluded(member);
|
||||
}
|
||||
|
||||
public PsiElement getPosition() {
|
||||
return myPosition;
|
||||
}
|
||||
|
||||
protected boolean isAccessible(PsiMember member) {
|
||||
return myResolveHelper.isAccessible(member, myPosition, null);
|
||||
}
|
||||
|
||||
@@ -17,13 +17,16 @@ package com.intellij.codeInsight.daemon.impl.quickfix;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightUtilCore;
|
||||
import com.intellij.codeInsight.ExpectedTypeInfo;
|
||||
import com.intellij.codeInsight.ExpectedTypesProvider;
|
||||
import com.intellij.codeInsight.template.Template;
|
||||
import com.intellij.codeInsight.template.TemplateBuilderImpl;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.introduceField.BaseExpressionToFieldHandler;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
@@ -38,7 +41,8 @@ public class JavaCreateFieldFromUsageHelper extends CreateFieldFromUsageHelper {
|
||||
PsiElement context,
|
||||
boolean createConstantField,
|
||||
PsiSubstitutor substitutor) {
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(field.getProject());
|
||||
Project project = field.getProject();
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
||||
|
||||
field = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(field);
|
||||
TemplateBuilderImpl builder = new TemplateBuilderImpl(field);
|
||||
@@ -57,7 +61,13 @@ public class JavaCreateFieldFromUsageHelper extends CreateFieldFromUsageHelper {
|
||||
}
|
||||
editor.getCaretModel().moveToOffset(field.getTextRange().getStartOffset());
|
||||
Template template = builder.buildInlineTemplate();
|
||||
if (((ExpectedTypeInfo[])expectedTypes).length > 1) template.setToShortenLongNames(false);
|
||||
if (ExpectedTypesProvider.processExpectedTypes((ExpectedTypeInfo[])expectedTypes, new PsiTypeVisitor<PsiType>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiType visitType(PsiType type) {
|
||||
return type;
|
||||
}
|
||||
}, project).length > 1) template.setToShortenLongNames(false);
|
||||
return template;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,10 +18,10 @@ package com.intellij.codeInsight.intention.impl
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.ModifierFix
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import org.jetbrains.uast.UDeclaration
|
||||
import com.intellij.codeInsight.intention.JvmCommonCodeModifications
|
||||
import com.intellij.codeInsight.intention.JvmCommonIntentionActionsFactory
|
||||
|
||||
|
||||
class JavaCommonCodeModifications : JvmCommonCodeModifications() {
|
||||
class JavaCommonIntentionActionsFactory : JvmCommonIntentionActionsFactory() {
|
||||
|
||||
override fun createChangeModifierAction(declaration: UDeclaration, modifier: String, shouldPresent: Boolean): IntentionAction {
|
||||
return ModifierFix(declaration.modifierList, modifier, shouldPresent, false)
|
||||
@@ -26,6 +26,7 @@ import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.LangBundle;
|
||||
import com.intellij.lang.java.JavaDocumentationProvider;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.IndexNotReadyException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.JavaSdk;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
@@ -908,7 +909,15 @@ public class JavaDocInfoGenerator {
|
||||
for (PsiAnnotation annotation : annotations) {
|
||||
final PsiJavaCodeReferenceElement nameReferenceElement = annotation.getNameReferenceElement();
|
||||
if (nameReferenceElement == null) continue;
|
||||
final PsiElement resolved = nameReferenceElement.resolve();
|
||||
PsiElement resolved = null;
|
||||
boolean resolveNotPossible = false;
|
||||
try {
|
||||
resolved = nameReferenceElement.resolve();
|
||||
}
|
||||
catch (IndexNotReadyException e) {
|
||||
LOG.debug(e);
|
||||
resolveNotPossible = true;
|
||||
}
|
||||
if (isNonDocumentedAnnotation(annotation, resolved)) continue;
|
||||
|
||||
boolean inferred = AnnotationUtil.isInferredAnnotation(annotation);
|
||||
@@ -933,7 +942,7 @@ public class JavaDocInfoGenerator {
|
||||
if (inferred) buffer.append("</i>");
|
||||
buffer.append(" ");
|
||||
}
|
||||
else if (external) {
|
||||
else if (external || resolveNotPossible) {
|
||||
if (inferred) buffer.append("<i>");
|
||||
String annoText = inferred ? "@" + annotation.getNameReferenceElement().getReferenceName() + annotation.getParameterList().getText()
|
||||
: annotation.getText();
|
||||
@@ -995,7 +1004,13 @@ public class JavaDocInfoGenerator {
|
||||
boolean generateLink) {
|
||||
if (generateLink && memberValue instanceof PsiQualifiedReferenceElement) {
|
||||
String text = ((PsiQualifiedReferenceElement)memberValue).getCanonicalText();
|
||||
PsiElement resolve = ((PsiQualifiedReferenceElement)memberValue).resolve();
|
||||
PsiElement resolve = null;
|
||||
try {
|
||||
resolve = ((PsiQualifiedReferenceElement)memberValue).resolve();
|
||||
}
|
||||
catch (IndexNotReadyException e) {
|
||||
LOG.debug(e);
|
||||
}
|
||||
|
||||
if (resolve instanceof PsiField) {
|
||||
PsiField field = (PsiField)resolve;
|
||||
@@ -1467,7 +1482,13 @@ public class JavaDocInfoGenerator {
|
||||
if (text.indexOf('#') == -1) {
|
||||
text = "#" + text;
|
||||
}
|
||||
PsiElement target = JavaDocUtil.findReferenceTarget(PsiManager.getInstance(myProject), text, myElement);
|
||||
PsiElement target = null;
|
||||
try {
|
||||
target = JavaDocUtil.findReferenceTarget(PsiManager.getInstance(myProject), text, myElement);
|
||||
}
|
||||
catch (IndexNotReadyException e) {
|
||||
LOG.debug(e);
|
||||
}
|
||||
if (target instanceof PsiField) {
|
||||
valueField = (PsiField) target;
|
||||
}
|
||||
@@ -1846,8 +1867,19 @@ public class JavaDocInfoGenerator {
|
||||
label = JavaDocUtil.getLabelText(manager.getProject(), manager, refText, context);
|
||||
}
|
||||
LOG.assertTrue(refText != null, "refText appears to be null.");
|
||||
PsiElement target = JavaDocUtil.findReferenceTarget(context.getManager(), refText, context);
|
||||
if (target == null) {
|
||||
PsiElement target = null;
|
||||
boolean resolveNotPossible = false;
|
||||
try {
|
||||
target = JavaDocUtil.findReferenceTarget(context.getManager(), refText, context);
|
||||
}
|
||||
catch (IndexNotReadyException e) {
|
||||
LOG.debug(e);
|
||||
resolveNotPossible = true;
|
||||
}
|
||||
if (resolveNotPossible) {
|
||||
buffer.append(label);
|
||||
}
|
||||
else if (target == null) {
|
||||
buffer.append("<font color=red>").append(label).append("</font>");
|
||||
}
|
||||
else {
|
||||
@@ -1911,7 +1943,16 @@ public class JavaDocInfoGenerator {
|
||||
}
|
||||
|
||||
if (type instanceof PsiClassType) {
|
||||
PsiClassType.ClassResolveResult result = ((PsiClassType)type).resolveGenerics();
|
||||
PsiClassType.ClassResolveResult result;
|
||||
try {
|
||||
result = ((PsiClassType)type).resolveGenerics();
|
||||
}
|
||||
catch (IndexNotReadyException e) {
|
||||
LOG.debug(e);
|
||||
String text = ((PsiClassType)type).getClassName();
|
||||
buffer.append(StringUtil.escapeXml(text));
|
||||
return text.length();
|
||||
}
|
||||
PsiClass psiClass = result.getElement();
|
||||
PsiSubstitutor psiSubst = result.getSubstitutor();
|
||||
|
||||
@@ -2080,24 +2121,28 @@ public class JavaDocInfoGenerator {
|
||||
PsiMethod method,
|
||||
DocTagLocator<T> loc,
|
||||
Set<PsiClass> visitedClasses) {
|
||||
for (PsiClassType superType : supers) {
|
||||
PsiClass aSuper = superType.resolve();
|
||||
if (aSuper != null) {
|
||||
Pair<T, InheritDocProvider<T>> tag = searchDocTagInOverriddenMethod(method, aSuper, loc);
|
||||
if (tag != null) return tag;
|
||||
try {
|
||||
for (PsiClassType superType : supers) {
|
||||
PsiClass aSuper = superType.resolve();
|
||||
if (aSuper != null) {
|
||||
Pair<T, InheritDocProvider<T>> tag = searchDocTagInOverriddenMethod(method, aSuper, loc);
|
||||
if (tag != null) return tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (PsiClassType superType : supers) {
|
||||
PsiClass aSuper = superType.resolve();
|
||||
if (aSuper != null && visitedClasses.add(aSuper)) {
|
||||
Pair<T, InheritDocProvider<T>> tag = findInheritDocTagInClass(method, aSuper, loc, visitedClasses);
|
||||
if (tag != null) {
|
||||
return tag;
|
||||
for (PsiClassType superType : supers) {
|
||||
PsiClass aSuper = superType.resolve();
|
||||
if (aSuper != null && visitedClasses.add(aSuper)) {
|
||||
Pair<T, InheritDocProvider<T>> tag = findInheritDocTagInClass(method, aSuper, loc, visitedClasses);
|
||||
if (tag != null) {
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch (IndexNotReadyException e) {
|
||||
LOG.debug(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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,6 +16,7 @@
|
||||
package com.intellij.codeInsight.javadoc;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.IndexNotReadyException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
@@ -269,13 +270,26 @@ public class JavaDocUtil {
|
||||
if (qName == null) return shortName;
|
||||
|
||||
final PsiManager manager = aClass.getManager();
|
||||
return manager.areElementsEquivalent(aClass, JavaPsiFacade.getInstance(manager.getProject()).getResolveHelper().resolveReferencedClass(shortName, context))
|
||||
PsiClass resolvedClass = null;
|
||||
try {
|
||||
resolvedClass = JavaPsiFacade.getInstance(manager.getProject()).getResolveHelper().resolveReferencedClass(shortName, context);
|
||||
}
|
||||
catch (IndexNotReadyException e) {
|
||||
LOG.debug(e);
|
||||
}
|
||||
return manager.areElementsEquivalent(aClass, resolvedClass)
|
||||
? shortName
|
||||
: StringUtil.trimStart(qName, "java.lang.");
|
||||
}
|
||||
|
||||
public static String getLabelText(Project project, PsiManager manager, String refText, PsiElement context) {
|
||||
PsiElement refElement = findReferenceTarget(manager, refText, context, false);
|
||||
PsiElement refElement = null;
|
||||
try {
|
||||
refElement = findReferenceTarget(manager, refText, context, false);
|
||||
}
|
||||
catch (IndexNotReadyException e) {
|
||||
LOG.debug(e);
|
||||
}
|
||||
if (refElement == null) {
|
||||
return refText.replaceFirst("^#", "").replaceAll("#", ".");
|
||||
}
|
||||
@@ -304,7 +318,13 @@ public class JavaDocUtil {
|
||||
String memberText = refText.substring(poundIndex + 1);
|
||||
String memberLabel = getMemberLabelText(project, manager, memberText, context);
|
||||
if (!classRef.isEmpty()) {
|
||||
PsiElement refClass = findReferenceTarget(manager, classRef, context);
|
||||
PsiElement refClass = null;
|
||||
try {
|
||||
refClass = findReferenceTarget(manager, classRef, context);
|
||||
}
|
||||
catch (IndexNotReadyException e) {
|
||||
LOG.debug(e);
|
||||
}
|
||||
if (refClass instanceof PsiClass) {
|
||||
PsiElement scope = context;
|
||||
while (true) {
|
||||
|
||||
@@ -66,8 +66,8 @@ public class ComparisonFailureData {
|
||||
public ComparisonFailureData(String expected, String actual, String filePath, String actualFilePath) {
|
||||
myExpected = expected;
|
||||
myActual = actual;
|
||||
myFilePath = filePath;
|
||||
myActualFilePath = actualFilePath;
|
||||
myFilePath = filePath != null ? new File(filePath).getAbsolutePath() : null;
|
||||
myActualFilePath = actualFilePath != null ? new File(actualFilePath).getAbsolutePath() : null;
|
||||
}
|
||||
|
||||
public static void registerSMAttributes(ComparisonFailureData notification,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// "Replace with new Thread() with lambda argument" "true"
|
||||
// "Replace with new Thread(() -> {…})" "true"
|
||||
public class Main {
|
||||
public void testThread() {
|
||||
// Comment outside
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// "Replace with new Thread() with lambda argument" "true"
|
||||
// "Replace with new Thread(() -> {…})" "true"
|
||||
public class Main {
|
||||
public void testThread() {
|
||||
new <caret>Thread() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// "Replace with new Thread() with lambda argument" "false"
|
||||
// "Replace with new Thread(() -> {…})" "false"
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// "Replace with new Thread() with lambda argument" "false"
|
||||
// "Replace with new Thread(() -> {…})" "false"
|
||||
public class Main {
|
||||
public void testThread() {
|
||||
new <caret>Thread() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// "Replace with new Thread() with lambda argument" "false"
|
||||
// "Replace with new Thread(() -> {…})" "false"
|
||||
public class Main {
|
||||
public void testThread() {
|
||||
new <caret>Thread() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// "Replace with new Thread() with lambda argument" "false"
|
||||
// "Replace with new Thread(() -> {…})" "false"
|
||||
public class Main {
|
||||
public void testThread() {
|
||||
new <caret>Thread() {
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<html><head><base href="placeholder"> <style type="text/css"> #error { background-color: #eeeeee; margin-bottom: 10px; } p { margin: 5px 0; } </style></head><body><PRE>class <b>C</b>
|
||||
extends java.lang.Object</PRE>
|
||||
some text
|
||||
|
||||
<DD><DL><DT><b>See Also:</b><DD>System.out</DD></DL></DD></body></html>
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* some text
|
||||
*
|
||||
* @see System#out
|
||||
*/
|
||||
class <caret>C {}
|
||||
@@ -1,6 +1,6 @@
|
||||
class Some {
|
||||
void m() {
|
||||
A someA = new A () {}<caret>
|
||||
A someA = new A<caret> () {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ class A {}
|
||||
class B extends A {}
|
||||
|
||||
class B1 extends B {}
|
||||
class B2 extends B {}
|
||||
class B3 extends B {}
|
||||
class B4 extends B {}
|
||||
class B5 extends B {}
|
||||
class B3 extends B {}
|
||||
class B6 extends B {}
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
class MyInheritor implement<caret>s A {
|
||||
|
||||
}
|
||||
|
||||
interface A {
|
||||
}
|
||||
|
||||
interface B extends A {}
|
||||
interface B1 extends A {}
|
||||
interface B6 extends A {}
|
||||
interface B2 extends A {}
|
||||
interface B3 extends A {}
|
||||
interface B4 extends A {}
|
||||
interface B5 extends A {}
|
||||
|
||||
interface C extends B {}
|
||||
interface C1 extends B {}
|
||||
interface C2 extends B {}
|
||||
interface C3 extends B {}
|
||||
interface C4 extends B {}
|
||||
|
||||
class D extends C {}
|
||||
@@ -1,25 +0,0 @@
|
||||
class MyInheritor implement<caret>s A {}
|
||||
|
||||
interface A {}
|
||||
|
||||
interface B extends A {}
|
||||
interface B1 extends A {}
|
||||
interface B6 extends A {}
|
||||
interface B2 extends A {}
|
||||
interface B3 extends A {}
|
||||
interface B4 extends A {}
|
||||
interface B5 extends A {}
|
||||
|
||||
interface C extends B {}
|
||||
interface C1 extends B {}
|
||||
interface C2 extends B {}
|
||||
interface C3 extends B {}
|
||||
interface C4 extends B {}
|
||||
|
||||
class D implements C {}
|
||||
|
||||
class E1 extends D {}
|
||||
class E2 extends D {}
|
||||
class E3 extends D {}
|
||||
class E4 extends D {}
|
||||
class E5 extends D {}
|
||||
@@ -1,4 +1,4 @@
|
||||
class MyInheritor extends A {
|
||||
class MyInheritor<caret> extends A {
|
||||
|
||||
}
|
||||
|
||||
@@ -18,20 +18,4 @@ class C32 extends B3 {}
|
||||
|
||||
class B4 extends A {}
|
||||
class C41 extends B4 {}
|
||||
class C42 extends B4 {}
|
||||
|
||||
class B5 extends A {}
|
||||
class C51 extends B5 {}
|
||||
class C52 extends B5 {}
|
||||
|
||||
class B6 extends A {}
|
||||
class C61 extends B6 {}
|
||||
class C62 extends B6 {}
|
||||
|
||||
class B7 extends A {}
|
||||
class C71 extends B7 {}
|
||||
class C72 extends B7 {}
|
||||
|
||||
class B8 extends A {}
|
||||
class C81 extends B8 {}
|
||||
class C82 extends B8 {}
|
||||
class C42 extends B4 {}
|
||||
@@ -103,5 +103,36 @@ class Test {
|
||||
}
|
||||
'''
|
||||
}
|
||||
|
||||
|
||||
void "test overload methods with single suggestion"() {
|
||||
TemplateManagerImpl.setTemplateTesting(project, myFixture.testRootDisposable)
|
||||
myFixture.configureByText "a.java", '''
|
||||
class Foo {}
|
||||
class Test {
|
||||
{
|
||||
foo(new Foo(), <caret>BAR);
|
||||
}
|
||||
|
||||
void foo(Foo f, String d) {}
|
||||
void foo(Foo f, String d, String d2) {}
|
||||
|
||||
}
|
||||
'''
|
||||
myFixture.launchAction(myFixture.findSingleIntention("Create constant field"))
|
||||
myFixture.checkResult '''
|
||||
class Foo {}
|
||||
class Test {
|
||||
private static final String BAR = ;
|
||||
|
||||
{
|
||||
foo(new Foo(), BAR);
|
||||
}
|
||||
|
||||
void foo(Foo f, String d) {}
|
||||
void foo(Foo f, String d, String d2) {}
|
||||
|
||||
}
|
||||
'''
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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,6 +23,7 @@ import com.intellij.lang.java.JavaDocumentationProvider;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.project.DumbServiceImpl;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.SdkModificator;
|
||||
import com.intellij.openapi.roots.ModuleRootModificationUtil;
|
||||
@@ -400,6 +401,16 @@ public class JavaDocInfoGeneratorTest extends CodeInsightTestCase {
|
||||
doTestAtCaret();
|
||||
}
|
||||
|
||||
public void testDumbMode() throws Exception {
|
||||
DumbServiceImpl.getInstance(myProject).setDumb(true);
|
||||
try {
|
||||
doTestAtCaret();
|
||||
}
|
||||
finally {
|
||||
DumbServiceImpl.getInstance(myProject).setDumb(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void doTestAtCaret() throws Exception {
|
||||
configureByFile();
|
||||
String docInfo = JavaExternalDocumentationTest.getDocumentationText(myFile, myEditor.getCaretModel().getOffset());
|
||||
|
||||
@@ -4,10 +4,11 @@ import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInsight.intention.IntentionActionDelegate;
|
||||
import com.intellij.codeInspection.ex.QuickFixWrapper;
|
||||
import com.intellij.codeInspection.inheritance.ChangeSuperClassFix;
|
||||
import com.intellij.codeInspection.inheritance.SuperClassHasFrequentlyUsedInheritorsInspection;
|
||||
import com.intellij.compiler.CompilerReferencesTestBase;
|
||||
import com.intellij.compiler.inspection.ChangeSuperClassFix;
|
||||
import com.intellij.compiler.inspection.FrequentlyUsedInheritorInspection;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
|
||||
import com.intellij.testFramework.SkipSlowTestLocally;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -15,37 +16,35 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class SuperClassHasFrequentlyUsedInheritorsInspectionTest extends JavaCodeInsightFixtureTestCase {
|
||||
@SkipSlowTestLocally
|
||||
public class FrequentlyUsedInheritorInspectionTest extends CompilerReferencesTestBase {
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
installCompiler();
|
||||
myFixture.enableInspections(FrequentlyUsedInheritorInspection.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return JavaTestUtil.getJavaTestDataPath() + "/inspection/smartInheritance/";
|
||||
}
|
||||
|
||||
//search tests
|
||||
|
||||
public void testRelevantClassShowed() {
|
||||
doTest(Pair.create("C", 75), Pair.create("B", 91));
|
||||
}
|
||||
|
||||
public void testInterfacesNotShowed() {
|
||||
assertEmptyResult();
|
||||
}
|
||||
|
||||
public void testInterfacesNotShowed2() {
|
||||
doTest(Pair.create("D", 83));
|
||||
doTest(Pair.create("B", 12));
|
||||
}
|
||||
|
||||
public void testAnonymousClasses() {
|
||||
doTest(Pair.create("B", 83));
|
||||
doTest(Pair.create("B", 7));
|
||||
}
|
||||
|
||||
public void testAnonymousClassesInStats() {
|
||||
doTest(Pair.create("A", 62));
|
||||
doTest(Pair.create("A", 6));
|
||||
}
|
||||
|
||||
public void testAbstractClass() {
|
||||
doTest(Pair.create("B", 85));
|
||||
doTest(Pair.create("B", 7));
|
||||
}
|
||||
|
||||
public void testNoCompletionForAbstractClasses() {
|
||||
@@ -53,31 +52,26 @@ public class SuperClassHasFrequentlyUsedInheritorsInspectionTest extends JavaCod
|
||||
}
|
||||
|
||||
public void testNoMoreThanMaxCountIntentions() {
|
||||
doTest(SuperClassHasFrequentlyUsedInheritorsInspection.MAX_QUICK_FIX_COUNTS);
|
||||
doTest(FrequentlyUsedInheritorInspection.MAX_RESULT);
|
||||
}
|
||||
|
||||
// completion tests
|
||||
|
||||
private void assertEmptyResult() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest(final Pair<String, Integer>... expectedResults) {
|
||||
myFixture.configureByFile(getTestName(false) + ".java");
|
||||
myFixture.enableInspections(SuperClassHasFrequentlyUsedInheritorsInspection.class);
|
||||
rebuildProject();
|
||||
|
||||
final Set<Pair<String, Integer>> actualSet = new HashSet<Pair<String, Integer>>();
|
||||
|
||||
for (Pair<String, Integer> pair : expectedResults) {
|
||||
IntentionAction action = myFixture.findSingleIntention("Make extends '" + pair.getFirst() +
|
||||
"' - " + pair.getSecond() +
|
||||
"%");
|
||||
|
||||
IntentionAction action = myFixture.findSingleIntention("Make extends '" + pair.getFirst());
|
||||
IntentionAction intentionAction = ((IntentionActionDelegate)action).getDelegate();
|
||||
if (intentionAction instanceof QuickFixWrapper) {
|
||||
ChangeSuperClassFix changeSuperClassFix = getQuickFixFromWrapper((QuickFixWrapper)intentionAction);
|
||||
if (changeSuperClassFix != null) {
|
||||
actualSet.add(Pair.create(changeSuperClassFix.getNewSuperClass().getQualifiedName(), changeSuperClassFix.getPercent()));
|
||||
actualSet.add(Pair.create(changeSuperClassFix.getNewSuperClass().getQualifiedName(), changeSuperClassFix.getInheritorCount()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,7 +81,7 @@ public class SuperClassHasFrequentlyUsedInheritorsInspectionTest extends JavaCod
|
||||
|
||||
private void doTest(final int expectedSize) {
|
||||
myFixture.configureByFile(getTestName(false) + ".java");
|
||||
myFixture.enableInspections(SuperClassHasFrequentlyUsedInheritorsInspection.class);
|
||||
rebuildProject();
|
||||
|
||||
List<IntentionAction> actions = myFixture.filterAvailableIntentions("Make extends '");
|
||||
|
||||
@@ -41,6 +41,8 @@ public interface LightRef extends RW.Savable {
|
||||
}
|
||||
|
||||
interface LightClassHierarchyElementDef extends NamedLightRef {
|
||||
LightClassHierarchyElementDef[] EMPTY_ARRAY = new LightClassHierarchyElementDef[0];
|
||||
|
||||
}
|
||||
|
||||
interface LightAnonymousClassDef extends LightClassHierarchyElementDef {
|
||||
|
||||
@@ -25,6 +25,8 @@ import java.awt.*;
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public static final int NO_GRAPHICS = 1;
|
||||
@@ -46,6 +48,8 @@ public class Main {
|
||||
private static boolean isHeadless;
|
||||
private static boolean isCommandLine;
|
||||
private static boolean hasGraphics = true;
|
||||
private static final List<String> HEADLESS_COMMANDS = Arrays.asList("ant", "duplocate", "traverseUI", "buildAppcodeCache", "format",
|
||||
"keymap", "update", "inspections", "intentions");
|
||||
|
||||
private Main() { }
|
||||
|
||||
@@ -107,15 +111,8 @@ public class Main {
|
||||
}
|
||||
|
||||
String firstArg = args[0];
|
||||
return Comparing.strEqual(firstArg, "ant") ||
|
||||
Comparing.strEqual(firstArg, "duplocate") ||
|
||||
Comparing.strEqual(firstArg, "traverseUI") ||
|
||||
Comparing.strEqual(firstArg, "buildAppcodeCache") ||
|
||||
Comparing.strEqual(firstArg, "format") ||
|
||||
Comparing.strEqual(firstArg, "keymap") ||
|
||||
Comparing.strEqual(firstArg, "inspections") ||
|
||||
Comparing.strEqual(firstArg, "intentions") ||
|
||||
firstArg.length() < 20 && firstArg.endsWith("inspect");
|
||||
return HEADLESS_COMMANDS.contains(firstArg)
|
||||
|| firstArg.length() < 20 && firstArg.endsWith("inspect");
|
||||
}
|
||||
|
||||
private static boolean isCommandLine(String[] args) {
|
||||
|
||||
@@ -88,7 +88,10 @@ class BuildTasksImpl extends BuildTasks {
|
||||
}
|
||||
}
|
||||
|
||||
void buildSearchableOptions(File targetDirectory, List<String> modulesToIndex, List<String> pathsToLicenses) {
|
||||
/**
|
||||
* Build index which is used to search options in the Settings dialog.
|
||||
*/
|
||||
void buildSearchableOptionsIndex(File targetDirectory, List<String> modulesToIndex, List<String> pathsToLicenses) {
|
||||
buildContext.executeStep("Build searchable options index", BuildOptions.SEARCHABLE_OPTIONS_INDEX_STEP, {
|
||||
def javaRuntimeClasses = "${buildContext.projectBuilder.moduleOutput(buildContext.findModule("java-runtime"))}"
|
||||
if (!new File(javaRuntimeClasses).exists()) {
|
||||
@@ -115,6 +118,8 @@ class BuildTasksImpl extends BuildTasks {
|
||||
String classpathFile = "$tempDir/classpath.txt"
|
||||
new File(classpathFile).text = ideClasspath.join("\n")
|
||||
|
||||
//Start the product in headless mode using com.intellij.ide.ui.search.TraverseUIStarter. It'll process all UI elements in Settings dialog
|
||||
// and build index for them.
|
||||
buildContext.ant.java(classname: "com.intellij.rt.execution.CommandLineWrapper", fork: true, failonerror: true) {
|
||||
jvmarg(line: "-ea -Xmx500m")
|
||||
jvmarg(value: "-Xbootclasspath/a:${buildContext.projectBuilder.moduleOutput(buildContext.findModule("boot"))}")
|
||||
|
||||
@@ -209,7 +209,7 @@ class DistributionJARsBuilder {
|
||||
|
||||
//todo[nik] move buildSearchableOptions and patchedApplicationInfo methods to this class
|
||||
def buildTasks = new BuildTasksImpl(buildContext)
|
||||
buildTasks.buildSearchableOptions(searchableOptionsDir, productLayout.mainModules, productLayout.licenseFilesToBuildSearchableOptions)
|
||||
buildTasks.buildSearchableOptionsIndex(searchableOptionsDir, productLayout.mainModules, productLayout.licenseFilesToBuildSearchableOptions)
|
||||
if (!buildContext.options.buildStepsToSkip.contains(BuildOptions.SEARCHABLE_OPTIONS_INDEX_STEP)) {
|
||||
layoutBuilder.patchModuleOutput(productLayout.searchableOptionsModule, FileUtil.toSystemIndependentName(searchableOptionsDir.absolutePath))
|
||||
}
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="kotlin-language" name="Kotlin">
|
||||
<configuration version="2" platform="JVM 1.8" useProjectSettings="false">
|
||||
<compilerSettings />
|
||||
<compilerArguments>
|
||||
<option name="jvmTarget" value="1.8" />
|
||||
<option name="languageVersion" value="1.1" />
|
||||
<option name="apiVersion" value="1.1" />
|
||||
<option name="coroutinesError" value="true" />
|
||||
</compilerArguments>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.intellij.openapi.components.impl.stores.StoreUtil
|
||||
import com.intellij.openapi.diagnostic.catchAndLog
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import com.intellij.openapi.module.impl.ModuleManagerImpl
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.ProjectCoreUtil
|
||||
import com.intellij.openapi.project.ex.ProjectNameProvider
|
||||
@@ -431,7 +432,7 @@ private fun removeWorkspaceComponentConfiguration(defaultProject: Project, eleme
|
||||
}
|
||||
}
|
||||
|
||||
ServiceManagerImpl.processAllImplementationClasses(defaultProject as ProjectImpl) { aClass, pluginDescriptor ->
|
||||
ServiceManagerImpl.processAllImplementationClasses(defaultProject as ProjectImpl) { aClass, _ ->
|
||||
getNameIfWorkspaceStorage(aClass)?.let {
|
||||
workspaceComponentNames.add(it)
|
||||
}
|
||||
@@ -481,12 +482,17 @@ fun normalizeDefaultProjectElement(defaultProject: Project, element: Element, pr
|
||||
component.removeChild("version")
|
||||
writeProfileSettings(schemeDir)
|
||||
}
|
||||
|
||||
"CopyrightManager" -> {
|
||||
iterator.remove()
|
||||
val schemeDir = projectConfigDir.resolve("copyright")
|
||||
convertProfiles(component.getChildren("copyright").iterator(), componentName, schemeDir)
|
||||
writeProfileSettings(schemeDir)
|
||||
}
|
||||
|
||||
ModuleManagerImpl.COMPONENT_NAME -> {
|
||||
iterator.remove()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,6 +161,15 @@ internal class DefaultProjectStoreTest {
|
||||
</state>
|
||||
</states>
|
||||
</component>
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://USER_HOME$/PycharmProjects/ttt002/.idea/ttt002.iml" filepath="USER_HOME$/PycharmProjects/ttt002/.idea/ttt002.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
<component name="PropertiesComponent">
|
||||
<property name="settings.editor.selected.configurable" value="preferences.lookFeel" />
|
||||
<property name="settings.editor.splitter.proportion" value="0.2" />
|
||||
</component>
|
||||
</state>""")
|
||||
|
||||
val tempDir = fsRule.fs.getPath("")
|
||||
|
||||
@@ -10,6 +10,8 @@ internal class AState : BaseState() {
|
||||
@get:Attribute("customName")
|
||||
var languageLevel by storedProperty<String?>()
|
||||
|
||||
var bar by string()
|
||||
|
||||
var property2 by storedProperty(0)
|
||||
|
||||
var floatProperty by storedProperty(0.3)
|
||||
@@ -37,6 +39,10 @@ class StoredPropertyStateTest {
|
||||
|
||||
assertThat(state).isNotEqualTo(AState())
|
||||
|
||||
val newEqualState = AState()
|
||||
newEqualState.languageLevel = String("foo".toCharArray())
|
||||
assertThat(state).isEqualTo(newEqualState)
|
||||
|
||||
assertThat(state.serialize()).isEqualTo("""<AState customName="foo" />""")
|
||||
assertThat(loadElement("""<AState customName="foo" />""").deserialize(AState::class.java).languageLevel).isEqualTo("foo")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.intellij.configurationStore
|
||||
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class ResourceLoader(id: String) : ReadOnlyProperty<MyUI, String> {
|
||||
operator fun provideDelegate(thisRef: MyUI, prop: KProperty<*>): ReadOnlyProperty<MyUI, String> {
|
||||
checkProperty(thisRef, prop.name)
|
||||
return this
|
||||
}
|
||||
|
||||
override fun getValue(thisRef: MyUI, property: KProperty<*>): String {
|
||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
private fun checkProperty(thisRef: MyUI, name: String) {}
|
||||
}
|
||||
|
||||
fun bindResource(id: String): ResourceLoader {
|
||||
return ResourceLoader(id)
|
||||
}
|
||||
|
||||
class MyUI {
|
||||
val image by bindResource("f")
|
||||
val text by bindResource("d")
|
||||
}
|
||||
|
||||
fun main(a: Array<String>) {
|
||||
MyUI()
|
||||
}
|
||||
@@ -29,6 +29,8 @@ public interface Iconable {
|
||||
@Deprecated int ICON_FLAG_OPEN = 0x0004;
|
||||
@Deprecated int ICON_FLAG_CLOSED = 0x0008;
|
||||
|
||||
Key<Integer> ICON_FLAG_IGNORE_MASK = new Key<>("ICON_FLAG_IGNORE_MASK");
|
||||
|
||||
@MagicConstant(flags = {ICON_FLAG_VISIBILITY, ICON_FLAG_READ_STATUS})
|
||||
@interface IconFlags {}
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ public class IconUtil {
|
||||
|
||||
private static final NullableFunction<FileIconKey, Icon> ICON_NULLABLE_FUNCTION = key -> {
|
||||
final VirtualFile file = key.getFile();
|
||||
final int flags = key.getFlags();
|
||||
final int flags = filterFileIconFlags(file, key.getFlags());
|
||||
final Project project = key.getProject();
|
||||
|
||||
if (!file.isValid() || project != null && (project.isDisposed() || !wasEverInitialized(project))) return null;
|
||||
@@ -163,6 +163,15 @@ public class IconUtil {
|
||||
return icon;
|
||||
};
|
||||
|
||||
@Iconable.IconFlags
|
||||
private static int filterFileIconFlags(@NotNull VirtualFile file, @Iconable.IconFlags int flags) {
|
||||
UserDataHolder fileTypeDataHolder = ObjectUtils.tryCast(file.getFileType(), UserDataHolder.class);
|
||||
int fileTypeFlagIgnoreMask = Iconable.ICON_FLAG_IGNORE_MASK.get(fileTypeDataHolder, 0);
|
||||
int flagIgnoreMask = Iconable.ICON_FLAG_IGNORE_MASK.get(file, fileTypeFlagIgnoreMask);
|
||||
//noinspection MagicConstant
|
||||
return flags & ~flagIgnoreMask;
|
||||
}
|
||||
|
||||
public static Icon getIcon(@NotNull final VirtualFile file, @Iconable.IconFlags final int flags, @Nullable final Project project) {
|
||||
Icon lastIcon = Iconable.LastComputedIcon.get(file, flags);
|
||||
|
||||
|
||||
@@ -156,6 +156,8 @@ public class ExternalSystemNotificationManager implements Disposable {
|
||||
public void showNotification(@NotNull final ProjectSystemId externalSystemId,
|
||||
@NotNull final NotificationData notificationData,
|
||||
@Nullable Key<String> notificationKey) {
|
||||
if(ApplicationManager.getApplication().isUnitTestMode()) return;
|
||||
|
||||
if (notificationKey != null && isNotificationActive(notificationKey)) return;
|
||||
myUpdater.submit(() -> {
|
||||
if (myProject.isDisposed()) return;
|
||||
@@ -221,6 +223,8 @@ public class ExternalSystemNotificationManager implements Disposable {
|
||||
@NotNull final NotificationSource notificationSource,
|
||||
@NotNull final ProjectSystemId externalSystemId) {
|
||||
myMessageCounter.remove(groupName, notificationSource, externalSystemId);
|
||||
if(ApplicationManager.getApplication().isUnitTestMode()) return;
|
||||
|
||||
myUpdater.submit(() -> {
|
||||
if (myProject.isDisposed()) return;
|
||||
for (Iterator<Notification> iterator = myNotifications.iterator(); iterator.hasNext(); ) {
|
||||
|
||||
|
Before Width: | Height: | Size: 397 B After Width: | Height: | Size: 362 B |
|
Before Width: | Height: | Size: 907 B After Width: | Height: | Size: 713 B |
|
After Width: | Height: | Size: 661 B |
|
After Width: | Height: | Size: 328 B |
|
Before Width: | Height: | Size: 565 B After Width: | Height: | Size: 298 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 580 B |
|
After Width: | Height: | Size: 666 B |
|
After Width: | Height: | Size: 343 B |
|
Before Width: | Height: | Size: 394 B After Width: | Height: | Size: 442 B |
|
Before Width: | Height: | Size: 932 B After Width: | Height: | Size: 995 B |
|
Before Width: | Height: | Size: 899 B After Width: | Height: | Size: 929 B |
|
Before Width: | Height: | Size: 375 B After Width: | Height: | Size: 426 B |
|
Before Width: | Height: | Size: 460 B After Width: | Height: | Size: 431 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 824 B |
|
After Width: | Height: | Size: 851 B |
|
After Width: | Height: | Size: 382 B |
@@ -28,7 +28,6 @@ import com.intellij.ide.ui.laf.darcula.DarculaLookAndFeelInfo;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.DataProvider;
|
||||
import com.intellij.openapi.application.ApplicationBundle;
|
||||
import com.intellij.openapi.application.ApplicationNamesInfo;
|
||||
import com.intellij.openapi.editor.colors.*;
|
||||
@@ -41,6 +40,7 @@ import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.options.SchemeManager;
|
||||
import com.intellij.openapi.options.SearchableConfigurable;
|
||||
import com.intellij.openapi.options.ShowSettingsUtil;
|
||||
import com.intellij.openapi.options.colors.*;
|
||||
import com.intellij.openapi.options.ex.Settings;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -76,6 +76,9 @@ import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static com.intellij.openapi.actionSystem.CommonDataKeys.PROJECT;
|
||||
import static com.intellij.openapi.actionSystem.PlatformDataKeys.CONTEXT_COMPONENT;
|
||||
|
||||
public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract
|
||||
implements EditorOptionsProvider, SchemesModel<EditorColorsScheme> {
|
||||
public static final String ID = "reference.settingsdialog.IDE.editor.colors";
|
||||
@@ -1417,23 +1420,53 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract
|
||||
}
|
||||
}
|
||||
|
||||
public static Runnable getColorSelector(DataProvider provider, String search, String name) {
|
||||
return getSelector(Settings.KEY.getData(provider), search, options -> options.findSubConfigurable(name));
|
||||
public static boolean selectOrEditColor(DataContext context, String search, String name) {
|
||||
return selectOrEdit(context, search, options -> options.findSubConfigurable(name));
|
||||
}
|
||||
|
||||
public static Runnable getColorSelector(DataContext context, String search, Class<?> type) {
|
||||
return getSelector(Settings.KEY.getData(context), search, options -> options.findSubConfigurable(type));
|
||||
public static boolean selectOrEditColor(DataContext context, String search, Class<?> type) {
|
||||
return selectOrEdit(context, search, options -> options.findSubConfigurable(type));
|
||||
}
|
||||
|
||||
private static Runnable getSelector(Settings settings, String search, Function<ColorAndFontOptions, SearchableConfigurable> function) {
|
||||
if (settings == null) return null;
|
||||
private static boolean selectOrEdit(DataContext context, String search, Function<ColorAndFontOptions, SearchableConfigurable> function) {
|
||||
return select(context, search, function) || edit(context, search, function);
|
||||
}
|
||||
|
||||
private static boolean select(DataContext context, String search, Function<ColorAndFontOptions, SearchableConfigurable> function) {
|
||||
Settings settings = Settings.KEY.getData(context);
|
||||
if (settings == null) return false;
|
||||
|
||||
ColorAndFontOptions options = settings.find(ColorAndFontOptions.class);
|
||||
if (options == null) return null;
|
||||
if (options == null) return false;
|
||||
|
||||
SearchableConfigurable page = function.apply(options);
|
||||
if (page == null) return null;
|
||||
if (page == null) return false;
|
||||
|
||||
return () -> settings.select(page, search);
|
||||
settings.select(page, search);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean edit(DataContext context, String search, Function<ColorAndFontOptions, SearchableConfigurable> function) {
|
||||
ColorAndFontOptions options = new ColorAndFontOptions();
|
||||
SearchableConfigurable page = function.apply(options);
|
||||
|
||||
Configurable[] configurables = options.getConfigurables();
|
||||
try {
|
||||
if (page != null) {
|
||||
Runnable runnable = search == null ? null : page.enableSearch(search);
|
||||
Window window = UIUtil.getWindow(CONTEXT_COMPONENT.getData(context));
|
||||
if (window != null) {
|
||||
ShowSettingsUtil.getInstance().editConfigurable(window, page, runnable);
|
||||
}
|
||||
else {
|
||||
ShowSettingsUtil.getInstance().editConfigurable(PROJECT.getData(context), page, runnable);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
for (Configurable configurable : configurables) configurable.disposeUIResources();
|
||||
options.disposeUIResources();
|
||||
}
|
||||
return page != null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package com.intellij.application.options.colors;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||
import com.intellij.codeInsight.hint.HintManager;
|
||||
import com.intellij.ide.actions.ShowSettingsUtilImpl;
|
||||
import com.intellij.injected.editor.EditorWindow;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
@@ -39,7 +38,6 @@ import com.intellij.openapi.fileTypes.SyntaxHighlighter;
|
||||
import com.intellij.openapi.options.colors.AttributesDescriptor;
|
||||
import com.intellij.openapi.options.colors.ColorSettingsPage;
|
||||
import com.intellij.openapi.options.colors.ColorSettingsPages;
|
||||
import com.intellij.openapi.options.newEditor.SettingsDialog;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
@@ -62,7 +60,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.intellij.application.options.colors.ColorAndFontOptions.getColorSelector;
|
||||
import static com.intellij.application.options.colors.ColorAndFontOptions.selectOrEditColor;
|
||||
import static com.intellij.ui.SimpleTextAttributes.*;
|
||||
|
||||
/**
|
||||
@@ -185,12 +183,6 @@ public class JumpToColorsAndFontsAction extends DumbAwareAction {
|
||||
}
|
||||
|
||||
private static boolean openSettingsAndSelectKey(@NotNull Project project, @NotNull ColorSettingsPage page, @NotNull AttributesDescriptor descriptor) {
|
||||
SettingsDialog dialog = (SettingsDialog)ShowSettingsUtilImpl.getDialog(
|
||||
project, ShowSettingsUtilImpl.getConfigurableGroups(project, true), null);
|
||||
Runnable selector = getColorSelector(dialog, descriptor.getDisplayName(), page.getDisplayName());
|
||||
if (selector == null) return false;
|
||||
selector.run();
|
||||
dialog.show();
|
||||
return true;
|
||||
return selectOrEditColor(id -> CommonDataKeys.PROJECT.is(id) ? project : null, descriptor.getDisplayName(), page.getDisplayName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package com.intellij.codeInspection.ex;
|
||||
|
||||
import com.intellij.application.options.colors.ColorAndFontDescriptionPanel;
|
||||
import com.intellij.application.options.colors.ColorAndFontOptions;
|
||||
import com.intellij.application.options.colors.InspectionColorSettingsPage;
|
||||
import com.intellij.application.options.colors.TextAttributesDescription;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
|
||||
@@ -27,15 +26,11 @@ import com.intellij.codeInspection.InspectionsBundle;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.colors.CodeInsightColors;
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.options.SearchableConfigurable;
|
||||
import com.intellij.openapi.options.ShowSettingsUtil;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.InputValidator;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
@@ -57,6 +52,7 @@ import java.awt.event.ActionListener;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.application.options.colors.ColorAndFontOptions.selectOrEditColor;
|
||||
import static com.intellij.codeInsight.daemon.impl.SeverityRegistrar.SeverityBasedTextAttributes;
|
||||
|
||||
/**
|
||||
@@ -237,25 +233,7 @@ public class SeverityEditorDialog extends DialogWrapper {
|
||||
}
|
||||
myOptionsList.clearSelection();
|
||||
final DataContext dataContext = DataManager.getInstance().getDataContext(myPanel);
|
||||
Runnable selector = ColorAndFontOptions.getColorSelector(dataContext, toConfigure, InspectionColorSettingsPage.class);
|
||||
if (selector != null) {
|
||||
selector.run();
|
||||
}
|
||||
else {
|
||||
ColorAndFontOptions colorAndFontOptions = new ColorAndFontOptions();
|
||||
final Configurable[] configurables = colorAndFontOptions.buildConfigurables();
|
||||
try {
|
||||
final SearchableConfigurable javaPage = colorAndFontOptions.findSubConfigurable(InspectionColorSettingsPage.class);
|
||||
LOG.assertTrue(javaPage != null);
|
||||
ShowSettingsUtil.getInstance().editConfigurable(CommonDataKeys.PROJECT.getData(dataContext), javaPage);
|
||||
}
|
||||
finally {
|
||||
for (Configurable configurable : configurables) {
|
||||
configurable.disposeUIResources();
|
||||
}
|
||||
colorAndFontOptions.disposeUIResources();
|
||||
}
|
||||
}
|
||||
selectOrEditColor(dataContext, toConfigure, InspectionColorSettingsPage.class);
|
||||
}
|
||||
|
||||
private void fillList(final @Nullable HighlightSeverity severity) {
|
||||
|
||||
@@ -517,14 +517,20 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
|
||||
public void waitAllRequests() {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
Future<?> future = ApplicationManager.getApplication().executeOnPooledThread(() -> {
|
||||
try {
|
||||
myFlushAlarm.waitForAllExecuted(10, TimeUnit.SECONDS);
|
||||
myFlushUserInputAlarm.waitForAllExecuted(10, TimeUnit.SECONDS);
|
||||
myFlushAlarm.waitForAllExecuted(10, TimeUnit.SECONDS);
|
||||
myFlushUserInputAlarm.waitForAllExecuted(10, TimeUnit.SECONDS);
|
||||
}
|
||||
catch (InterruptedException | ExecutionException | TimeoutException e) {
|
||||
throw new RuntimeException(e);
|
||||
while (true) {
|
||||
try {
|
||||
myFlushAlarm.waitForAllExecuted(10, TimeUnit.SECONDS);
|
||||
myFlushUserInputAlarm.waitForAllExecuted(10, TimeUnit.SECONDS);
|
||||
myFlushAlarm.waitForAllExecuted(10, TimeUnit.SECONDS);
|
||||
myFlushUserInputAlarm.waitForAllExecuted(10, TimeUnit.SECONDS);
|
||||
return;
|
||||
}
|
||||
catch (CancellationException e) {
|
||||
//try again
|
||||
}
|
||||
catch (InterruptedException | ExecutionException | TimeoutException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
try {
|
||||
|
||||
@@ -147,7 +147,7 @@ public class InspectionsConfigTreeTable extends TreeTable {
|
||||
case IS_ENABLED_COLUMN:
|
||||
if (Registry.is("ide.intellij.laf.win10.ui")) {
|
||||
JComponent rc = (JComponent)getColumnModel().getColumn(column).getCellRenderer();
|
||||
rc.putClientProperty("ThreeStateCheckBoxRenderer.rolloverRow", row);
|
||||
rc.putClientProperty(UIUtil.CHECKBOX_ROLLOVER_PROPERTY, row);
|
||||
((AbstractTableModel)getModel()).fireTableCellUpdated(row, column);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2025,70 +2025,72 @@ public class FileBasedIndexImpl extends FileBasedIndex implements BaseComponent,
|
||||
|
||||
@Override
|
||||
public boolean processFile(@NotNull final VirtualFile file) {
|
||||
if (!file.isValid()) {
|
||||
return true;
|
||||
}
|
||||
if (file instanceof VirtualFileSystemEntry && ((VirtualFileSystemEntry)file).isFileIndexed()) {
|
||||
return true;
|
||||
}
|
||||
try (AccessToken ignore = ReadAction.start()) {
|
||||
if (!file.isValid()) {
|
||||
return true;
|
||||
}
|
||||
if (file instanceof VirtualFileSystemEntry && ((VirtualFileSystemEntry)file).isFileIndexed()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(file instanceof VirtualFileWithId)) {
|
||||
return true;
|
||||
}
|
||||
myFileTypeManager.freezeFileTypeTemporarilyIn(file, () -> {
|
||||
boolean oldStuff = true;
|
||||
if (file.isDirectory() || !isTooLarge(file)) {
|
||||
final List<ID<?, ?>> affectedIndexCandidates = getAffectedIndexCandidates(file);
|
||||
//noinspection ForLoopReplaceableByForEach
|
||||
for (int i = 0, size = affectedIndexCandidates.size(); i < size; ++i) {
|
||||
final ID<?, ?> indexId = affectedIndexCandidates.get(i);
|
||||
try {
|
||||
if (needsFileContentLoading(indexId) && shouldIndexFile(file, indexId)) {
|
||||
if (myDoTraceForFilesToBeIndexed) {
|
||||
LOG.info("Scheduling indexing of " + file + " by request of index " + indexId);
|
||||
if (!(file instanceof VirtualFileWithId)) {
|
||||
return true;
|
||||
}
|
||||
myFileTypeManager.freezeFileTypeTemporarilyIn(file, () -> {
|
||||
boolean oldStuff = true;
|
||||
if (file.isDirectory() || !isTooLarge(file)) {
|
||||
final List<ID<?, ?>> affectedIndexCandidates = getAffectedIndexCandidates(file);
|
||||
//noinspection ForLoopReplaceableByForEach
|
||||
for (int i = 0, size = affectedIndexCandidates.size(); i < size; ++i) {
|
||||
final ID<?, ?> indexId = affectedIndexCandidates.get(i);
|
||||
try {
|
||||
if (needsFileContentLoading(indexId) && shouldIndexFile(file, indexId)) {
|
||||
if (myDoTraceForFilesToBeIndexed) {
|
||||
LOG.info("Scheduling indexing of " + file + " by request of index " + indexId);
|
||||
}
|
||||
synchronized (myFiles) {
|
||||
myFiles.add(file);
|
||||
}
|
||||
oldStuff = false;
|
||||
break;
|
||||
}
|
||||
synchronized (myFiles) {
|
||||
myFiles.add(file);
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
final Throwable cause = e.getCause();
|
||||
if (cause instanceof IOException || cause instanceof StorageException) {
|
||||
LOG.info(e);
|
||||
requestRebuild(indexId);
|
||||
}
|
||||
else {
|
||||
throw e;
|
||||
}
|
||||
oldStuff = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
final Throwable cause = e.getCause();
|
||||
if (cause instanceof IOException || cause instanceof StorageException) {
|
||||
LOG.info(e);
|
||||
requestRebuild(indexId);
|
||||
}
|
||||
else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
FileContent fileContent = null;
|
||||
int inputId = Math.abs(getIdMaskingNonIdBasedFile(file));
|
||||
for (ID<?, ?> indexId : myNotRequiringContentIndices) {
|
||||
if (shouldIndexFile(file, indexId)) {
|
||||
oldStuff = false;
|
||||
if (fileContent == null) {
|
||||
fileContent = new FileContentImpl(file);
|
||||
FileContent fileContent = null;
|
||||
int inputId = Math.abs(getIdMaskingNonIdBasedFile(file));
|
||||
for (ID<?, ?> indexId : myNotRequiringContentIndices) {
|
||||
if (shouldIndexFile(file, indexId)) {
|
||||
oldStuff = false;
|
||||
if (fileContent == null) {
|
||||
fileContent = new FileContentImpl(file);
|
||||
}
|
||||
updateSingleIndex(indexId, file, inputId, fileContent);
|
||||
}
|
||||
updateSingleIndex(indexId, file, inputId, fileContent);
|
||||
}
|
||||
}
|
||||
IndexingStamp.flushCache(inputId);
|
||||
IndexingStamp.flushCache(inputId);
|
||||
|
||||
if (oldStuff && file instanceof VirtualFileSystemEntry) {
|
||||
((VirtualFileSystemEntry)file).setFileIndexed(true);
|
||||
}
|
||||
});
|
||||
if (oldStuff && file instanceof VirtualFileSystemEntry) {
|
||||
((VirtualFileSystemEntry)file).setFileIndexed(true);
|
||||
}
|
||||
});
|
||||
|
||||
if (myProgressIndicator != null && file.isDirectory()) { // once for dir is cheap enough
|
||||
myProgressIndicator.checkCanceled();
|
||||
myProgressIndicator.setText("Scanning files to index");
|
||||
if (myProgressIndicator != null && file.isDirectory()) { // once for dir is cheap enough
|
||||
myProgressIndicator.checkCanceled();
|
||||
myProgressIndicator.setText("Scanning files to index");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
package com.intellij.util.indexing;
|
||||
|
||||
import com.intellij.openapi.application.AccessToken;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
@@ -126,10 +125,6 @@ public class FileBasedIndexScanRunnableCollectorImpl extends FileBasedIndexScanR
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0, size = tasks.size(); i < size; ++i) {
|
||||
Runnable runnable = tasks.get(i);
|
||||
tasks.set(i, () -> ApplicationManager.getApplication().runReadAction(runnable));
|
||||
}
|
||||
return tasks;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public abstract class ShowSettingsUtil {
|
||||
|
||||
public abstract boolean editConfigurable(@Nullable Component parent, @NotNull Configurable configurable);
|
||||
|
||||
public abstract boolean editConfigurable(Component parent, Configurable configurable, @NotNull Runnable advancedInitialization);
|
||||
public abstract boolean editConfigurable(Component parent, Configurable configurable, Runnable advancedInitialization);
|
||||
|
||||
public abstract boolean editConfigurable(Project project, @NonNls String dimensionServiceKey, Configurable configurable);
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ package com.intellij.ide.plugins;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ApplicationNamesInfo;
|
||||
import com.intellij.openapi.application.TransactionGuard;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.options.newEditor.SettingsDialog;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.GraphicsConfig;
|
||||
@@ -292,13 +292,13 @@ public class PluginHeaderPanel {
|
||||
if (dialog != null && dialog.isModal()) {
|
||||
dialog.close(DialogWrapper.OK_EXIT_CODE);
|
||||
}
|
||||
TransactionGuard.getInstance().submitTransactionLater(ApplicationManager.getApplication(), () -> {
|
||||
IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> {
|
||||
DialogWrapper settings = DialogWrapper.findInstance(IdeFocusManager.findInstance().getFocusOwner());
|
||||
if (settings instanceof SettingsDialog) {
|
||||
((SettingsDialog)settings).doOKAction();
|
||||
}
|
||||
ApplicationManager.getApplication().restart();
|
||||
});
|
||||
}, ModalityState.current());
|
||||
break;
|
||||
}
|
||||
setPlugin(myPlugin);
|
||||
|
||||
@@ -18,6 +18,9 @@ package com.intellij.ide.ui.laf.darcula;
|
||||
import com.intellij.ide.IdeEventQueue;
|
||||
import com.intellij.ide.ui.laf.IntelliJLaf;
|
||||
import com.intellij.ide.ui.laf.darcula.ui.DarculaEditorTextFieldBorder;
|
||||
import com.intellij.openapi.editor.event.EditorMouseAdapter;
|
||||
import com.intellij.openapi.editor.event.EditorMouseEvent;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.ui.ColorUtil;
|
||||
import com.intellij.ui.EditorTextField;
|
||||
import com.intellij.ui.Gray;
|
||||
@@ -38,6 +41,7 @@ import java.awt.geom.Rectangle2D;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.ide.ui.laf.intellij.WinIntelliJTextFieldUI.HOVER_PROPERTY;
|
||||
import static com.intellij.util.ui.MacUIUtil.MAC_FILL_BORDER;
|
||||
import static javax.swing.SwingConstants.EAST;
|
||||
import static javax.swing.SwingConstants.WEST;
|
||||
@@ -136,7 +140,7 @@ public class DarculaUIUtil {
|
||||
|
||||
@SuppressWarnings("SuspiciousNameCombination")
|
||||
private static void doPaint(Graphics2D g, int width, int height, int arc, boolean symmetric) {
|
||||
double bw = UIUtil.isRetina(g) ? 0.5 : 1.0;
|
||||
double bw = UIUtil.isUnderDefaultMacTheme() ? (UIUtil.isRetina(g) ? 0.5 : 1.0) : 0.0;
|
||||
double lw = JBUI.scale(UIUtil.isUnderDefaultMacTheme() ? 3 : 2);
|
||||
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
@@ -195,11 +199,9 @@ public class DarculaUIUtil {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static class EditorTextFieldBorder extends DarculaEditorTextFieldBorder {
|
||||
private final JComponent myEnabledComponent;
|
||||
|
||||
public EditorTextFieldBorder(JComponent enabledComponent) {
|
||||
myEnabledComponent = enabledComponent;
|
||||
public static class MacEditorTextFieldBorder extends DarculaEditorTextFieldBorder {
|
||||
public MacEditorTextFieldBorder(EditorTextField editorTextField, EditorEx editor) {
|
||||
super(editorTextField, editor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -225,8 +227,8 @@ public class DarculaUIUtil {
|
||||
g2.setColor(c.getBackground());
|
||||
g2.fill(rect);
|
||||
|
||||
if (!myEnabledComponent.isEnabled()) {
|
||||
((Graphics2D)g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f));
|
||||
if (!editorTextField.isEnabled()) {
|
||||
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f));
|
||||
}
|
||||
|
||||
double bw = UIUtil.isRetina(g2) ? 0.5 : 1.0;
|
||||
@@ -239,7 +241,7 @@ public class DarculaUIUtil {
|
||||
g2.setColor(Gray.xBC);
|
||||
g2.fill(outline);
|
||||
|
||||
if (myEnabledComponent.isEnabled() && myEnabledComponent.isVisible() && hasFocus(myEnabledComponent)) {
|
||||
if (editorTextField.isEnabled() && editorTextField.isVisible() && hasFocus(editorTextField)) {
|
||||
g2.translate(x, y);
|
||||
paintFocusBorder(g2, width, height, 0, true);
|
||||
}
|
||||
@@ -254,6 +256,74 @@ public class DarculaUIUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static class WinEditorTextFieldBorder extends DarculaEditorTextFieldBorder {
|
||||
private final JComponent editorComponent;
|
||||
|
||||
public WinEditorTextFieldBorder(EditorTextField editorTextField, EditorEx editor) {
|
||||
super(editorTextField, editor);
|
||||
editorComponent = editor.getComponent();
|
||||
|
||||
editor.addEditorMouseListener(new EditorMouseAdapter() {
|
||||
@Override
|
||||
public void mouseEntered(EditorMouseEvent e) {
|
||||
JComponent c = e.getEditor().getComponent();
|
||||
c.putClientProperty(HOVER_PROPERTY, Boolean.TRUE);
|
||||
editorTextField.repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(EditorMouseEvent e) {
|
||||
JComponent c = e.getEditor().getComponent();
|
||||
c.putClientProperty(HOVER_PROPERTY, Boolean.FALSE);
|
||||
editorTextField.repaint();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
|
||||
g.setColor(c.getBackground());
|
||||
g.fillRect(x, y, width, height);
|
||||
|
||||
if (!isComboBoxEditor(c) && UIUtil.getParentOfType(EditorTextField.class, c) != null) {
|
||||
Graphics2D g2 = (Graphics2D)g.create();
|
||||
try {
|
||||
g2.translate(x, y);
|
||||
|
||||
if (hasFocus(editorTextField)) {
|
||||
g2.setColor(UIManager.getColor("TextField.focusedBorderColor"));
|
||||
} else if (editorTextField.isEnabled() &&
|
||||
editorComponent != null && editorComponent.getClientProperty(HOVER_PROPERTY) == Boolean.TRUE) {
|
||||
g2.setColor(UIManager.getColor("TextField.hoverBorderColor"));
|
||||
} else {
|
||||
g2.setColor(UIManager.getColor("TextField.borderColor"));
|
||||
}
|
||||
|
||||
if (!editorTextField.isEnabled()) {
|
||||
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.35f));
|
||||
}
|
||||
|
||||
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
|
||||
|
||||
int bw = JBUI.scale(1);
|
||||
Path2D border = new Path2D.Double(Path2D.WIND_EVEN_ODD);
|
||||
border.append(new Rectangle2D.Double(0, 0, width, height), false);
|
||||
border.append(new Rectangle2D.Double(bw, bw, width - bw*2, height - bw*2), false);
|
||||
|
||||
g2.fill(border);
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets(Component c) {
|
||||
return isComboBoxEditor(c) ? JBUI.insets(0, 5).asUIResource() : JBUI.insets(4, 5).asUIResource();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasFocus(@NotNull Component component) {
|
||||
if (component.hasFocus()) return true;
|
||||
if (!(component instanceof JComponent)) return false;
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
package com.intellij.ide.ui.laf.darcula.ui;
|
||||
|
||||
import com.intellij.ide.ui.laf.darcula.DarculaUIUtil;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.ex.FocusChangeListener;
|
||||
import com.intellij.ui.EditorTextField;
|
||||
import com.intellij.ui.Gray;
|
||||
import com.intellij.ui.JBColor;
|
||||
@@ -30,6 +33,29 @@ import java.awt.*;
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public class DarculaEditorTextFieldBorder implements Border {
|
||||
protected final JComponent editorTextField;
|
||||
|
||||
public DarculaEditorTextFieldBorder() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
public DarculaEditorTextFieldBorder(EditorTextField editorTextField, EditorEx editor) {
|
||||
this.editorTextField = editorTextField;
|
||||
if (editorTextField != null && editor != null) {
|
||||
editor.addFocusListener(new FocusChangeListener() {
|
||||
@Override
|
||||
public void focusGained(Editor editor) {
|
||||
editorTextField.repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(Editor editor) {
|
||||
editorTextField.repaint();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
|
||||
if (isComboBoxEditor(c) /*|| isCellEditor(c)*/) {
|
||||
@@ -79,7 +105,7 @@ public class DarculaEditorTextFieldBorder implements Border {
|
||||
return UIUtil.getParentOfType(JComboBox.class, c) != null;
|
||||
}
|
||||
|
||||
public static boolean isCellEditor(Component c) {
|
||||
return UIUtil.getParentOfType(JTable.class, c) != null;
|
||||
}
|
||||
//public static boolean isCellEditor(Component c) {
|
||||
// return UIUtil.getParentOfType(JTable.class, c) != null;
|
||||
//}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ public class DarculaTextBorder implements Border, UIResource, ErrorBorderCapable
|
||||
|
||||
Object eop = ((JComponent)c).getClientProperty("JComponent.error.outline");
|
||||
if (Registry.is("ide.inplace.errors.outline") && Boolean.parseBoolean(String.valueOf(eop))) {
|
||||
DarculaUIUtil.paintErrorBorder(g2, width, height, 0, true, c.hasFocus());
|
||||
DarculaUIUtil.paintErrorBorder(g2, width, height, JBUI.scale(5), true, c.hasFocus());
|
||||
} else if (c.hasFocus()) {
|
||||
DarculaUIUtil.paintFocusRing(g2, new Rectangle(JBUI.scale(1), JBUI.scale(1), width - JBUI.scale(2), height - JBUI.scale(2)));
|
||||
} else {
|
||||
|
||||
@@ -126,4 +126,9 @@ public class WinIntelliJComboBoxUI extends DarculaComboBoxUI {
|
||||
g2.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Insets getInsets() {
|
||||
return JBUI.insets(4, 5).asUIResource();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,18 +19,38 @@ import com.intellij.ide.ui.laf.darcula.DarculaUIUtil;
|
||||
import com.intellij.ide.ui.laf.darcula.ui.DarculaTextBorder;
|
||||
import com.intellij.ide.ui.laf.darcula.ui.TextFieldWithPopupHandlerUI;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.ui.ColorPanel;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
import static com.intellij.ide.ui.laf.intellij.WinIntelliJTextFieldUI.HOVER_PROPERTY;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public class WinIntelliJTextBorder extends DarculaTextBorder {
|
||||
@Override
|
||||
public Insets getBorderInsets(Component c) {
|
||||
|
||||
int vOffset = TextFieldWithPopupHandlerUI.isSearchField(c) ? 6 : 4;
|
||||
if (TextFieldWithPopupHandlerUI.isSearchFieldWithHistoryPopup(c)) {
|
||||
return JBUI.insets(vOffset, 7 + 16 + 3, vOffset, 7 + 16).asUIResource();
|
||||
}
|
||||
else if (TextFieldWithPopupHandlerUI.isSearchField(c)) {
|
||||
return JBUI.insets(vOffset, 4 + 16 + 3, vOffset, 7 + 16).asUIResource();
|
||||
}
|
||||
else if (c instanceof JTextField && c.getParent() instanceof ColorPanel) {
|
||||
return JBUI.insets(3, 3, 2, 2).asUIResource();
|
||||
}
|
||||
else {
|
||||
return JBUI.insets(4, 5).asUIResource();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
|
||||
if (TextFieldWithPopupHandlerUI.isSearchField(c)) return;
|
||||
@@ -38,37 +58,37 @@ public class WinIntelliJTextBorder extends DarculaTextBorder {
|
||||
Graphics2D g2 = (Graphics2D)g.create();
|
||||
try {
|
||||
g2.translate(x, y);
|
||||
boolean editable = !(c instanceof JTextComponent) || ((JTextComponent)c).isEditable();
|
||||
|
||||
Object eop = ((JComponent)c).getClientProperty("JComponent.error.outline");
|
||||
if (Registry.is("ide.inplace.errors.outline") && Boolean.parseBoolean(String.valueOf(eop))) {
|
||||
DarculaUIUtil.paintErrorBorder(g2, width, height, 0, true, c.hasFocus());
|
||||
} else {
|
||||
int d = JBUI.scale(1);
|
||||
int dd = JBUI.scale(2);
|
||||
//boolean editable = !(c instanceof JTextComponent) || ((JTextComponent)c).isEditable();
|
||||
JComponent jc = (JComponent)c;
|
||||
if (c.hasFocus()) {
|
||||
g2.setColor(getBorderColor(c.isEnabled() && editable, true));
|
||||
g2.setColor(UIManager.getColor("TextField.focusedBorderColor"));
|
||||
} else if (jc.isEnabled() && jc.getClientProperty(HOVER_PROPERTY) == Boolean.TRUE) {
|
||||
g2.setColor(UIManager.getColor("TextField.hoverBorderColor"));
|
||||
} else {
|
||||
g2.setColor(UIManager.getColor("TextField.borderColor"));
|
||||
}
|
||||
|
||||
Area s1 = new Area(new Rectangle2D.Float(d, d, width - 2 * d, height - 2 * d));
|
||||
Area s2 = new Area(new Rectangle2D.Float(d + dd, d + dd, width - 2*d - 2*dd, height - 2*d - 2*dd));
|
||||
s1.subtract(s2);
|
||||
g2.fill(s1);
|
||||
}
|
||||
else {
|
||||
g2.setColor(getBorderColor(c.isEnabled() && editable, false));
|
||||
g2.drawRect(d, d, width - 2 * d, height - 2 * d);
|
||||
if (!jc.isEnabled()) {
|
||||
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.35f));
|
||||
}
|
||||
|
||||
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
|
||||
|
||||
int bw = JBUI.scale(1);
|
||||
Path2D border = new Path2D.Double(Path2D.WIND_EVEN_ODD);
|
||||
border.append(new Rectangle2D.Double(0, 0, width, height), false);
|
||||
border.append(new Rectangle2D.Double(bw, bw, width - bw*2, height - bw*2), false);
|
||||
|
||||
g2.fill(border);
|
||||
}
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private static Color getBorderColor(boolean enabled, boolean focus) {
|
||||
if (focus) {
|
||||
return UIManager.getColor("TextField.activeBorderColor");
|
||||
}
|
||||
return UIManager.getColor(enabled ? "TextField.borderColor" : "disabledBorderColor");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,38 +16,75 @@
|
||||
package com.intellij.ide.ui.laf.intellij;
|
||||
|
||||
import com.intellij.ide.ui.laf.darcula.ui.DarculaTextFieldUI;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public class WinIntelliJTextFieldUI extends DarculaTextFieldUI {
|
||||
public static final String HOVER_PROPERTY = "JTextField.hover";
|
||||
|
||||
public WinIntelliJTextFieldUI(JTextField textField) {
|
||||
super(textField);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"})
|
||||
public static ComponentUI createUI(JComponent c) {
|
||||
c.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
JComponent c = (JComponent)e.getComponent();
|
||||
c.putClientProperty(HOVER_PROPERTY, Boolean.TRUE);
|
||||
c.repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
JComponent c = (JComponent)e.getComponent();
|
||||
c.putClientProperty(HOVER_PROPERTY, Boolean.FALSE);
|
||||
c.repaint();
|
||||
}
|
||||
});
|
||||
|
||||
return new WinIntelliJTextFieldUI((JTextField)c);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintBackground(Graphics graphics) {
|
||||
super.paintBackground(graphics);
|
||||
protected void paintBackground(Graphics g) {
|
||||
Graphics2D g2 = (Graphics2D)g.create();
|
||||
try {
|
||||
JTextComponent c = getComponent();
|
||||
Container parent = c.getParent();
|
||||
|
||||
if (c.isOpaque() && parent != null) {
|
||||
g2.setColor(parent.getBackground());
|
||||
g2.fillRect(0, 0, c.getWidth(), c.getHeight());
|
||||
}
|
||||
|
||||
if (isSearchField(c)) {
|
||||
Rectangle r = getDrawingRect();
|
||||
paintSearchField(g2, c, r);
|
||||
} else {
|
||||
g2.setColor(c.isEnabled() ? c.getBackground() : UIManager.getColor("Button.background"));
|
||||
|
||||
int bw = JBUI.scale(1);
|
||||
g2.fillRect(bw, bw, c.getWidth() - bw*2, c.getHeight() - bw*2);
|
||||
}
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintDarculaBackground(Graphics2D g, JTextComponent c, Border border) {
|
||||
super.paintDarculaBackground(g, c, border);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintSearchField(Graphics2D g, JTextComponent c, Rectangle r) {
|
||||
super.paintSearchField(g, c, r);
|
||||
@Override public Dimension getPreferredSize(JComponent c) {
|
||||
Dimension size = super.getPreferredSize(c);
|
||||
size.height = isSearchField(c) ? size.height : JBUI.scale(22);
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,9 +60,9 @@ Focus.color=ff0000
|
||||
TextField.background=ffffff
|
||||
TextFieldUI=com.intellij.ide.ui.laf.intellij.WinIntelliJTextFieldUI
|
||||
TextField.border=com.intellij.ide.ui.laf.intellij.WinIntelliJTextBorder
|
||||
TextField.activeBorderColor=0078d7
|
||||
TextField.borderColor=e8e8e8
|
||||
TextField.disabledBorderColor=e8e8e8
|
||||
TextField.borderColor=bdbdbd
|
||||
TextField.hoverBorderColor=a1a1a1
|
||||
TextField.focusedBorderColor=0784de
|
||||
TextField.darcula.search.icon=/com/intellij/ide/ui/laf/icons/search.png
|
||||
TextField.darcula.searchWithHistory.icon=/com/intellij/ide/ui/laf/icons/searchWithHistory.png
|
||||
TextField.darcula.clear.icon=/com/intellij/ide/ui/laf/icons/clear.png
|
||||
@@ -127,6 +127,7 @@ StatusBar.bottomColor=2c2c2c
|
||||
|
||||
Button.border=com.intellij.ide.ui.laf.intellij.WinIntelliJButtonBorder
|
||||
ButtonUI=com.intellij.ide.ui.laf.intellij.WinIntelliJButtonUI
|
||||
Button.background=e3e3e3
|
||||
Button.disabledText=8a8a8a
|
||||
Button.intellij.native.borderColor=adadad
|
||||
Button.intellij.native.focusDottedRingColor=000000
|
||||
@@ -134,7 +135,6 @@ Button.intellij.native.focusedBorderColor=0784de
|
||||
Button.intellij.native.pressedBorderColor=005499
|
||||
Button.intellij.native.focusedBackgroundColor=e3f1fa
|
||||
Button.intellij.native.pressedBackgroundColor=cce4f7
|
||||
Button.background=e3e3e3
|
||||
|
||||
ToggleButton.border=com.intellij.ide.ui.laf.darcula.ui.DarculaButtonPainter
|
||||
ToggleButtonUI=com.intellij.ide.ui.laf.darcula.ui.DarculaButtonUI
|
||||
|
||||
@@ -275,7 +275,7 @@ public class NotificationsConfigurablePanel extends JPanel implements Disposable
|
||||
UIUtil.resetEnabledRollOver(NotificationsTreeTable.this, LOG_COLUMN);
|
||||
if (column == LOG_COLUMN) {
|
||||
JComponent rc = (JComponent)getColumnModel().getColumn(column).getCellRenderer();
|
||||
rc.putClientProperty("ThreeStateCheckBoxRenderer.rolloverRow", row);
|
||||
rc.putClientProperty(UIUtil.CHECKBOX_ROLLOVER_PROPERTY, row);
|
||||
((AbstractTableModel)getModel()).fireTableCellUpdated(row, column);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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.openapi.command.impl;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ApplicationStarterEx;
|
||||
import com.intellij.openapi.progress.EmptyProgressIndicator;
|
||||
import com.intellij.openapi.updateSettings.impl.PluginDownloader;
|
||||
import com.intellij.openapi.updateSettings.impl.UpdateChecker;
|
||||
import com.intellij.openapi.updateSettings.impl.UpdateInstaller;
|
||||
import com.intellij.openapi.updateSettings.impl.UpdateSettings;
|
||||
import com.intellij.openapi.util.ActionCallback;
|
||||
import com.intellij.openapi.util.BuildNumber;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public class UpdatePluginsApp extends ApplicationStarterEx {
|
||||
@Override
|
||||
public boolean isHeadless() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return "update";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void premain(String[] args) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void main(String[] args) {
|
||||
List<String> pluginsToUpdate = getPluginsToUpdate(args);
|
||||
ActionCallback callback = new ActionCallback()
|
||||
.doWhenDone(() -> System.exit(0))
|
||||
.doWhenRejected(() -> System.exit(1));
|
||||
|
||||
Runnable update = () -> updateAllPlugins(callback, pluginsToUpdate);
|
||||
ApplicationManager.getApplication().executeOnPooledThread(update);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static List<String> getPluginsToUpdate(String[] args) {
|
||||
if (args.length < 2) return null;
|
||||
ArrayList<String> pluginIds = new ArrayList<>(args.length - 1);
|
||||
//skip "update" command and read plugin ids
|
||||
for (int i = 1; i < args.length; i++) {
|
||||
pluginIds.add(i - 1, args[i]);
|
||||
}
|
||||
return pluginIds;
|
||||
}
|
||||
|
||||
private static void updateAllPlugins(ActionCallback callback, @Nullable List<String> plugins) {
|
||||
Collection<PluginDownloader> availableUpdates = UpdateChecker.checkPluginsUpdate(UpdateSettings.getInstance(),
|
||||
new EmptyProgressIndicator(),
|
||||
new HashSet<>(),
|
||||
BuildNumber.currentVersion());
|
||||
if (availableUpdates == null) {
|
||||
log("All plugins up to date.");
|
||||
callback.setDone();
|
||||
return;
|
||||
}
|
||||
|
||||
Collection<PluginDownloader> pluginsToUpdate = plugins == null || plugins.isEmpty()
|
||||
? availableUpdates
|
||||
: availableUpdates.stream()
|
||||
.filter(downloader -> plugins.contains(downloader.getPluginId()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
|
||||
log("Plugins to update:");
|
||||
pluginsToUpdate.forEach(d -> log("\t" + d.getPluginName()));
|
||||
|
||||
if (UpdateInstaller.installPluginUpdates(pluginsToUpdate, new EmptyProgressIndicator())) {
|
||||
callback.setDone();
|
||||
} else {
|
||||
log("Update failed");
|
||||
callback.setRejected();
|
||||
}
|
||||
}
|
||||
|
||||
private static void log(String msg) {
|
||||
System.out.println(msg);
|
||||
}
|
||||
}
|
||||
@@ -498,7 +498,8 @@ public class EditorWindow {
|
||||
else {
|
||||
EditorWithProviderComposite editor = getSelectedEditor();
|
||||
JComponent preferred = editor == null ? null : editor.getPreferredFocusedComponent();
|
||||
IdeFocusManager.findInstanceByComponent(preferred == null ? myPanel : preferred).requestFocus(myPanel, forced);
|
||||
if (preferred == null) preferred = myPanel;
|
||||
IdeFocusManager.findInstanceByComponent(preferred).requestFocus(preferred, forced);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -107,7 +107,8 @@ object UpdateChecker {
|
||||
})
|
||||
}
|
||||
|
||||
private fun doUpdateAndShowResult(project: Project?,
|
||||
@JvmStatic
|
||||
fun doUpdateAndShowResult(project: Project?,
|
||||
fromSettings: Boolean,
|
||||
manualCheck: Boolean,
|
||||
updateSettings: UpdateSettings,
|
||||
@@ -193,7 +194,8 @@ object UpdateChecker {
|
||||
return strategy.checkForUpdates()
|
||||
}
|
||||
|
||||
private fun checkPluginsUpdate(updateSettings: UpdateSettings,
|
||||
@JvmStatic
|
||||
fun checkPluginsUpdate(updateSettings: UpdateSettings,
|
||||
indicator: ProgressIndicator?,
|
||||
incompatiblePlugins: MutableCollection<IdeaPluginDescriptor>?,
|
||||
buildNumber: BuildNumber?): Collection<PluginDownloader>? {
|
||||
|
||||
@@ -119,10 +119,19 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
|
||||
final MouseEvent me = (MouseEvent)e;
|
||||
final boolean insideBalloon = isInsideBalloon(me);
|
||||
|
||||
if (myHideOnMouse && id == MouseEvent.MOUSE_PRESSED) {
|
||||
if (!insideBalloon && !isWithinChildWindow(me)) {
|
||||
boolean forcedExit = id == MouseEvent.MOUSE_EXITED && me.getButton() != MouseEvent.NOBUTTON;
|
||||
if (myHideOnMouse && (id == MouseEvent.MOUSE_PRESSED || forcedExit)) {
|
||||
if ((!insideBalloon || forcedExit) && !isWithinChildWindow(me)) {
|
||||
if (myHideListener == null) {
|
||||
hide();
|
||||
if (forcedExit) {
|
||||
int[] ids = {MouseEvent.MOUSE_ENTERED, MouseEvent.MOUSE_PRESSED, MouseEvent.MOUSE_RELEASED, MouseEvent.MOUSE_CLICKED};
|
||||
for (int id_ : ids) {
|
||||
IdeEventQueue.getInstance()
|
||||
.dispatchEvent(new MouseEvent(me.getComponent(), id_, me.getWhen(), me.getModifiers(), me.getX(), me
|
||||
.getY(), me.getClickCount(), me.isPopupTrigger(), me.getButton()));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
myHideListener.run();
|
||||
|
||||
@@ -35,7 +35,6 @@ import com.intellij.openapi.editor.colors.EditorColorsUtil;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.editor.event.DocumentListener;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.ex.FocusChangeListener;
|
||||
import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
|
||||
import com.intellij.openapi.editor.impl.EditorImpl;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
@@ -545,18 +544,14 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener,
|
||||
|
||||
protected void setupBorder(@NotNull EditorEx editor) {
|
||||
if (UIUtil.isUnderAquaLookAndFeel() || UIUtil.isUnderDarcula() || UIUtil.isUnderIntelliJLaF()) {
|
||||
editor.setBorder(UIUtil.isUnderDefaultMacTheme() ? new DarculaUIUtil.EditorTextFieldBorder(this) : new DarculaEditorTextFieldBorder());
|
||||
editor.addFocusListener(new FocusChangeListener() {
|
||||
@Override
|
||||
public void focusGained(Editor editor) {
|
||||
repaint();
|
||||
}
|
||||
if (UIUtil.isUnderDefaultMacTheme()) {
|
||||
editor.setBorder(new DarculaUIUtil.MacEditorTextFieldBorder(this, editor));
|
||||
} else if (UIUtil.isUnderWin10LookAndFeel()) {
|
||||
editor.setBorder(new DarculaUIUtil.WinEditorTextFieldBorder(this, editor));
|
||||
} else {
|
||||
editor.setBorder(new DarculaEditorTextFieldBorder(this, editor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(Editor editor) {
|
||||
repaint();
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (UIUtil.isUnderAlloyLookAndFeel() || UIUtil.isUnderJGoodiesLookAndFeel()) {
|
||||
editor.setBorder(BorderFactory.createCompoundBorder(UIUtil.getTextFieldBorder(), BorderFactory.createEmptyBorder(1, 1, 1, 1)));
|
||||
|
||||
@@ -30,7 +30,6 @@ import java.awt.*;
|
||||
*/
|
||||
public class OwnerOptional {
|
||||
|
||||
@NotNull
|
||||
private static Window findOwnerByComponent(Component component) {
|
||||
if (component == null) component = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow();
|
||||
if (component == null) {
|
||||
|
||||
@@ -1031,7 +1031,6 @@ action.XDebugger.JumpToTypeSource.text=Jump To Type Source
|
||||
action.XDebugger.JumpToTypeSource.description=Open source of the selected value's type
|
||||
action.XDebugger.Inspect.text=Inspect...
|
||||
|
||||
action.Debugger.Tree.AddToWatches.text=Add to Watches
|
||||
action.Debugger.Tree.EvaluateInConsole.text=Evaluate In Console
|
||||
|
||||
action.XDebugger.RemoveWatch.text=Remove Watch
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<appStarter implementation="com.intellij.diff.applications.DiffApplication"/>
|
||||
<appStarter implementation="com.intellij.diff.applications.MergeApplication"/>
|
||||
<appStarter implementation="com.intellij.ui.win.RecentProjectApplication"/>
|
||||
<appStarter implementation="com.intellij.openapi.command.impl.UpdatePluginsApp"/>
|
||||
<appStarter implementation="com.intellij.help.impl.KeymapGenerator"/>
|
||||
<appStarter implementation="com.intellij.help.impl.IntentionDump"/>
|
||||
<appStarter implementation="com.intellij.help.impl.InspectionDump"/>
|
||||
|
||||
@@ -730,7 +730,6 @@
|
||||
<action id="XDebugger.JumpToTypeSource" class="com.intellij.xdebugger.impl.ui.tree.actions.XJumpToTypeSourceAction"
|
||||
use-shortcut-of="Debugger.EditTypeSource"/>
|
||||
|
||||
<action id="Debugger.Tree.AddToWatches" class="com.intellij.xdebugger.impl.ui.tree.actions.XAddToWatchesAction" icon="AllIcons.Debugger.AddToWatch"/>
|
||||
<action id="Debugger.Tree.EvaluateInConsole" class="com.intellij.xdebugger.impl.ui.tree.actions.EvaluateInConsoleFromTreeAction"/>
|
||||
|
||||
<action id="XDebugger.NewWatch" class="com.intellij.xdebugger.impl.frame.actions.XNewWatchAction" icon="AllIcons.Debugger.NewWatch"/>
|
||||
@@ -796,7 +795,7 @@
|
||||
<separator/>
|
||||
<reference ref="EvaluateExpression"/>
|
||||
<reference ref="Debugger.Tree.EvaluateInConsole"/>
|
||||
<reference ref="Debugger.Tree.AddToWatches"/>
|
||||
<reference ref="Debugger.AddToWatch"/>
|
||||
<reference ref="Debugger.ShowReferring"/>
|
||||
<separator/>
|
||||
<reference ref="XDebugger.JumpToSource"/>
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="kotlin-language" name="Kotlin">
|
||||
<configuration version="2" platform="JVM 1.8" useProjectSettings="false">
|
||||
<compilerSettings />
|
||||
<compilerArguments>
|
||||
<option name="jvmTarget" value="1.8" />
|
||||
<option name="languageVersion" value="1.1" />
|
||||
<option name="apiVersion" value="1.1" />
|
||||
<option name="coroutinesError" value="true" />
|
||||
</compilerArguments>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.intellij.util.SmartList
|
||||
import com.intellij.util.xmlb.Accessor
|
||||
import com.intellij.util.xmlb.SerializationFilter
|
||||
import com.intellij.util.xmlb.annotations.Transient
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
abstract class BaseState : SerializationFilter, ModificationTracker {
|
||||
@@ -39,16 +38,7 @@ abstract class BaseState : SerializationFilter, ModificationTracker {
|
||||
modificationCount++
|
||||
}
|
||||
|
||||
override fun accepts(accessor: Accessor, bean: Any): Boolean {
|
||||
for (property in properties) {
|
||||
if (property.name == accessor.name) {
|
||||
return property.value != property.defaultValue
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun <T> storedProperty(defaultValue: T? = null): ReadWriteProperty<BaseState, T?> {
|
||||
fun <T> storedProperty(defaultValue: T? = null): StoredPropertyBase<T?> {
|
||||
val result = ObjectStoredProperty(defaultValue)
|
||||
properties.add(result)
|
||||
return result
|
||||
@@ -57,30 +47,39 @@ abstract class BaseState : SerializationFilter, ModificationTracker {
|
||||
/**
|
||||
* Empty string is always normalized to null.
|
||||
*/
|
||||
fun string(defaultValue: String? = null): ReadWriteProperty<BaseState, String?> {
|
||||
val result = StringStoredProperty(defaultValue)
|
||||
fun string(defaultValue: String? = null): StoredPropertyBase<String?> {
|
||||
val result = NormalizedStringStoredProperty(defaultValue)
|
||||
properties.add(result)
|
||||
return result
|
||||
}
|
||||
|
||||
fun storedProperty(defaultValue: Int = 0): ReadWriteProperty<BaseState, Int> {
|
||||
fun storedProperty(defaultValue: Int = 0): StoredPropertyBase<Int> {
|
||||
val result = IntStoredProperty(defaultValue)
|
||||
properties.add(result)
|
||||
return result
|
||||
}
|
||||
|
||||
fun storedProperty(defaultValue: Float = 0f): ReadWriteProperty<BaseState, Float> {
|
||||
fun storedProperty(defaultValue: Float = 0f): StoredPropertyBase<Float> {
|
||||
val result = FloatStoredProperty(defaultValue)
|
||||
properties.add(result)
|
||||
return result
|
||||
}
|
||||
|
||||
fun storedProperty(defaultValue: Boolean = false): ReadWriteProperty<BaseState, Boolean> {
|
||||
fun storedProperty(defaultValue: Boolean = false): StoredPropertyBase<Boolean> {
|
||||
val result = ObjectStoredProperty(defaultValue)
|
||||
properties.add(result)
|
||||
return result
|
||||
}
|
||||
|
||||
override fun accepts(accessor: Accessor, bean: Any): Boolean {
|
||||
for (property in properties) {
|
||||
if (property.name == accessor.name) {
|
||||
return property.value != property.defaultValue
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@Transient
|
||||
override fun getModificationCount(): Long {
|
||||
var result = modificationCount
|
||||
@@ -114,41 +113,19 @@ abstract class BaseState : SerializationFilter, ModificationTracker {
|
||||
assert(state.properties.size == properties.size)
|
||||
for ((index, property) in properties.withIndex()) {
|
||||
val otherProperty = state.properties.get(index)
|
||||
if (property.name != null) {
|
||||
if (otherProperty.name == null) {
|
||||
otherProperty.name = property.name
|
||||
}
|
||||
else {
|
||||
assert(otherProperty.name == property.name)
|
||||
}
|
||||
}
|
||||
assert(otherProperty.name == property.name)
|
||||
property.setValue(otherProperty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal interface StoredProperty {
|
||||
val defaultValue: Any?
|
||||
val value: Any?
|
||||
|
||||
var name: String?
|
||||
|
||||
fun setValue(other: StoredProperty)
|
||||
}
|
||||
|
||||
private class ObjectStoredProperty<T>(override val defaultValue: T) : ReadWriteProperty<BaseState, T>, StoredProperty {
|
||||
private class ObjectStoredProperty<T>(override val defaultValue: T) : StoredPropertyBase<T>() {
|
||||
override var value = defaultValue
|
||||
override var name: String? = null
|
||||
|
||||
override operator fun getValue(thisRef: BaseState, property: KProperty<*>): T {
|
||||
name = property.name
|
||||
return value
|
||||
}
|
||||
override operator fun getValue(thisRef: BaseState, property: KProperty<*>) = value
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun setValue(thisRef: BaseState, property: KProperty<*>, @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") newValue: T) {
|
||||
name = property.name
|
||||
|
||||
if (value != newValue) {
|
||||
thisRef.modificationCount++
|
||||
|
||||
@@ -160,7 +137,7 @@ private class ObjectStoredProperty<T>(override val defaultValue: T) : ReadWriteP
|
||||
|
||||
override fun hashCode() = value?.hashCode() ?: 0
|
||||
|
||||
override fun toString() = if (value === defaultValue) "" else value?.toString() ?: super.toString()
|
||||
override fun toString() = if (value == defaultValue) "" else value?.toString() ?: super.toString()
|
||||
|
||||
override fun setValue(other: StoredProperty) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@@ -168,19 +145,13 @@ private class ObjectStoredProperty<T>(override val defaultValue: T) : ReadWriteP
|
||||
}
|
||||
}
|
||||
|
||||
private class StringStoredProperty(override val defaultValue: String?) : ReadWriteProperty<BaseState, String?>, StoredProperty {
|
||||
private class NormalizedStringStoredProperty(override val defaultValue: String?) : StoredPropertyBase<String?>() {
|
||||
override var value = defaultValue
|
||||
override var name: String? = null
|
||||
|
||||
override operator fun getValue(thisRef: BaseState, property: KProperty<*>): String? {
|
||||
name = property.name
|
||||
return value
|
||||
}
|
||||
override operator fun getValue(thisRef: BaseState, property: KProperty<*>) = value
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun setValue(thisRef: BaseState, property: KProperty<*>, @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") _newValue: String?) {
|
||||
name = property.name
|
||||
|
||||
var newValue = _newValue
|
||||
if (newValue != null && newValue.isEmpty()) {
|
||||
newValue = null
|
||||
@@ -192,30 +163,24 @@ private class StringStoredProperty(override val defaultValue: String?) : ReadWri
|
||||
}
|
||||
}
|
||||
|
||||
override fun equals(other: Any?) = this === other || (other is ObjectStoredProperty<*> && value == other.value)
|
||||
override fun equals(other: Any?) = this === other || (other is NormalizedStringStoredProperty && value == other.value)
|
||||
|
||||
override fun hashCode() = value?.hashCode() ?: 0
|
||||
|
||||
override fun toString() = if (value == defaultValue) "" else value ?: super.toString()
|
||||
|
||||
override fun setValue(other: StoredProperty) {
|
||||
value = (other as StringStoredProperty).value
|
||||
value = (other as NormalizedStringStoredProperty).value
|
||||
}
|
||||
}
|
||||
|
||||
private class IntStoredProperty(override val defaultValue: Int) : ReadWriteProperty<BaseState, Int>, StoredProperty {
|
||||
private class IntStoredProperty(override val defaultValue: Int) : StoredPropertyBase<Int>() {
|
||||
override var value = defaultValue
|
||||
override var name: String? = null
|
||||
|
||||
override operator fun getValue(thisRef: BaseState, property: KProperty<*>): Int {
|
||||
name = property.name
|
||||
return value
|
||||
}
|
||||
override operator fun getValue(thisRef: BaseState, property: KProperty<*>) = value
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun setValue(thisRef: BaseState, property: KProperty<*>, @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") newValue: Int) {
|
||||
name = property.name
|
||||
|
||||
if (value != newValue) {
|
||||
thisRef.modificationCount++
|
||||
|
||||
@@ -234,19 +199,13 @@ private class IntStoredProperty(override val defaultValue: Int) : ReadWritePrope
|
||||
}
|
||||
}
|
||||
|
||||
private class FloatStoredProperty(override val defaultValue: Float) : ReadWriteProperty<BaseState, Float>, StoredProperty {
|
||||
private class FloatStoredProperty(override val defaultValue: Float) : StoredPropertyBase<Float>() {
|
||||
override var value = defaultValue
|
||||
override var name: String? = null
|
||||
|
||||
override operator fun getValue(thisRef: BaseState, property: KProperty<*>): Float {
|
||||
name = property.name
|
||||
return value
|
||||
}
|
||||
override operator fun getValue(thisRef: BaseState, property: KProperty<*>) = value
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun setValue(thisRef: BaseState, property: KProperty<*>, @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") newValue: Float) {
|
||||
name = property.name
|
||||
|
||||
if (value != newValue) {
|
||||
thisRef.modificationCount++
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.openapi.components
|
||||
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
internal interface StoredProperty {
|
||||
val defaultValue: Any?
|
||||
val value: Any?
|
||||
|
||||
var name: String?
|
||||
|
||||
fun setValue(other: StoredProperty)
|
||||
}
|
||||
|
||||
// type must be exposed otherwise `provideDelegate` doesn't work
|
||||
abstract class StoredPropertyBase<T> : ReadWriteProperty<BaseState, T>, StoredProperty {
|
||||
override final var name: String? = null
|
||||
|
||||
operator fun provideDelegate(thisRef: Any, property: KProperty<*>): ReadWriteProperty<BaseState, T> {
|
||||
name = property.name
|
||||
return this
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="kotlin-language" name="Kotlin">
|
||||
<configuration version="2" platform="JVM 1.8" useProjectSettings="false">
|
||||
<compilerSettings />
|
||||
<compilerArguments>
|
||||
<option name="jvmTarget" value="1.8" />
|
||||
<option name="languageVersion" value="1.1" />
|
||||
<option name="apiVersion" value="1.1" />
|
||||
<option name="coroutinesError" value="true" />
|
||||
</compilerArguments>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
|
||||
@@ -31,8 +31,8 @@ import java.net.URL
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||
import kotlin.concurrent.read
|
||||
import kotlin.concurrent.write
|
||||
import kotlin.reflect.full.primaryConstructor
|
||||
import kotlin.reflect.jvm.isAccessible
|
||||
import kotlin.reflect.primaryConstructor
|
||||
|
||||
@JvmOverloads
|
||||
fun <T : Any> T.serialize(filter: SerializationFilter? = SkipDefaultsSerializationFilter()): Element {
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* 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.structuralsearch.impl.matcher;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -5,20 +20,18 @@ import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: maxim
|
||||
* @author maxim
|
||||
* Date: 24.12.2003
|
||||
* Time: 22:10:20
|
||||
* To change this template use Options | File Templates.
|
||||
*/
|
||||
public class MatchUtils {
|
||||
public static final String SPECIAL_CHARS = "*(){}[]^$\\.-|";
|
||||
public static final String SPECIAL_CHARS = ".$|()[{^?*+\\";
|
||||
|
||||
public static final boolean compareWithNoDifferenceToPackage(String typeImage, String typeImage2) {
|
||||
public static boolean compareWithNoDifferenceToPackage(String typeImage, String typeImage2) {
|
||||
return compareWithNoDifferenceToPackage(typeImage, typeImage2, false);
|
||||
}
|
||||
|
||||
public static final boolean compareWithNoDifferenceToPackage(final String typeImage,@NonNls final String typeImage2, boolean ignoreCase) {
|
||||
public static boolean compareWithNoDifferenceToPackage(String typeImage, @NonNls String typeImage2, boolean ignoreCase) {
|
||||
if (typeImage == null || typeImage2 == null) return typeImage == typeImage2;
|
||||
final boolean endsWith = ignoreCase ? StringUtil.endsWithIgnoreCase(typeImage2, typeImage) : typeImage2.endsWith(typeImage);
|
||||
return endsWith && (
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* 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.structuralsearch;
|
||||
|
||||
import com.intellij.structuralsearch.impl.matcher.compiler.PatternCompiler;
|
||||
@@ -19,6 +34,14 @@ public class OptimizedSearchScanTest extends StructuralSearchTestCase {
|
||||
assertEquals("exception should not be in plan", "[in code:C]", plan);
|
||||
}
|
||||
|
||||
public void testRegExpChar() {
|
||||
final String plan = findWordsToBeUsedWhenSearchingFor("'x:[regex( a+ )]");
|
||||
assertEquals("", plan);
|
||||
|
||||
final String plan2 = findWordsToBeUsedWhenSearchingFor("'x:[ regex(a}) ]");
|
||||
assertEquals("[in code:a}]", plan2);
|
||||
}
|
||||
|
||||
private String findWordsToBeUsedWhenSearchingFor(final String s) {
|
||||
findMatchesCount("{}",s);
|
||||
return PatternCompiler.getLastFindPlan();
|
||||
|
||||
@@ -721,7 +721,7 @@ public class StructuralSearchTest extends StructuralSearchTestCase {
|
||||
|
||||
final String in = "class D<T> {}\n" +
|
||||
"class T {}";
|
||||
assertEquals("search for class should not find type parameters", 1, findMatchesCount(in, "class T {}"));
|
||||
assertEquals("search for class should not find type parameters", 2, findMatchesCount(in, "class 'A {}"));
|
||||
}
|
||||
|
||||
public void testParameterlessConstructorSearch() {
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
@@ -227,6 +228,19 @@ public class StringToConstraintsTransformerTest {
|
||||
assertEquals(".*(?:comment).*", constraint1.getRegExp());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvert() {
|
||||
test("'a:[!regexw(a)&&formal(*List)]");
|
||||
assertEquals("$a$", myOptions.getSearchPattern());
|
||||
final MatchVariableConstraint constraint = myOptions.getVariableConstraint("a");
|
||||
assertTrue(constraint.isWholeWordsOnly());
|
||||
assertEquals("a", constraint.getRegExp());
|
||||
assertTrue(constraint.isInvertRegExp());
|
||||
assertTrue(constraint.isFormalArgTypeWithinHierarchy());
|
||||
assertFalse(constraint.isInvertFormalType());
|
||||
assertEquals("List", constraint.getNameOfFormalArgType());
|
||||
}
|
||||
|
||||
@Test(expected = MalformedPatternException.class)
|
||||
public void testAmpersandsExpected() {
|
||||
test("'a:[regex(a) regex(b)]");
|
||||
|
||||