Merge branch 'master' of git@git.labs.intellij.net:idea/community

This commit is contained in:
Eugene Kudelevsky
2011-03-24 21:07:47 +03:00
108 changed files with 2113 additions and 1223 deletions
Binary file not shown.
Binary file not shown.
+2
View File
@@ -38,6 +38,8 @@ target('default': 'The default target') {
};
}
commonJvmArgs().each { jvmarg(value: it) }
if (isDefined("jvm_args")) {
jvm_args.each { jvmarg(value: it) }
}
@@ -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,
@@ -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);
}
@@ -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) {
@@ -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;
}
}
@@ -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;
@@ -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
@@ -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);
@@ -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++) {
@@ -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++) {
@@ -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);
}
@@ -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();
@@ -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 {
@@ -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) {
@@ -1,7 +0,0 @@
public class Foo {
{
aa<caret>
}
}
@@ -3,7 +3,7 @@ public class Test {
public static void main() {
Collection[] cc = new MyCollection[10];
}
}<caret>
}
public class MyCollection {
<caret>public class MyCollection {
}
@@ -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 {
}
@@ -3,7 +3,7 @@ class Test {
void foo () {
new Generic<String> ();
}
}<caret>
}
public class Generic<T> {
<caret>public class Generic<T> {
}
@@ -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();
@@ -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()) {
@@ -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;
}
}
@@ -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 {
@@ -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"),
@@ -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;
}
@@ -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);
}
@@ -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"/>
@@ -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(),
@@ -112,6 +112,7 @@ public class SMTRunnerConsoleView extends BaseTestsOutputConsoleView {
}
public void attachToProcess(final ProcessHandler processHandler) {
super.attachToProcess(processHandler);
if (processHandler == null) {
return;
}
@@ -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;
}
@@ -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);
}
}
}
}
}
@@ -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,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) {
@@ -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);
}
}
@@ -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;
}
@@ -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 &&
@@ -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);
}
}
}
@@ -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);
}
}
@@ -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);
@@ -272,6 +272,7 @@ public class GroovyExpectedTypesProvider {
expression, PsiType.EMPTY_ARRAY).length > 0;
}
@NotNull
@Override
public PsiType getDefaultType() {
return PsiType.INT;
@@ -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);
}
@@ -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);
}
}
@@ -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;
}
@@ -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);
}
}
@@ -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() {
@@ -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();
@@ -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);
}
}
@@ -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);
}
@@ -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());
}
@@ -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);
@@ -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