mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git@git.labs.intellij.net:idea/community
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -38,6 +38,8 @@ target('default': 'The default target') {
|
||||
};
|
||||
}
|
||||
|
||||
commonJvmArgs().each { jvmarg(value: it) }
|
||||
|
||||
if (isDefined("jvm_args")) {
|
||||
jvm_args.each { jvmarg(value: it) }
|
||||
}
|
||||
|
||||
+1
-14
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.TailType;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.ImportClassFix;
|
||||
import com.intellij.codeInsight.hint.ShowParameterInfoHandler;
|
||||
@@ -249,7 +248,6 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
if (reference instanceof PsiJavaReference) {
|
||||
final ElementFilter filter = getReferenceFilter(position);
|
||||
if (filter != null) {
|
||||
boolean showCapitalizedClasses = showCapitalizedClasses(result);
|
||||
final boolean isSwitchLabel = SWITCH_LABEL.accepts(position);
|
||||
final PsiFile originalFile = parameters.getOriginalFile();
|
||||
for (LookupElement element : JavaCompletionUtil.processJavaReference(position,
|
||||
@@ -261,12 +259,6 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!showCapitalizedClasses &&
|
||||
element.getObject() instanceof PsiClass &&
|
||||
StringUtil.isCapitalized(((PsiClass)element.getObject()).getName())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isSwitchLabel) {
|
||||
result.addElement(TailTypeDecorator.withTail(element, TailType.createSimpleTailType(':')));
|
||||
}
|
||||
@@ -308,11 +300,6 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean showCapitalizedClasses(CompletionResultSet result) {
|
||||
String prefix = result.getPrefixMatcher().getPrefix();
|
||||
return StringUtil.isEmpty(prefix) || StringUtil.isCapitalized(prefix) || CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE == CodeInsightSettings.NONE;
|
||||
}
|
||||
|
||||
private static void addKeywords(CompletionParameters parameters, CompletionResultSet result) {
|
||||
PsiElement position = parameters.getPosition();
|
||||
final Set<LookupElement> lookupSet = new LinkedHashSet<LookupElement>();
|
||||
@@ -344,7 +331,7 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
return false;
|
||||
}
|
||||
|
||||
return StringUtil.isCapitalized(result.getPrefixMatcher().getPrefix());
|
||||
return StringUtil.isNotEmpty(result.getPrefixMatcher().getPrefix());
|
||||
}
|
||||
|
||||
private static void completeAnnotationAttributeName(CompletionResultSet result, PsiElement insertedElement,
|
||||
|
||||
+1
-2
@@ -849,7 +849,6 @@ public class HighlightMethodUtil {
|
||||
|
||||
|
||||
static HighlightInfo checkConstructorCallMustBeFirstStatement(PsiReferenceExpression expression) {
|
||||
String text = expression.getText();
|
||||
PsiElement methodCall = expression.getParent();
|
||||
if (!HighlightUtil.isSuperOrThisMethodCall(methodCall)) return null;
|
||||
PsiElement codeBlock = methodCall.getParent().getParent();
|
||||
@@ -863,7 +862,7 @@ public class HighlightMethodUtil {
|
||||
prevSibling = prevSibling.getPrevSibling();
|
||||
}
|
||||
}
|
||||
String message = JavaErrorMessages.message("constructor.call.must.be.first.statement", text + "()");
|
||||
String message = JavaErrorMessages.message("constructor.call.must.be.first.statement", expression.getText() + "()");
|
||||
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression.getParent(), message);
|
||||
}
|
||||
|
||||
|
||||
+12
-4
@@ -48,11 +48,19 @@ public class CreateClassFromNewFix extends CreateFromUsageBaseFix {
|
||||
protected void invokeImpl(PsiClass targetClass) {
|
||||
assert ApplicationManager.getApplication().isWriteAccessAllowed();
|
||||
|
||||
PsiNewExpression newExpression = getNewExpression();
|
||||
final PsiNewExpression newExpression = getNewExpression();
|
||||
|
||||
PsiJavaCodeReferenceElement referenceElement = getReferenceElement(newExpression);
|
||||
final PsiClass psiClass = CreateFromUsageUtils.createClass(referenceElement, CreateClassKind.CLASS, null);
|
||||
setupClassFromNewExpression(psiClass, newExpression);
|
||||
final PsiJavaCodeReferenceElement referenceElement = getReferenceElement(newExpression);
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
final PsiClass psiClass = CreateFromUsageUtils.createClass(referenceElement, CreateClassKind.CLASS, null);
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
setupClassFromNewExpression(psiClass, newExpression);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected static void setupClassFromNewExpression(final PsiClass psiClass, final PsiNewExpression newExpression) {
|
||||
|
||||
+46
-31
@@ -41,6 +41,7 @@ import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Pass;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
@@ -264,6 +265,7 @@ public class CreateFromUsageUtils {
|
||||
public static PsiClass createClass(final PsiJavaCodeReferenceElement referenceElement,
|
||||
final CreateClassKind classKind,
|
||||
final String superClassName) {
|
||||
assert !ApplicationManager.getApplication().isWriteAccessAllowed();
|
||||
final String name = referenceElement.getReferenceName();
|
||||
|
||||
final PsiElement qualifierElement;
|
||||
@@ -274,23 +276,7 @@ public class CreateFromUsageUtils {
|
||||
return ApplicationManager.getApplication().runWriteAction(
|
||||
new Computable<PsiClass>() {
|
||||
public PsiClass compute() {
|
||||
try {
|
||||
PsiClass psiClass = (PsiClass) qualifierElement;
|
||||
if (!CodeInsightUtilBase.preparePsiElementForWrite(psiClass)) return null;
|
||||
|
||||
PsiManager manager = psiClass.getManager();
|
||||
PsiElementFactory elementFactory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
|
||||
PsiClass result = classKind == INTERFACE ? elementFactory.createInterface(name) :
|
||||
classKind == CLASS ? elementFactory.createClass(name) :
|
||||
elementFactory.createEnum(name);
|
||||
CreateFromUsageBaseFix.setupGenericParameters(result, referenceElement);
|
||||
result = (PsiClass)manager.getCodeStyleManager().reformat(result);
|
||||
return (PsiClass) psiClass.add(result);
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
return null;
|
||||
}
|
||||
return createClassInQualifier((PsiClass)qualifierElement, classKind, name, referenceElement);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -302,20 +288,7 @@ public class CreateFromUsageUtils {
|
||||
final PsiManager manager = referenceElement.getManager();
|
||||
final PsiFile sourceFile = referenceElement.getContainingFile();
|
||||
final Module module = ModuleUtil.findModuleForPsiElement(sourceFile);
|
||||
PsiPackage aPackage = null;
|
||||
if (qualifierElement instanceof PsiPackage) {
|
||||
aPackage = (PsiPackage)qualifierElement;
|
||||
}
|
||||
else {
|
||||
final PsiDirectory directory = sourceFile.getContainingDirectory();
|
||||
if (directory != null) {
|
||||
aPackage = JavaDirectoryService.getInstance().getPackage(directory);
|
||||
}
|
||||
|
||||
if (aPackage == null) {
|
||||
aPackage = JavaPsiFacade.getInstance(manager.getProject()).findPackage("");
|
||||
}
|
||||
}
|
||||
PsiPackage aPackage = findTargetPackage(qualifierElement, manager, sourceFile);
|
||||
if (aPackage == null) return null;
|
||||
final PsiDirectory targetDirectory;
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
@@ -335,6 +308,48 @@ public class CreateFromUsageUtils {
|
||||
return createClass(classKind, targetDirectory, name, manager, referenceElement, sourceFile, superClassName);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiPackage findTargetPackage(PsiElement qualifierElement, PsiManager manager, PsiFile sourceFile) {
|
||||
PsiPackage aPackage = null;
|
||||
if (qualifierElement instanceof PsiPackage) {
|
||||
aPackage = (PsiPackage)qualifierElement;
|
||||
}
|
||||
else {
|
||||
final PsiDirectory directory = sourceFile.getContainingDirectory();
|
||||
if (directory != null) {
|
||||
aPackage = JavaDirectoryService.getInstance().getPackage(directory);
|
||||
}
|
||||
|
||||
if (aPackage == null) {
|
||||
aPackage = JavaPsiFacade.getInstance(manager.getProject()).findPackage("");
|
||||
}
|
||||
}
|
||||
if (aPackage == null) return null;
|
||||
return aPackage;
|
||||
}
|
||||
|
||||
public static PsiClass createClassInQualifier(PsiClass psiClass,
|
||||
CreateClassKind classKind,
|
||||
String name,
|
||||
PsiJavaCodeReferenceElement referenceElement) {
|
||||
try {
|
||||
if (!CodeInsightUtilBase.preparePsiElementForWrite(psiClass)) return null;
|
||||
|
||||
PsiManager manager = psiClass.getManager();
|
||||
PsiElementFactory elementFactory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
|
||||
PsiClass result = classKind == INTERFACE ? elementFactory.createInterface(name) :
|
||||
classKind == CLASS ? elementFactory.createClass(name) :
|
||||
elementFactory.createEnum(name);
|
||||
CreateFromUsageBaseFix.setupGenericParameters(result, referenceElement);
|
||||
result = (PsiClass)manager.getCodeStyleManager().reformat(result);
|
||||
return (PsiClass) psiClass.add(result);
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static PsiClass createClass(final CreateClassKind classKind,
|
||||
final PsiDirectory directory,
|
||||
final String name,
|
||||
|
||||
@@ -78,8 +78,8 @@ public class PsiSuperMethodImplUtil {
|
||||
|
||||
@NotNull
|
||||
private static List<MethodSignatureBackedByPsiMethod> findSuperMethodSignatures(PsiMethod method,
|
||||
PsiClass parentClass,
|
||||
boolean allowStaticMethod) {
|
||||
PsiClass parentClass,
|
||||
boolean allowStaticMethod) {
|
||||
|
||||
return new ArrayList<MethodSignatureBackedByPsiMethod>(SuperMethodsSearch.search(method, parentClass, true, allowStaticMethod).findAll());
|
||||
}
|
||||
@@ -306,4 +306,58 @@ public class PsiSuperMethodImplUtil {
|
||||
private static Map<MethodSignature, HierarchicalMethodSignature> getSignaturesMap(final PsiClass aClass) {
|
||||
return SIGNATURES_KEY.getValue(aClass);
|
||||
}
|
||||
|
||||
|
||||
// uses hierarchy signature tree if available, traverses class structure by itself otherwise
|
||||
public static boolean isSuperMethodSmart(@NotNull PsiMethod method, @NotNull PsiMethod superMethod) {
|
||||
//boolean old = PsiSuperMethodUtil.isSuperMethod(method, superMethod);
|
||||
|
||||
if (method == superMethod) return false;
|
||||
PsiClass aClass = method.getContainingClass();
|
||||
PsiClass superClass = superMethod.getContainingClass();
|
||||
|
||||
if (aClass == null || superClass == null || superClass == aClass) return false;
|
||||
|
||||
if (!canHaveSuperMethod(method, true, false)) return false;
|
||||
|
||||
PsiMethod[] superMethods = null;
|
||||
Map<MethodSignature, HierarchicalMethodSignature> cachedMap = SIGNATURES_KEY.getCachedValueOrNull(aClass);
|
||||
if (cachedMap != null) {
|
||||
HierarchicalMethodSignature signature = cachedMap.get(method.getSignature(PsiSubstitutor.EMPTY));
|
||||
if (signature != null) {
|
||||
superMethods = MethodSignatureUtil.convertMethodSignaturesToMethods(signature.getSuperSignatures());
|
||||
}
|
||||
}
|
||||
if (superMethods == null) {
|
||||
PsiClassType[] directSupers = aClass.getSuperTypes();
|
||||
List<PsiMethod> found = null;
|
||||
boolean canceled = false;
|
||||
for (PsiClassType directSuper : directSupers) {
|
||||
PsiClassType.ClassResolveResult resolveResult = directSuper.resolveGenerics();
|
||||
if (resolveResult.getSubstitutor() != PsiSubstitutor.EMPTY) {
|
||||
// generics
|
||||
canceled = true;
|
||||
break;
|
||||
}
|
||||
PsiClass directSuperClass = resolveResult.getElement();
|
||||
if (directSuperClass == null) continue;
|
||||
PsiMethod[] candidates = directSuperClass.findMethodsBySignature(method, false);
|
||||
if (candidates.length != 0) {
|
||||
if (found == null) found = new ArrayList<PsiMethod>();
|
||||
for (PsiMethod candidate : candidates) {
|
||||
if (PsiUtil.canBeOverriden(candidate)) found.add(candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
superMethods = canceled ? null : found == null ? PsiMethod.EMPTY_ARRAY : found.toArray(new PsiMethod[found.size()]);
|
||||
}
|
||||
if (superMethods == null) {
|
||||
superMethods = MethodSignatureUtil.convertMethodSignaturesToMethods(method.getHierarchicalMethodSignature().getSuperSignatures());
|
||||
}
|
||||
|
||||
for (PsiMethod superCandidate : superMethods) {
|
||||
if (superMethod.equals(superCandidate) || isSuperMethodSmart(superCandidate, superMethod)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ public class SmartTypePointerManagerImpl extends SmartTypePointerManager {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SmartTypePointer createSmartTypePointer(PsiType type) {
|
||||
public SmartTypePointer createSmartTypePointer(@NotNull PsiType type) {
|
||||
return type.accept(new SmartTypeCreatingVisitor());
|
||||
}
|
||||
|
||||
|
||||
@@ -49,14 +49,23 @@ public class JavaResolveUtil {
|
||||
public static boolean isAccessible(@NotNull PsiMember member,
|
||||
@Nullable final PsiClass memberClass,
|
||||
@Nullable PsiModifierList modifierList,
|
||||
@NotNull PsiElement place,
|
||||
@NotNull PsiElement place,
|
||||
@Nullable PsiClass accessObjectClass,
|
||||
@Nullable final PsiElement fileResolveScope) {
|
||||
return isAccessible(member, memberClass, modifierList, place, accessObjectClass, fileResolveScope, place.getContainingFile());
|
||||
}
|
||||
|
||||
public static boolean isAccessible(@NotNull PsiMember member,
|
||||
@Nullable final PsiClass memberClass,
|
||||
@Nullable PsiModifierList modifierList,
|
||||
@NotNull PsiElement place,
|
||||
@Nullable PsiClass accessObjectClass,
|
||||
@Nullable final PsiElement fileResolveScope,
|
||||
final PsiFile placeFile) {
|
||||
if (modifierList == null) return true;
|
||||
final PsiFile placeContainingFile = place.getContainingFile();
|
||||
final PsiManager manager = member.getManager();
|
||||
if (placeContainingFile instanceof JavaCodeFragment) {
|
||||
JavaCodeFragment fragment = (JavaCodeFragment)placeContainingFile;
|
||||
if (placeFile instanceof JavaCodeFragment) {
|
||||
JavaCodeFragment fragment = (JavaCodeFragment)placeFile;
|
||||
JavaCodeFragment.VisibilityChecker visibilityChecker = fragment.getVisibilityChecker();
|
||||
if (visibilityChecker != null) {
|
||||
JavaCodeFragment.VisibilityChecker.Visibility visibility = visibilityChecker.isDeclarationVisible(member, place);
|
||||
@@ -64,17 +73,17 @@ public class JavaResolveUtil {
|
||||
if (visibility == JavaCodeFragment.VisibilityChecker.Visibility.NOT_VISIBLE) return false;
|
||||
}
|
||||
}
|
||||
else if (placeContainingFile instanceof XmlFile && !JspPsiUtil.isInJspFile(placeContainingFile)) return true;
|
||||
else if (placeFile instanceof XmlFile && !JspPsiUtil.isInJspFile(placeFile)) return true;
|
||||
// We don't care about access rights in javadoc
|
||||
if (isInJavaDoc(place)) return true;
|
||||
|
||||
if (accessObjectClass != null) {
|
||||
if (!isAccessible(accessObjectClass, accessObjectClass.getContainingClass(), accessObjectClass.getModifierList(), place, null,
|
||||
null)) return false;
|
||||
null, placeFile)) return false;
|
||||
}
|
||||
|
||||
int effectiveAccessLevel = PsiUtil.getAccessLevel(modifierList);
|
||||
PsiFile file = FileContextUtil.getContextFile(place); //TODO: implementation method!!!!
|
||||
PsiFile file = placeFile == null ? null : FileContextUtil.getContextFile(placeFile); //TODO: implementation method!!!!
|
||||
if (JspPsiUtil.isInJspFile(file) && JspPsiUtil.isInJspFile(member.getContainingFile())) return true;
|
||||
if (file instanceof XmlFile && !JspPsiUtil.isInJspFile(file)) return true;
|
||||
if (effectiveAccessLevel == PsiUtil.ACCESS_LEVEL_PUBLIC) {
|
||||
|
||||
@@ -15,7 +15,10 @@
|
||||
*/
|
||||
package com.intellij.psi.impl.source.resolve;
|
||||
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.RecursionGuard;
|
||||
import com.intellij.openapi.util.RecursionManager;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.infos.CandidateInfo;
|
||||
@@ -32,10 +35,8 @@ import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
private static final RecursionGuard ourGuard = RecursionManager.createGuard("typeArgInference");
|
||||
private final PsiManager myManager;
|
||||
|
||||
public PsiResolveHelperImpl(PsiManager manager) {
|
||||
@@ -146,7 +147,7 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
if (parameters.length > 0) {
|
||||
for (int j = 0; j < arguments.length; j++) {
|
||||
PsiExpression argument = arguments[j];
|
||||
if (argument instanceof PsiMethodCallExpression && myBlockedForInferenceMethodCalls.get().contains(argument)) continue;
|
||||
if (argument instanceof PsiMethodCallExpression && ourGuard.currentStack().contains(argument)) continue;
|
||||
|
||||
final PsiParameter parameter = parameters[Math.min(j, parameters.length - 1)];
|
||||
if (j >= parameters.length && !parameter.isVarArgs()) break;
|
||||
@@ -701,12 +702,7 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static final ThreadLocal<List<PsiCallExpression>> myBlockedForInferenceMethodCalls = new ThreadLocal<List<PsiCallExpression>>() {
|
||||
protected List<PsiCallExpression> initialValue() {
|
||||
return new ArrayList<PsiCallExpression>(2);
|
||||
}
|
||||
};
|
||||
|
||||
@Nullable
|
||||
private static Pair<PsiType, ConstraintType> inferTypeForCompletionFromCallContext(final PsiCallExpression innerMethodCall,
|
||||
final PsiExpressionList expressionList,
|
||||
final PsiCallExpression contextCall,
|
||||
@@ -722,7 +718,7 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
if (owner == null) return null;
|
||||
|
||||
final PsiType innerReturnType = owner.getReturnType();
|
||||
for (JavaResolveResult result : results) {
|
||||
for (final JavaResolveResult result : results) {
|
||||
final PsiElement element = result.getElement();
|
||||
if (element instanceof PsiMethod) {
|
||||
final PsiMethod method = (PsiMethod)element;
|
||||
@@ -735,10 +731,14 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
parameter = parameters[parameters.length - 1];
|
||||
}
|
||||
if (parameter != null) {
|
||||
//prevent infinite recursion
|
||||
myBlockedForInferenceMethodCalls.get().add(innerMethodCall);
|
||||
PsiType type = result.getSubstitutor().substitute(parameter.getType());
|
||||
myBlockedForInferenceMethodCalls.get().remove(innerMethodCall);
|
||||
final PsiParameter finalParameter = parameter;
|
||||
PsiType type = ourGuard
|
||||
.doPreventingRecursion(innerMethodCall, new Computable<PsiType>() {
|
||||
@Override
|
||||
public PsiType compute() {
|
||||
return result.getSubstitutor().substitute(finalParameter.getType());
|
||||
}
|
||||
}) ;
|
||||
final Pair<PsiType, ConstraintType> constraint =
|
||||
getSubstitutionForTypeParameterConstraint(typeParameter, innerReturnType, type, false, PsiUtil.getLanguageLevel(innerMethodCall));
|
||||
if (constraint != null) return constraint;
|
||||
|
||||
+7
-1
@@ -332,6 +332,7 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
|
||||
|
||||
public boolean isReferenceTo(PsiElement element) {
|
||||
IElementType i = getLastChildNode().getElementType();
|
||||
boolean resolvingToMethod = element instanceof PsiMethod;
|
||||
if (i == JavaTokenType.IDENTIFIER) {
|
||||
if (!(element instanceof PsiPackage)) {
|
||||
if (!(element instanceof PsiNamedElement)) return false;
|
||||
@@ -341,10 +342,15 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
|
||||
}
|
||||
}
|
||||
else if (i == JavaTokenType.SUPER_KEYWORD || i == JavaTokenType.THIS_KEYWORD) {
|
||||
if (!(element instanceof PsiMethod)) return false;
|
||||
if (!resolvingToMethod) return false;
|
||||
if (!((PsiMethod)element).isConstructor()) return false;
|
||||
}
|
||||
|
||||
PsiElement parent = getParent();
|
||||
boolean parentIsMethodCall = parent instanceof PsiMethodCallExpression;
|
||||
// optimization: methodCallExpression should resolve to a method
|
||||
if (parentIsMethodCall != resolvingToMethod) return false;
|
||||
|
||||
return element.getManager().areElementsEquivalent(element, resolve());
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.psi.resolve;
|
||||
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.infos.CandidateInfo;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
@@ -25,6 +26,7 @@ import com.intellij.psi.scope.conflictResolvers.DuplicateConflictResolver;
|
||||
import com.intellij.psi.scope.processor.MethodCandidatesProcessor;
|
||||
import com.intellij.psi.scope.processor.MethodResolverProcessor;
|
||||
import com.intellij.psi.util.MethodSignature;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import gnu.trove.THashSet;
|
||||
@@ -45,12 +47,14 @@ public class JavaMethodResolveHelper {
|
||||
|
||||
public JavaMethodResolveHelper(final PsiElement argumentList, @Nullable final PsiType[] parameterTypes) {
|
||||
myParameterTypes = parameterTypes;
|
||||
final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(argumentList);
|
||||
final PsiConflictResolver resolver = parameterTypes == null ? DuplicateConflictResolver.INSTANCE : new JavaMethodsConflictResolver(argumentList, parameterTypes);
|
||||
myProcessor = new MethodResolverProcessor(argumentList, new PsiConflictResolver[]{resolver}) {
|
||||
protected MethodCandidateInfo createCandidateInfo(final PsiMethod method, final PsiSubstitutor substitutor,
|
||||
final boolean staticProblem,
|
||||
final boolean accessible) {
|
||||
return new MethodCandidateInfo(method, substitutor, !accessible, staticProblem, argumentList, myCurrentFileContext, parameterTypes, PsiType.EMPTY_ARRAY);
|
||||
return new MethodCandidateInfo(method, substitutor, !accessible, staticProblem, argumentList, myCurrentFileContext, parameterTypes,
|
||||
PsiType.EMPTY_ARRAY, languageLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
-3
@@ -19,6 +19,7 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiSuperMethodImplUtil;
|
||||
import com.intellij.psi.infos.CandidateInfo;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.scope.PsiConflictResolver;
|
||||
@@ -150,7 +151,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
|
||||
if (!method.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
for (int k=i-1; k>=0; k--) {
|
||||
PsiMethod existingMethod = (PsiMethod)conflicts.get(k).getElement();
|
||||
if (PsiSuperMethodUtil.isSuperMethod(existingMethod, method)) {
|
||||
if (PsiSuperMethodImplUtil.isSuperMethodSmart(existingMethod, method)) {
|
||||
conflicts.remove(i);
|
||||
i--;
|
||||
continue nextConflict;
|
||||
@@ -189,12 +190,12 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
|
||||
// filter out methods with incorrect inferred bounds (for unrelated methods only)
|
||||
boolean existingTypeParamAgree = areTypeParametersAgree(existing);
|
||||
boolean infoTypeParamAgree = areTypeParametersAgree(info);
|
||||
if (existingTypeParamAgree && !infoTypeParamAgree && !PsiSuperMethodUtil.isSuperMethod(method, existingMethod)) {
|
||||
if (existingTypeParamAgree && !infoTypeParamAgree && !PsiSuperMethodImplUtil.isSuperMethodSmart(method, existingMethod)) {
|
||||
conflicts.remove(i);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
else if (!existingTypeParamAgree && infoTypeParamAgree && !PsiSuperMethodUtil.isSuperMethod(existingMethod, method)) {
|
||||
else if (!existingTypeParamAgree && infoTypeParamAgree && !PsiSuperMethodImplUtil.isSuperMethodSmart(existingMethod, method)) {
|
||||
signatures.put(signature, info);
|
||||
int index = conflicts.indexOf(existing);
|
||||
conflicts.remove(index);
|
||||
|
||||
@@ -16,10 +16,7 @@
|
||||
package com.intellij.psi.scope.processor;
|
||||
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.JavaResolveResult;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiSubstitutor;
|
||||
import com.intellij.psi.ResolveState;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.filters.ElementFilter;
|
||||
import com.intellij.psi.infos.CandidateInfo;
|
||||
import com.intellij.psi.scope.JavaScopeProcessorEvent;
|
||||
@@ -41,6 +38,7 @@ public class ConflictFilterProcessor extends FilterScopeProcessor<CandidateInfo>
|
||||
private JavaResolveResult[] myCachedResult = null;
|
||||
protected String myName;
|
||||
protected final PsiElement myPlace;
|
||||
protected final PsiFile myPlaceFile;
|
||||
|
||||
public ConflictFilterProcessor(String name, ElementFilter filter, PsiConflictResolver[] resolvers, List<CandidateInfo> container,
|
||||
final PsiElement place){
|
||||
@@ -48,6 +46,7 @@ public class ConflictFilterProcessor extends FilterScopeProcessor<CandidateInfo>
|
||||
myResolvers = resolvers;
|
||||
myName = name;
|
||||
myPlace = place;
|
||||
myPlaceFile = place.getContainingFile();
|
||||
}
|
||||
|
||||
public boolean execute(PsiElement element, ResolveState state){
|
||||
|
||||
@@ -50,7 +50,7 @@ public class MethodCandidatesProcessor extends MethodsProcessor{
|
||||
|
||||
public void addMethod(final PsiMethod method, final PsiSubstitutor substitutor, final boolean staticProblem) {
|
||||
boolean isAccessible = JavaResolveUtil.isAccessible(method, method.getContainingClass(), method.getModifierList(),
|
||||
myPlace, myAccessClass, myCurrentFileContext);
|
||||
myPlace, myAccessClass, myCurrentFileContext, myPlaceFile);
|
||||
myHasAccessibleStaticCorrectCandidate |= isAccessible && !staticProblem;
|
||||
|
||||
if (isAccepted(method)) {
|
||||
@@ -62,7 +62,7 @@ public class MethodCandidatesProcessor extends MethodsProcessor{
|
||||
final boolean staticProblem,
|
||||
final boolean accessible) {
|
||||
return new MethodCandidateInfo(method, substitutor, !accessible, staticProblem, getArgumentList(), myCurrentFileContext,
|
||||
getArgumentList().getExpressionTypes(), getTypeArguments());
|
||||
getArgumentList().getExpressionTypes(), getTypeArguments(), getLanguageLevel());
|
||||
}
|
||||
|
||||
protected boolean isAccepted(final PsiMethod candidate) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.intellij.psi.scope.processor;
|
||||
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.filters.ElementFilter;
|
||||
import com.intellij.psi.infos.CandidateInfo;
|
||||
@@ -23,6 +24,7 @@ import com.intellij.psi.scope.ElementClassFilter;
|
||||
import com.intellij.psi.scope.ElementClassHint;
|
||||
import com.intellij.psi.scope.JavaScopeProcessorEvent;
|
||||
import com.intellij.psi.scope.PsiConflictResolver;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
|
||||
/**
|
||||
@@ -41,6 +43,7 @@ public abstract class MethodsProcessor extends ConflictFilterProcessor implement
|
||||
protected PsiClass myAccessClass = null;
|
||||
private PsiExpressionList myArgumentList;
|
||||
private PsiType[] myTypeArguments;
|
||||
private LanguageLevel myLanguageLevel;
|
||||
|
||||
public MethodsProcessor(PsiConflictResolver[] resolvers, SmartList<CandidateInfo> container, final PsiElement place) {
|
||||
super(null, ourFilter, resolvers, container, place);
|
||||
@@ -52,6 +55,11 @@ public abstract class MethodsProcessor extends ConflictFilterProcessor implement
|
||||
|
||||
public void setArgumentList(PsiExpressionList argList) {
|
||||
myArgumentList = argList;
|
||||
myLanguageLevel = PsiUtil.getLanguageLevel(myArgumentList);
|
||||
}
|
||||
|
||||
protected LanguageLevel getLanguageLevel() {
|
||||
return myLanguageLevel;
|
||||
}
|
||||
|
||||
public void obtainTypeArguments(PsiCallExpression callExpression) {
|
||||
|
||||
@@ -252,7 +252,7 @@ public class CopyClassesHandler implements CopyHandlerDelegate {
|
||||
return newElement;
|
||||
}
|
||||
|
||||
private static PsiFile copy(PsiFile file, PsiDirectory directory, String name, String relativePath) {
|
||||
private static PsiFile copy(@NotNull PsiFile file, PsiDirectory directory, String name, String relativePath) {
|
||||
final String fileName = name != null ? (name + "." + file.getViewProvider().getVirtualFile().getExtension()) : file.getName();
|
||||
if (relativePath != null && !relativePath.isEmpty()) {
|
||||
return buildRelativeDir(directory, relativePath).findOrCreateTargetDirectory().copyFileFrom(fileName, file);
|
||||
|
||||
+15
-6
@@ -24,6 +24,7 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.editor.ScrollType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
@@ -116,7 +117,7 @@ public class InplaceIntroduceConstantPopup {
|
||||
}
|
||||
myOccurenceManager = occurenceManager;
|
||||
|
||||
myExprMarker = expr != null ? myEditor.getDocument().createRangeMarker(expr.getTextRange()) : null;
|
||||
myExprMarker = expr != null && expr.isPhysical() ? myEditor.getDocument().createRangeMarker(expr.getTextRange()) : null;
|
||||
myExprText = expr != null ? expr.getText() : null;
|
||||
myLocalName = localVariable != null ? localVariable.getName() : null;
|
||||
|
||||
@@ -200,6 +201,7 @@ public class InplaceIntroduceConstantPopup {
|
||||
final PsiField field = createFieldToStartTemplateOn(names, defaultType);
|
||||
if (field != null) {
|
||||
myEditor.getCaretModel().moveToOffset(field.getTextOffset());
|
||||
myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
|
||||
final LinkedHashSet<String> nameSuggestions = new LinkedHashSet<String>();
|
||||
nameSuggestions.add(field.getName());
|
||||
nameSuggestions.addAll(Arrays.asList(names));
|
||||
@@ -218,6 +220,10 @@ public class InplaceIntroduceConstantPopup {
|
||||
PsiField field = elementFactory.createFieldFromText(psiType.getCanonicalText() + " " + (myConstantName != null ? myConstantName : names[0]) + " = " + myExprText + ";", myParentClass);
|
||||
PsiUtil.setModifierProperty(field, PsiModifier.FINAL, true);
|
||||
PsiUtil.setModifierProperty(field, PsiModifier.STATIC, true);
|
||||
final String visibility = myVisibilityPanel.getVisibility();
|
||||
if (visibility != null) {
|
||||
PsiUtil.setModifierProperty(field, visibility, true);
|
||||
}
|
||||
field = BaseExpressionToFieldHandler.ConvertToFieldRunnable.appendField(myExpr, myParentClass, myParentClass, myAnchorElementIfAll, field);
|
||||
return field;
|
||||
}
|
||||
@@ -255,7 +261,7 @@ public class InplaceIntroduceConstantPopup {
|
||||
super(myProject, new TypeExpression(myProject, myTypeSelectorManager.getTypesForAll()),
|
||||
myEditor, field, false,
|
||||
myTypeSelectorManager.getTypesForAll().length > 1,
|
||||
myExpr != null ? myEditor.getDocument().createRangeMarker(myExpr.getTextRange()) : null, InplaceIntroduceConstantPopup.this.getOccurrenceMarkers());
|
||||
myExpr != null && myExpr.isPhysical() ? myEditor.getDocument().createRangeMarker(myExpr.getTextRange()) : null, InplaceIntroduceConstantPopup.this.getOccurrenceMarkers());
|
||||
|
||||
myDefaultParameterTypePointer =
|
||||
SmartTypePointerManager.getInstance(myProject).createSmartTypePointer(myTypeSelectorManager.getDefaultType());
|
||||
@@ -269,7 +275,7 @@ public class InplaceIntroduceConstantPopup {
|
||||
|
||||
@Override
|
||||
protected PsiExpression getExpr() {
|
||||
return myExpr;
|
||||
return myExpr != null && myExpr.isValid() && myExpr.isPhysical() ? myExpr : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -392,9 +398,12 @@ public class InplaceIntroduceConstantPopup {
|
||||
public void run() {
|
||||
final PsiFile containingFile = myParentClass.getContainingFile();
|
||||
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject);
|
||||
myExpr = restoreExpression(containingFile, psiField, elementFactory, getExprMarker(), myExprText);
|
||||
if (myExpr != null) {
|
||||
myExprMarker = myEditor.getDocument().createRangeMarker(myExpr.getTextRange());
|
||||
final RangeMarker exprMarker = getExprMarker();
|
||||
if (exprMarker != null) {
|
||||
myExpr = restoreExpression(containingFile, psiField, elementFactory, exprMarker, myExprText);
|
||||
if (myExpr != null && myExpr.isPhysical()) {
|
||||
myExprMarker = myEditor.getDocument().createRangeMarker(myExpr.getTextRange());
|
||||
}
|
||||
}
|
||||
final List<RangeMarker> occurrenceMarkers = getOccurrenceMarkers();
|
||||
for (int i = 0, occurrenceMarkersSize = occurrenceMarkers.size(); i < occurrenceMarkersSize; i++) {
|
||||
|
||||
+14
-6
@@ -22,6 +22,7 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.editor.ScrollType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.psi.*;
|
||||
@@ -95,7 +96,7 @@ public class InplaceIntroduceFieldPopup {
|
||||
myInitializerExpression = initializerExpression;
|
||||
myExprText = myInitializerExpression != null ? myInitializerExpression.getText() : null;
|
||||
myLocalName = localVariable != null ? localVariable.getName() : null;
|
||||
myExprMarker = myInitializerExpression != null ? editor.getDocument().createRangeMarker(myInitializerExpression.getTextRange()) : null;
|
||||
myExprMarker = myInitializerExpression != null && myInitializerExpression.isPhysical() ? editor.getDocument().createRangeMarker(myInitializerExpression.getTextRange()) : null;
|
||||
myTypeSelectorManager = typeSelectorManager;
|
||||
myAnchorElement = anchorElement;
|
||||
myAnchorElementIfAll = anchorElementIfAll;
|
||||
@@ -176,6 +177,7 @@ public class InplaceIntroduceFieldPopup {
|
||||
final PsiField field = createFieldToStartTemplateOn(suggestedNameInfo.names, defaultType);
|
||||
if (field != null) {
|
||||
myEditor.getCaretModel().moveToOffset(field.getTextOffset());
|
||||
myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
|
||||
final LinkedHashSet<String> nameSuggestions = new LinkedHashSet<String>();
|
||||
nameSuggestions.add(field.getName());
|
||||
nameSuggestions.addAll(Arrays.asList(suggestedNameInfo.names));
|
||||
@@ -195,6 +197,10 @@ public class InplaceIntroduceFieldPopup {
|
||||
PsiField field = elementFactory.createField(myFieldName != null ? myFieldName : names[0], defaultType);
|
||||
field = (PsiField)myParentClass.add(field);
|
||||
PsiUtil.setModifierProperty(field, PsiModifier.FINAL, myIntroduceFieldPanel.isDeclareFinal());
|
||||
final String visibility = myIntroduceFieldPanel.getFieldVisibility();
|
||||
if (visibility != null) {
|
||||
PsiUtil.setModifierProperty(field, visibility, true);
|
||||
}
|
||||
return field;
|
||||
}
|
||||
});
|
||||
@@ -233,7 +239,7 @@ public class InplaceIntroduceFieldPopup {
|
||||
super(myProject, new TypeExpression(myProject, myTypeSelectorManager.getTypesForAll()),
|
||||
myEditor, psiVariable, false,
|
||||
myTypeSelectorManager.getTypesForAll().length > 1,
|
||||
myInitializerExpression != null ? myEditor.getDocument().createRangeMarker(myInitializerExpression.getTextRange()) : null, InplaceIntroduceFieldPopup.this.getOccurrenceMarkers());
|
||||
myInitializerExpression != null && myInitializerExpression.isPhysical() ? myEditor.getDocument().createRangeMarker(myInitializerExpression.getTextRange()) : null, InplaceIntroduceFieldPopup.this.getOccurrenceMarkers());
|
||||
myDefaultParameterTypePointer =
|
||||
SmartTypePointerManager.getInstance(myProject).createSmartTypePointer(myTypeSelectorManager.getDefaultType());
|
||||
myFieldRangeStart = myEditor.getDocument().createRangeMarker(psiVariable.getTextRange());
|
||||
@@ -246,7 +252,7 @@ public class InplaceIntroduceFieldPopup {
|
||||
|
||||
@Override
|
||||
protected PsiExpression getExpr() {
|
||||
return myInitializerExpression;
|
||||
return myInitializerExpression != null && myInitializerExpression.isValid() && myInitializerExpression.isPhysical() ? myInitializerExpression : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -354,9 +360,11 @@ public class InplaceIntroduceFieldPopup {
|
||||
public void run() {
|
||||
final PsiFile containingFile = myParentClass.getContainingFile();
|
||||
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject);
|
||||
myInitializerExpression = restoreExpression(containingFile, psiField, elementFactory, getExprMarker(), myExprText);
|
||||
if (myInitializerExpression != null) {
|
||||
myExprMarker = myEditor.getDocument().createRangeMarker(myInitializerExpression.getTextRange());
|
||||
if (getExprMarker() != null) {
|
||||
myInitializerExpression = restoreExpression(containingFile, psiField, elementFactory, getExprMarker(), myExprText);
|
||||
if (myInitializerExpression != null) {
|
||||
myExprMarker = myEditor.getDocument().createRangeMarker(myInitializerExpression.getTextRange());
|
||||
}
|
||||
}
|
||||
final List<RangeMarker> occurrenceMarkers = getOccurrenceMarkers();
|
||||
for (int i = 0, occurrenceMarkersSize = occurrenceMarkers.size(); i < occurrenceMarkersSize; i++) {
|
||||
|
||||
+16
-9
@@ -22,6 +22,7 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.editor.ScrollType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.psi.*;
|
||||
@@ -135,6 +136,7 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI {
|
||||
if (parameter != null) {
|
||||
myParameterIndex = myMethod.getParameterList().getParameterIndex(parameter);
|
||||
myEditor.getCaretModel().moveToOffset(parameter.getTextOffset());
|
||||
myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
|
||||
final LinkedHashSet<String> nameSuggestions = new LinkedHashSet<String>();
|
||||
nameSuggestions.add(parameter.getName());
|
||||
nameSuggestions.addAll(Arrays.asList(names));
|
||||
@@ -247,20 +249,25 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI {
|
||||
getReplaceFieldsWithGetters(), myMustBeFinal || myFinal, isGenerateDelegate(),
|
||||
myParameterTypePointer.getType(),
|
||||
parametersToRemove);
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
final Runnable runnable = new Runnable() {
|
||||
public void run() {
|
||||
final boolean [] conflictsFound = new boolean[] {true};
|
||||
processor.setPrepareSuccessfulSwingThreadCallback(new Runnable() {
|
||||
@Override
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
conflictsFound[0] = processor.hasConflicts();
|
||||
final boolean [] conflictsFound = new boolean[] {true};
|
||||
processor.setPrepareSuccessfulSwingThreadCallback(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
conflictsFound[0] = processor.hasConflicts();
|
||||
}
|
||||
});
|
||||
processor.run();
|
||||
normalizeParameterIdxAccordingToRemovedParams(parametersToRemove);
|
||||
ParameterInplaceIntroducer.super.moveOffsetAfter(!conflictsFound[0]);
|
||||
}
|
||||
});
|
||||
processor.run();
|
||||
normalizeParameterIdxAccordingToRemovedParams(parametersToRemove);
|
||||
ParameterInplaceIntroducer.super.moveOffsetAfter(!conflictsFound[0]);
|
||||
}
|
||||
});
|
||||
};
|
||||
CommandProcessor.getInstance().executeCommand(myProject, runnable, IntroduceParameterHandler.REFACTORING_NAME, null);
|
||||
} else {
|
||||
super.moveOffsetAfter(success);
|
||||
}
|
||||
|
||||
+5
-1
@@ -90,7 +90,11 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
|
||||
final PsiElement[] statementsInRange = findStatementsAtOffset(editor, file, offset);
|
||||
|
||||
//try line selection
|
||||
if (statementsInRange.length == 1 && (PsiUtil.hasErrorElementChild(statementsInRange[0]) || !PsiUtil.isStatement(statementsInRange[0]) || isPreferStatements())) {
|
||||
if (statementsInRange.length == 1 && (PsiUtil.hasErrorElementChild(statementsInRange[0]) ||
|
||||
!PsiUtil.isStatement(statementsInRange[0]) ||
|
||||
statementsInRange[0].getTextRange().getStartOffset() >= offset ||
|
||||
statementsInRange[0].getTextRange().getEndOffset() <= offset ||
|
||||
isPreferStatements())) {
|
||||
selectionModel.selectLineAtCaret();
|
||||
if (findExpressionInRange(project, file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()) == null) {
|
||||
selectionModel.removeSelection();
|
||||
|
||||
+13
-9
@@ -28,10 +28,7 @@ import com.intellij.ide.IdeTooltipManager;
|
||||
import com.intellij.openapi.actionSystem.Shortcut;
|
||||
import com.intellij.openapi.application.*;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.editor.SelectionModel;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.keymap.Keymap;
|
||||
import com.intellij.openapi.keymap.KeymapManager;
|
||||
@@ -55,6 +52,7 @@ import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
|
||||
import com.intellij.ui.NonFocusableCheckBox;
|
||||
import com.intellij.ui.TitlePanel;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.ui.PositionTracker;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -161,8 +159,9 @@ public class VariableInplaceIntroducer extends VariableInplaceRenamer {
|
||||
|
||||
@Override
|
||||
public boolean performInplaceRename(boolean processTextOccurrences, LinkedHashSet<String> nameSuggestions) {
|
||||
final boolean result = super.performInplaceRename(processTextOccurrences, nameSuggestions);
|
||||
showBalloon();
|
||||
return super.performInplaceRename(processTextOccurrences, nameSuggestions);
|
||||
return result;
|
||||
}
|
||||
|
||||
public RangeMarker getExprMarker() {
|
||||
@@ -178,12 +177,13 @@ public class VariableInplaceIntroducer extends VariableInplaceRenamer {
|
||||
if (psiVariable == null) {
|
||||
return;
|
||||
}
|
||||
LOG.assertTrue(psiVariable.isValid());
|
||||
saveSettings(psiVariable);
|
||||
adjustLine(psiVariable, document);
|
||||
int startOffset = myExprMarker != null && myExprMarker.isValid() ? myExprMarker.getStartOffset() : psiVariable.getTextOffset();
|
||||
final PsiFile file = psiVariable.getContainingFile();
|
||||
final PsiReference referenceAt = file.findReferenceAt(startOffset);
|
||||
if (referenceAt != null && referenceAt.resolve() instanceof PsiLocalVariable) {
|
||||
if (referenceAt != null && referenceAt.resolve() instanceof PsiVariable) {
|
||||
startOffset = referenceAt.getElement().getTextRange().getEndOffset();
|
||||
}
|
||||
else {
|
||||
@@ -193,6 +193,7 @@ public class VariableInplaceIntroducer extends VariableInplaceRenamer {
|
||||
}
|
||||
}
|
||||
myEditor.getCaretModel().moveToOffset(startOffset);
|
||||
myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
|
||||
if (psiVariable.getInitializer() != null) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
@@ -353,7 +354,7 @@ public class VariableInplaceIntroducer extends VariableInplaceRenamer {
|
||||
if (ApplicationManager.getApplication().isHeadlessEnvironment()) return;
|
||||
final BalloonBuilder balloonBuilder = JBPopupFactory.getInstance().createBalloonBuilder(component);
|
||||
balloonBuilder.setFadeoutTime(0)
|
||||
.setFillColor(IdeTooltipManager.GRAPHITE_COLOR)
|
||||
.setFillColor(IdeTooltipManager.GRAPHITE_COLOR.brighter().brighter())
|
||||
.setAnimationCycle(0)
|
||||
.setHideOnClickOutside(false)
|
||||
.setHideOnKeyOutside(false)
|
||||
@@ -363,8 +364,11 @@ public class VariableInplaceIntroducer extends VariableInplaceRenamer {
|
||||
final RelativePoint target = JBPopupFactory.getInstance().guessBestPopupLocation(myEditor);
|
||||
final Point screenPoint = target.getScreenPoint();
|
||||
myBalloon = balloonBuilder.createBalloon();
|
||||
myBalloon
|
||||
.show(new RelativePoint(new Point(screenPoint.x, screenPoint.y - myEditor.getLineHeight())), Balloon.Position.above);
|
||||
int y = screenPoint.y;
|
||||
if (target.getPoint().getY() > myEditor.getLineHeight() + myBalloon.getPreferredSize().getHeight()) {
|
||||
y -= myEditor.getLineHeight();
|
||||
}
|
||||
myBalloon.show(new RelativePoint(new Point(screenPoint.x, y)), Balloon.Position.above);
|
||||
}
|
||||
|
||||
public class FinalListener implements ActionListener {
|
||||
|
||||
+21
-2
@@ -33,7 +33,10 @@ import com.intellij.psi.util.PsiUtilBase;
|
||||
import com.intellij.refactoring.BaseRefactoringProcessor;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.listeners.RefactoringElementListener;
|
||||
import com.intellij.refactoring.move.FileReferenceContextUtil;
|
||||
import com.intellij.refactoring.move.MoveCallback;
|
||||
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFileHandler;
|
||||
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil;
|
||||
import com.intellij.refactoring.rename.RenameUtil;
|
||||
import com.intellij.refactoring.util.NonCodeUsageInfo;
|
||||
import com.intellij.refactoring.util.RefactoringUIUtil;
|
||||
@@ -67,7 +70,8 @@ public class MoveDirectoryWithClassesProcessor extends BaseRefactoringProcessor
|
||||
if (targetDirectory != null) {
|
||||
final List<PsiDirectory> dirs = new ArrayList<PsiDirectory>(Arrays.asList(directories));
|
||||
for (Iterator<PsiDirectory> iterator = dirs.iterator(); iterator.hasNext();) {
|
||||
if (targetDirectory.equals(iterator.next().getParentDirectory())) {
|
||||
final PsiDirectory directory = iterator.next();
|
||||
if (targetDirectory.equals(directory.getParentDirectory()) || targetDirectory.equals(directory)) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
@@ -182,6 +186,7 @@ public class MoveDirectoryWithClassesProcessor extends BaseRefactoringProcessor
|
||||
Messages.showErrorDialog(myProject, e.getMessage(), CommonBundle.getErrorTitle());
|
||||
return;
|
||||
}
|
||||
final List<PsiFile> movedFiles = new ArrayList<PsiFile>();
|
||||
final Map<PsiElement, PsiElement> oldToNewElementsMapping = new HashMap<PsiElement, PsiElement>();
|
||||
for (PsiFile psiFile : myFilesToMove.keySet()) {
|
||||
ChangeContextUtil.encodeContextInfo(psiFile, true);
|
||||
@@ -195,7 +200,14 @@ public class MoveDirectoryWithClassesProcessor extends BaseRefactoringProcessor
|
||||
}
|
||||
} else {
|
||||
if (!moveDestination.equals(psiFile.getContainingDirectory())) {
|
||||
psiFile.getManager().moveFile(psiFile, moveDestination);
|
||||
MoveFileHandler.forElement(psiFile).prepareMovedFile(psiFile, moveDestination, oldToNewElementsMapping);
|
||||
|
||||
PsiFile moving = moveDestination.findFile(psiFile.getName());
|
||||
if (moving == null) {
|
||||
MoveFilesOrDirectoriesUtil.doMoveFile(psiFile, moveDestination);
|
||||
}
|
||||
moving = moveDestination.findFile(psiFile.getName());
|
||||
movedFiles.add(moving);
|
||||
listener.elementMoved(psiFile);
|
||||
}
|
||||
}
|
||||
@@ -203,6 +215,13 @@ public class MoveDirectoryWithClassesProcessor extends BaseRefactoringProcessor
|
||||
for (PsiElement newElement : oldToNewElementsMapping.values()) {
|
||||
ChangeContextUtil.decodeContextInfo(newElement, null, null);
|
||||
}
|
||||
|
||||
// fix references in moved files to outer files
|
||||
for (PsiFile movedFile : movedFiles) {
|
||||
MoveFileHandler.forElement(movedFile).updateMovedFile(movedFile);
|
||||
FileReferenceContextUtil.decodeFileReferences(movedFile);
|
||||
}
|
||||
|
||||
myNonCodeUsages = MoveClassesOrPackagesProcessor.retargetUsages(usages, oldToNewElementsMapping);
|
||||
for (UsageInfo usage : usages) {
|
||||
if (usage instanceof RemoveOnDemandImportStatementsUsageInfo) {
|
||||
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
public class Foo {
|
||||
|
||||
{
|
||||
aa<caret>
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -3,7 +3,7 @@ public class Test {
|
||||
public static void main() {
|
||||
Collection[] cc = new MyCollection[10];
|
||||
}
|
||||
}<caret>
|
||||
}
|
||||
|
||||
public class MyCollection {
|
||||
<caret>public class MyCollection {
|
||||
}
|
||||
+2
-2
@@ -6,7 +6,7 @@ public class Test {
|
||||
public static void main() {
|
||||
JTable table = new JTable(new MyTableModel());
|
||||
}
|
||||
}<caret>
|
||||
}
|
||||
|
||||
public class MyTableModel implements TableModel {
|
||||
<caret>public class MyTableModel implements TableModel {
|
||||
}
|
||||
+2
-2
@@ -3,7 +3,7 @@ class Test {
|
||||
void foo () {
|
||||
new Generic<String> ();
|
||||
}
|
||||
}<caret>
|
||||
}
|
||||
|
||||
public class Generic<T> {
|
||||
<caret>public class Generic<T> {
|
||||
}
|
||||
-7
@@ -48,13 +48,6 @@ public class HeavyNormalCompletionTest extends CompletionTestCase{
|
||||
checkResultByFile("/codeInsight/completion/normal/" + getTestName(false) + "_after.java");
|
||||
}
|
||||
|
||||
public void testOnlyUppercaseClassesWhenNothingIsFound() throws Throwable {
|
||||
createClass("package foo.bar; public class aaaxBxCxDxEx {}");
|
||||
|
||||
configureByFile("/codeInsight/completion/normal/" + getTestName(false) + ".java");
|
||||
checkResultByFile("/codeInsight/completion/normal/" + getTestName(false) + ".java");
|
||||
}
|
||||
|
||||
public void testAllClassesOnSecondBasicCompletion() throws Throwable {
|
||||
createClass("package foo.bar; public class AxBxCxDxEx {}");
|
||||
|
||||
|
||||
@@ -29,5 +29,5 @@ public abstract class SmartTypePointerManager {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public abstract SmartTypePointer createSmartTypePointer(PsiType type);
|
||||
public abstract SmartTypePointer createSmartTypePointer(@NotNull PsiType type);
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.psi.infos;
|
||||
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -28,6 +29,7 @@ public class MethodCandidateInfo extends CandidateInfo{
|
||||
private final PsiType[] myArgumentTypes;
|
||||
private final PsiType[] myTypeArguments;
|
||||
private PsiSubstitutor myCalcedSubstitutor = null;
|
||||
private final LanguageLevel myLanguageLevel;
|
||||
|
||||
public MethodCandidateInfo(PsiElement candidate,
|
||||
PsiSubstitutor substitutor,
|
||||
@@ -37,10 +39,24 @@ public class MethodCandidateInfo extends CandidateInfo{
|
||||
PsiElement currFileContext,
|
||||
@Nullable PsiType[] argumentTypes,
|
||||
PsiType[] typeArguments) {
|
||||
this(candidate, substitutor, accessProblem, staticsProblem, argumentList, currFileContext, argumentTypes, typeArguments,
|
||||
PsiUtil.getLanguageLevel(argumentList));
|
||||
}
|
||||
|
||||
public MethodCandidateInfo(PsiElement candidate,
|
||||
PsiSubstitutor substitutor,
|
||||
boolean accessProblem,
|
||||
boolean staticsProblem,
|
||||
PsiElement argumentList,
|
||||
PsiElement currFileContext,
|
||||
@Nullable PsiType[] argumentTypes,
|
||||
PsiType[] typeArguments,
|
||||
final LanguageLevel languageLevel) {
|
||||
super(candidate, substitutor, accessProblem, staticsProblem, currFileContext);
|
||||
myArgumentList = argumentList;
|
||||
myArgumentTypes = argumentTypes;
|
||||
myTypeArguments = typeArguments;
|
||||
myLanguageLevel = languageLevel;
|
||||
}
|
||||
|
||||
public boolean isApplicable(){
|
||||
@@ -50,7 +66,7 @@ public class MethodCandidateInfo extends CandidateInfo{
|
||||
private int getApplicabilityLevelInner() {
|
||||
if (myArgumentTypes == null) return ApplicabilityLevel.NOT_APPLICABLE;
|
||||
|
||||
int level = PsiUtil.getApplicabilityLevel(getElement(), getSubstitutor(), myArgumentTypes, PsiUtil.getLanguageLevel(myArgumentList));
|
||||
int level = PsiUtil.getApplicabilityLevel(getElement(), getSubstitutor(), myArgumentTypes, myLanguageLevel);
|
||||
if (level > ApplicabilityLevel.NOT_APPLICABLE && !isTypeArgumentsApplicable()) level = ApplicabilityLevel.NOT_APPLICABLE;
|
||||
return level;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class PsiSuperMethodUtil {
|
||||
@@ -70,7 +71,9 @@ public class PsiSuperMethodUtil {
|
||||
|
||||
public static boolean isSuperMethod(@NotNull PsiMethod method, @NotNull PsiMethod superMethod) {
|
||||
HierarchicalMethodSignature signature = method.getHierarchicalMethodSignature();
|
||||
for (HierarchicalMethodSignature supsig : signature.getSuperSignatures()) {
|
||||
List<HierarchicalMethodSignature> superSignatures = signature.getSuperSignatures();
|
||||
for (int i = 0, superSignaturesSize = superSignatures.size(); i < superSignaturesSize; i++) {
|
||||
HierarchicalMethodSignature supsig = superSignatures.get(i);
|
||||
PsiMethod supsigme = supsig.getMethod();
|
||||
if (superMethod.equals(supsigme) || isSuperMethod(supsigme, superMethod)) return true;
|
||||
}
|
||||
|
||||
@@ -190,26 +190,29 @@ public final class PsiUtil extends PsiUtilBase {
|
||||
PsiElement blockSoFar = null;
|
||||
while (element != null) {
|
||||
// variable can be defined in for loop initializer
|
||||
if (element instanceof PsiCodeBlock || element instanceof PsiForStatement || element instanceof PsiForeachStatement) {
|
||||
blockSoFar = element;
|
||||
}
|
||||
PsiElement parent = element.getParent();
|
||||
if (parent instanceof PsiMethod
|
||||
&& parent.getParent() instanceof PsiClass
|
||||
&& !isLocalOrAnonymousClass((PsiClass)parent.getParent()))
|
||||
break;
|
||||
if (parent instanceof PsiClassInitializer && !(parent.getParent() instanceof PsiAnonymousClass)) break;
|
||||
if (parent instanceof PsiField && ((PsiField) parent).getInitializer() == element) {
|
||||
blockSoFar = element;
|
||||
}
|
||||
if (parent instanceof PsiClassLevelDeclarationStatement) {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
if (element instanceof PsiClass && !isLocalOrAnonymousClass((PsiClass)element)) {
|
||||
break;
|
||||
}
|
||||
if (element instanceof PsiFile && PsiUtilBase.getTemplateLanguageFile(element) != null) {
|
||||
return element;
|
||||
if (!(parent instanceof PsiExpression)) {
|
||||
if (element instanceof PsiCodeBlock || element instanceof PsiForStatement || element instanceof PsiForeachStatement) {
|
||||
blockSoFar = element;
|
||||
}
|
||||
|
||||
if (parent instanceof PsiMethod
|
||||
&& parent.getParent() instanceof PsiClass
|
||||
&& !isLocalOrAnonymousClass((PsiClass)parent.getParent()))
|
||||
break;
|
||||
if (parent instanceof PsiClassInitializer && !(parent.getParent() instanceof PsiAnonymousClass)) break;
|
||||
if (parent instanceof PsiField && ((PsiField) parent).getInitializer() == element) {
|
||||
blockSoFar = element;
|
||||
}
|
||||
if (parent instanceof PsiClassLevelDeclarationStatement) {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
if (element instanceof PsiClass && !isLocalOrAnonymousClass((PsiClass)element)) {
|
||||
break;
|
||||
}
|
||||
if (element instanceof PsiFile && PsiUtilBase.getTemplateLanguageFile(element) != null) {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
if (element == scope) break;
|
||||
element = parent;
|
||||
|
||||
@@ -123,7 +123,9 @@ public abstract class StubBase<T extends PsiElement> extends UserDataHolderBase
|
||||
|
||||
private int countChildren(final IElementType elementType) {
|
||||
int count = 0;
|
||||
for (StubElement childStub : getChildrenStubs()) {
|
||||
List<StubElement> childrenStubs = getChildrenStubs();
|
||||
for (int i = 0, childrenStubsSize = childrenStubs.size(); i < childrenStubsSize; i++) {
|
||||
StubElement childStub = childrenStubs.get(i);
|
||||
if (childStub.getStubType() == elementType) count++;
|
||||
}
|
||||
|
||||
@@ -132,7 +134,9 @@ public abstract class StubBase<T extends PsiElement> extends UserDataHolderBase
|
||||
|
||||
private int countChildren(final TokenSet types) {
|
||||
int count = 0;
|
||||
for (StubElement childStub : getChildrenStubs()) {
|
||||
List<StubElement> childrenStubs = getChildrenStubs();
|
||||
for (int i = 0, childrenStubsSize = childrenStubs.size(); i < childrenStubsSize; i++) {
|
||||
StubElement childStub = childrenStubs.get(i);
|
||||
if (types.contains(childStub.getStubType())) count++;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,9 +21,11 @@ package com.intellij.psi.util;
|
||||
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.UserDataHolderEx;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.Function;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PsiCacheKey<T,H extends PsiElement> extends Key<Pair<Long, T>> {
|
||||
private final Function<H,T> myFunction;
|
||||
@@ -34,10 +36,34 @@ public class PsiCacheKey<T,H extends PsiElement> extends Key<Pair<Long, T>> {
|
||||
}
|
||||
|
||||
public final T getValue(H h) {
|
||||
while (true) {
|
||||
Pair<Long, T> data = h.getUserData(this);
|
||||
|
||||
final long count = h.getManager().getModificationTracker().getJavaStructureModificationCount();
|
||||
if (data == null) {
|
||||
data = new Pair<Long, T>(count, myFunction.fun(h));
|
||||
data = ((UserDataHolderEx)h).putUserDataIfAbsent(this, data);
|
||||
}
|
||||
else if (data.getFirst() != count) {
|
||||
Pair<Long, T> newData = new Pair<Long, T>(count, myFunction.fun(h));
|
||||
if (((UserDataHolderEx)h).replace(this, data, newData)) {
|
||||
data = newData;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return data.getSecond();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public final T getCachedValueOrNull(H h) {
|
||||
Pair<Long, T> data = h.getUserData(this);
|
||||
final long count = h.getManager().getModificationTracker().getJavaStructureModificationCount();
|
||||
if (data == null || data.getFirst() != count) {
|
||||
h.putUserData(this, data = new Pair<Long, T>(count, myFunction.fun(h)));
|
||||
return null;
|
||||
}
|
||||
|
||||
return data.getSecond();
|
||||
|
||||
+3
-1
@@ -103,7 +103,9 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
assert psiFile != null : "no PSI file: " + FileDocumentManager.getInstance().getFile(editor.getDocument());
|
||||
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
assert !ApplicationManager.getApplication().isWriteAccessAllowed() : "Completion should not be invoked inside write action";
|
||||
if (ApplicationManager.getApplication().isWriteAccessAllowed()) {
|
||||
throw new AssertionError("Completion should not be invoked inside write action");
|
||||
}
|
||||
}
|
||||
|
||||
if (editor.isViewer()) {
|
||||
|
||||
+1
-1
@@ -320,7 +320,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
if (isOutdated()) return;
|
||||
|
||||
if (!myLookup.isShown()) {
|
||||
if (!myLookup.isShown() && (!isAutopopupCompletion() || !myLookup.isCalculating())) {
|
||||
if (hideAutopopupIfMeaningless()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import com.intellij.openapi.editor.EditorModificationUtil;
|
||||
import com.intellij.openapi.editor.actionSystem.TypedActionHandler;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@@ -98,26 +99,43 @@ public class TypedHandler implements TypedActionHandler {
|
||||
}
|
||||
|
||||
static CharFilter.Result getLookupAction(final char charTyped, final LookupImpl lookup) {
|
||||
final CharFilter.Result filtersDecision = getFiltersDecision(charTyped, lookup);
|
||||
|
||||
final LookupElement currentItem = lookup.getCurrentItem();
|
||||
if (currentItem != null && charTyped != ' ') {
|
||||
String postfix = lookup.getAdditionalPrefix() + charTyped;
|
||||
final PrefixMatcher matcher = currentItem.getPrefixMatcher();
|
||||
if (matcher.cloneWithPrefix(matcher.getPrefix() + postfix).prefixMatches(currentItem)) {
|
||||
return CharFilter.Result.ADD_TO_PREFIX;
|
||||
}
|
||||
for (final LookupElement element : lookup.getItems()) {
|
||||
if (element.isPrefixMatched() && element.getPrefixMatcher().cloneWithPrefix(element.getPrefixMatcher().getPrefix() + postfix).prefixMatches(element)) {
|
||||
if (charTyped != '*' || filtersDecision != CharFilter.Result.SELECT_ITEM_AND_FINISH_LOOKUP) {
|
||||
String postfix = lookup.getAdditionalPrefix() + charTyped;
|
||||
final PrefixMatcher matcher = currentItem.getPrefixMatcher();
|
||||
if (matcher.cloneWithPrefix(matcher.getPrefix() + postfix).prefixMatches(currentItem)) {
|
||||
return CharFilter.Result.ADD_TO_PREFIX;
|
||||
}
|
||||
for (final LookupElement element : lookup.getItems()) {
|
||||
if (element.isPrefixMatched() &&
|
||||
element.getPrefixMatcher().cloneWithPrefix(element.getPrefixMatcher().getPrefix() + postfix).prefixMatches(element)) {
|
||||
return CharFilter.Result.ADD_TO_PREFIX;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
final CharFilter[] filters = Extensions.getExtensions(CharFilter.EP_NAME);
|
||||
for (final CharFilter extension : filters) {
|
||||
|
||||
if (filtersDecision != null) return filtersDecision;
|
||||
throw new AssertionError("Typed char not handler by char filter: c=" + charTyped +
|
||||
"; prefix=" + currentItem +
|
||||
"; filters=" + Arrays.toString(getFilters()));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static CharFilter.Result getFiltersDecision(char charTyped, LookupImpl lookup) {
|
||||
for (final CharFilter extension : getFilters()) {
|
||||
final CharFilter.Result result = extension.acceptChar(charTyped, lookup.getMinPrefixLength() + lookup.getAdditionalPrefix().length(), lookup);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
throw new AssertionError("Typed char not handler by char filter: c=" + charTyped + "; prefix=" + currentItem + "; filters=" + Arrays.toString(filters));
|
||||
return null;
|
||||
}
|
||||
|
||||
private static CharFilter[] getFilters() {
|
||||
return Extensions.getExtensions(CharFilter.EP_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,6 @@ import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
@@ -61,6 +60,7 @@ import com.intellij.psi.impl.PsiManagerEx;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import com.intellij.ui.SideBorder;
|
||||
import com.intellij.util.FileContentUtil;
|
||||
import com.intellij.util.ui.AbstractLayoutManager;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.update.MergingUpdateQueue;
|
||||
import com.intellij.util.ui.update.Update;
|
||||
@@ -88,7 +88,7 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
|
||||
private final Document myEditorDocument;
|
||||
protected PsiFile myFile;
|
||||
|
||||
private final JPanel myPanel = new JPanel(new BorderLayout());
|
||||
private final JPanel myPanel = new JPanel(new MyLayout());
|
||||
|
||||
private String myTitle;
|
||||
private String myPrompt = "> ";
|
||||
@@ -125,20 +125,17 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
|
||||
};
|
||||
myConsoleEditor.setColorsScheme(scheme);
|
||||
myHistoryViewer.setColorsScheme(scheme);
|
||||
myPanel.add(myHistoryViewer.getComponent(), BorderLayout.CENTER);
|
||||
myPanel.add(myConsoleEditor.getComponent(), BorderLayout.SOUTH);
|
||||
myPanel.add(myHistoryViewer.getComponent());
|
||||
myPanel.add(myConsoleEditor.getComponent());
|
||||
setupComponents();
|
||||
myPanel.putClientProperty(DataManager.CLIENT_PROPERTY_DATA_PROVIDER, new TypeSafeDataProviderAdapter(this));
|
||||
myUpdateQueue = new MergingUpdateQueue("ConsoleUpdateQueue", 300, true, null);
|
||||
Disposer.register(this, myUpdateQueue);
|
||||
myPanel.addComponentListener(new ComponentAdapter() {
|
||||
myHistoryViewer.getComponent().addComponentListener(new ComponentAdapter() {
|
||||
public void componentResized(ComponentEvent e) {
|
||||
try {
|
||||
myHistoryViewer.getScrollingModel().disableAnimation();
|
||||
updateSizes(true);
|
||||
}
|
||||
finally {
|
||||
myHistoryViewer.getScrollingModel().enableAnimation();
|
||||
if (myForceScrollToEnd.getAndSet(false)) {
|
||||
final JScrollBar scrollBar = myHistoryViewer.getScrollPane().getVerticalScrollBar();
|
||||
scrollBar.setValue(scrollBar.getMaximum());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,8 +155,8 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
|
||||
fileManager.closeFile(virtualFile);
|
||||
myFullEditor = null;
|
||||
myPanel.removeAll();
|
||||
myPanel.add(myHistoryViewer.getComponent(), BorderLayout.CENTER);
|
||||
myPanel.add(myConsoleEditor.getComponent(), BorderLayout.SOUTH);
|
||||
myPanel.add(myHistoryViewer.getComponent());
|
||||
myPanel.add(myConsoleEditor.getComponent());
|
||||
|
||||
myHistoryViewer.setHorizontalScrollbarVisible(false);
|
||||
}
|
||||
@@ -390,14 +387,8 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
|
||||
|
||||
public boolean shouldScrollHistoryToEnd() {
|
||||
final Rectangle visibleArea = myHistoryViewer.getScrollingModel().getVisibleArea();
|
||||
final LogicalPosition pos = ApplicationManager.getApplication().runReadAction(new Computable<LogicalPosition>() {
|
||||
@Override
|
||||
public LogicalPosition compute() {
|
||||
return myHistoryViewer.xyToLogicalPosition(new Point(visibleArea.x, visibleArea.y + visibleArea.height));
|
||||
}
|
||||
});
|
||||
final int lineCount = myHistoryViewer.getDocument().getLineCount();
|
||||
return pos.line >= lineCount - 1;
|
||||
final Dimension contentSize = myHistoryViewer.getContentSize();
|
||||
return contentSize.getHeight() - visibleArea.getMaxY() < 2*myHistoryViewer.getLineHeight();
|
||||
}
|
||||
|
||||
private void scrollHistoryToEnd() {
|
||||
@@ -470,7 +461,7 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
|
||||
myUpdateQueue.queue(new Update("UpdateUi") {
|
||||
public void run() {
|
||||
if (Disposer.isDisposed(LanguageConsoleImpl.this)) return;
|
||||
updateSizes(myForceScrollToEnd.getAndSet(false));
|
||||
updateSizes();
|
||||
if (myUiUpdateRunnable != null) {
|
||||
ApplicationManager.getApplication().runReadAction(myUiUpdateRunnable);
|
||||
}
|
||||
@@ -478,63 +469,10 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
|
||||
});
|
||||
}
|
||||
|
||||
private void updateSizes(boolean forceScrollToEnd) {
|
||||
private void updateSizes() {
|
||||
if (myFullEditor != null) return;
|
||||
final Dimension panelSize = myPanel.getSize();
|
||||
if (panelSize.getHeight() <= 0) return;
|
||||
final Dimension historySize = myHistoryViewer.getContentSize();
|
||||
final Dimension editorSize = myConsoleEditor.getContentSize();
|
||||
final Dimension newEditorSize = new Dimension();
|
||||
|
||||
// deal with width
|
||||
final int width = Math.max(editorSize.width, historySize.width);
|
||||
newEditorSize.width = width + myConsoleEditor.getScrollPane().getHorizontalScrollBar().getHeight();
|
||||
myConsoleEditor.getSettings().setAdditionalColumnsCount(2 + (width - editorSize.width) / EditorUtil.getSpaceWidth(Font.PLAIN, myConsoleEditor));
|
||||
myHistoryViewer.getSettings().setAdditionalColumnsCount(2 + (width - historySize.width) / EditorUtil.getSpaceWidth(Font.PLAIN, myHistoryViewer));
|
||||
|
||||
// deal with height
|
||||
if (historySize.width == 0) historySize.height = 0;
|
||||
final int minHistorySize = historySize.height > 0 ? 2 * myHistoryViewer.getLineHeight() + SEPARATOR_THICKNESS : 0;
|
||||
final int minEditorSize = myConsoleEditor.isViewer()? 0 : myConsoleEditor.getLineHeight();
|
||||
final int editorPreferred = myConsoleEditor.isViewer()? 0 : Math.max(minEditorSize, editorSize.height);
|
||||
final int historyPreferred = Math.max(minHistorySize, historySize.height);
|
||||
if (panelSize.height < minEditorSize) {
|
||||
newEditorSize.height = panelSize.height;
|
||||
}
|
||||
else if (panelSize.height < editorPreferred) {
|
||||
newEditorSize.height = panelSize.height - minHistorySize;
|
||||
}
|
||||
else if (panelSize.height < editorPreferred + historyPreferred) {
|
||||
newEditorSize.height = editorPreferred;
|
||||
}
|
||||
else {
|
||||
newEditorSize.height = editorPreferred == 0? 0 : panelSize.height - historyPreferred;
|
||||
}
|
||||
final Dimension newHistorySize = new Dimension(width, panelSize.height - newEditorSize.height);
|
||||
|
||||
// apply
|
||||
boolean changed = false;
|
||||
final Dimension curEditorSize = myConsoleEditor.getComponent().getPreferredSize();
|
||||
if (!curEditorSize.equals(newEditorSize)) {
|
||||
myConsoleEditor.getComponent().setPreferredSize(newEditorSize);
|
||||
changed = true;
|
||||
}
|
||||
final boolean scrollToEnd;
|
||||
final Dimension curHistorySize = myHistoryViewer.getComponent().getPreferredSize();
|
||||
if (!curHistorySize.equals(newHistorySize) && (curHistorySize.height != 0 || newHistorySize.height != 0)) {
|
||||
scrollToEnd = forceScrollToEnd || shouldScrollHistoryToEnd();
|
||||
myHistoryViewer.getComponent().setPreferredSize(newHistorySize);
|
||||
changed = true;
|
||||
}
|
||||
else scrollToEnd = forceScrollToEnd;
|
||||
|
||||
if (changed) {
|
||||
// layout immediately
|
||||
myPanel.doLayout();
|
||||
}
|
||||
if (scrollToEnd) {
|
||||
scrollHistoryToEnd();
|
||||
}
|
||||
myPanel.revalidate();
|
||||
myPanel.repaint();
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
@@ -622,7 +560,6 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
|
||||
((PsiManagerEx)prevFile.getManager()).getFileManager().setViewProvider(file, null);
|
||||
}
|
||||
|
||||
final FileType type = language.getAssociatedFileType();
|
||||
@NonNls final String name = getTitle();
|
||||
final LightVirtualFile newVFile = new LightVirtualFile(name, language, myEditorDocument.getText());
|
||||
FileDocumentManagerImpl.registerDocument(myEditorDocument, newVFile);
|
||||
@@ -701,4 +638,61 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
|
||||
}, ModalityState.stateForComponent(console.getComponent()));
|
||||
}
|
||||
}
|
||||
|
||||
private class MyLayout extends AbstractLayoutManager {
|
||||
@Override
|
||||
public Dimension preferredLayoutSize(final Container parent) {
|
||||
return new Dimension(0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void layoutContainer(final Container parent) {
|
||||
final int componentCount = parent.getComponentCount();
|
||||
if (componentCount == 0) return;
|
||||
final EditorEx history = myHistoryViewer;
|
||||
final EditorEx editor = componentCount == 2? myConsoleEditor : null;
|
||||
|
||||
if (editor == null) {
|
||||
parent.getComponent(0).setBounds(parent.getBounds());
|
||||
return;
|
||||
}
|
||||
|
||||
final Dimension panelSize = parent.getSize();
|
||||
if (panelSize.getHeight() <= 0) return;
|
||||
final Dimension historySize = history.getContentSize();
|
||||
final Dimension editorSize = editor.getContentSize();
|
||||
final Dimension newEditorSize = new Dimension();
|
||||
|
||||
// deal with width
|
||||
final int width = Math.max(editorSize.width, historySize.width);
|
||||
newEditorSize.width = width + editor.getScrollPane().getHorizontalScrollBar().getHeight();
|
||||
editor.getSettings().setAdditionalColumnsCount(2 + (width - editorSize.width) / EditorUtil.getSpaceWidth(Font.PLAIN, editor));
|
||||
history.getSettings().setAdditionalColumnsCount(2 + (width - historySize.width) / EditorUtil.getSpaceWidth(Font.PLAIN, history));
|
||||
|
||||
// deal with height
|
||||
if (historySize.width == 0) historySize.height = 0;
|
||||
final int minHistorySize = historySize.height > 0 ? 2 * history.getLineHeight() + SEPARATOR_THICKNESS : 0;
|
||||
final int minEditorSize = editor.isViewer() ? 0 : editor.getLineHeight();
|
||||
final int editorPreferred = editor.isViewer() ? 0 : Math.max(minEditorSize, editorSize.height);
|
||||
final int historyPreferred = Math.max(minHistorySize, historySize.height);
|
||||
if (panelSize.height < minEditorSize) {
|
||||
newEditorSize.height = panelSize.height;
|
||||
}
|
||||
else if (panelSize.height < editorPreferred) {
|
||||
newEditorSize.height = panelSize.height - minHistorySize;
|
||||
}
|
||||
else if (panelSize.height < editorPreferred + historyPreferred) {
|
||||
newEditorSize.height = editorPreferred;
|
||||
}
|
||||
else {
|
||||
newEditorSize.height = editorPreferred == 0 ? 0 : panelSize.height - historyPreferred;
|
||||
}
|
||||
final Dimension newHistorySize = new Dimension(width, panelSize.height - newEditorSize.height);
|
||||
|
||||
// apply
|
||||
editor.getComponent().setBounds(0, newHistorySize.height, panelSize.width, newEditorSize.height);
|
||||
myForceScrollToEnd.compareAndSet(false, shouldScrollHistoryToEnd());
|
||||
history.getComponent().setBounds(0, 0, panelSize.width, newHistorySize.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,4 +62,19 @@ public class TextConsoleBuilderImpl extends TextConsoleBuilder {
|
||||
myViewer = isViewer;
|
||||
}
|
||||
|
||||
protected Project getProject() {
|
||||
return myProject;
|
||||
}
|
||||
|
||||
protected GlobalSearchScope getScope() {
|
||||
return myScope;
|
||||
}
|
||||
|
||||
protected ArrayList<Filter> getFilters() {
|
||||
return myFilters;
|
||||
}
|
||||
|
||||
protected boolean isViewer() {
|
||||
return myViewer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,28 +16,15 @@
|
||||
|
||||
package com.intellij.execution.impl;
|
||||
|
||||
import com.intellij.execution.process.ProcessAdapter;
|
||||
import com.intellij.execution.process.ProcessEvent;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.execution.ui.ConsoleViewContentType;
|
||||
import com.intellij.execution.ExecutionBundle;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
|
||||
public abstract class ConsoleState {
|
||||
public static final ConsoleState NOT_STARTED = new ConsoleState(){
|
||||
public ConsoleState attachTo(final ConsoleViewImpl console, final ProcessHandler processHandler) {
|
||||
return new RunningState(console, processHandler);
|
||||
}
|
||||
};
|
||||
|
||||
public ConsoleState dispose() {
|
||||
return NOT_STARTED;
|
||||
}
|
||||
public abstract ConsoleState attachTo(ConsoleViewImpl console, ProcessHandler processHandler);
|
||||
@NotNull
|
||||
public abstract ConsoleState dispose();
|
||||
|
||||
public boolean isFinished() {
|
||||
return false;
|
||||
@@ -49,50 +36,17 @@ public abstract class ConsoleState {
|
||||
|
||||
public void sendUserInput(final String input) throws IOException {}
|
||||
|
||||
public abstract ConsoleState attachTo(ConsoleViewImpl console, ProcessHandler processHandler);
|
||||
|
||||
private static class RunningState extends ConsoleState {
|
||||
private final ConsoleViewImpl myConsole;
|
||||
private final ProcessAdapter myProcessListener = new ProcessAdapter() {
|
||||
public void onTextAvailable(final ProcessEvent event, final Key outputType) {
|
||||
myConsole.print(event.getText(), ConsoleViewContentType.getConsoleViewType(outputType));
|
||||
}
|
||||
};
|
||||
private final ProcessHandler myProcessHandler;
|
||||
private final Writer myUserInputWriter;
|
||||
|
||||
public RunningState(final ConsoleViewImpl console, final ProcessHandler processHandler) {
|
||||
myConsole = console;
|
||||
myProcessHandler = processHandler;
|
||||
processHandler.addProcessListener(myProcessListener);
|
||||
final OutputStream processInput = myProcessHandler.getProcessInput();
|
||||
myUserInputWriter = processInput != null ? new OutputStreamWriter(processInput) : null;
|
||||
}
|
||||
|
||||
public abstract static class NotStartedStated extends ConsoleState {
|
||||
@NotNull
|
||||
@Override
|
||||
public ConsoleState dispose() {
|
||||
if (myProcessHandler != null) {
|
||||
myProcessHandler.removeProcessListener(myProcessListener);
|
||||
}
|
||||
return NOT_STARTED;
|
||||
// not disposable
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
return myProcessHandler == null || myProcessHandler.isProcessTerminated();
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return myProcessHandler != null && !myProcessHandler.isProcessTerminated();
|
||||
}
|
||||
|
||||
public void sendUserInput(final String input) throws IOException {
|
||||
if (myUserInputWriter == null)
|
||||
throw new IOException(ExecutionBundle.message("no.user.process.input.error.message"));
|
||||
myUserInputWriter.write(input);
|
||||
myUserInputWriter.flush();
|
||||
}
|
||||
|
||||
public ConsoleState attachTo(final ConsoleViewImpl console, final ProcessHandler processHandler) {
|
||||
return dispose().attachTo(console, processHandler);
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Not started state";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +147,8 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
|
||||
private final DisposedPsiManagerCheck myPsiDisposedCheck;
|
||||
private final boolean isViewer;
|
||||
|
||||
private ConsoleState myState = ConsoleState.NOT_STARTED;
|
||||
private ConsoleState myState;
|
||||
|
||||
private Computable<ModalityState> myStateForUpdate;
|
||||
|
||||
private static int getCycleBufferSize() {
|
||||
@@ -366,8 +367,20 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
|
||||
}
|
||||
|
||||
public ConsoleViewImpl(final Project project, GlobalSearchScope searchScope, boolean viewer, FileType fileType) {
|
||||
this(project, searchScope, viewer, fileType,
|
||||
new ConsoleState.NotStartedStated() {
|
||||
@Override
|
||||
public ConsoleState attachTo(ConsoleViewImpl console, ProcessHandler processHandler) {
|
||||
return new ConsoleViewRunningState(console, processHandler, this, true, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected ConsoleViewImpl(final Project project, GlobalSearchScope searchScope, boolean viewer, FileType fileType,
|
||||
@NotNull final ConsoleState initialState) {
|
||||
super(new BorderLayout());
|
||||
isViewer = viewer;
|
||||
myState = initialState;
|
||||
myPsiDisposedCheck = new DisposedPsiManagerCheck(project);
|
||||
myProject = project;
|
||||
myFileType = fileType;
|
||||
@@ -1061,7 +1074,10 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
|
||||
}
|
||||
});
|
||||
|
||||
setEditorUpActions(editor);
|
||||
if (!isViewer) {
|
||||
setEditorUpActions(editor);
|
||||
}
|
||||
|
||||
return editor;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.execution.impl;
|
||||
|
||||
import com.intellij.execution.ExecutionBundle;
|
||||
import com.intellij.execution.process.ProcessAdapter;
|
||||
import com.intellij.execution.process.ProcessEvent;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.execution.ui.ConsoleViewContentType;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
|
||||
|
||||
public class ConsoleViewRunningState extends ConsoleState {
|
||||
private final ConsoleViewImpl myConsole;
|
||||
private final ProcessHandler myProcessHandler;
|
||||
private final ConsoleState myFinishedStated;
|
||||
private final Writer myUserInputWriter;
|
||||
|
||||
private final ProcessAdapter myProcessListener = new ProcessAdapter() {
|
||||
public void onTextAvailable(final ProcessEvent event, final Key outputType) {
|
||||
myConsole.print(event.getText(), ConsoleViewContentType.getConsoleViewType(outputType));
|
||||
}
|
||||
};
|
||||
|
||||
public ConsoleViewRunningState(final ConsoleViewImpl console, final ProcessHandler processHandler,
|
||||
final ConsoleState finishedStated,
|
||||
final boolean attachToStdOut,
|
||||
final boolean attachToStdIn) {
|
||||
|
||||
myConsole = console;
|
||||
myProcessHandler = processHandler;
|
||||
myFinishedStated = finishedStated;
|
||||
|
||||
// attach to process stdout
|
||||
if (attachToStdOut) {
|
||||
processHandler.addProcessListener(myProcessListener);
|
||||
}
|
||||
|
||||
// attach to process stdin
|
||||
if (attachToStdIn) {
|
||||
final OutputStream processInput = myProcessHandler.getProcessInput();
|
||||
myUserInputWriter = processInput != null ? new OutputStreamWriter(processInput) : null;
|
||||
} else {
|
||||
myUserInputWriter = null;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ConsoleState dispose() {
|
||||
if (myProcessHandler != null) {
|
||||
myProcessHandler.removeProcessListener(myProcessListener);
|
||||
}
|
||||
return myFinishedStated;
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
return myProcessHandler == null || myProcessHandler.isProcessTerminated();
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return myProcessHandler != null && !myProcessHandler.isProcessTerminated();
|
||||
}
|
||||
|
||||
public void sendUserInput(final String input) throws IOException {
|
||||
if (myUserInputWriter == null)
|
||||
throw new IOException(ExecutionBundle.message("no.user.process.input.error.message"));
|
||||
myUserInputWriter.write(input);
|
||||
myUserInputWriter.flush();
|
||||
}
|
||||
|
||||
public ConsoleState attachTo(final ConsoleViewImpl console, final ProcessHandler processHandler) {
|
||||
return dispose().attachTo(console, processHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Running state";
|
||||
}
|
||||
}
|
||||
@@ -468,6 +468,7 @@ public class EditorSearchComponent extends JPanel implements DataProvider, Selec
|
||||
add(myReplacementPane, BorderLayout.SOUTH);
|
||||
|
||||
myReplaceButton = new JButton("Replace");
|
||||
myReplaceButton.setFocusable(false);
|
||||
myReplaceButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
@@ -477,6 +478,7 @@ public class EditorSearchComponent extends JPanel implements DataProvider, Selec
|
||||
myReplaceButton.setMnemonic('p');
|
||||
|
||||
myReplaceAllButton = new JButton("Replace all");
|
||||
myReplaceAllButton.setFocusable(false);
|
||||
myReplaceAllButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
@@ -486,7 +488,7 @@ public class EditorSearchComponent extends JPanel implements DataProvider, Selec
|
||||
myReplaceAllButton.setMnemonic('a');
|
||||
|
||||
myExcludeButton = new JButton("");
|
||||
|
||||
myExcludeButton.setFocusable(false);
|
||||
myExcludeButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
|
||||
@@ -335,7 +335,7 @@ public class SearchResults {
|
||||
if (searchResult.getPrimaryRange().intersects(oldCursorRange)) {
|
||||
mayBeOldCursor = searchResult;
|
||||
}
|
||||
if (searchResult.getPrimaryRange().equals(oldCursorRange)) {
|
||||
if (searchResult.getPrimaryRange().getStartOffset() == oldCursorRange.getStartOffset()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -25,6 +25,7 @@ import com.intellij.ide.plugins.cl.PluginClassLoader;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ApplicationNamesInfo;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.application.ex.ApplicationEx;
|
||||
import com.intellij.openapi.components.ExportableComponent;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -763,7 +764,9 @@ public class FileTemplateManagerImpl extends FileTemplateManager implements Expo
|
||||
parentDir = topDir;
|
||||
}
|
||||
else {
|
||||
if (topDir instanceof NewVirtualFile) {
|
||||
final ApplicationEx app = (ApplicationEx)ApplicationManager.getApplication();
|
||||
if (topDir instanceof NewVirtualFile && (!app.holdsReadLock() || app.isDispatchThread())) {
|
||||
// need dispatch-thread-check because sync refresh in non-awt thread may cause deadlock
|
||||
parentDir = ((NewVirtualFile)topDir).refreshAndFindChild(myDefaultTemplatesDir);
|
||||
}
|
||||
else {
|
||||
|
||||
+18
-4
@@ -41,8 +41,10 @@ import com.intellij.psi.impl.file.PsiDirectoryFactory;
|
||||
import com.intellij.ui.LayeredIcon;
|
||||
import com.intellij.ui.RowIcon;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.util.IconUtil;
|
||||
import com.intellij.util.Icons;
|
||||
import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.PlatformUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -117,14 +119,26 @@ public class PsiDirectoryNode extends BasePsiNode<PsiDirectory> implements Navig
|
||||
|
||||
private void setupIcon(PresentationData data, PsiDirectory psiDirectory) {
|
||||
final VirtualFile virtualFile = psiDirectory.getVirtualFile();
|
||||
for (final IconProvider provider : Extensions.getExtensions(IconProvider.EXTENSION_POINT_NAME)) {
|
||||
final Icon openIcon = provider.getIcon(psiDirectory, Iconable.ICON_FLAG_OPEN);
|
||||
if (PlatformUtils.isCidr()) {
|
||||
final Icon openIcon = IconUtil.getIcon(virtualFile, Iconable.ICON_FLAG_OPEN, myProject);
|
||||
if (openIcon != null) {
|
||||
final Icon closedIcon = provider.getIcon(psiDirectory, Iconable.ICON_FLAG_CLOSED);
|
||||
final Icon closedIcon = IconUtil.getIcon(virtualFile, Iconable.ICON_FLAG_CLOSED, myProject);
|
||||
if (closedIcon != null) {
|
||||
data.setOpenIcon(patchIcon(openIcon, virtualFile));
|
||||
data.setClosedIcon(patchIcon(closedIcon, virtualFile));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (final IconProvider provider : Extensions.getExtensions(IconProvider.EXTENSION_POINT_NAME)) {
|
||||
final Icon openIcon = provider.getIcon(psiDirectory, Iconable.ICON_FLAG_OPEN);
|
||||
if (openIcon != null) {
|
||||
final Icon closedIcon = provider.getIcon(psiDirectory, Iconable.ICON_FLAG_CLOSED);
|
||||
if (closedIcon != null) {
|
||||
data.setOpenIcon(patchIcon(openIcon, virtualFile));
|
||||
data.setClosedIcon(patchIcon(closedIcon, virtualFile));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.LangDataKeys;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ApplicationNamesInfo;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
@@ -145,7 +146,7 @@ public class DeleteHandler {
|
||||
}
|
||||
|
||||
if (safeDeleteApplicable && dumb) {
|
||||
warningMessage += "\n\nWarning:\n Safe delete is not available while IntelliJ IDEA updates indices,\n no usages will be checked.";
|
||||
warningMessage += "\n\nWarning:\n Safe delete is not available while " + ApplicationNamesInfo.getInstance().getFullProductName() + " updates indices,\n no usages will be checked.";
|
||||
}
|
||||
|
||||
int result = Messages.showDialog(project, warningMessage, IdeBundle.message("title.delete"),
|
||||
|
||||
+32
-4
@@ -19,10 +19,12 @@ package com.intellij.openapi.fileTypes.impl;
|
||||
import com.intellij.ide.FileIconProvider;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.impl.ElementBase;
|
||||
import com.intellij.ui.DeferredIconImpl;
|
||||
import com.intellij.ui.mac.foundation.Foundation;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.ui.update.ComparableObject;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -43,10 +45,15 @@ public class NativeFileIconProvider implements FileIconProvider {
|
||||
|
||||
private static final Ext NO_EXT = new Ext(null);
|
||||
|
||||
public Icon getIcon(VirtualFile file, int flags, @Nullable Project project) {
|
||||
private static final Ext OPEN_DIR = new Ext(null, Iconable.ICON_FLAG_OPEN);
|
||||
private static final Ext CLOSED_DIR = new Ext(null, Iconable.ICON_FLAG_CLOSED);
|
||||
|
||||
private static final Icon DIR_OPEN_ICON = UIManager.getDefaults().getIcon( "Tree.openIcon" );
|
||||
|
||||
public Icon getIcon(VirtualFile file, final int flags, @Nullable Project project) {
|
||||
if (!isNativeFileType(file)) return null;
|
||||
|
||||
final Ext ext = file.getExtension() != null ? new Ext(file.getExtension()) : NO_EXT;
|
||||
final Ext ext = getExtension(file, flags);
|
||||
final String filePath = file.getPath();
|
||||
|
||||
Icon icon;
|
||||
@@ -70,7 +77,13 @@ public class NativeFileIconProvider implements FileIconProvider {
|
||||
Icon icon;
|
||||
try { // VM will ensure lock to init -static final field--, note we should have no read access here, to avoid deadlock with EDT needed to init component
|
||||
assert SwingComponentHolder.ourFileChooser != null || !ApplicationManager.getApplication().isReadAccessAllowed();
|
||||
icon = SwingComponentHolder.ourFileChooser.getIcon(f);
|
||||
|
||||
if (SystemInfo.isMac && virtualFile.isDirectory() && (flags & Iconable.ICON_FLAG_OPEN) == Iconable.ICON_FLAG_OPEN) {
|
||||
icon = Foundation.isPackageAtPath(f) ? SwingComponentHolder.ourFileChooser.getIcon(f) : DIR_OPEN_ICON;
|
||||
}
|
||||
else {
|
||||
icon = SwingComponentHolder.ourFileChooser.getIcon(f);
|
||||
}
|
||||
}
|
||||
catch (Exception e) { // see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4854174
|
||||
return null;
|
||||
@@ -90,6 +103,18 @@ public class NativeFileIconProvider implements FileIconProvider {
|
||||
});
|
||||
}
|
||||
|
||||
private static Ext getExtension(final VirtualFile file, final int flags) {
|
||||
if (file.isDirectory()) {
|
||||
if (file.getExtension() == null) {
|
||||
return flags == Iconable.ICON_FLAG_OPEN ? OPEN_DIR : CLOSED_DIR;
|
||||
} else {
|
||||
return new Ext(file.getExtension(), flags);
|
||||
}
|
||||
}
|
||||
|
||||
return file.getExtension() != null ? new Ext(file.getExtension()) : NO_EXT;
|
||||
}
|
||||
|
||||
static class SwingComponentHolder {
|
||||
private static final JFileChooser ourFileChooser = new JFileChooser();
|
||||
}
|
||||
@@ -99,13 +124,16 @@ public class NativeFileIconProvider implements FileIconProvider {
|
||||
}
|
||||
|
||||
private static class Ext extends ComparableObject.Impl {
|
||||
|
||||
private final Object[] myText;
|
||||
|
||||
private Ext(@Nullable String text) {
|
||||
myText = new Object[] {text};
|
||||
}
|
||||
|
||||
private Ext(@Nullable String text, final int flags) {
|
||||
myText = new Object[] {text, flags};
|
||||
}
|
||||
|
||||
public Object[] getEqualityObjects() {
|
||||
return myText;
|
||||
}
|
||||
|
||||
+2
-1
@@ -111,12 +111,13 @@ public class IndexCacheManagerImpl implements CacheManager{
|
||||
if (vFiles.isEmpty()) return true;
|
||||
|
||||
final ProjectFileIndex index = ProjectRootManager.getInstance(myProject).getFileIndex();
|
||||
final boolean globalScope = scope.isSearchOutsideRootModel();
|
||||
|
||||
final Processor<VirtualFile> virtualFileProcessor = new ReadActionProcessor<VirtualFile>() {
|
||||
@Override
|
||||
public boolean processInReadAction(VirtualFile virtualFile) {
|
||||
LOG.assertTrue(virtualFile.isValid());
|
||||
if (virtualFile.isValid() && scope.contains(virtualFile) && shouldBeFound(virtualFile, index)) {
|
||||
if (virtualFile.isValid() && scope.contains(virtualFile) && (globalScope || shouldBeFound(virtualFile, index))) {
|
||||
final PsiFile psiFile = myPsiManager.findFile(virtualFile);
|
||||
return psiFile == null || psiFileProcessor.process(psiFile);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ package com.intellij.psi.impl.search;
|
||||
|
||||
import com.intellij.codeInsight.CommentUtil;
|
||||
import com.intellij.concurrency.JobUtil;
|
||||
import com.intellij.ide.todo.TodoConfiguration;
|
||||
import com.intellij.ide.todo.TodoIndexPatternProvider;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
@@ -44,6 +43,7 @@ import com.intellij.psi.search.searches.IndexPatternSearch;
|
||||
import com.intellij.psi.util.PsiUtilBase;
|
||||
import com.intellij.util.CommonProcessors;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.CollectionFactory;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.intellij.util.indexing.FileBasedIndex;
|
||||
@@ -489,8 +489,7 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
|
||||
refProcessor = new Processor<PsiReference>() {
|
||||
@Override
|
||||
public boolean process(PsiReference psiReference) {
|
||||
if (!myProcessor.process(psiReference)) return false;
|
||||
return another.refProcessor.process(psiReference);
|
||||
return myProcessor.process(psiReference) && another.refProcessor.process(psiReference);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -571,7 +570,7 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
|
||||
progress.setText(PsiBundle.message("psi.scanning.files.progress"));
|
||||
}
|
||||
|
||||
final MultiMap<VirtualFile, RequestWithProcessor> candidateFiles = collectFiles(singles);
|
||||
final MultiMap<VirtualFile, RequestWithProcessor> candidateFiles = collectFiles(singles, progress);
|
||||
|
||||
if (candidateFiles.isEmpty()) {
|
||||
return true;
|
||||
@@ -593,7 +592,8 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
|
||||
final VirtualFile vfile = psiRoot.getContainingFile().getVirtualFile();
|
||||
for (final RequestWithProcessor singleRequest : candidateFiles.get(vfile)) {
|
||||
StringSearcher searcher = searchers.get(singleRequest);
|
||||
if (!LowLevelSearchUtil.processElementsContainingWordInElement(adaptProcessor(singleRequest.request, singleRequest.refProcessor), psiRoot, searcher, false, progress)) {
|
||||
TextOccurenceProcessor adapted = adaptProcessor(singleRequest.request, singleRequest.refProcessor);
|
||||
if (!LowLevelSearchUtil.processElementsContainingWordInElement(adapted, psiRoot, searcher, false, progress)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -616,9 +616,10 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
|
||||
};
|
||||
}
|
||||
|
||||
private MultiMap<VirtualFile, RequestWithProcessor> collectFiles(MultiMap<Set<IdIndexEntry>, RequestWithProcessor> singles) {
|
||||
private MultiMap<VirtualFile, RequestWithProcessor> collectFiles(MultiMap<Set<IdIndexEntry>, RequestWithProcessor> singles,
|
||||
ProgressIndicator progress) {
|
||||
final ProjectFileIndex index = ProjectRootManager.getInstance(myManager.getProject()).getFileIndex();
|
||||
final MultiMap<VirtualFile, RequestWithProcessor> result = new MultiMap<VirtualFile, RequestWithProcessor>();
|
||||
final MultiMap<VirtualFile, RequestWithProcessor> result = createMultiMap();
|
||||
for (Set<IdIndexEntry> key : singles.keySet()) {
|
||||
if (key.isEmpty()) {
|
||||
continue;
|
||||
@@ -631,7 +632,7 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
|
||||
|
||||
boolean first = true;
|
||||
for (IdIndexEntry entry : key) {
|
||||
final MultiMap<VirtualFile, RequestWithProcessor> local = findFilesWithIndexEntry(entry, index, data, commonScope);
|
||||
final MultiMap<VirtualFile, RequestWithProcessor> local = findFilesWithIndexEntry(entry, index, data, commonScope, progress);
|
||||
if (first) {
|
||||
intersection = local;
|
||||
first = false;
|
||||
@@ -648,6 +649,15 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static MultiMap<VirtualFile, RequestWithProcessor> createMultiMap() {
|
||||
return new MultiMap<VirtualFile, RequestWithProcessor>(){
|
||||
@Override
|
||||
protected Collection<RequestWithProcessor> createCollection() {
|
||||
return new SmartList<RequestWithProcessor>(); // usually there is just one request
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static GlobalSearchScope uniteScopes(Collection<RequestWithProcessor> requests) {
|
||||
GlobalSearchScope commonScope = null;
|
||||
for (RequestWithProcessor r : requests) {
|
||||
@@ -659,29 +669,31 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
|
||||
}
|
||||
|
||||
private static MultiMap<VirtualFile, RequestWithProcessor> findFilesWithIndexEntry(final IdIndexEntry entry,
|
||||
final ProjectFileIndex index,
|
||||
final Collection<RequestWithProcessor> data,
|
||||
final GlobalSearchScope commonScope) {
|
||||
final MultiMap<VirtualFile, RequestWithProcessor> local = new MultiMap<VirtualFile, RequestWithProcessor>();
|
||||
final ProjectFileIndex index,
|
||||
final Collection<RequestWithProcessor> data,
|
||||
final GlobalSearchScope commonScope,
|
||||
final ProgressIndicator progress) {
|
||||
final MultiMap<VirtualFile, RequestWithProcessor> local = createMultiMap();
|
||||
final boolean inRootsOnly = !commonScope.isSearchOutsideRootModel();
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
ProgressManager.checkCanceled();
|
||||
if (progress != null) progress.checkCanceled();
|
||||
FileBasedIndex.getInstance().processValues(IdIndex.NAME, entry, null, new FileBasedIndex.ValueProcessor<Integer>() {
|
||||
public boolean process(VirtualFile file, Integer value) {
|
||||
ProgressManager.checkCanceled();
|
||||
if (!IndexCacheManagerImpl.shouldBeFound(file, index)) {
|
||||
public boolean process(VirtualFile file, Integer value) {
|
||||
if (progress != null) progress.checkCanceled();
|
||||
if (inRootsOnly && !IndexCacheManagerImpl.shouldBeFound(file, index)) {
|
||||
return true;
|
||||
}
|
||||
int mask = value.intValue();
|
||||
for (RequestWithProcessor single : data) {
|
||||
final PsiSearchRequest request = single.request;
|
||||
if ((mask & request.searchContext) != 0 && ((GlobalSearchScope)request.searchScope).contains(file)) {
|
||||
local.putValue(file, single);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
int mask = value.intValue();
|
||||
for (RequestWithProcessor single : data) {
|
||||
final PsiSearchRequest request = single.request;
|
||||
if ((mask & request.searchContext) != 0 && ((GlobalSearchScope)request.searchScope).contains(file)) {
|
||||
local.putValue(file, single);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}, commonScope);
|
||||
}, commonScope);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -17,7 +17,10 @@
|
||||
package com.intellij.psi.impl.source.resolve;
|
||||
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.RecursionGuard;
|
||||
import com.intellij.openapi.util.RecursionManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiPolyVariantReference;
|
||||
import com.intellij.psi.PsiReference;
|
||||
@@ -26,13 +29,11 @@ import com.intellij.psi.impl.PsiManagerEx;
|
||||
import com.intellij.reference.SoftReference;
|
||||
import com.intellij.util.containers.ConcurrentWeakHashMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@@ -48,6 +49,7 @@ public class ResolveCache {
|
||||
private final PsiManagerEx myManager;
|
||||
|
||||
private final List<Runnable> myRunnablesToRunOnDropCaches = ContainerUtil.createEmptyCOWList();
|
||||
private final RecursionGuard myGuard = RecursionManager.createGuard("resolveCache");
|
||||
|
||||
public interface AbstractResolver<TRef extends PsiReference,TResult> {
|
||||
TResult resolve(TRef ref, boolean incompleteCode);
|
||||
@@ -88,8 +90,6 @@ public class ResolveCache {
|
||||
for (Runnable r : myRunnablesToRunOnDropCaches) {
|
||||
r.run();
|
||||
}
|
||||
|
||||
blockedElements.remove();
|
||||
}
|
||||
|
||||
public void addRunnableToRunOnDropCaches(Runnable r) {
|
||||
@@ -97,32 +97,33 @@ public class ResolveCache {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private <TRef extends PsiReference, TResult> TResult resolve(TRef ref,
|
||||
AbstractResolver<TRef, TResult> resolver,
|
||||
Map<? super TRef,Reference<TResult>>[] maps,
|
||||
private <TRef extends PsiReference, TResult> TResult resolve(final TRef ref,
|
||||
final AbstractResolver<TRef, TResult> resolver,
|
||||
final Map<? super TRef,Reference<TResult>>[] maps,
|
||||
boolean needToPreventRecursion,
|
||||
boolean incompleteCode) {
|
||||
final boolean incompleteCode) {
|
||||
ProgressManager.checkCanceled();
|
||||
|
||||
int clearCountOnStart = myClearCount.intValue();
|
||||
final int clearCountOnStart = myClearCount.intValue();
|
||||
|
||||
boolean physical = ref.getElement().isPhysical();
|
||||
TResult result = getCached(ref, maps, physical, incompleteCode);
|
||||
final boolean physical = ref.getElement().isPhysical();
|
||||
final TResult result = getCached(ref, maps, physical, incompleteCode);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (needToPreventRecursion && !lockElement(ref)) return null;
|
||||
try {
|
||||
result = resolver.resolve(ref, incompleteCode);
|
||||
}
|
||||
finally {
|
||||
if (needToPreventRecursion) {
|
||||
unlockElement(ref);
|
||||
Computable<TResult> computable = new Computable<TResult>() {
|
||||
@Override
|
||||
public TResult compute() {
|
||||
RecursionGuard.StackStamp stamp = myGuard.markStack();
|
||||
TResult result = resolver.resolve(ref, incompleteCode);
|
||||
if (stamp.mayCacheNow()) {
|
||||
cache(ref, result, maps, physical, incompleteCode, clearCountOnStart);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
cache(ref, result, maps, physical, incompleteCode, clearCountOnStart);
|
||||
return result;
|
||||
};
|
||||
return needToPreventRecursion ? myGuard.doPreventingRecursion(ref, computable) : computable.compute();
|
||||
}
|
||||
|
||||
public <T extends PsiPolyVariantReference> ResolveResult[] resolveWithCaching(T ref,
|
||||
@@ -140,23 +141,6 @@ public class ResolveCache {
|
||||
return resolve(ref, resolver, myResolveMaps, needToPreventRecursion, incompleteCode);
|
||||
}
|
||||
|
||||
private static final ThreadLocal<Set<PsiElement>> blockedElements = new ThreadLocal<Set<PsiElement>>() {
|
||||
@Override
|
||||
protected Set<PsiElement> initialValue() {
|
||||
return new THashSet<PsiElement>();
|
||||
}
|
||||
};
|
||||
|
||||
private static boolean lockElement(PsiReference ref) {
|
||||
Set<PsiElement> blocked = blockedElements.get();
|
||||
return blocked.add(ref.getElement());
|
||||
}
|
||||
|
||||
private static void unlockElement(PsiReference ref) {
|
||||
Set<PsiElement> blocked = blockedElements.get();
|
||||
blocked.remove(ref.getElement());
|
||||
}
|
||||
|
||||
private static int getIndex(boolean physical, boolean incompleteCode){
|
||||
return (physical ? 0 : 1) << 1 | (incompleteCode ? 1 : 0);
|
||||
}
|
||||
|
||||
+4
-3
@@ -18,6 +18,7 @@ package com.intellij.refactoring.move.moveFilesOrDirectories;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.paths.PsiDynaReference;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
@@ -172,14 +173,14 @@ public class MoveFilesOrDirectoriesProcessor extends BaseRefactoringProcessor {
|
||||
}
|
||||
});
|
||||
|
||||
retargetUsages(usages, oldToNewMap);
|
||||
|
||||
// fix references in moved files to outer files
|
||||
for (PsiFile movedFile : movedFiles) {
|
||||
MoveFileHandler.forElement(movedFile).updateMovedFile(movedFile);
|
||||
FileReferenceContextUtil.decodeFileReferences(movedFile);
|
||||
}
|
||||
|
||||
retargetUsages(usages, oldToNewMap);
|
||||
|
||||
// Perform CVS "add", "remove" commands on moved files.
|
||||
|
||||
if (myMoveCallback != null) {
|
||||
@@ -226,7 +227,7 @@ public class MoveFilesOrDirectoriesProcessor extends BaseRefactoringProcessor {
|
||||
final MyUsageInfo info = (MyUsageInfo)usageInfo;
|
||||
final PsiElement element = myElementsToMove[info.myIndex];
|
||||
|
||||
if (info.getReference() instanceof FileReference) {
|
||||
if (info.getReference() instanceof FileReference || info.getReference() instanceof PsiDynaReference) {
|
||||
final PsiElement usageElement = info.getElement();
|
||||
if (usageElement != null) {
|
||||
final PsiFile usageFile = usageElement.getContainingFile();
|
||||
|
||||
@@ -21,18 +21,14 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.project.ProjectManagerAdapter;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.LowMemoryWatcher;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiManagerEx;
|
||||
import com.intellij.psi.impl.source.PsiFileImpl;
|
||||
import com.intellij.psi.impl.source.tree.LazyParseableElement;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.util.ConcurrencyUtil;
|
||||
import com.intellij.util.NullableFunction;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.containers.ConcurrentWeakHashMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
@@ -181,7 +177,7 @@ public class SemServiceImpl extends SemService{
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public <T extends SemElement> List<T> getSemElements(SemKey<T> key, @NotNull PsiElement psi) {
|
||||
public <T extends SemElement> List<T> getSemElements(final SemKey<T> key, @NotNull final PsiElement psi) {
|
||||
final PsiElement root = getRootElement(psi);
|
||||
if (root == null) {
|
||||
return Collections.emptyList();
|
||||
@@ -192,21 +188,24 @@ public class SemServiceImpl extends SemService{
|
||||
return cached;
|
||||
}
|
||||
|
||||
RecursionGuard.StackStamp stamp = RecursionManager.createGuard("semService").markStack();
|
||||
|
||||
LinkedHashSet<T> result = new LinkedHashSet<T>();
|
||||
final Map<SemKey, List<SemElement>> map = new THashMap<SemKey, List<SemElement>>();
|
||||
LinkedHashSet<T> result = null;
|
||||
for (final SemKey each : myInheritors.get(key)) {
|
||||
List<SemElement> list = createSemElements(each, psi);
|
||||
map.put(each, list);
|
||||
if (!list.isEmpty()) {
|
||||
if (result == null) result = new LinkedHashSet<T>();
|
||||
result.addAll((List<T>)list);
|
||||
result.addAll((List<T>)list);
|
||||
}
|
||||
|
||||
if (stamp.mayCacheNow()) {
|
||||
final ConcurrentMap<SemKey, List<SemElement>> persistent = cacheOrGetMap(psi, root);
|
||||
for (SemKey semKey : map.keySet()) {
|
||||
persistent.putIfAbsent(semKey, map.get(semKey));
|
||||
}
|
||||
}
|
||||
final ConcurrentMap<SemKey, List<SemElement>> persistent = cacheOrGetMap(psi, root);
|
||||
for (SemKey semKey : map.keySet()) {
|
||||
persistent.putIfAbsent(semKey, map.get(semKey));
|
||||
}
|
||||
return result == null ? Collections.<T>emptyList() : new ArrayList<T>(result);
|
||||
|
||||
return new ArrayList<T>(result);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -977,7 +977,11 @@ public class FileBasedIndex implements ApplicationComponent {
|
||||
public <K> void scheduleRebuild(final ID<K, ?> indexId, final Throwable e) {
|
||||
LOG.info(e);
|
||||
requestRebuild(indexId);
|
||||
checkRebuild(indexId, false);
|
||||
try {
|
||||
checkRebuild(indexId, false);
|
||||
}
|
||||
catch (ProcessCanceledException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkRebuild(final ID<?, ?> indexId, final boolean cleanupOnly) {
|
||||
|
||||
@@ -234,6 +234,14 @@ public class Messages {
|
||||
return showDialog(message, title, new String[]{YES_BUTTON, NO_BUTTON}, 0, icon);
|
||||
}
|
||||
|
||||
public static int showYesNoDialog(Component parent, String message, String title, int defaultOptionIndex, int focusedOptionIndex, Icon icon) {
|
||||
return showDialog(parent, message, title, new String[]{YES_BUTTON, NO_BUTTON}, defaultOptionIndex, focusedOptionIndex, icon);
|
||||
}
|
||||
|
||||
public static int showYesNoDialog(Project project, String message, String title, int defaultOptionIndex, int focusedOptionIndex, Icon icon) {
|
||||
return showDialog(project, message, title, new String[]{YES_BUTTON, NO_BUTTON}, defaultOptionIndex, focusedOptionIndex, icon);
|
||||
}
|
||||
|
||||
public static int showOkCancelDialog(Project project, String message, String title, Icon icon) {
|
||||
return showDialog(project, message, title, new String[]{OK_BUTTON, CANCEL_BUTTON}, 0, icon);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ public class TreeComboBox extends JComboBox {
|
||||
final static int INDENT = UIUtil.getTreeLeftChildIndent();
|
||||
private TreeModel myTreeModel;
|
||||
private String myDefaultText;
|
||||
private boolean myShowRootNode;
|
||||
|
||||
public TreeComboBox(@NotNull final TreeModel model) {
|
||||
this(model, true);
|
||||
@@ -55,6 +56,7 @@ public class TreeComboBox extends JComboBox {
|
||||
public TreeComboBox(@NotNull final TreeModel model, final boolean showRootNode, final String defaultText) {
|
||||
myTreeModel = model;
|
||||
myDefaultText = defaultText;
|
||||
myShowRootNode = showRootNode;
|
||||
setModel(new TreeModelWrapper(myTreeModel, showRootNode));
|
||||
setRenderer(new TreeListCellRenderer(this, showRootNode, defaultText));
|
||||
if (SystemInfo.isMac && UIUtil.isUnderAquaLookAndFeel()) setMaximumRowCount(25);
|
||||
@@ -69,6 +71,12 @@ public class TreeComboBox extends JComboBox {
|
||||
return myTreeModel;
|
||||
}
|
||||
|
||||
public JTree createFakeTree() {
|
||||
final JTree tree = new JTree(getTreeModel());
|
||||
tree.setRootVisible(myShowRootNode);
|
||||
return tree;
|
||||
}
|
||||
|
||||
private static class TreeListCellRenderer extends SimpleColoredRenderer implements ListCellRenderer {
|
||||
private static final Border SELECTION_PAINTER = (Border)UIManager.get("MenuItem.selectedBackgroundPainter");
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.util;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public interface RecursionGuard {
|
||||
@Nullable
|
||||
<T> T doPreventingRecursion(Object key, Computable<T> computation);
|
||||
|
||||
StackStamp markStack();
|
||||
|
||||
List<Object> currentStack();
|
||||
|
||||
void prohibitResultCaching(Object since);
|
||||
|
||||
interface StackStamp {
|
||||
boolean mayCacheNow();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
@SuppressWarnings({"UtilityClassWithoutPrivateConstructor"})
|
||||
public class RecursionManager {
|
||||
private static final ThreadLocal<Integer> ourStamp = new ThreadLocal<Integer>() {
|
||||
@Override
|
||||
protected Integer initialValue() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
private static final ThreadLocal<LinkedHashMap<Pair<String, Object>, Integer>> ourProgress = new ThreadLocal<LinkedHashMap<Pair<String, Object>, Integer>>() {
|
||||
@Override
|
||||
protected LinkedHashMap<Pair<String, Object>, Integer> initialValue() {
|
||||
return new LinkedHashMap<Pair<String, Object>, Integer>();
|
||||
}
|
||||
};
|
||||
|
||||
public static RecursionGuard createGuard(final String id) {
|
||||
return new RecursionGuard() {
|
||||
@Override
|
||||
public <T> T doPreventingRecursion(Object key, Computable<T> computation) {
|
||||
Pair<String, Object> realKey = Pair.create(id, key);
|
||||
LinkedHashMap<Pair<String, Object>, Integer> progressMap = ourProgress.get();
|
||||
if (progressMap.containsKey(realKey)) {
|
||||
prohibitResultCaching(key);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
progressMap.put(realKey, ourStamp.get());
|
||||
|
||||
try {
|
||||
return computation.compute();
|
||||
}
|
||||
finally {
|
||||
ourStamp.set(progressMap.remove(realKey));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public StackStamp markStack() {
|
||||
final Integer stamp = ourStamp.get();
|
||||
return new StackStamp() {
|
||||
@Override
|
||||
public boolean mayCacheNow() {
|
||||
return Comparing.equal(stamp, ourStamp.get());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> currentStack() {
|
||||
ArrayList<Object> result = new ArrayList<Object>();
|
||||
LinkedHashMap<Pair<String, Object>, Integer> map = ourProgress.get();
|
||||
for (Pair<String, Object> pair : map.keySet()) {
|
||||
if (pair.first == id) {
|
||||
result.add(pair.second);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prohibitResultCaching(Object since) {
|
||||
int stamp = ourStamp.get() + 1;
|
||||
ourStamp.set(stamp);
|
||||
|
||||
boolean inLoop = false;
|
||||
for (Map.Entry<Pair<String, Object>, Integer> entry: ourProgress.get().entrySet()) {
|
||||
if (inLoop) {
|
||||
entry.setValue(stamp);
|
||||
}
|
||||
else if (entry.getKey().first.equals(id) && entry.getKey().second.equals(since)) {
|
||||
inLoop = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -383,7 +383,7 @@ public class SimpleColoredComponent extends JComponent implements Accessible {
|
||||
g.fillRect(0, 0, icon.getIconWidth() + myIpad.left + myIconTextGap, getHeight());
|
||||
}
|
||||
|
||||
icon.paintIcon(this, g, myIpad.left, (getHeight() - icon.getIconHeight()) / 2);
|
||||
paintIcon(g, icon);
|
||||
|
||||
xOffset += myIpad.left + icon.getIconWidth() + myIconTextGap;
|
||||
}
|
||||
@@ -405,6 +405,7 @@ public class SimpleColoredComponent extends JComponent implements Accessible {
|
||||
final List<Object[]> searchMatches = new ArrayList<Object[]>();
|
||||
|
||||
// Paint text
|
||||
applyAdditionalHints(g);
|
||||
UIUtil.applyRenderingHints(g);
|
||||
for (int i = 0; i < myFragments.size(); i++) {
|
||||
final SimpleTextAttributes attributes = myAttributes.get(i);
|
||||
@@ -497,6 +498,13 @@ public class SimpleColoredComponent extends JComponent implements Accessible {
|
||||
}
|
||||
}
|
||||
|
||||
protected void paintIcon(Graphics g, Icon icon) {
|
||||
icon.paintIcon(this, g, myIpad.left, (getHeight() - icon.getIconHeight()) / 2);
|
||||
}
|
||||
|
||||
protected void applyAdditionalHints(final Graphics g) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBaseline(int width, int height) {
|
||||
super.getBaseline(width, height);
|
||||
|
||||
@@ -19,6 +19,8 @@ import com.intellij.openapi.components.ApplicationComponent;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.project.ProjectManagerAdapter;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.wm.impl.IdeFrameImpl;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.Application;
|
||||
@@ -29,12 +31,20 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.FocusManager;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.CaretListener;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.plaf.basic.BasicPopupMenuUI;
|
||||
import javax.swing.text.AbstractDocument;
|
||||
import javax.swing.text.Document;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import java.awt.*;
|
||||
import java.awt.dnd.DragGestureRecognizer;
|
||||
import java.awt.event.AWTEventListener;
|
||||
import java.awt.event.HierarchyEvent;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.EventListener;
|
||||
|
||||
/**
|
||||
* This class listens event from ProjectManager and cleanup some
|
||||
@@ -181,6 +191,60 @@ public final class SwingCleanuper implements ApplicationComponent{
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
|
||||
@Override
|
||||
public void eventDispatched(AWTEvent event) {
|
||||
if (!SystemInfo.isMac || !Registry.is("jvmbugfix.mac.caccessibleLeak")) return;
|
||||
|
||||
HierarchyEvent he = (HierarchyEvent)event;
|
||||
if ((he.getChangeFlags() & (HierarchyEvent.SHOWING_CHANGED)) > 0) {
|
||||
if (he.getComponent() != null && !he.getComponent().isShowing()) {
|
||||
Component c = he.getComponent();
|
||||
if (c instanceof JTextComponent) {
|
||||
JTextComponent textComponent = (JTextComponent)c;
|
||||
|
||||
CaretListener[] carets = textComponent.getListeners(CaretListener.class);
|
||||
for (CaretListener each : carets) {
|
||||
if (isCAccessibleListener(each)) {
|
||||
textComponent.removeCaretListener(each);
|
||||
}
|
||||
}
|
||||
|
||||
Document document = textComponent.getDocument();
|
||||
if (document instanceof AbstractDocument) {
|
||||
DocumentListener[] documentListeners = ((AbstractDocument)document).getDocumentListeners();
|
||||
for (DocumentListener each : documentListeners) {
|
||||
if (isCAccessibleListener(each)) {
|
||||
document.removeDocumentListener(each);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (c instanceof JProgressBar) {
|
||||
JProgressBar bar = (JProgressBar)c;
|
||||
ChangeListener[] changeListeners = bar.getChangeListeners();
|
||||
for (ChangeListener each : changeListeners) {
|
||||
if (isCAccessibleListener(each)) {
|
||||
bar.removeChangeListener(each);
|
||||
}
|
||||
}
|
||||
} else if (c instanceof JSlider) {
|
||||
JSlider slider = (JSlider)c;
|
||||
ChangeListener[] changeListeners = slider.getChangeListeners();
|
||||
for (ChangeListener each : changeListeners) {
|
||||
if (isCAccessibleListener(each)) {
|
||||
slider.removeChangeListener(each);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, HierarchyEvent.HIERARCHY_EVENT_MASK);
|
||||
}
|
||||
|
||||
private boolean isCAccessibleListener(EventListener listener) {
|
||||
return listener != null && listener.toString().contains("AXTextChangeNotifier");
|
||||
}
|
||||
|
||||
private static void resetField(Object object, Class type, @NonNls String name) {
|
||||
|
||||
@@ -562,6 +562,9 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener,
|
||||
}
|
||||
|
||||
public Dimension getPreferredSize() {
|
||||
if (super.isPreferredSizeSet()) {
|
||||
return super.getPreferredSize();
|
||||
}
|
||||
if (myEditor != null) {
|
||||
final Dimension preferredSize = new Dimension(myEditor.getComponent().getPreferredSize());
|
||||
final Insets insets = getInsets();
|
||||
|
||||
@@ -19,9 +19,7 @@ import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.ModificationTracker;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.reference.SoftReference;
|
||||
import gnu.trove.TLongArrayList;
|
||||
@@ -76,9 +74,6 @@ public abstract class CachedValueBase<T> {
|
||||
myData = null;
|
||||
}
|
||||
|
||||
public void setDataLocked(boolean value) {
|
||||
}
|
||||
|
||||
public boolean hasUpToDateValue() {
|
||||
return getUpToDateOrNull(false) != null;
|
||||
}
|
||||
@@ -186,10 +181,15 @@ public abstract class CachedValueBase<T> {
|
||||
return value == ObjectUtils.NULL ? null : value;
|
||||
}
|
||||
|
||||
RecursionGuard.StackStamp stamp = RecursionManager.createGuard("cachedValue").markStack();
|
||||
|
||||
// compute outside lock to avoid deadlock
|
||||
CachedValueProvider.Result<T> result = doCompute(param);
|
||||
|
||||
return setValue(result);
|
||||
if (stamp.mayCacheNow()) {
|
||||
return setValue(result);
|
||||
}
|
||||
return result == null ? null : result.getValue();
|
||||
}
|
||||
|
||||
protected abstract <P> CachedValueProvider.Result<T> doCompute(P param);
|
||||
|
||||
@@ -11,7 +11,7 @@ element.is.not.allowed.here=Element {0} is not allowed here
|
||||
element.must.be.declared=Element {0} must be declared
|
||||
element.doesnt.have.required.attribute=Element {0} doesn''t have required attribute {1}
|
||||
wrong.root.element=Wrong root element
|
||||
unbound.namespace=Namespace {0} is not bound
|
||||
unbound.namespace=Namespace ''{0}'' is not bound
|
||||
unbound.namespace.no.param=Namespace is not bound
|
||||
attribute.is.not.allowed.here=Attribute {0} is not allowed here
|
||||
empty.attribute.is.not.allowed=Empty attribute {0} is not allowed
|
||||
|
||||
@@ -123,3 +123,5 @@ navbar.newpopup=true
|
||||
inspectionGadgets.telemetry.enabled=false
|
||||
minuscule.humps.matching=false
|
||||
minuscule.humps.matching.description=Camel Case without holding Shift in Ctrl+N/Ctrl+Shift+N etc
|
||||
|
||||
jvmbugfix.mac.caccessibleLeak=true
|
||||
|
||||
@@ -591,7 +591,6 @@
|
||||
<applicationService serviceInterface="com.intellij.codeInsight.template.TemplateBuilderFactory"
|
||||
serviceImplementation="com.intellij.codeInsight.template.TemplateBuilderFactoryImpl"/>
|
||||
|
||||
<projectViewPane implementation="com.intellij.ide.projectView.impl.ProjectViewPane"/>
|
||||
<projectViewPane implementation="com.intellij.ide.favoritesTreeView.FavoritesProjectViewPane"/>
|
||||
<projectViewPane implementation="com.intellij.ide.scopeView.ScopeViewPane"/>
|
||||
|
||||
|
||||
@@ -157,7 +157,8 @@
|
||||
<projectService serviceInterface="com.intellij.execution.testframework.export.ExportTestResultsConfiguration"
|
||||
serviceImplementation="com.intellij.execution.testframework.export.ExportTestResultsConfiguration"/>
|
||||
|
||||
|
||||
<projectService serviceInterface="com.intellij.execution.testframework.autotest.AutoTestManager"
|
||||
serviceImplementation="com.intellij.execution.testframework.autotest.AutoTestManager"/>
|
||||
<!-- General -->
|
||||
<applicationConfigurable instance="com.intellij.ide.GeneralSettingsConfigurable"/>
|
||||
|
||||
|
||||
+4
-3
@@ -92,6 +92,7 @@ public class SMTestRunnerConnectionUtil {
|
||||
@Override
|
||||
public void attachToProcess(final ProcessHandler processHandler) {
|
||||
// attach listeners
|
||||
super.attachToProcess(processHandler);
|
||||
attachEventsProcessors(consoleProperties, getResultsViewer(),
|
||||
getResultsViewer().getStatisticsPane(),
|
||||
processHandler, testFrameworkName);
|
||||
@@ -177,9 +178,9 @@ public class SMTestRunnerConnectionUtil {
|
||||
final ProcessHandler processHandler,
|
||||
@NotNull final String testFrameworkName) {
|
||||
//build messages consumer
|
||||
final OutputToGeneralTestEventsConverter outputConsumer = consoleProperties instanceof SMCustomMessagesParsing ?
|
||||
((SMCustomMessagesParsing)consoleProperties).createTestEventsConverter(testFrameworkName) :
|
||||
new OutputToGeneralTestEventsConverter(testFrameworkName);
|
||||
final OutputToGeneralTestEventsConverter outputConsumer = consoleProperties instanceof SMCustomMessagesParsing
|
||||
? ((SMCustomMessagesParsing)consoleProperties).createTestEventsConverter(testFrameworkName)
|
||||
: new OutputToGeneralTestEventsConverter(testFrameworkName);
|
||||
|
||||
//events processor
|
||||
final GeneralToSMTRunnerEventsConvertor eventsProcessor = new GeneralToSMTRunnerEventsConvertor(resultsViewer.getTestsRootNode(),
|
||||
|
||||
+1
@@ -112,6 +112,7 @@ public class SMTRunnerConsoleView extends BaseTestsOutputConsoleView {
|
||||
}
|
||||
|
||||
public void attachToProcess(final ProcessHandler processHandler) {
|
||||
super.attachToProcess(processHandler);
|
||||
if (processHandler == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
+14
@@ -132,6 +132,20 @@ public abstract class TestConsoleProperties extends StoringPropertyContainer imp
|
||||
|
||||
public abstract RuntimeConfiguration getConfiguration();
|
||||
|
||||
/**
|
||||
* Allows to make console editable and disable/enable input sending in process stdin stream.
|
||||
* Normally tests shouldn't ask anything in stdin so console is view only by default.
|
||||
*
|
||||
* NB: Process input support feature isn't fully implemented. Input text will be lost after
|
||||
* switching to any other test/suite in tests results view. It's highly not recommended to change
|
||||
* default behaviour. Please do it only in critical cases and only if you are sure that you need this feature.
|
||||
*
|
||||
* @return False for view-only mode and true for stdin support.
|
||||
*/
|
||||
public boolean isEditable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected ExecutionConsole getConsole() {
|
||||
return myConsole;
|
||||
}
|
||||
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
package com.intellij.execution.testframework.autotest;
|
||||
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.execution.ui.RunContentDescriptor;
|
||||
import com.intellij.execution.ui.RunContentManagerImpl;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.EditorFactory;
|
||||
import com.intellij.openapi.editor.event.DocumentAdapter;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileEditor.FileEditor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.content.Content;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.containers.WeakList;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class AutoTestManager {
|
||||
private final Project myProject;
|
||||
private final Alarm myAutoTestAlarm;
|
||||
|
||||
private static final int AUTOTEST_DELAY = 2000;
|
||||
private final Runnable myRunTestsRunnable;
|
||||
private boolean myListenerAttached;
|
||||
private final MyDocumentAdapter myListener;
|
||||
|
||||
public static AutoTestManager getInstance(Project project) {
|
||||
return ServiceManager.getService(project, AutoTestManager.class);
|
||||
}
|
||||
|
||||
private final Collection<Content> myEnabledDescriptors = new WeakList<Content>();
|
||||
|
||||
public AutoTestManager(Project project) {
|
||||
myProject = project;
|
||||
myAutoTestAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, project);
|
||||
myRunTestsRunnable = new Runnable() {
|
||||
public void run() {
|
||||
runAutoTests();
|
||||
}
|
||||
};
|
||||
myListener = new MyDocumentAdapter();
|
||||
}
|
||||
|
||||
public void setAutoTestEnabled(RunContentDescriptor descriptor, boolean enabled) {
|
||||
Content content = descriptor.getAttachedContent();
|
||||
if (enabled) {
|
||||
if (!myEnabledDescriptors.contains(content)) {
|
||||
myEnabledDescriptors.add(content);
|
||||
}
|
||||
if (!myListenerAttached) {
|
||||
myListenerAttached = true;
|
||||
EditorFactory.getInstance().getEventMulticaster().addDocumentListener(myListener, myProject);
|
||||
}
|
||||
}
|
||||
else {
|
||||
myEnabledDescriptors.remove(content);
|
||||
if (myEnabledDescriptors.isEmpty() && myListenerAttached) {
|
||||
myListenerAttached = false;
|
||||
EditorFactory.getInstance().getEventMulticaster().removeDocumentListener(myListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAutoTestEnabled(RunContentDescriptor descriptor) {
|
||||
return myEnabledDescriptors.contains(descriptor.getAttachedContent());
|
||||
}
|
||||
|
||||
public void runAutoTests() {
|
||||
for (Content content : myEnabledDescriptors) {
|
||||
runAutoTest(content);
|
||||
}
|
||||
}
|
||||
|
||||
private static void runAutoTest(Content content) {
|
||||
RunContentDescriptor descriptor = RunContentManagerImpl.getRunContentDescriptorByContent(content);
|
||||
if (descriptor == null) {
|
||||
return;
|
||||
}
|
||||
Runnable restarter = descriptor.getRestarter();
|
||||
if (restarter == null) {
|
||||
return;
|
||||
}
|
||||
final ProcessHandler processHandler = descriptor.getProcessHandler();
|
||||
if (processHandler != null && !processHandler.isProcessTerminated()) {
|
||||
return;
|
||||
}
|
||||
restarter.run();
|
||||
}
|
||||
|
||||
private class MyDocumentAdapter extends DocumentAdapter {
|
||||
public void documentChanged(DocumentEvent event) {
|
||||
final Document document = event.getDocument();
|
||||
final VirtualFile vFile = FileDocumentManager.getInstance().getFile(document);
|
||||
if (vFile != null) {
|
||||
final FileEditor[] editors = FileEditorManager.getInstance(myProject).getEditors(vFile);
|
||||
if (editors.length > 0) {
|
||||
myAutoTestAlarm.cancelAllRequests();
|
||||
myAutoTestAlarm.addRequest(myRunTestsRunnable, AUTOTEST_DELAY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package com.intellij.execution.testframework.autotest;
|
||||
|
||||
import com.intellij.execution.ui.RunContentDescriptor;
|
||||
import com.intellij.execution.ui.RunContentManager;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.actionSystem.ToggleAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class ToggleAutoTestAction extends ToggleAction {
|
||||
public ToggleAutoTestAction() {
|
||||
super("Toggle auto-test", "Toggle automatic rerun of tests on code changes",
|
||||
IconLoader.getIcon("/actions/swapPanels.png"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
Project project = e.getData(PlatformDataKeys.PROJECT);
|
||||
RunContentDescriptor descriptor = e.getData(RunContentManager.RUN_CONTENT_DESCRIPTOR);
|
||||
return project == null || descriptor == null
|
||||
? false
|
||||
: AutoTestManager.getInstance(project).isAutoTestEnabled(descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
Project project = e.getData(PlatformDataKeys.PROJECT);
|
||||
RunContentDescriptor descriptor = e.getData(RunContentManager.RUN_CONTENT_DESCRIPTOR);
|
||||
if (project != null && descriptor != null) {
|
||||
AutoTestManager.getInstance(project).setAutoTestEnabled(descriptor, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
-3
@@ -10,14 +10,14 @@
|
||||
* 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
|
||||
* See the Lice the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.execution.testframework.ui;
|
||||
|
||||
import com.intellij.execution.filters.Filter;
|
||||
import com.intellij.execution.filters.HyperlinkInfo;
|
||||
import com.intellij.execution.filters.TextConsoleBuilderFactory;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.execution.testframework.*;
|
||||
import com.intellij.execution.ui.ConsoleView;
|
||||
import com.intellij.execution.ui.ConsoleViewContentType;
|
||||
@@ -37,7 +37,10 @@ public abstract class BaseTestsOutputConsoleView implements ConsoleView, Observa
|
||||
|
||||
public BaseTestsOutputConsoleView(final TestConsoleProperties properties, final AbstractTestProxy unboundOutputRoot) {
|
||||
myProperties = properties;
|
||||
myConsole = TextConsoleBuilderFactory.getInstance().createBuilder(properties.getProject(), myProperties.getScope()).getConsole();
|
||||
|
||||
myConsole = new TestsConsoleBuilderImpl(properties.getProject(),
|
||||
myProperties.getScope(),
|
||||
!properties.isEditable()).getConsole();
|
||||
myPrinter = new TestsOutputConsolePrinter(myConsole, properties, unboundOutputRoot);
|
||||
myProperties.setConsole(this);
|
||||
|
||||
@@ -53,6 +56,10 @@ public abstract class BaseTestsOutputConsoleView implements ConsoleView, Observa
|
||||
|
||||
protected abstract TestResultsPanel createTestResultsPanel();
|
||||
|
||||
public void attachToProcess(final ProcessHandler processHandler) {
|
||||
myConsole.attachToProcess(processHandler);
|
||||
}
|
||||
|
||||
public void print(final String s, final ConsoleViewContentType contentType) {
|
||||
printNew(new Printable() {
|
||||
public void printOn(final Printer printer) {
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.execution.testframework.ui;
|
||||
|
||||
import com.intellij.execution.filters.TextConsoleBuilderImpl;
|
||||
import com.intellij.execution.ui.ConsoleView;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
|
||||
/**
|
||||
* @author Roman.Chernyatchik
|
||||
*/
|
||||
public class TestsConsoleBuilderImpl extends TextConsoleBuilderImpl {
|
||||
public TestsConsoleBuilderImpl(final Project project,
|
||||
final GlobalSearchScope scope,
|
||||
boolean isViewer) {
|
||||
super(project, scope);
|
||||
setViewer(isViewer);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConsoleView createConsole() {
|
||||
return new TestsConsoleViewImpl(getProject(), getScope(), isViewer(), null);
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.execution.testframework.ui;
|
||||
|
||||
import com.intellij.execution.impl.ConsoleState;
|
||||
import com.intellij.execution.impl.ConsoleViewImpl;
|
||||
import com.intellij.execution.impl.ConsoleViewRunningState;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
|
||||
/**
|
||||
* @author Roman.Chernyatchik
|
||||
*/
|
||||
public class TestsConsoleViewImpl extends ConsoleViewImpl {
|
||||
|
||||
public TestsConsoleViewImpl(final Project project,
|
||||
final GlobalSearchScope searchScope,
|
||||
final boolean viewer,
|
||||
final FileType fileType) {
|
||||
super(project, searchScope, viewer, fileType,
|
||||
new ConsoleState.NotStartedStated() {
|
||||
@Override
|
||||
public ConsoleState attachTo(ConsoleViewImpl console, ProcessHandler processHandler) {
|
||||
return new ConsoleViewRunningState(console, processHandler, this, false, !viewer);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ public abstract class ListCellRendererWrapper<T> implements ListCellRenderer {
|
||||
private Icon myIcon;
|
||||
private String myText;
|
||||
private String myToolTipText;
|
||||
private Color myForeground;
|
||||
|
||||
/**
|
||||
* A combo box for which this cell renderer is created should be passed here.
|
||||
@@ -62,6 +63,7 @@ public abstract class ListCellRendererWrapper<T> implements ListCellRenderer {
|
||||
final JLabel label = (JLabel)component;
|
||||
label.setIcon(myIcon);
|
||||
if (myText != null) label.setText(myText);
|
||||
if (myForeground != null) label.setForeground(myForeground);
|
||||
label.setToolTipText(myToolTipText);
|
||||
}
|
||||
return component;
|
||||
@@ -97,4 +99,7 @@ public abstract class ListCellRendererWrapper<T> implements ListCellRenderer {
|
||||
myToolTipText = toolTipText;
|
||||
}
|
||||
|
||||
public void setForeground(final Color foreground) {
|
||||
myForeground = foreground;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,6 @@ public class NameUtil {
|
||||
}
|
||||
index++;
|
||||
}
|
||||
if (upperCaseCount == 0 && lowerCaseCount == 0 && digitCount == 0) continue;
|
||||
String word = name.substring(wordStart, index);
|
||||
array.add(word);
|
||||
}
|
||||
@@ -290,7 +289,7 @@ public class NameUtil {
|
||||
String prevWord = words[i - 1];
|
||||
if (upperCaseStyle) {
|
||||
word = word.toUpperCase();
|
||||
if (prevWord.charAt(prevWord.length() - 1) != '_') {
|
||||
if (prevWord.charAt(prevWord.length() - 1) != '_' && word.charAt(0) != '_') {
|
||||
word = "_" + word;
|
||||
}
|
||||
}
|
||||
@@ -380,7 +379,7 @@ public class NameUtil {
|
||||
}
|
||||
|
||||
public static Matcher buildCompletionMatcher(String pattern, int exactPrefixLen, boolean allowToUpper, boolean allowToLower) {
|
||||
return buildMatcher(pattern, buildRegexp(pattern, exactPrefixLen, allowToUpper, allowToLower, false, true), false);
|
||||
return buildMatcher(pattern, buildRegexp(pattern, exactPrefixLen, allowToUpper, allowToLower, false, true), exactPrefixLen > 0);
|
||||
}
|
||||
|
||||
public static Matcher buildMatcher(String pattern, int exactPrefixLen, boolean allowToUpper, boolean allowToLower) {
|
||||
|
||||
@@ -19,7 +19,9 @@ import com.intellij.util.containers.HashMap;
|
||||
import com.sun.jna.Callback;
|
||||
import com.sun.jna.Native;
|
||||
import com.sun.jna.Pointer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -89,6 +91,18 @@ public class Foundation {
|
||||
return toStringViaUTF8(myFoundationLibrary.NSFullUserName());
|
||||
}
|
||||
|
||||
public static boolean isPackageAtPath(@NotNull final String path) {
|
||||
final ID workspace = invoke("NSWorkspace", "sharedWorkspace");
|
||||
final ID result = invoke(workspace, createSelector("isFilePackageAtPath:"), cfString(path));
|
||||
|
||||
return result.intValue() == 1;
|
||||
}
|
||||
|
||||
public static boolean isPackageAtPath(@NotNull final File file) {
|
||||
if (!file.isDirectory()) return false;
|
||||
return isPackageAtPath(file.getPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a CFString as an ID, toll-free bridged to NSString.
|
||||
* <p/>
|
||||
|
||||
@@ -46,7 +46,7 @@ public class FormBuilder {
|
||||
this(false, 5);
|
||||
}
|
||||
|
||||
public FormBuilder addLabeledComponent(String labelText, JComponent component) {
|
||||
public FormBuilder addLabeledComponent(String labelText, JComponent component, final int verticalSpace) {
|
||||
JLabel label = null;
|
||||
if (labelText != null) {
|
||||
label = new JLabel(UIUtil.removeMnemonic(labelText));
|
||||
@@ -55,7 +55,7 @@ public class FormBuilder {
|
||||
}
|
||||
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
int verticalInset = line > 0 ? 10 : 0;
|
||||
int verticalInset = line > 0 ? verticalSpace : 0;
|
||||
|
||||
if (vertical) {
|
||||
c.gridwidth = 1;
|
||||
@@ -103,6 +103,10 @@ public class FormBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public FormBuilder addLabeledComponent(String labelText, JComponent component) {
|
||||
return addLabeledComponent(labelText, component, 10);
|
||||
}
|
||||
|
||||
public JPanel getPanel() {
|
||||
return panel;
|
||||
}
|
||||
|
||||
+58
-1
@@ -20,6 +20,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.siyeh.HardcodedMethodConstants;
|
||||
@@ -337,6 +338,19 @@ public class TryFinallyCanBeTryWithResourcesInspection extends BaseInspection {
|
||||
final int index = findInitialization(tryBlockStatements,
|
||||
variable, hasInitializer);
|
||||
if (index >= 0 ^ hasInitializer) {
|
||||
final VariableUsedOutsideContextVisitor visitor =
|
||||
new VariableUsedOutsideContextVisitor(variable,
|
||||
tryStatement);
|
||||
final PsiElement context =
|
||||
PsiTreeUtil.getParentOfType(variable,
|
||||
PsiCodeBlock.class);
|
||||
if (context == null) {
|
||||
continue;
|
||||
}
|
||||
context.accept(visitor);
|
||||
if (visitor.variableIsUsed()) {
|
||||
continue;
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@@ -483,7 +497,7 @@ public class TryFinallyCanBeTryWithResourcesInspection extends BaseInspection {
|
||||
final PsiClassType classType = (PsiClassType) type;
|
||||
final PsiClass aClass = classType.resolve();
|
||||
return aClass != null && InheritanceUtil.isInheritor(aClass,
|
||||
"java.io.Closeable");
|
||||
"java.lang.AutoCloseable");
|
||||
}
|
||||
|
||||
static int findInitialization(
|
||||
@@ -521,4 +535,47 @@ public class TryFinallyCanBeTryWithResourcesInspection extends BaseInspection {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static class VariableUsedOutsideContextVisitor
|
||||
extends JavaRecursiveElementVisitor {
|
||||
|
||||
private boolean used = false;
|
||||
@NotNull private final PsiVariable variable;
|
||||
private final PsiElement skipContext;
|
||||
|
||||
public VariableUsedOutsideContextVisitor(@NotNull PsiVariable variable,
|
||||
PsiElement skipContext){
|
||||
this.variable = variable;
|
||||
this.skipContext = skipContext;
|
||||
}
|
||||
|
||||
@Override public void visitElement(@NotNull PsiElement element){
|
||||
if (element.equals(skipContext)) {
|
||||
return;
|
||||
}
|
||||
if (used) {
|
||||
return;
|
||||
}
|
||||
super.visitElement(element);
|
||||
}
|
||||
|
||||
@Override public void visitReferenceExpression(
|
||||
@NotNull PsiReferenceExpression referenceExpression){
|
||||
if(used){
|
||||
return;
|
||||
}
|
||||
super.visitReferenceExpression(referenceExpression);
|
||||
final PsiElement target = referenceExpression.resolve();
|
||||
if(target == null){
|
||||
return;
|
||||
}
|
||||
if(target.equals(variable)){
|
||||
used = true;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean variableIsUsed(){
|
||||
return used;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ public class GroovyBlock implements Block, GroovyElementTypes {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns spacing between neighrbour elements
|
||||
* Returns spacing between neighbour elements
|
||||
*
|
||||
* @param child1 left element
|
||||
* @param child2 right element
|
||||
@@ -120,7 +120,7 @@ public class GroovyBlock implements Block, GroovyElementTypes {
|
||||
@Nullable
|
||||
public Spacing getSpacing(Block child1, Block child2) {
|
||||
if ((child1 instanceof GroovyBlock) && (child2 instanceof GroovyBlock)) {
|
||||
Spacing spacing = GroovySpacingProcessor.getSpacing(((GroovyBlock) child1), ((GroovyBlock) child2), mySettings);
|
||||
Spacing spacing = new GroovySpacingProcessor(((GroovyBlock)child2).getNode(), mySettings).getSpacing();
|
||||
return spacing != null ? spacing : GroovySpacingProcessorBasic.getSpacing(((GroovyBlock) child1), ((GroovyBlock) child2), mySettings);
|
||||
}
|
||||
return null;
|
||||
@@ -188,7 +188,7 @@ public class GroovyBlock implements Block, GroovyElementTypes {
|
||||
* @param node Tree node
|
||||
* @return true if node is incomplete
|
||||
*/
|
||||
public boolean isIncomplete(@NotNull final ASTNode node) {
|
||||
public static boolean isIncomplete(@NotNull final ASTNode node) {
|
||||
if (node.getElementType() instanceof ILazyParseableElementType) return false;
|
||||
ASTNode lastChild = node.getLastChildNode();
|
||||
while (lastChild != null &&
|
||||
|
||||
+408
-479
@@ -18,7 +18,6 @@ package org.jetbrains.plugins.groovy.formatter.processors;
|
||||
|
||||
import com.intellij.formatting.Spacing;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiIdentifier;
|
||||
@@ -26,12 +25,10 @@ import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
|
||||
import com.intellij.psi.impl.source.tree.CompositeElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.plugins.groovy.formatter.GroovyBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.editor.actions.GroovyEditorActionUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.*;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementVisitor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.*;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
|
||||
@@ -70,519 +67,451 @@ import static org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.mRCURL
|
||||
/**
|
||||
* @author ilyas
|
||||
*/
|
||||
public class GroovySpacingProcessor extends GroovyPsiElementVisitor {
|
||||
private static final ThreadLocal<GroovySpacingProcessor> mySharedProcessorAllocator = new ThreadLocal<GroovySpacingProcessor>();
|
||||
protected MyGroovySpacingVisitor myGroovyElementVisitor;
|
||||
protected static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.formatter.processors.GroovySpacingProcessor");
|
||||
public class GroovySpacingProcessor extends GroovyElementVisitor {
|
||||
private PsiElement myParent;
|
||||
private final CodeStyleSettings mySettings;
|
||||
|
||||
private GroovySpacingProcessor(MyGroovySpacingVisitor visitor) {
|
||||
super(visitor);
|
||||
myGroovyElementVisitor = visitor;
|
||||
}
|
||||
private Spacing myResult;
|
||||
private ASTNode myChild1;
|
||||
private ASTNode myChild2;
|
||||
|
||||
public static Spacing getSpacing(GroovyBlock child1, GroovyBlock child2, CodeStyleSettings settings) {
|
||||
return getSpacing(child2.getNode(), settings);
|
||||
}
|
||||
public GroovySpacingProcessor(ASTNode node, CodeStyleSettings settings) {
|
||||
mySettings = settings;
|
||||
|
||||
private static Spacing getSpacing(ASTNode node, CodeStyleSettings settings) {
|
||||
GroovySpacingProcessor spacingProcessor = mySharedProcessorAllocator.get();
|
||||
try {
|
||||
if (spacingProcessor == null) {
|
||||
spacingProcessor = new GroovySpacingProcessor(new MyGroovySpacingVisitor(node, settings));
|
||||
mySharedProcessorAllocator.set(spacingProcessor);
|
||||
} else {
|
||||
spacingProcessor.setVisitor(new MyGroovySpacingVisitor(node, settings));
|
||||
_init(node);
|
||||
|
||||
if (myChild1 == null || myChild2 == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
PsiElement psi1 = myChild1.getPsi();
|
||||
PsiElement psi2 = myChild2.getPsi();
|
||||
if (psi1 == null || psi2 == null) return;
|
||||
if (psi1.getLanguage() != GROOVY_LANGUAGE || psi2.getLanguage() != GROOVY_LANGUAGE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (myChild2 != null && mySettings.KEEP_FIRST_COLUMN_COMMENT && SpacingUtil.COMMENT_BIT_SET.contains(myChild2.getElementType())) {
|
||||
if (myChild1.getElementType() != IMPORT_STATEMENT) {
|
||||
myResult = Spacing.createKeepingFirstColumnSpacing(0, Integer.MAX_VALUE, true, 1);
|
||||
}
|
||||
spacingProcessor.doInit();
|
||||
return spacingProcessor.getResult();
|
||||
return;
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e);
|
||||
return null;
|
||||
|
||||
if (myChild1 != null && myChild2 != null && myChild1.getElementType() == mNLS) {
|
||||
final ASTNode prev = SpacingUtil.getPrevElementType(myChild1);
|
||||
if (prev != null && prev.getElementType() == mSL_COMMENT) {
|
||||
myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
spacingProcessor.clear();
|
||||
|
||||
if (myParent instanceof GroovyPsiElement) {
|
||||
((GroovyPsiElement) myParent).accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void doInit() {
|
||||
myGroovyElementVisitor.doInit();
|
||||
}
|
||||
|
||||
private void clear() {
|
||||
if (myGroovyElementVisitor != null) {
|
||||
myGroovyElementVisitor.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private Spacing getResult() {
|
||||
return myGroovyElementVisitor.getResult();
|
||||
}
|
||||
|
||||
public void setVisitor(MyGroovySpacingVisitor visitor) {
|
||||
myGroovyElementVisitor = visitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visitor to adjust spaces via user Code Style Settings
|
||||
*/
|
||||
private static class MyGroovySpacingVisitor extends GroovyElementVisitor {
|
||||
private PsiElement myParent;
|
||||
private final CodeStyleSettings mySettings;
|
||||
|
||||
private Spacing myResult;
|
||||
private ASTNode myChild1;
|
||||
private ASTNode myChild2;
|
||||
|
||||
public MyGroovySpacingVisitor(ASTNode node, CodeStyleSettings settings) {
|
||||
mySettings = settings;
|
||||
init(node);
|
||||
}
|
||||
|
||||
private void init(final ASTNode child) {
|
||||
if (child == null) return;
|
||||
private void _init(final ASTNode child) {
|
||||
if (child != null) {
|
||||
ASTNode treePrev = child.getTreePrev();
|
||||
while (treePrev != null && SpacingUtil.isWhiteSpace(treePrev)) {
|
||||
treePrev = treePrev.getTreePrev();
|
||||
}
|
||||
if (treePrev == null) {
|
||||
init(child.getTreeParent());
|
||||
} else {
|
||||
_init(child.getTreeParent());
|
||||
}
|
||||
else {
|
||||
myChild2 = child;
|
||||
myChild1 = treePrev;
|
||||
final CompositeElement parent = (CompositeElement) treePrev.getTreeParent();
|
||||
final CompositeElement parent = (CompositeElement)treePrev.getTreeParent();
|
||||
myParent = SourceTreeToPsiMap.treeElementToPsi(parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Method to start visiting
|
||||
*/
|
||||
private void doInit() {
|
||||
if (myChild1 == null || myChild2 == null) return;
|
||||
PsiElement psi1 = myChild1.getPsi();
|
||||
PsiElement psi2 = myChild2.getPsi();
|
||||
if (psi1 == null || psi2 == null) return;
|
||||
if (psi1.getLanguage() != GROOVY_LANGUAGE ||
|
||||
psi2.getLanguage() != GROOVY_LANGUAGE) {
|
||||
return;
|
||||
}
|
||||
@Override
|
||||
public void visitAnnotation(GrAnnotation annotation) {
|
||||
if (myChild2.getElementType() == ANNOTATION_ARGUMENTS) {
|
||||
myResult = Spacing.createSpacing(0, 0, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
if (myChild2 != null && mySettings.KEEP_FIRST_COLUMN_COMMENT && SpacingUtil.COMMENT_BIT_SET.contains(myChild2.getElementType())) {
|
||||
if (myChild1.getElementType() != IMPORT_STATEMENT) {
|
||||
myResult = Spacing.createKeepingFirstColumnSpacing(0, Integer.MAX_VALUE, true, 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
public void visitArgumentList(GrArgumentList list) {
|
||||
if (myChild1.getElementType() == mLBRACK || myChild2.getElementType() == mRBRACK) {
|
||||
createSpaceInCode(mySettings.SPACE_WITHIN_BRACKETS);
|
||||
}
|
||||
// todo add other cases
|
||||
}
|
||||
|
||||
if (myChild1 != null && myChild2 != null && myChild1.getElementType() == mNLS) {
|
||||
final ASTNode prev = SpacingUtil.getPrevElementType(myChild1);
|
||||
if (prev != null && prev.getElementType() == mSL_COMMENT) {
|
||||
myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void visitMethodCallExpression(GrMethodCallExpression methodCallExpression) {
|
||||
if (myChild2.getElementType() == ARGUMENTS) createSpaceInCode(mySettings.SPACE_BEFORE_METHOD_CALL_PARENTHESES);
|
||||
}
|
||||
|
||||
if (myParent instanceof GroovyPsiElement) {
|
||||
((GroovyPsiElement) myParent).accept(this);
|
||||
public void visitClosure(GrClosableBlock closure) {
|
||||
if ((myChild1.getElementType() == mLCURLY && myChild2.getElementType() != PARAMETERS_LIST && myChild2.getElementType() != mCLOSABLE_BLOCK_OP)
|
||||
|| myChild2.getElementType() == mRCURLY) {
|
||||
myResult = Spacing.createDependentLFSpacing(0, Integer.MAX_VALUE, closure.getTextRange(), mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else if (myChild1.getElementType() == mCLOSABLE_BLOCK_OP) {
|
||||
GrStatement[] statements = closure.getStatements();
|
||||
if (statements.length > 0) {
|
||||
TextRange range = new TextRange(statements[0].getTextRange().getStartOffset(), statements[statements.length - 1].getTextRange().getEndOffset());
|
||||
myResult = Spacing.createDependentLFSpacing(1, Integer.MAX_VALUE, range, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitAnnotation(GrAnnotation annotation) {
|
||||
if (myChild2.getElementType() == ANNOTATION_ARGUMENTS) {
|
||||
myResult = Spacing.createSpacing(0, 0, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
public void visitOpenBlock(GrOpenBlock block) {
|
||||
if (myChild1.getElementType() == mLCURLY && myChild2.getElementType() == mRCURLY && block.getParent() instanceof GrBlockStatement) {
|
||||
myResult = Spacing.createSpacing(1, 1, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else
|
||||
if (myChild1.getElementType() == mLCURLY && !GroovyEditorActionUtil.isMultilineStringElement(myChild2) ||
|
||||
myChild2.getElementType() == mRCURLY && !GroovyEditorActionUtil.isMultilineStringElement(myChild1)) {
|
||||
myResult = Spacing.createDependentLFSpacing(0, 1, block.getTextRange(), mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitArgumentList(GrArgumentList list) {
|
||||
if (myChild1.getElementType() == mLBRACK || myChild2.getElementType() == mRBRACK) {
|
||||
createSpaceInCode(mySettings.SPACE_WITHIN_BRACKETS);
|
||||
}
|
||||
// todo add other cases
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodCallExpression(GrMethodCallExpression methodCallExpression) {
|
||||
if (myChild2.getElementType() == ARGUMENTS) createSpaceInCode(mySettings.SPACE_BEFORE_METHOD_CALL_PARENTHESES);
|
||||
}
|
||||
|
||||
public void visitClosure(GrClosableBlock closure) {
|
||||
if ((myChild1.getElementType() == mLCURLY && myChild2.getElementType() != PARAMETERS_LIST && myChild2.getElementType() != mCLOSABLE_BLOCK_OP)
|
||||
|| myChild2.getElementType() == mRCURLY) {
|
||||
myResult = Spacing.createDependentLFSpacing(0, Integer.MAX_VALUE, closure.getTextRange(), mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else if (myChild1.getElementType() == mCLOSABLE_BLOCK_OP) {
|
||||
GrStatement[] statements = closure.getStatements();
|
||||
if (statements.length > 0) {
|
||||
TextRange range = new TextRange(statements[0].getTextRange().getStartOffset(), statements[statements.length - 1].getTextRange().getEndOffset());
|
||||
myResult = Spacing.createDependentLFSpacing(1, Integer.MAX_VALUE, range, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void visitOpenBlock(GrOpenBlock block) {
|
||||
if (myChild1.getElementType() == mLCURLY && myChild2.getElementType() == mRCURLY && block.getParent() instanceof GrBlockStatement) {
|
||||
myResult = Spacing.createSpacing(1, 1, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else
|
||||
if (myChild1.getElementType() == mLCURLY && !GroovyEditorActionUtil.isMultilineStringElement(myChild2) ||
|
||||
myChild2.getElementType() == mRCURLY && !GroovyEditorActionUtil.isMultilineStringElement(myChild1)) {
|
||||
myResult = Spacing.createDependentLFSpacing(0, 1, block.getTextRange(), mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitNewExpression(GrNewExpression newExpression) {
|
||||
if (myChild1.getElementType() == kNEW) {
|
||||
createSpaceInCode(true);
|
||||
} else if (myChild2.getElementType() == ARGUMENTS) {
|
||||
createSpaceInCode(mySettings.SPACE_BEFORE_METHOD_CALL_PARENTHESES);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitTypeDefinition(GrTypeDefinition typeDefinition) {
|
||||
if (myChild2.getElementType() == CLASS_BODY) {
|
||||
PsiIdentifier nameIdentifier = typeDefinition.getNameIdentifier();
|
||||
int dependanceStart = nameIdentifier == null ? myParent.getTextRange().getStartOffset() : nameIdentifier.getTextRange().getStartOffset();
|
||||
myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_CLASS_LBRACE, mySettings.CLASS_BRACE_STYLE,
|
||||
new TextRange(dependanceStart, myChild1.getTextRange().getEndOffset()), false);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitTypeDefinitionBody(GrTypeDefinitionBody typeDefinitionBody) {
|
||||
if (myChild1.getElementType() == mLCURLY && myChild2.getElementType() == mRCURLY) {
|
||||
myResult = Spacing.createSpacing(0, 0, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_BEFORE_RBRACE);
|
||||
} else if (myChild1.getElementType() == mLCURLY) {
|
||||
myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_AFTER_CLASS_HEADER + 1,
|
||||
mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_DECLARATIONS);
|
||||
} else if (myChild2.getElementType() == mRCURLY) {
|
||||
myResult = Spacing.createSpacing(0, Integer.MAX_VALUE, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_BEFORE_RBRACE);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitMethod(GrMethod method) {
|
||||
if (myChild2.getElementType() == mLPAREN) {
|
||||
createSpaceInCode(mySettings.SPACE_BEFORE_METHOD_PARENTHESES);
|
||||
} else if (myChild2.getElementType() == mRPAREN && myChild2.getElementType() == THROW_CLAUSE) {
|
||||
createSpaceInCode(true);
|
||||
} else if (isOpenBlock(myChild2)) {
|
||||
PsiElement methodName = method.getNameIdentifier();
|
||||
int dependancyStart = methodName == null ? myParent.getTextRange().getStartOffset() : methodName.getTextRange().getStartOffset();
|
||||
myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_METHOD_LBRACE, mySettings.METHOD_BRACE_STYLE,
|
||||
new TextRange(dependancyStart, myChild1.getTextRange().getEndOffset()), mySettings.KEEP_SIMPLE_METHODS_IN_ONE_LINE);
|
||||
} else if (myChild1.getElementType() == MODIFIERS) {
|
||||
processModifierList(myChild1);
|
||||
} else if (COMMENT_SET.contains(myChild1.getElementType())
|
||||
&& (myChild2.getElementType() == MODIFIERS || myChild2.getElementType() == REFERENCE_ELEMENT)) {
|
||||
myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static boolean isOpenBlock(final ASTNode node) {
|
||||
return node.getElementType() == OPEN_BLOCK || node.getElementType() == CONSTRUCTOR_BODY;
|
||||
}
|
||||
|
||||
public void visitDocMethodReference(GrDocMethodReference reference) {
|
||||
visitDocMember();
|
||||
}
|
||||
|
||||
|
||||
public void visitDocFieldReference(GrDocFieldReference reference) {
|
||||
visitDocMember();
|
||||
}
|
||||
|
||||
private void visitDocMember() {
|
||||
myResult = Spacing.createSpacing(0, 0, 0, false, 0);
|
||||
}
|
||||
|
||||
public void visitDocMethodParameterList(GrDocMethodParams params) {
|
||||
if (myChild1.getElementType() == mGDOC_TAG_VALUE_LPAREN || myChild2.getElementType() == mGDOC_TAG_VALUE_RPAREN) {
|
||||
myResult = Spacing.createSpacing(0, 0, 0, false, 0);
|
||||
return;
|
||||
}
|
||||
if (myChild2.getElementType() == mGDOC_TAG_VALUE_COMMA) {
|
||||
myResult = Spacing.createSpacing(0, 0, 0, false, 0);
|
||||
return;
|
||||
}
|
||||
public void visitNewExpression(GrNewExpression newExpression) {
|
||||
if (myChild1.getElementType() == kNEW) {
|
||||
createSpaceInCode(true);
|
||||
} else if (myChild2.getElementType() == ARGUMENTS) {
|
||||
createSpaceInCode(mySettings.SPACE_BEFORE_METHOD_CALL_PARENTHESES);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitDocMethodParameter(GrDocMethodParameter parameter) {
|
||||
if (myChild1.getTreePrev() == null) {
|
||||
createSpaceInCode(true);
|
||||
}
|
||||
public void visitTypeDefinition(GrTypeDefinition typeDefinition) {
|
||||
if (myChild2.getElementType() == CLASS_BODY) {
|
||||
PsiIdentifier nameIdentifier = typeDefinition.getNameIdentifier();
|
||||
int dependanceStart = nameIdentifier == null ? myParent.getTextRange().getStartOffset() : nameIdentifier.getTextRange().getStartOffset();
|
||||
myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_CLASS_LBRACE, mySettings.CLASS_BRACE_STYLE,
|
||||
new TextRange(dependanceStart, myChild1.getTextRange().getEndOffset()), false);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitWhileStatement(GrWhileStatement statement) {
|
||||
if (myChild2.getElementType() == mLPAREN) {
|
||||
createSpaceInCode(mySettings.SPACE_BEFORE_WHILE_PARENTHESES);
|
||||
} else if (myChild1.getElementType() == mLPAREN || myChild2.getElementType() == mRPAREN) {
|
||||
createSpaceInCode(mySettings.SPACE_WITHIN_WHILE_PARENTHESES);
|
||||
} else if (myChild2.getPsi() instanceof GrBlockStatement) {
|
||||
myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_WHILE_LBRACE, mySettings.BRACE_STYLE,
|
||||
new TextRange(myParent.getTextRange().getStartOffset(), myChild1.getTextRange().getEndOffset()), mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE);
|
||||
} else {
|
||||
createSpacingBeforeElementInsideControlStatement();
|
||||
}
|
||||
public void visitTypeDefinitionBody(GrTypeDefinitionBody typeDefinitionBody) {
|
||||
if (myChild1.getElementType() == mLCURLY && myChild2.getElementType() == mRCURLY) {
|
||||
myResult = Spacing.createSpacing(0, 0, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_BEFORE_RBRACE);
|
||||
} else if (myChild1.getElementType() == mLCURLY) {
|
||||
myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_AFTER_CLASS_HEADER + 1,
|
||||
mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_DECLARATIONS);
|
||||
} else if (myChild2.getElementType() == mRCURLY) {
|
||||
myResult = Spacing.createSpacing(0, Integer.MAX_VALUE, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_BEFORE_RBRACE);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitCatchClause(GrCatchClause catchClause) {
|
||||
if (isOpenBlock(myChild2)) {
|
||||
myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_TRY_LBRACE, mySettings.BRACE_STYLE, null,
|
||||
mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE);
|
||||
}
|
||||
public void visitMethod(GrMethod method) {
|
||||
if (myChild2.getElementType() == mLPAREN) {
|
||||
createSpaceInCode(mySettings.SPACE_BEFORE_METHOD_PARENTHESES);
|
||||
} else if (myChild2.getElementType() == mRPAREN && myChild2.getElementType() == THROW_CLAUSE) {
|
||||
createSpaceInCode(true);
|
||||
} else if (isOpenBlock(myChild2)) {
|
||||
PsiElement methodName = method.getNameIdentifier();
|
||||
int dependancyStart = methodName == null ? myParent.getTextRange().getStartOffset() : methodName.getTextRange().getStartOffset();
|
||||
myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_METHOD_LBRACE, mySettings.METHOD_BRACE_STYLE,
|
||||
new TextRange(dependancyStart, myChild1.getTextRange().getEndOffset()), mySettings.KEEP_SIMPLE_METHODS_IN_ONE_LINE);
|
||||
} else if (myChild1.getElementType() == MODIFIERS) {
|
||||
processModifierList(myChild1);
|
||||
} else if (COMMENT_SET.contains(myChild1.getElementType())
|
||||
&& (myChild2.getElementType() == MODIFIERS || myChild2.getElementType() == REFERENCE_ELEMENT)) {
|
||||
myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, 0);
|
||||
}
|
||||
|
||||
public void visitFinallyClause(GrFinallyClause catchClause) {
|
||||
if (isOpenBlock(myChild2)) {
|
||||
myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_TRY_LBRACE, mySettings.BRACE_STYLE, null,
|
||||
mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitTryStatement(GrTryCatchStatement tryCatchStatement) {
|
||||
if (myChild2.getElementType() == FINALLY_CLAUSE) {
|
||||
processOnNewLineCondition(mySettings.FINALLY_ON_NEW_LINE);
|
||||
} else if (isOpenBlock(myChild2)) {
|
||||
myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_TRY_LBRACE, mySettings.BRACE_STYLE, null,
|
||||
mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE);
|
||||
} else if (myChild2.getElementType() == CATCH_CLAUSE) {
|
||||
processOnNewLineCondition(mySettings.CATCH_ON_NEW_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitSwitchStatement(GrSwitchStatement switchStatement) {
|
||||
if (myChild1.getElementType() == kSWITCH && myChild2.getElementType() == mLPAREN) {
|
||||
createSpaceInCode(mySettings.SPACE_BEFORE_SWITCH_PARENTHESES);
|
||||
} else if (myChild1.getElementType() == mLPAREN || myChild2.getElementType() == mRPAREN) {
|
||||
createSpaceInCode(mySettings.SPACE_WITHIN_SWITCH_PARENTHESES);
|
||||
} else if (myChild2.getElementType() == mLCURLY) {
|
||||
myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_SWITCH_LBRACE, mySettings.BRACE_STYLE, null,
|
||||
mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitSynchronizedStatement(GrSynchronizedStatement synchronizedStatement) {
|
||||
if (myChild1.getElementType() == kSYNCHRONIZED || myChild2.getElementType() == mLPAREN) {
|
||||
createSpaceInCode(mySettings.SPACE_BEFORE_SYNCHRONIZED_PARENTHESES);
|
||||
} else if (myChild1.getElementType() == mLPAREN || myChild2.getElementType() == mRPAREN) {
|
||||
createSpaceInCode(mySettings.SPACE_WITHIN_SYNCHRONIZED_PARENTHESES);
|
||||
} else if (isOpenBlock(myChild2)) {
|
||||
myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_SYNCHRONIZED_LBRACE,
|
||||
mySettings.BRACE_STYLE, null,
|
||||
mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void visitDocComment(GrDocComment comment) {
|
||||
if (myChild1.getElementType() == GDOC_TAG &&
|
||||
myChild2.getElementType() == GDOC_TAG &&
|
||||
mySettings.JD_LEADING_ASTERISKS_ARE_ENABLED) {
|
||||
IElementType type = myChild1.getLastChildNode().getElementType();
|
||||
if (type == mGDOC_ASTERISKS) {
|
||||
myResult = Spacing.createSpacing(1, 1, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void visitDocTag(GrDocTag docTag) {
|
||||
if (myChild1.getElementType() == mGDOC_INLINE_TAG_START ||
|
||||
myChild2.getElementType() == mGDOC_INLINE_TAG_END) {
|
||||
myResult = Spacing.createSpacing(0, 0, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitIfStatement(GrIfStatement ifStatement) {
|
||||
if (myChild2.getElementType() == kELSE) {
|
||||
if (!isOpenBlock(myChild1) && myChild1.getElementType() != BLOCK_STATEMENT) {
|
||||
myResult = Spacing.createSpacing(1, 1, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else {
|
||||
if (mySettings.ELSE_ON_NEW_LINE) {
|
||||
myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else {
|
||||
createSpaceProperty(true, false, 0);
|
||||
}
|
||||
}
|
||||
} else if (myChild1.getElementType() == kELSE) {
|
||||
if (myChild2.getElementType() == IF_STATEMENT) {
|
||||
if (mySettings.SPECIAL_ELSE_IF_TREATMENT) {
|
||||
createSpaceProperty(true, false, 0);
|
||||
} else {
|
||||
myResult = Spacing.createSpacing(1, 1, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
} else {
|
||||
if (myChild2.getElementType() == BLOCK_STATEMENT || isOpenBlock(myChild2)) {
|
||||
myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_ELSE_LBRACE, mySettings.BRACE_STYLE,
|
||||
null,
|
||||
mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE);
|
||||
} else {
|
||||
createSpacingBeforeElementInsideControlStatement();
|
||||
}
|
||||
}
|
||||
} else if (myChild2.getElementType() == BLOCK_STATEMENT || isOpenBlock(myChild2)) {
|
||||
boolean space = myChild2.getPsi() == ((GrIfStatement) myParent).getElseBranch() ? mySettings.SPACE_BEFORE_ELSE_LBRACE : mySettings.SPACE_BEFORE_IF_LBRACE;
|
||||
myResult = getSpaceBeforeLBrace(space, mySettings.BRACE_STYLE, new TextRange(myParent.getTextRange().getStartOffset(),
|
||||
myChild1.getTextRange().getEndOffset()),
|
||||
mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE);
|
||||
} else if (myChild2.getElementType() == mLPAREN) {
|
||||
createSpaceInCode(mySettings.SPACE_BEFORE_IF_PARENTHESES);
|
||||
} else if (myChild1.getElementType() == mLPAREN) {
|
||||
createSpaceInCode(mySettings.SPACE_WITHIN_IF_PARENTHESES);
|
||||
} else if (myChild2.getElementType() == mRPAREN) {
|
||||
createSpaceInCode(mySettings.SPACE_WITHIN_IF_PARENTHESES);
|
||||
} else if (((GrIfStatement) myParent).getThenBranch() == myChild2.getPsi()) {
|
||||
createSpacingBeforeElementInsideControlStatement();
|
||||
}
|
||||
}
|
||||
|
||||
public void visitForStatement(GrForStatement forStatement) {
|
||||
if (myChild2.getElementType() == mLPAREN) {
|
||||
createSpaceInCode(mySettings.SPACE_BEFORE_FOR_PARENTHESES);
|
||||
} else if (myChild1.getElementType() == mLPAREN) {
|
||||
ASTNode rparenth = findFrom(myChild2, mRPAREN, true);
|
||||
if (rparenth == null) {
|
||||
createSpaceInCode(mySettings.SPACE_WITHIN_FOR_PARENTHESES);
|
||||
} else {
|
||||
createParenSpace(mySettings.FOR_STATEMENT_LPAREN_ON_NEXT_LINE, mySettings.SPACE_WITHIN_FOR_PARENTHESES,
|
||||
new TextRange(myChild1.getTextRange().getStartOffset(), rparenth.getTextRange().getEndOffset()));
|
||||
}
|
||||
} else if (myChild2.getElementType() == mRPAREN) {
|
||||
ASTNode lparenth = findFrom(myChild2, mLPAREN, false);
|
||||
if (lparenth == null) {
|
||||
createSpaceInCode(mySettings.SPACE_WITHIN_FOR_PARENTHESES);
|
||||
} else {
|
||||
createParenSpace(mySettings.FOR_STATEMENT_RPAREN_ON_NEXT_LINE, mySettings.SPACE_WITHIN_FOR_PARENTHESES,
|
||||
new TextRange(lparenth.getTextRange().getStartOffset(), myChild2.getTextRange().getEndOffset()));
|
||||
}
|
||||
|
||||
} else if (myChild2.getElementType() == BLOCK_STATEMENT || isOpenBlock(myChild2)) {
|
||||
if (myChild2.getElementType() == BLOCK_STATEMENT) {
|
||||
myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_FOR_LBRACE, mySettings.BRACE_STYLE,
|
||||
new TextRange(myParent.getTextRange().getStartOffset(), myChild1.getTextRange().getEndOffset()), mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE);
|
||||
} else if (mySettings.KEEP_CONTROL_STATEMENT_IN_ONE_LINE) {
|
||||
myResult = Spacing.createDependentLFSpacing(1, 1, myParent.getTextRange(), false, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else {
|
||||
myResult = Spacing.createSpacing(0, 0, 1, false, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void createParenSpace(final boolean onNewLine, final boolean space) {
|
||||
createParenSpace(onNewLine, space, myParent.getTextRange());
|
||||
}
|
||||
|
||||
private void createParenSpace(final boolean onNewLine, final boolean space, final TextRange dependance) {
|
||||
if (onNewLine) {
|
||||
final int spaces = space ? 1 : 0;
|
||||
myResult = Spacing
|
||||
.createDependentLFSpacing(spaces, spaces, dependance, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else {
|
||||
createSpaceInCode(space);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static ASTNode findFrom(ASTNode current, final IElementType expected, boolean forward) {
|
||||
while (current != null) {
|
||||
if (current.getElementType() == expected) return current;
|
||||
current = forward ? current.getTreeNext() : current.getTreePrev();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private void processOnNewLineCondition(final boolean onNewLine) {
|
||||
if (onNewLine) {
|
||||
if (!mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE) {
|
||||
myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else {
|
||||
myResult = Spacing.createDependentLFSpacing(0, 1, myParent.getTextRange(), mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
} else {
|
||||
createSpaceProperty(true, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void createSpacingBeforeElementInsideControlStatement() {
|
||||
if (mySettings.KEEP_CONTROL_STATEMENT_IN_ONE_LINE && myChild1.getElementType() != mSL_COMMENT) {
|
||||
createSpaceProperty(true, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else {
|
||||
myResult = Spacing.createSpacing(1, 1, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void processModifierList(ASTNode modifierList) {
|
||||
if (modifierList.getLastChildNode().getElementType() == ANNOTATION && mySettings.METHOD_ANNOTATION_WRAP == CodeStyleSettings.WRAP_ALWAYS) {
|
||||
myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
else if (mySettings.MODIFIER_LIST_WRAP) {
|
||||
myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
else {
|
||||
createSpaceProperty(true, false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void clear() {
|
||||
myResult = null;
|
||||
myChild2 = myChild1 = null;
|
||||
myParent = null;
|
||||
}
|
||||
|
||||
protected Spacing getResult() {
|
||||
final Spacing result = myResult;
|
||||
clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
private void createSpaceInCode(final boolean space) {
|
||||
createSpaceProperty(space, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
|
||||
private void createSpaceProperty(boolean space, int keepBlankLines) {
|
||||
createSpaceProperty(space, mySettings.KEEP_LINE_BREAKS, keepBlankLines);
|
||||
}
|
||||
|
||||
private void createSpaceProperty(boolean space, boolean keepLineBreaks, final int keepBlankLines) {
|
||||
final ASTNode prev = SpacingUtil.getPrevElementType(myChild2);
|
||||
if (prev != null && prev.getElementType() == mSL_COMMENT) {
|
||||
myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else {
|
||||
myResult = Spacing.createSpacing(space ? 1 : 0, space ? 1 : 0, 0, keepLineBreaks, keepBlankLines);
|
||||
}
|
||||
}
|
||||
|
||||
private Spacing getSpaceBeforeLBrace(final boolean spaceBeforeLbrace, int braceStyle, TextRange dependantRange, boolean keepOneLine) {
|
||||
if (dependantRange != null && braceStyle == CodeStyleSettings.NEXT_LINE_IF_WRAPPED) {
|
||||
int space = spaceBeforeLbrace ? 1 : 0;
|
||||
return createNonLFSpace(space, dependantRange, false);
|
||||
} else if (braceStyle == CodeStyleSettings.END_OF_LINE || braceStyle == CodeStyleSettings.NEXT_LINE_IF_WRAPPED) {
|
||||
int space = spaceBeforeLbrace ? 1 : 0;
|
||||
return createNonLFSpace(space, null, false);
|
||||
} else if (keepOneLine) {
|
||||
int space = spaceBeforeLbrace ? 1 : 0;
|
||||
return Spacing.createDependentLFSpacing(space, space, myParent.getTextRange(), mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else {
|
||||
return Spacing.createSpacing(0, 0, 1, false, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
private Spacing createNonLFSpace(int spaces, final TextRange dependantRange, final boolean keepLineBreaks) {
|
||||
final ASTNode prev = SpacingUtil.getPrevElementType(myChild2);
|
||||
if (prev != null && prev.getElementType() == mSL_COMMENT) {
|
||||
return Spacing.createSpacing(0, Integer.MAX_VALUE, 1, keepLineBreaks, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else if (dependantRange != null) {
|
||||
return Spacing.createDependentLFSpacing(spaces, spaces, dependantRange, keepLineBreaks, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else {
|
||||
return Spacing.createSpacing(spaces, spaces, 0, keepLineBreaks, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static boolean isOpenBlock(final ASTNode node) {
|
||||
return node.getElementType() == OPEN_BLOCK || node.getElementType() == CONSTRUCTOR_BODY;
|
||||
}
|
||||
|
||||
public void visitDocMethodReference(GrDocMethodReference reference) {
|
||||
visitDocMember();
|
||||
}
|
||||
|
||||
|
||||
public void visitDocFieldReference(GrDocFieldReference reference) {
|
||||
visitDocMember();
|
||||
}
|
||||
|
||||
private void visitDocMember() {
|
||||
myResult = Spacing.createSpacing(0, 0, 0, false, 0);
|
||||
}
|
||||
|
||||
public void visitDocMethodParameterList(GrDocMethodParams params) {
|
||||
if (myChild1.getElementType() == mGDOC_TAG_VALUE_LPAREN || myChild2.getElementType() == mGDOC_TAG_VALUE_RPAREN) {
|
||||
myResult = Spacing.createSpacing(0, 0, 0, false, 0);
|
||||
return;
|
||||
}
|
||||
if (myChild2.getElementType() == mGDOC_TAG_VALUE_COMMA) {
|
||||
myResult = Spacing.createSpacing(0, 0, 0, false, 0);
|
||||
return;
|
||||
}
|
||||
createSpaceInCode(true);
|
||||
}
|
||||
|
||||
public void visitDocMethodParameter(GrDocMethodParameter parameter) {
|
||||
if (myChild1.getTreePrev() == null) {
|
||||
createSpaceInCode(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitWhileStatement(GrWhileStatement statement) {
|
||||
if (myChild2.getElementType() == mLPAREN) {
|
||||
createSpaceInCode(mySettings.SPACE_BEFORE_WHILE_PARENTHESES);
|
||||
} else if (myChild1.getElementType() == mLPAREN || myChild2.getElementType() == mRPAREN) {
|
||||
createSpaceInCode(mySettings.SPACE_WITHIN_WHILE_PARENTHESES);
|
||||
} else if (myChild2.getPsi() instanceof GrBlockStatement) {
|
||||
myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_WHILE_LBRACE, mySettings.BRACE_STYLE,
|
||||
new TextRange(myParent.getTextRange().getStartOffset(), myChild1.getTextRange().getEndOffset()), mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE);
|
||||
} else {
|
||||
createSpacingBeforeElementInsideControlStatement();
|
||||
}
|
||||
}
|
||||
|
||||
public void visitCatchClause(GrCatchClause catchClause) {
|
||||
if (isOpenBlock(myChild2)) {
|
||||
myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_TRY_LBRACE, mySettings.BRACE_STYLE, null,
|
||||
mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitFinallyClause(GrFinallyClause catchClause) {
|
||||
if (isOpenBlock(myChild2)) {
|
||||
myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_TRY_LBRACE, mySettings.BRACE_STYLE, null,
|
||||
mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitTryStatement(GrTryCatchStatement tryCatchStatement) {
|
||||
if (myChild2.getElementType() == FINALLY_CLAUSE) {
|
||||
processOnNewLineCondition(mySettings.FINALLY_ON_NEW_LINE);
|
||||
} else if (isOpenBlock(myChild2)) {
|
||||
myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_TRY_LBRACE, mySettings.BRACE_STYLE, null,
|
||||
mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE);
|
||||
} else if (myChild2.getElementType() == CATCH_CLAUSE) {
|
||||
processOnNewLineCondition(mySettings.CATCH_ON_NEW_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitSwitchStatement(GrSwitchStatement switchStatement) {
|
||||
if (myChild1.getElementType() == kSWITCH && myChild2.getElementType() == mLPAREN) {
|
||||
createSpaceInCode(mySettings.SPACE_BEFORE_SWITCH_PARENTHESES);
|
||||
} else if (myChild1.getElementType() == mLPAREN || myChild2.getElementType() == mRPAREN) {
|
||||
createSpaceInCode(mySettings.SPACE_WITHIN_SWITCH_PARENTHESES);
|
||||
} else if (myChild2.getElementType() == mLCURLY) {
|
||||
myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_SWITCH_LBRACE, mySettings.BRACE_STYLE, null,
|
||||
mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitSynchronizedStatement(GrSynchronizedStatement synchronizedStatement) {
|
||||
if (myChild1.getElementType() == kSYNCHRONIZED || myChild2.getElementType() == mLPAREN) {
|
||||
createSpaceInCode(mySettings.SPACE_BEFORE_SYNCHRONIZED_PARENTHESES);
|
||||
} else if (myChild1.getElementType() == mLPAREN || myChild2.getElementType() == mRPAREN) {
|
||||
createSpaceInCode(mySettings.SPACE_WITHIN_SYNCHRONIZED_PARENTHESES);
|
||||
} else if (isOpenBlock(myChild2)) {
|
||||
myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_SYNCHRONIZED_LBRACE,
|
||||
mySettings.BRACE_STYLE, null,
|
||||
mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void visitDocComment(GrDocComment comment) {
|
||||
if (myChild1.getElementType() == GDOC_TAG &&
|
||||
myChild2.getElementType() == GDOC_TAG &&
|
||||
mySettings.JD_LEADING_ASTERISKS_ARE_ENABLED) {
|
||||
IElementType type = myChild1.getLastChildNode().getElementType();
|
||||
if (type == mGDOC_ASTERISKS) {
|
||||
myResult = Spacing.createSpacing(1, 1, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void visitDocTag(GrDocTag docTag) {
|
||||
if (myChild1.getElementType() == mGDOC_INLINE_TAG_START ||
|
||||
myChild2.getElementType() == mGDOC_INLINE_TAG_END) {
|
||||
myResult = Spacing.createSpacing(0, 0, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitIfStatement(GrIfStatement ifStatement) {
|
||||
if (myChild2.getElementType() == kELSE) {
|
||||
if (!isOpenBlock(myChild1) && myChild1.getElementType() != BLOCK_STATEMENT) {
|
||||
myResult = Spacing.createSpacing(1, 1, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else {
|
||||
if (mySettings.ELSE_ON_NEW_LINE) {
|
||||
myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else {
|
||||
createSpaceProperty(true, false, 0);
|
||||
}
|
||||
}
|
||||
} else if (myChild1.getElementType() == kELSE) {
|
||||
if (myChild2.getElementType() == IF_STATEMENT) {
|
||||
if (mySettings.SPECIAL_ELSE_IF_TREATMENT) {
|
||||
createSpaceProperty(true, false, 0);
|
||||
} else {
|
||||
myResult = Spacing.createSpacing(1, 1, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
} else {
|
||||
if (myChild2.getElementType() == BLOCK_STATEMENT || isOpenBlock(myChild2)) {
|
||||
myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_ELSE_LBRACE, mySettings.BRACE_STYLE,
|
||||
null,
|
||||
mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE);
|
||||
} else {
|
||||
createSpacingBeforeElementInsideControlStatement();
|
||||
}
|
||||
}
|
||||
} else if (myChild2.getElementType() == BLOCK_STATEMENT || isOpenBlock(myChild2)) {
|
||||
boolean space = myChild2.getPsi() == ((GrIfStatement) myParent).getElseBranch() ? mySettings.SPACE_BEFORE_ELSE_LBRACE : mySettings.SPACE_BEFORE_IF_LBRACE;
|
||||
myResult = getSpaceBeforeLBrace(space, mySettings.BRACE_STYLE, new TextRange(myParent.getTextRange().getStartOffset(),
|
||||
myChild1.getTextRange().getEndOffset()),
|
||||
mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE);
|
||||
} else if (myChild2.getElementType() == mLPAREN) {
|
||||
createSpaceInCode(mySettings.SPACE_BEFORE_IF_PARENTHESES);
|
||||
} else if (myChild1.getElementType() == mLPAREN) {
|
||||
createSpaceInCode(mySettings.SPACE_WITHIN_IF_PARENTHESES);
|
||||
} else if (myChild2.getElementType() == mRPAREN) {
|
||||
createSpaceInCode(mySettings.SPACE_WITHIN_IF_PARENTHESES);
|
||||
} else if (((GrIfStatement) myParent).getThenBranch() == myChild2.getPsi()) {
|
||||
createSpacingBeforeElementInsideControlStatement();
|
||||
}
|
||||
}
|
||||
|
||||
public void visitForStatement(GrForStatement forStatement) {
|
||||
if (myChild2.getElementType() == mLPAREN) {
|
||||
createSpaceInCode(mySettings.SPACE_BEFORE_FOR_PARENTHESES);
|
||||
} else if (myChild1.getElementType() == mLPAREN) {
|
||||
ASTNode rparenth = findFrom(myChild2, mRPAREN, true);
|
||||
if (rparenth == null) {
|
||||
createSpaceInCode(mySettings.SPACE_WITHIN_FOR_PARENTHESES);
|
||||
} else {
|
||||
createParenSpace(mySettings.FOR_STATEMENT_LPAREN_ON_NEXT_LINE, mySettings.SPACE_WITHIN_FOR_PARENTHESES,
|
||||
new TextRange(myChild1.getTextRange().getStartOffset(), rparenth.getTextRange().getEndOffset()));
|
||||
}
|
||||
} else if (myChild2.getElementType() == mRPAREN) {
|
||||
ASTNode lparenth = findFrom(myChild2, mLPAREN, false);
|
||||
if (lparenth == null) {
|
||||
createSpaceInCode(mySettings.SPACE_WITHIN_FOR_PARENTHESES);
|
||||
} else {
|
||||
createParenSpace(mySettings.FOR_STATEMENT_RPAREN_ON_NEXT_LINE, mySettings.SPACE_WITHIN_FOR_PARENTHESES,
|
||||
new TextRange(lparenth.getTextRange().getStartOffset(), myChild2.getTextRange().getEndOffset()));
|
||||
}
|
||||
|
||||
} else if (myChild2.getElementType() == BLOCK_STATEMENT || isOpenBlock(myChild2)) {
|
||||
if (myChild2.getElementType() == BLOCK_STATEMENT) {
|
||||
myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_FOR_LBRACE, mySettings.BRACE_STYLE,
|
||||
new TextRange(myParent.getTextRange().getStartOffset(), myChild1.getTextRange().getEndOffset()), mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE);
|
||||
} else if (mySettings.KEEP_CONTROL_STATEMENT_IN_ONE_LINE) {
|
||||
myResult = Spacing.createDependentLFSpacing(1, 1, myParent.getTextRange(), false, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else {
|
||||
myResult = Spacing.createSpacing(0, 0, 1, false, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void createParenSpace(final boolean onNewLine, final boolean space) {
|
||||
createParenSpace(onNewLine, space, myParent.getTextRange());
|
||||
}
|
||||
|
||||
private void createParenSpace(final boolean onNewLine, final boolean space, final TextRange dependance) {
|
||||
if (onNewLine) {
|
||||
final int spaces = space ? 1 : 0;
|
||||
myResult = Spacing
|
||||
.createDependentLFSpacing(spaces, spaces, dependance, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else {
|
||||
createSpaceInCode(space);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static ASTNode findFrom(ASTNode current, final IElementType expected, boolean forward) {
|
||||
while (current != null) {
|
||||
if (current.getElementType() == expected) return current;
|
||||
current = forward ? current.getTreeNext() : current.getTreePrev();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private void processOnNewLineCondition(final boolean onNewLine) {
|
||||
if (onNewLine) {
|
||||
if (!mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE) {
|
||||
myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else {
|
||||
myResult = Spacing.createDependentLFSpacing(0, 1, myParent.getTextRange(), mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
} else {
|
||||
createSpaceProperty(true, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void createSpacingBeforeElementInsideControlStatement() {
|
||||
if (mySettings.KEEP_CONTROL_STATEMENT_IN_ONE_LINE && myChild1.getElementType() != mSL_COMMENT) {
|
||||
createSpaceProperty(true, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else {
|
||||
myResult = Spacing.createSpacing(1, 1, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void processModifierList(ASTNode modifierList) {
|
||||
if (modifierList.getLastChildNode().getElementType() == ANNOTATION && mySettings.METHOD_ANNOTATION_WRAP == CodeStyleSettings.WRAP_ALWAYS) {
|
||||
myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
else if (mySettings.MODIFIER_LIST_WRAP) {
|
||||
myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
else {
|
||||
createSpaceProperty(true, false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public Spacing getSpacing() {
|
||||
return myResult;
|
||||
}
|
||||
|
||||
private void createSpaceInCode(final boolean space) {
|
||||
createSpaceProperty(space, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
|
||||
private void createSpaceProperty(boolean space, int keepBlankLines) {
|
||||
createSpaceProperty(space, mySettings.KEEP_LINE_BREAKS, keepBlankLines);
|
||||
}
|
||||
|
||||
private void createSpaceProperty(boolean space, boolean keepLineBreaks, final int keepBlankLines) {
|
||||
final ASTNode prev = SpacingUtil.getPrevElementType(myChild2);
|
||||
if (prev != null && prev.getElementType() == mSL_COMMENT) {
|
||||
myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else {
|
||||
myResult = Spacing.createSpacing(space ? 1 : 0, space ? 1 : 0, 0, keepLineBreaks, keepBlankLines);
|
||||
}
|
||||
}
|
||||
|
||||
private Spacing getSpaceBeforeLBrace(final boolean spaceBeforeLbrace, int braceStyle, TextRange dependantRange, boolean keepOneLine) {
|
||||
if (dependantRange != null && braceStyle == CodeStyleSettings.NEXT_LINE_IF_WRAPPED) {
|
||||
int space = spaceBeforeLbrace ? 1 : 0;
|
||||
return createNonLFSpace(space, dependantRange, false);
|
||||
} else if (braceStyle == CodeStyleSettings.END_OF_LINE || braceStyle == CodeStyleSettings.NEXT_LINE_IF_WRAPPED) {
|
||||
int space = spaceBeforeLbrace ? 1 : 0;
|
||||
return createNonLFSpace(space, null, false);
|
||||
} else if (keepOneLine) {
|
||||
int space = spaceBeforeLbrace ? 1 : 0;
|
||||
return Spacing.createDependentLFSpacing(space, space, myParent.getTextRange(), mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else {
|
||||
return Spacing.createSpacing(0, 0, 1, false, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
private Spacing createNonLFSpace(int spaces, final TextRange dependantRange, final boolean keepLineBreaks) {
|
||||
final ASTNode prev = SpacingUtil.getPrevElementType(myChild2);
|
||||
if (prev != null && prev.getElementType() == mSL_COMMENT) {
|
||||
return Spacing.createSpacing(0, Integer.MAX_VALUE, 1, keepLineBreaks, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else if (dependantRange != null) {
|
||||
return Spacing.createDependentLFSpacing(spaces, spaces, dependantRange, keepLineBreaks, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
} else {
|
||||
return Spacing.createSpacing(spaces, spaces, 0, keepLineBreaks, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
+1
-6
@@ -362,7 +362,6 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
|
||||
final ElementFilter classFilter = getClassFilter(position);
|
||||
|
||||
final boolean showCapitalizedClasses = JavaCompletionContributor.showCapitalizedClasses(result);
|
||||
reference.processVariants(new Consumer<Object>() {
|
||||
public void consume(Object element) {
|
||||
if (element instanceof PsiClass && inheritors.alreadyProcessed((PsiClass)element)) {
|
||||
@@ -384,10 +383,6 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
object = ((GroovyResolveResult)object).getElement();
|
||||
}
|
||||
|
||||
if (!showCapitalizedClasses && object instanceof PsiClass && StringUtil.isCapitalized(((PsiClass)object).getName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean autopopup = parameters.getInvocationCount() == 0;
|
||||
//skip default groovy methods
|
||||
if (!secondCompletionInvoked &&
|
||||
@@ -458,7 +453,7 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
});
|
||||
|
||||
if (StringUtil.isCapitalized(prefix)) {
|
||||
if (StringUtil.isNotEmpty(result.getPrefixMatcher().getPrefix())) {
|
||||
addAllClasses(parameters, result, inheritors);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-4
@@ -29,7 +29,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.SubtypeConstraint;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.SupertypeConstraint;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeEquals;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
@@ -52,9 +51,7 @@ public class ChooseTypeExpression extends Expression {
|
||||
Set<LookupElement> result = new LinkedHashSet<LookupElement>();
|
||||
|
||||
for (TypeConstraint constraint : constraints) {
|
||||
if (constraint instanceof TypeEquals) {
|
||||
result.add(PsiTypeLookupItem.createLookupItem(constraint.getType(), null));
|
||||
} else if (constraint instanceof SubtypeConstraint) {
|
||||
if (constraint instanceof SubtypeConstraint) {
|
||||
result.add(PsiTypeLookupItem.createLookupItem(constraint.getDefaultType(), null));
|
||||
} else if (constraint instanceof SupertypeConstraint) {
|
||||
processSupertypes(constraint.getType(), result);
|
||||
|
||||
+1
@@ -272,6 +272,7 @@ public class GroovyExpectedTypesProvider {
|
||||
expression, PsiType.EMPTY_ARRAY).length > 0;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiType getDefaultType() {
|
||||
return PsiType.INT;
|
||||
|
||||
+5
-12
@@ -20,6 +20,7 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
|
||||
|
||||
import static org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil.createType;
|
||||
@@ -30,7 +31,7 @@ import static org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.
|
||||
public class SubtypeConstraint extends TypeConstraint {
|
||||
private final PsiType myDefaultType;
|
||||
|
||||
protected SubtypeConstraint(PsiType type, PsiType defaultType) {
|
||||
protected SubtypeConstraint(@NotNull PsiType type, @NotNull PsiType defaultType) {
|
||||
super(type);
|
||||
myDefaultType = defaultType;
|
||||
}
|
||||
@@ -39,24 +40,16 @@ public class SubtypeConstraint extends TypeConstraint {
|
||||
return TypesUtil.isAssignableByMethodCallConversion(getType(), type, manager, scope);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiType getDefaultType() {
|
||||
return myDefaultType;
|
||||
}
|
||||
|
||||
public static SubtypeConstraint create (PsiType type, PsiType defaultType) {
|
||||
return new SubtypeConstraint(type, defaultType);
|
||||
}
|
||||
|
||||
public static SubtypeConstraint create (String fqName, String defaultFqName, PsiElement context) {
|
||||
return new SubtypeConstraint(createType(fqName, context),
|
||||
createType(defaultFqName, context));
|
||||
}
|
||||
|
||||
public static SubtypeConstraint create (PsiType type) {
|
||||
public static SubtypeConstraint create(@NotNull PsiType type) {
|
||||
return new SubtypeConstraint(type, type);
|
||||
}
|
||||
|
||||
public static SubtypeConstraint create (String fqName, PsiElement context) {
|
||||
public static SubtypeConstraint create(String fqName, PsiElement context) {
|
||||
PsiClassType type = createType(fqName, context);
|
||||
return new SubtypeConstraint(type, type);
|
||||
}
|
||||
|
||||
+5
-16
@@ -15,22 +15,19 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.lang.psi.expectedTypes;
|
||||
|
||||
import com.intellij.psi.PsiClassType;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
|
||||
|
||||
import static org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil.createType;
|
||||
|
||||
/**
|
||||
* @author ven
|
||||
*/
|
||||
public class SupertypeConstraint extends TypeConstraint {
|
||||
private final PsiType myDefaultType;
|
||||
|
||||
protected SupertypeConstraint(PsiType type, PsiType defaultType) {
|
||||
protected SupertypeConstraint(@NotNull PsiType type, @NotNull PsiType defaultType) {
|
||||
super(type);
|
||||
myDefaultType = defaultType;
|
||||
}
|
||||
@@ -39,25 +36,17 @@ public class SupertypeConstraint extends TypeConstraint {
|
||||
return TypesUtil.isAssignableByMethodCallConversion(type, getType(), manager, scope);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiType getDefaultType() {
|
||||
return myDefaultType;
|
||||
}
|
||||
|
||||
public static SupertypeConstraint create (PsiType type, PsiType defaultType) {
|
||||
public static SupertypeConstraint create(@NotNull PsiType type, @NotNull PsiType defaultType) {
|
||||
return new SupertypeConstraint(type, defaultType);
|
||||
}
|
||||
|
||||
public static SupertypeConstraint create (String fqName, String defaultFqName, PsiElement context) {
|
||||
return new SupertypeConstraint(createType(fqName, context),
|
||||
createType(defaultFqName, context));
|
||||
}
|
||||
|
||||
public static SupertypeConstraint create (PsiType type) {
|
||||
public static SupertypeConstraint create(@NotNull PsiType type) {
|
||||
return new SupertypeConstraint(type, type);
|
||||
}
|
||||
|
||||
public static SupertypeConstraint create (String fqName, PsiElement context) {
|
||||
PsiClassType type = createType(fqName, context);
|
||||
return new SupertypeConstraint(type, type);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -18,6 +18,7 @@ package org.jetbrains.plugins.groovy.lang.psi.expectedTypes;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author ven
|
||||
@@ -29,12 +30,14 @@ public abstract class TypeConstraint {
|
||||
|
||||
public abstract boolean satisfied(PsiType type, PsiManager manager, GlobalSearchScope scope);
|
||||
|
||||
@NotNull
|
||||
public abstract PsiType getDefaultType();
|
||||
|
||||
protected TypeConstraint(PsiType type) {
|
||||
protected TypeConstraint(@NotNull PsiType type) {
|
||||
myType = type;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiType getType() {
|
||||
return myType;
|
||||
}
|
||||
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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 org.jetbrains.plugins.groovy.lang.psi.expectedTypes;
|
||||
|
||||
import com.intellij.psi.PsiClassType;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
|
||||
import static org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil.createType;
|
||||
|
||||
/**
|
||||
* @author ven
|
||||
*/
|
||||
public class TypeEquals extends TypeConstraint {
|
||||
protected TypeEquals(PsiType type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
public boolean satisfied(PsiType type, PsiManager manager, GlobalSearchScope scope){
|
||||
return type.equals(myType);
|
||||
}
|
||||
|
||||
public PsiType getDefaultType() {
|
||||
return getType();
|
||||
}
|
||||
|
||||
public static TypeEquals create (PsiType type) {
|
||||
return new TypeEquals(type);
|
||||
}
|
||||
|
||||
public static TypeEquals create (String fqName, PsiElement context) {
|
||||
PsiClassType type = createType(fqName, context);
|
||||
return new TypeEquals(type);
|
||||
}
|
||||
}
|
||||
+18
-57
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.jetbrains.plugins.groovy.lang.psi.impl;
|
||||
|
||||
import com.google.common.collect.HashMultiset;
|
||||
import com.google.common.collect.Multiset;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.ProjectTopics;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
@@ -26,6 +24,8 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ModuleRootEvent;
|
||||
import com.intellij.openapi.roots.ModuleRootListener;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.RecursionGuard;
|
||||
import com.intellij.openapi.util.RecursionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiManagerEx;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
@@ -46,7 +46,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefini
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
|
||||
import org.jetbrains.plugins.groovy.lang.stubs.GroovyShortNamesCache;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -74,6 +73,7 @@ public class GroovyPsiManager {
|
||||
private final TypeInferenceHelper myTypeInferenceHelper;
|
||||
|
||||
private static final String SYNTHETIC_CLASS_TEXT = "class __ARRAY__ { public int length }";
|
||||
private static final RecursionGuard ourGuard = RecursionManager.createGuard("groovyPsiManager");
|
||||
|
||||
public GroovyPsiManager(Project project) {
|
||||
myProject = project;
|
||||
@@ -156,46 +156,22 @@ public class GroovyPsiManager {
|
||||
return result;
|
||||
}
|
||||
|
||||
private final ThreadLocal<Multiset<GroovyPsiElement>> inferring = new ThreadLocal<Multiset<GroovyPsiElement>>(){
|
||||
@Override
|
||||
protected Multiset<GroovyPsiElement> initialValue() {
|
||||
return HashMultiset.create();
|
||||
}
|
||||
};
|
||||
|
||||
private boolean lock(GroovyPsiElement element) {
|
||||
final Multiset<GroovyPsiElement> set = inferring.get();
|
||||
boolean alreadyContains = set.contains(element);
|
||||
inferring.get().add(element);
|
||||
return alreadyContains;
|
||||
}
|
||||
|
||||
private void unlock(GroovyPsiElement element) {
|
||||
inferring.get().remove(element);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public <T extends GroovyPsiElement> PsiType getType(T element, Function<T, PsiType> calculator) {
|
||||
PsiType type = myCalculatedTypes.get(element);
|
||||
if (type == null) {
|
||||
try {
|
||||
boolean locked = lock(element);
|
||||
type = calculator.fun(element);
|
||||
if (type == null) {
|
||||
type = PsiType.NULL;
|
||||
}
|
||||
if (locked) {
|
||||
final PsiType alreadyInferred = myCalculatedTypes.get(element);
|
||||
if (alreadyInferred != null) {
|
||||
type = alreadyInferred;
|
||||
}
|
||||
}
|
||||
else {
|
||||
type = ConcurrencyUtil.cacheOrGet(myCalculatedTypes, element, type);
|
||||
}
|
||||
RecursionGuard.StackStamp stamp = ourGuard.markStack();
|
||||
type = calculator.fun(element);
|
||||
if (type == null) {
|
||||
type = PsiType.NULL;
|
||||
}
|
||||
finally {
|
||||
unlock(element);
|
||||
if (stamp.mayCacheNow()) {
|
||||
type = ConcurrencyUtil.cacheOrGet(myCalculatedTypes, element, type);
|
||||
} else {
|
||||
final PsiType alreadyInferred = myCalculatedTypes.get(element);
|
||||
if (alreadyInferred != null) {
|
||||
type = alreadyInferred;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!type.isValid()) {
|
||||
@@ -217,30 +193,15 @@ public class GroovyPsiManager {
|
||||
return myArrayClass;
|
||||
}
|
||||
|
||||
private static final ThreadLocal<List<PsiElement>> myElementsWithTypesBeingInferred = new ThreadLocal<List<PsiElement>>() {
|
||||
protected List<PsiElement> initialValue() {
|
||||
return new ArrayList<PsiElement>();
|
||||
}
|
||||
};
|
||||
|
||||
@Nullable
|
||||
public static PsiType inferType(PsiElement element, Computable<PsiType> computable) {
|
||||
final List<PsiElement> curr = myElementsWithTypesBeingInferred.get();
|
||||
if (curr.size() > 7) { //don't end up walking the whole project PSI
|
||||
List<Object> stack = ourGuard.currentStack();
|
||||
if (stack.size() > 7) { //don't end up walking the whole project PSI
|
||||
ourGuard.prohibitResultCaching(stack.get(0));
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
curr.add(element);
|
||||
return computable.compute();
|
||||
}
|
||||
finally {
|
||||
curr.remove(element);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isTypeBeingInferred(PsiElement element) {
|
||||
return myElementsWithTypesBeingInferred.get().contains(element);
|
||||
return ourGuard.doPreventingRecursion(element, computable);
|
||||
}
|
||||
|
||||
public GroovyShortNamesCache getNamesCache() {
|
||||
|
||||
+12
-6
@@ -17,6 +17,9 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.NullableComputable;
|
||||
import com.intellij.openapi.util.RecursionGuard;
|
||||
import com.intellij.openapi.util.RecursionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
@@ -55,7 +58,7 @@ import javax.swing.*;
|
||||
public abstract class GrVariableBaseImpl<T extends StubElement> extends GrStubElementBase<T> implements GrVariable {
|
||||
public static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.lang.psi.impl.statements.GrVariableImpl");
|
||||
|
||||
private final ThreadLocal<Boolean> isInferringType = new ThreadLocal<Boolean>();
|
||||
private final RecursionGuard myGuard = RecursionManager.createGuard("grVariableInitializer");
|
||||
|
||||
public GrVariableBaseImpl(ASTNode node) {
|
||||
super(node);
|
||||
@@ -143,7 +146,7 @@ public abstract class GrVariableBaseImpl<T extends StubElement> extends GrStubEl
|
||||
|
||||
@Nullable
|
||||
public PsiType getTypeGroovy() {
|
||||
GrExpression initializer = getInitializerGroovy();
|
||||
final GrExpression initializer = getInitializerGroovy();
|
||||
final PsiElement parent = getParent();
|
||||
|
||||
if (parent instanceof GrTupleDeclaration && initializer != null){
|
||||
@@ -159,10 +162,13 @@ public abstract class GrVariableBaseImpl<T extends StubElement> extends GrStubEl
|
||||
}
|
||||
}
|
||||
|
||||
if (initializer != null && isInferringType.get() == null) {
|
||||
isInferringType.set(Boolean.TRUE);
|
||||
PsiType initializerType = initializer.getType(); // WARNING may give rise to SOE
|
||||
isInferringType.set(null);
|
||||
if (initializer != null) {
|
||||
PsiType initializerType = myGuard.doPreventingRecursion(this, new NullableComputable<PsiType>() {
|
||||
@Override
|
||||
public PsiType compute() {
|
||||
return initializer.getType();
|
||||
}
|
||||
});
|
||||
if (initializerType != null) {
|
||||
if (declaredType != null && initializerType instanceof PsiClassType) {
|
||||
final PsiClass declaredClass = ((PsiClassType)declaredType).resolve();
|
||||
|
||||
-3
@@ -218,9 +218,6 @@ public class GrClosableBlockImpl extends GrBlockImpl implements GrClosableBlock
|
||||
|
||||
@Nullable
|
||||
public PsiType getReturnType() {
|
||||
if (GroovyPsiManager.isTypeBeingInferred(this)) {
|
||||
return null;
|
||||
}
|
||||
return GroovyPsiManager.getInstance(getProject()).getType(this, ourTypesCalculator);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -426,7 +426,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
} else if (resolved instanceof PsiVariable) {
|
||||
result = ((PsiVariable) resolved).getType();
|
||||
} else
|
||||
if (resolved instanceof PsiMethod && !GroovyPsiManager.isTypeBeingInferred(resolved)) {
|
||||
if (resolved instanceof PsiMethod) {
|
||||
if (dotType == GroovyTokenTypes.mMEMBER_POINTER) {
|
||||
return TypesUtil.createTypeByFQClassName(GroovyCommonClassNames.GROOVY_LANG_CLOSURE, this);
|
||||
}
|
||||
|
||||
+2
@@ -318,6 +318,7 @@ public class TypesUtil {
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiClassType createType(String fqName, @NotNull PsiElement context) {
|
||||
return createTypeByFQClassName(fqName, context);
|
||||
}
|
||||
@@ -447,6 +448,7 @@ public class TypesUtil {
|
||||
return PsiSubstitutorImpl.createSubstitutor(result);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiClassType createTypeByFQClassName(@NotNull String fqName, @NotNull PsiElement context) {
|
||||
return GroovyPsiManager.getInstance(context.getProject()).createTypeByFQClassName(fqName, context.getResolveScope());
|
||||
}
|
||||
|
||||
+1
-2
@@ -27,7 +27,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpres
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
@@ -49,7 +48,7 @@ public class DefaultCallExpressionTypeCalculator extends GrCallExpressionTypeCal
|
||||
for (GroovyResolveResult resolveResult : resolveResults) {
|
||||
PsiElement resolved = resolveResult.getElement();
|
||||
PsiType returnType = null;
|
||||
if (resolved instanceof PsiMethod && !GroovyPsiManager.isTypeBeingInferred(resolved)) {
|
||||
if (resolved instanceof PsiMethod) {
|
||||
PsiMethod method = (PsiMethod) resolved;
|
||||
if (resolveResult.isInvokedOnProperty()) {
|
||||
final PsiType propertyType = PsiUtil.getSmartReturnType(method);
|
||||
|
||||
-4
@@ -211,10 +211,6 @@ public abstract class GrMethodBaseImpl extends GrStubElementBase<GrMethodStub> i
|
||||
if (block == null) return null;
|
||||
assert block.isValid() : "invalid code block";
|
||||
|
||||
if (GroovyPsiManager.isTypeBeingInferred(method)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return GroovyPsiManager.inferType(method, new MethodTypeInferencer(block));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
package org.jetbrains.plugins.groovy.lang
|
||||
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.testFramework.IdeaTestUtil
|
||||
import com.intellij.testFramework.LightProjectDescriptor
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import org.jetbrains.plugins.groovy.LightGroovyTestCase
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.testFramework.IdeaTestUtil
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager
|
||||
|
||||
/**
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
class GroovyStressTest extends LightCodeInsightFixtureTestCase {
|
||||
@@ -19,24 +21,41 @@ class GroovyStressTest extends LightCodeInsightFixtureTestCase {
|
||||
}
|
||||
|
||||
public void testDontWalkLongInferenceChain() throws Exception {
|
||||
Map<Integer, PsiClass> classes = [:]
|
||||
myFixture.addFileToProject "Foo0.groovy", """class Foo0 {
|
||||
def foo() { return 0 }
|
||||
}"""
|
||||
def max = 100
|
||||
for (i in 1..max) {
|
||||
myFixture.addFileToProject "Foo${i}.groovy", """class Foo$i {
|
||||
def foo() { return Foo${i-1}.foo() }
|
||||
}"""
|
||||
def file = myFixture.addFileToProject("Foo${i}.groovy", """class Foo$i {
|
||||
def foo() { return Foo${i - 1}.foo() }
|
||||
}""")
|
||||
classes[i] = (file as GroovyFile).classes[0]
|
||||
}
|
||||
|
||||
def deepFile = myFixture.addFileToProject("DeepTest.groovy", "def test() { return Foo${max}.foo() }") as GroovyFile
|
||||
assert Object.name == (deepFile.scriptClass.findMethodsByName("test", false)[0] as GrMethod).inferredReturnType.canonicalText
|
||||
assert Object.name == inferredType(deepFile.scriptClass, 'test')
|
||||
|
||||
def shallowFile = myFixture.addFileToProject("ShallowTest.groovy", "def test() { return Foo2.foo() }") as GroovyFile
|
||||
assert Integer.name == (shallowFile.scriptClass.findMethodsByName("test", false)[0] as GrMethod).inferredReturnType.canonicalText
|
||||
assert Integer.name == inferredType(shallowFile.scriptClass, 'test')
|
||||
|
||||
int border = (1..max).find { int i ->
|
||||
GroovyPsiManager.getInstance(project).dropTypesCache()
|
||||
return inferredType(classes[i], 'foo') == Object.name
|
||||
}
|
||||
|
||||
assert border
|
||||
|
||||
GroovyPsiManager.getInstance(project).dropTypesCache()
|
||||
assert inferredType(classes[border], 'foo') == Object.name
|
||||
assert inferredType(classes[border - 1], 'foo') == Integer.name
|
||||
}
|
||||
|
||||
String inferredType(PsiClass clazz, String method) {
|
||||
(clazz.findMethodsByName(method, false)[0] as GrMethod).inferredReturnType.canonicalText
|
||||
}
|
||||
|
||||
|
||||
public void testQuickIncrementalReparse() {
|
||||
def story = '''scenario {
|
||||
given "some precondition", {
|
||||
|
||||
@@ -18,7 +18,6 @@ package com.intellij.execution.junit2.ui;
|
||||
|
||||
import com.intellij.execution.configurations.ConfigurationPerRunnerSettings;
|
||||
import com.intellij.execution.configurations.RunnerSettings;
|
||||
import com.intellij.execution.junit2.TestProxy;
|
||||
import com.intellij.execution.junit2.ui.model.JUnitRunningModel;
|
||||
import com.intellij.execution.junit2.ui.model.TreeCollapser;
|
||||
import com.intellij.execution.junit2.ui.properties.JUnitConsoleProperties;
|
||||
@@ -53,6 +52,7 @@ public class JUnitTreeConsoleView extends BaseTestsOutputConsoleView {
|
||||
}
|
||||
|
||||
public void attachToProcess(final ProcessHandler processHandler) {
|
||||
super.attachToProcess(processHandler);
|
||||
myConsolePanel.onProcessStarted(processHandler);
|
||||
}
|
||||
|
||||
|
||||
@@ -94,9 +94,13 @@ public class JUnit4TestResultsSender extends RunListener {
|
||||
catch (Throwable ignore) {}
|
||||
}
|
||||
|
||||
if (assertion.getMessage() != null) {
|
||||
final Matcher matcher =
|
||||
Pattern.compile("\nExpected: \"(.*)\"\n got: \"(.*)\"\n", Pattern.DOTALL).matcher(assertion.getMessage());
|
||||
final String message = assertion.getMessage();
|
||||
if (message != null) {
|
||||
Matcher matcher =
|
||||
Pattern.compile("\nExpected: (.*)\n\\s*got: (.*)", Pattern.DOTALL).matcher(message);
|
||||
if (!matcher.matches()) {
|
||||
matcher = Pattern.compile("expected same:<(.*)> was not:<(.*)>", Pattern.DOTALL).matcher(message);
|
||||
}
|
||||
if (matcher.matches()) {
|
||||
return ComparisonDetailsExtractor
|
||||
.create(assertion, matcher.group(1).replaceAll("\\\\n", "\n"), matcher.group(2).replaceAll("\\\\n", "\n"));
|
||||
|
||||
@@ -25,8 +25,6 @@ package com.theoryinpractice.testng.ui;
|
||||
import com.intellij.execution.Executor;
|
||||
import com.intellij.execution.configurations.ConfigurationPerRunnerSettings;
|
||||
import com.intellij.execution.configurations.RunnerSettings;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.execution.testframework.AbstractTestProxy;
|
||||
import com.intellij.execution.testframework.TestTreeView;
|
||||
import com.intellij.execution.testframework.ui.BaseTestsOutputConsoleView;
|
||||
import com.intellij.execution.testframework.ui.TestResultsPanel;
|
||||
@@ -124,9 +122,6 @@ public class TestNGConsoleView extends BaseTestsOutputConsoleView {
|
||||
}
|
||||
}
|
||||
|
||||
public void attachToProcess(ProcessHandler processHandler) {
|
||||
}
|
||||
|
||||
public TestProxy getCurrentTest() {
|
||||
return currentTest;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user