Merge remote-tracking branch 'origin/master'

This commit is contained in:
Vladimir.Orlov
2017-05-03 00:43:54 +03:00
133 changed files with 1476 additions and 925 deletions
@@ -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("&nbsp;");
}
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(); ) {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 397 B

After

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 907 B

After

Width:  |  Height:  |  Size: 713 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 661 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 565 B

After

Width:  |  Height:  |  Size: 298 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 580 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 666 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 394 B

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 932 B

After

Width:  |  Height:  |  Size: 995 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 899 B

After

Width:  |  Height:  |  Size: 929 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 375 B

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 460 B

After

Width:  |  Height:  |  Size: 431 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 824 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 851 B

Binary file not shown.

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)]");

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