Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Trofimov
2015-07-03 11:19:55 +02:00
354 changed files with 5456 additions and 4523 deletions
+2 -2
View File
@@ -61,7 +61,7 @@ IDE_BIN_HOME=`dirname "$SCRIPT_LOCATION"`
# ---------------------------------------------------------------------
if [ -n "$@@product_uc@@_JDK" -a -x "$@@product_uc@@_JDK/bin/java" ]; then
JDK="$@@product_uc@@_JDK"
elif [ -x "$IDE_HOME/jre/bin/java" ] && "$IDE_HOME/jre/bin/java" -version > /dev/null 2>&1 ; then
elif [ -x "$IDE_HOME/jre/jre/bin/java" ] && "$IDE_HOME/jre/jre/bin/java" -version > /dev/null 2>&1 ; then
JDK="$IDE_HOME/jre"
elif [ -n "$JDK_HOME" -a -x "$JDK_HOME/bin/java" ]; then
JDK="$JDK_HOME"
@@ -173,7 +173,7 @@ fi
# ---------------------------------------------------------------------
# Run the IDE.
# ---------------------------------------------------------------------
LD_LIBRARY_PATH="$IDE_BIN_HOME:$LD_LIBRARY_PATH" "$JDK/bin/java" \
LD_LIBRARY_PATH="$IDE_BIN_HOME:$LD_LIBRARY_PATH" "$JDK/jre/bin/java" \
$AGENT \
"-Xbootclasspath/a:$IDE_HOME/lib/boot.jar" \
-classpath "$CLASSPATH" \
+1 -1
View File
@@ -172,7 +172,7 @@ def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps =
buildTarGz("idea-${args.buildNumber}", "$paths.artifacts/idea${args.buildNumber}.tar", [paths.distAll, paths.distUnix])
if (p("jdk.bundled.linux") != "false") {
buildTarGz("idea-${args.buildNumber}", "$paths.artifacts/idea${args.buildNumber}-jdk-bundled.tar", [paths.distAll, paths.distUnix, "${paths.sandbox}/bundled.linux.jdk"], ["jre/bin/*"])
buildTarGz("idea-${args.buildNumber}", "$paths.artifacts/idea${args.buildNumber}-jdk-bundled.tar", [paths.distAll, paths.distUnix, "${paths.sandbox}/bundled.linux.jdk"], ["jre/jre/bin/*"])
}
return info
}
@@ -45,7 +45,6 @@ public class ResumeThreadAction extends DebuggerAction{
final ThreadReferenceProxyImpl thread = threadDescriptor.getThreadReference();
debugProcess.getManagerThread().schedule(new SuspendContextCommandImpl(debuggerContext.getSuspendContext()) {
public void contextAction() throws Exception {
debugProcess.getSession().getXDebugSession().sessionResumed();
debugProcess.createResumeThreadCommand(getSuspendContext(), thread).run();
debuggerTreeNode.calcValue();
}
@@ -456,6 +456,8 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
catch (IllegalThreadStateException e) {
LOG.info(e); // undocumented by JDI: may be thrown when querying thread status
}
catch (ObjectCollectedException ignored) {
}
}
requestManager.deleteEventRequests(toDelete);
}
@@ -1694,6 +1696,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
final Set<SuspendContextImpl> suspendingContexts = SuspendManagerUtil.getSuspendingContexts(getSuspendManager(), myThread);
for (SuspendContextImpl suspendContext : suspendingContexts) {
if (suspendContext.getThread() == myThread) {
getSession().getXDebugSession().sessionResumed();
getManagerThread().invoke(createResumeCommand(suspendContext));
}
else {
@@ -28,16 +28,14 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.NullableComputable;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.DocumentUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.EmptyIterable;
@@ -285,13 +283,12 @@ public class PositionManagerImpl implements PositionManager, MultiRequestPositio
if (document == null || lineNumber >= document.getLineCount()) {
return EmptyIterable.getInstance();
}
final int startOffset = document.getLineStartOffset(lineNumber);
final int endOffset = document.getLineEndOffset(lineNumber);
final TextRange lineRange = DocumentUtil.getLineTextRange(document, lineNumber);
return new Iterable<PsiElement>() {
@Override
public Iterator<PsiElement> iterator() {
return new Iterator<PsiElement>() {
PsiElement myElement = file.findElementAt(startOffset);
PsiElement myElement = DebuggerUtilsEx.findElementAt(file, lineRange.getStartOffset());
@Override
public boolean hasNext() {
@@ -303,7 +300,7 @@ public class PositionManagerImpl implements PositionManager, MultiRequestPositio
PsiElement res = myElement;
do {
myElement = PsiTreeUtil.nextLeaf(myElement);
if (myElement == null || myElement.getTextOffset() > endOffset) {
if (myElement == null || myElement.getTextOffset() > lineRange.getEndOffset()) {
myElement = null;
break;
}
@@ -589,7 +589,9 @@ public class DebuggerSession implements AbstractDebuggerSession {
@Override
public void resumed(final SuspendContextImpl suspendContext) {
final SuspendContextImpl currentContext = isSteppingThrough(suspendContext.getThread()) ? null : getProcess().getSuspendManager().getPausedContext();
final SuspendContextImpl currentContext = suspendContext != null && isSteppingThrough(suspendContext.getThread())
? null
: getProcess().getSuspendManager().getPausedContext();
DebuggerInvocationUtil.invokeLater(getProject(), new Runnable() {
@Override
public void run() {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -26,6 +26,7 @@ import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.impl.FindSuperElementsHelper;
import com.intellij.psi.impl.source.PsiClassImpl;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiSearchHelper;
@@ -135,14 +136,15 @@ public class UnusedSymbolUtil {
}
else {
//class maybe used in some weird way, e.g. from XML, therefore the only constructor is used too
if (containingClass != null && method.isConstructor()
boolean isConstructor = method.isConstructor();
if (containingClass != null && isConstructor
&& containingClass.getConstructors().length == 1
&& isClassUsed(project, containingFile, containingClass, progress, helper)) {
return true;
}
if (isImplicitUsage(project, method, progress)) return true;
if (method.findSuperMethods().length != 0) {
if (!isConstructor && FindSuperElementsHelper.findSuperElements(method).length != 0) {
return true;
}
if (!weAreSureThereAreNoUsages(project, containingFile, method, progress, helper)) {
@@ -193,7 +195,7 @@ public class UnusedSymbolUtil {
@NotNull PsiFile containingFile,
@NotNull PsiMember member,
@NotNull ProgressIndicator progress,
final PsiFile ignoreFile,
@Nullable PsiFile ignoreFile,
@NotNull Processor<UsageInfo> usageInfoProcessor) {
String name = member.getName();
if (name == null) {
@@ -247,10 +249,8 @@ public class UnusedSymbolUtil {
}
else if (member instanceof PsiMethod) {
PsiMethod method = (PsiMethod)member;
JavaMethodFindUsagesOptions o = new JavaMethodFindUsagesOptions(project);
//o.isIncludeOverloadUsages = true;
options = o;
options.isSearchForTextOccurrences = method.isConstructor();;
options = new JavaMethodFindUsagesOptions(project);
options.isSearchForTextOccurrences = method.isConstructor();
}
else if (member instanceof PsiVariable) {
options = new JavaVariableFindUsagesOptions(project);
@@ -271,7 +271,7 @@ public class UnusedSymbolUtil {
@NotNull ProgressIndicator progress,
@NotNull GlobalUsageHelper helper) {
final PsiClass containingClass = member.getContainingClass();
if (containingClass == null || !(containingClass instanceof PsiClassImpl)) return true;
if (!(containingClass instanceof PsiClassImpl)) return true;
final PsiMethod valuesMethod = ((PsiClassImpl)containingClass).getValuesMethod();
return valuesMethod == null || isMethodReferenced(project, containingFile, valuesMethod, progress, helper);
}
@@ -36,6 +36,7 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -663,8 +664,7 @@ public class AnnotationsHighlightUtil {
if (methods.length == 1) {
PsiType expected = new PsiImmediateClassType((PsiClass)target, PsiSubstitutor.EMPTY).createArrayType();
if (!expected.equals(methods[0].getReturnType())) {
return JavaErrorMessages.message("annotation.container.bad.type", container.getQualifiedName(), JavaHighlightUtil
.formatType(expected));
return JavaErrorMessages.message("annotation.container.bad.type", container.getQualifiedName(), JavaHighlightUtil.formatType(expected));
}
}
@@ -698,6 +698,64 @@ public class AnnotationsHighlightUtil {
return container;
}
@Nullable
static HighlightInfo checkReceiverPlacement(PsiReceiverParameter parameter) {
PsiElement owner = parameter.getParent().getParent();
if (owner == null) return null;
if (!(owner instanceof PsiMethod)) {
String text = JavaErrorMessages.message("receiver.wrong.context");
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(parameter.getIdentifier()).descriptionAndTooltip(text).create();
}
PsiMethod method = (PsiMethod)owner;
if (isStatic(method) || (method).isConstructor() && isStatic(method.getContainingClass())) {
String text = JavaErrorMessages.message("receiver.static.context");
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(parameter.getIdentifier()).descriptionAndTooltip(text).create();
}
PsiElement leftNeighbour = PsiTreeUtil.skipSiblingsBackward(parameter, PsiWhiteSpace.class);
if (leftNeighbour != null && !PsiUtil.isJavaToken(leftNeighbour, JavaTokenType.LPARENTH)) {
String text = JavaErrorMessages.message("receiver.wrong.position");
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(parameter.getIdentifier()).descriptionAndTooltip(text).create();
}
return null;
}
@Nullable
static HighlightInfo checkReceiverType(PsiReceiverParameter parameter) {
PsiElement owner = parameter.getParent().getParent();
if (!(owner instanceof PsiMethod)) return null;
PsiMethod method = (PsiMethod)owner;
PsiClass enclosingClass = method.getContainingClass();
if (method.isConstructor() && enclosingClass != null) {
enclosingClass = enclosingClass.getContainingClass();
}
if (enclosingClass != null && !enclosingClass.equals(PsiUtil.resolveClassInType(parameter.getType()))) {
PsiElement range = ObjectUtils.notNull(parameter.getTypeElement(), parameter);
String text = JavaErrorMessages.message("receiver.type.mismatch");
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range).descriptionAndTooltip(text).create();
}
PsiThisExpression identifier = parameter.getIdentifier();
if (enclosingClass != null && !enclosingClass.equals(PsiUtil.resolveClassInType(identifier.getType()))) {
String text = JavaErrorMessages.message("receiver.name.mismatch");
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(identifier).descriptionAndTooltip(text).create();
}
return null;
}
private static boolean isStatic(PsiModifierListOwner owner) {
if (owner == null) return false;
if (owner instanceof PsiClass && ((PsiClass)owner).getContainingClass() == null) return true;
PsiModifierList modifierList = owner.getModifierList();
return modifierList != null && modifierList.hasModifierProperty(PsiModifier.STATIC);
}
@Nullable
public static RetentionPolicy getRetentionPolicy(@NotNull PsiClass annotation) {
PsiModifierList modifierList = annotation.getModifierList();
@@ -965,6 +965,9 @@ public class HighlightUtil extends HighlightUtilBase {
else if (modifierOwner instanceof PsiLocalVariable || modifierOwner instanceof PsiParameter) {
isAllowed = PsiModifier.FINAL.equals(modifier);
}
else if (modifierOwner instanceof PsiReceiverParameter) {
isAllowed = false;
}
isAllowed &= incompatibles != null;
if (!isAllowed) {
@@ -2899,7 +2902,8 @@ public class HighlightUtil extends HighlightUtilBase {
EXTENSION_METHODS(LanguageLevel.JDK_1_8, "feature.extension.methods"),
METHOD_REFERENCES(LanguageLevel.JDK_1_8, "feature.method.references"),
LAMBDA_EXPRESSIONS(LanguageLevel.JDK_1_8, "feature.lambda.expressions"),
TYPE_ANNOTATIONS(LanguageLevel.JDK_1_8, "feature.type.annotations");
TYPE_ANNOTATIONS(LanguageLevel.JDK_1_8, "feature.type.annotations"),
RECEIVERS(LanguageLevel.JDK_1_8, "feature.type.receivers");
private final LanguageLevel level;
private final String key;
@@ -1460,12 +1460,10 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
@Override
public void visitThisExpression(PsiThisExpression expr) {
myHolder.add(HighlightUtil.checkThisOrSuperExpressionInIllegalContext(expr, expr.getQualifier(), myLanguageLevel));
if (!myHolder.hasErrorResults()) {
myHolder.add(HighlightUtil.checkMemberReferencedBeforeConstructorCalled(expr, null, myFile));
}
if (!myHolder.hasErrorResults()) {
visitExpression(expr);
if (!(expr.getParent() instanceof PsiReceiverParameter)) {
myHolder.add(HighlightUtil.checkThisOrSuperExpressionInIllegalContext(expr, expr.getQualifier(), myLanguageLevel));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkMemberReferencedBeforeConstructorCalled(expr, null, myFile));
if (!myHolder.hasErrorResults()) visitExpression(expr);
}
}
@@ -1580,6 +1578,14 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
@Override
public void visitReceiverParameter(PsiReceiverParameter parameter) {
super.visitReceiverParameter(parameter);
if (!myHolder.hasErrorResults()) myHolder.add(checkFeature(parameter, Feature.RECEIVERS));
if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkReceiverPlacement(parameter));
if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkReceiverType(parameter));
}
@Nullable
private HighlightInfo checkFeature(@NotNull PsiElement element, @NotNull Feature feature) {
return HighlightUtil.checkFeature(element, feature, myLanguageLevel, myFile);
@@ -0,0 +1,125 @@
/*
* Copyright 2000-2015 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.psi.impl;
import com.intellij.psi.*;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.psi.util.MethodSignature;
import com.intellij.psi.util.MethodSignatureUtil;
import com.intellij.psi.util.PsiSuperMethodUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.Processor;
import com.intellij.util.containers.FactoryMap;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
public class FindSuperElementsHelper {
@NotNull
public static PsiElement[] findSuperElements(@NotNull PsiElement element) {
if (element instanceof PsiClass) {
PsiClass aClass = (PsiClass) element;
List<PsiClass> allSupers = new ArrayList<PsiClass>(Arrays.asList(aClass.getSupers()));
for (Iterator<PsiClass> iterator = allSupers.iterator(); iterator.hasNext();) {
PsiClass superClass = iterator.next();
if (CommonClassNames.JAVA_LANG_OBJECT.equals(superClass.getQualifiedName())) iterator.remove();
}
return allSupers.toArray(new PsiClass[allSupers.size()]);
}
if (element instanceof PsiMethod) {
PsiMethod method = (PsiMethod) element;
if (method.isConstructor()) {
PsiMethod constructorInSuper = PsiSuperMethodUtil.findConstructorInSuper(method);
if (constructorInSuper != null) {
return new PsiMethod[]{constructorInSuper};
}
}
else {
PsiMethod[] superMethods = method.findSuperMethods(false);
if (superMethods.length == 0) {
PsiMethod superMethod = getSiblingInheritedViaSubClass(method);
if (superMethod != null) {
superMethods = new PsiMethod[]{superMethod};
}
}
return superMethods;
}
}
return PsiElement.EMPTY_ARRAY;
}
public static PsiMethod getSiblingInheritedViaSubClass(@NotNull PsiMethod method) {
return getSiblingInheritedViaSubClass(method, createSubClassCache());
}
public static PsiMethod getSiblingInheritedViaSubClass(@NotNull final PsiMethod method,
@NotNull Map<PsiClass, PsiClass> subClassCache) {
if (!method.hasModifierProperty(PsiModifier.PUBLIC)) return null;
if (method.hasModifierProperty(PsiModifier.STATIC)) return null;
final PsiClass containingClass = method.getContainingClass();
boolean hasSubClass = containingClass != null && !containingClass.isInterface() && subClassCache.get(containingClass) != null;
if (!hasSubClass) {
return null;
}
final Collection<PsiClass> checkedInterfaces = new THashSet<PsiClass>();
final PsiMethod[] result = new PsiMethod[1];
ClassInheritorsSearch.search(containingClass, true).forEach(new Processor<PsiClass>() {
@Override
public boolean process(PsiClass inheritor) {
for (PsiClassType interfaceType : inheritor.getImplementsListTypes()) {
PsiClassType.ClassResolveResult resolved = interfaceType.resolveGenerics();
PsiClass anInterface = resolved.getElement();
if (anInterface == null || !checkedInterfaces.add(anInterface)) continue;
for (PsiMethod superMethod : anInterface.findMethodsByName(method.getName(), true)) {
PsiClass superInterface = superMethod.getContainingClass();
if (superInterface == null) {
continue;
}
// calculate substitutor of containingClass --> inheritor
PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(containingClass, inheritor, PsiSubstitutor.EMPTY);
// calculate substitutor of inheritor --> superInterface
substitutor = TypeConversionUtil.getSuperClassSubstitutor(superInterface, inheritor, substitutor);
final MethodSignature superSignature = superMethod.getSignature(substitutor);
final MethodSignature derivedSignature = method.getSignature(PsiSubstitutor.EMPTY);
boolean isOverridden = MethodSignatureUtil.isSubsignature(superSignature, derivedSignature);
if (isOverridden) {
result[0] = superMethod;
return false;
}
}
}
return true;
}
});
return result[0];
}
@NotNull
public static Map<PsiClass, PsiClass> createSubClassCache() {
return new FactoryMap<PsiClass, PsiClass>() {
@Nullable
@Override
protected PsiClass create(PsiClass aClass) {
return ClassInheritorsSearch.search(aClass, false).findFirst();
}
};
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -31,8 +31,8 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.FindSuperElementsHelper;
import com.intellij.psi.search.searches.AllOverridingMethodsSearch;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.psi.search.searches.FunctionalExpressionSearch;
import com.intellij.psi.search.searches.SuperMethodsSearch;
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
@@ -48,12 +48,12 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class JavaLineMarkerProvider implements LineMarkerProvider {
protected final DaemonCodeAnalyzerSettings myDaemonSettings;
protected final EditorColorsManager myColorsManager;
private final DaemonCodeAnalyzerSettings myDaemonSettings;
private final EditorColorsManager myColorsManager;
public JavaLineMarkerProvider(DaemonCodeAnalyzerSettings daemonSettings, EditorColorsManager colorsManager) {
myDaemonSettings = daemonSettings;
@@ -72,19 +72,14 @@ public class JavaLineMarkerProvider implements LineMarkerProvider {
method.hasModifierProperty(PsiModifier.ABSTRACT) == superSignature.getMethod().hasModifierProperty(PsiModifier.ABSTRACT);
final Icon icon = overrides ? AllIcons.Gutter.OverridingMethod : AllIcons.Gutter.ImplementingMethod;
final MarkerType type = MarkerType.OVERRIDING_METHOD;
ArrowUpLineMarkerInfo info = new ArrowUpLineMarkerInfo(element, icon, type);
return NavigateAction.setNavigateAction(info, "Go to super method", "GotoSuperMethod");
return createSuperMethodLineMarkerInfo(element, icon, Pass.UPDATE_ALL);
}
}
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(element);
final PsiElement firstChild = element.getFirstChild();
if (interfaceMethod != null && firstChild != null) {
final Icon icon = AllIcons.Gutter.ImplementingMethod;
final MarkerType type = MarkerType.OVERRIDING_METHOD;
ArrowUpLineMarkerInfo info = new ArrowUpLineMarkerInfo(firstChild, icon, type);
return NavigateAction.setNavigateAction(info, "Go to super method", "GotoSuperMethod");
return createSuperMethodLineMarkerInfo(firstChild, AllIcons.Gutter.ImplementingMethod, Pass.UPDATE_ALL);
}
if (myDaemonSettings.SHOW_METHOD_SEPARATORS && firstChild == null) {
@@ -128,6 +123,12 @@ public class JavaLineMarkerProvider implements LineMarkerProvider {
return null;
}
@NotNull
private static LineMarkerInfo createSuperMethodLineMarkerInfo(@NotNull PsiElement name, @NotNull Icon icon, int passId) {
ArrowUpLineMarkerInfo info = new ArrowUpLineMarkerInfo(name, icon, MarkerType.OVERRIDING_METHOD, passId);
return NavigateAction.setNavigateAction(info, "Go to super method", IdeActions.ACTION_GOTO_SUPER);
}
private static int getCategory(@NotNull PsiElement element, @NotNull CharSequence documentChars) {
if (element instanceof PsiField || element instanceof PsiTypeParameter) return 1;
if (element instanceof PsiClass || element instanceof PsiClassInitializer) return 2;
@@ -147,37 +148,87 @@ public class JavaLineMarkerProvider implements LineMarkerProvider {
@Override
public void collectSlowLineMarkers(@NotNull final List<PsiElement> elements, @NotNull final Collection<LineMarkerInfo> result) {
ApplicationManager.getApplication().assertReadAccessAllowed();
Map<PsiClass, PsiClass> subClassCache = FindSuperElementsHelper.createSubClassCache();
Set<PsiMethod> methods = new HashSet<PsiMethod>();
Collection<PsiMethod> methods = new THashSet<PsiMethod>();
//noinspection ForLoopReplaceableByForEach
for (int i = 0; i < elements.size(); i++) {
PsiElement element = elements.get(i);
ProgressManager.checkCanceled();
if (element instanceof PsiMethod) {
final PsiMethod method = (PsiMethod)element;
if (!(element instanceof PsiIdentifier)) continue;
PsiElement parent = element.getParent();
if (parent instanceof PsiMethod) {
final PsiMethod method = (PsiMethod)parent;
if (PsiUtil.canBeOverriden(method)) {
methods.add(method);
}
}
else if (element instanceof PsiClass && !(element instanceof PsiTypeParameter)) {
collectInheritingClasses((PsiClass)element, result);
else if (parent instanceof PsiClass && !(parent instanceof PsiTypeParameter)) {
collectInheritingClasses((PsiClass)parent, result, subClassCache);
}
}
if (!methods.isEmpty()) {
collectOverridingAccessors(methods, result);
collectOverridingMethods(methods, result);
collectSiblingInheritedMethods(methods, result, subClassCache);
}
}
public static void collectInheritingClasses(PsiClass aClass, Collection<LineMarkerInfo> result) {
private static void collectSiblingInheritedMethods(@NotNull final Collection<PsiMethod> methods,
@NotNull Collection<LineMarkerInfo> result,
@NotNull Map<PsiClass, PsiClass> subClassCache) {
for (PsiMethod method : methods) {
ProgressManager.checkCanceled();
PsiClass aClass = method.getContainingClass();
if (aClass == null || aClass.hasModifierProperty(PsiModifier.FINAL) || aClass.isInterface()) continue;
boolean canHaveSiblingSuper = !method.hasModifierProperty(PsiModifier.ABSTRACT) && !method.hasModifierProperty(PsiModifier.STATIC) && method.hasModifierProperty(PsiModifier.PUBLIC)&& !method.hasModifierProperty(PsiModifier.FINAL)&& !method.hasModifierProperty(PsiModifier.NATIVE);
if (!canHaveSiblingSuper) continue;
PsiMethod siblingInheritedViaSubClass = FindSuperElementsHelper.getSiblingInheritedViaSubClass(method, subClassCache);
if (siblingInheritedViaSubClass == null) {
continue;
}
PsiElement range = getMethodRange(method);
LineMarkerInfo info = createSuperMethodLineMarkerInfo(range, AllIcons.Gutter.ImplementingMethod, Pass.UPDATE_OVERRIDEN_MARKERS);
result.add(info);
PsiClass sClass = siblingInheritedViaSubClass.getContainingClass();
String sName = sClass == null ? null : sClass.getQualifiedName();
}
}
@NotNull
private static PsiElement getMethodRange(@NotNull PsiMethod method) {
PsiElement range;
if (method.isPhysical()) {
range = method.getNameIdentifier();
}
else {
final PsiElement navigationElement = method.getNavigationElement();
range = navigationElement instanceof PsiNameIdentifierOwner
? ((PsiNameIdentifierOwner)navigationElement).getNameIdentifier()
: navigationElement;
}
if (range == null) {
range = method;
}
return range;
}
public static void collectInheritingClasses(@NotNull PsiClass aClass,
@NotNull Collection<LineMarkerInfo> result,
@NotNull Map<PsiClass, PsiClass> subClassCache) {
if (aClass.hasModifierProperty(PsiModifier.FINAL)) {
return;
}
if (CommonClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) return; // It's useless to have overridden markers for object.
if (ClassInheritorsSearch.search(aClass, false).findFirst() != null || FunctionalExpressionSearch.search(aClass).findFirst() != null) {
PsiClass subClass = subClassCache.get(aClass);
if (subClass != null || FunctionalExpressionSearch.search(aClass).findFirst() != null) {
final Icon icon = aClass.isInterface() ? AllIcons.Gutter.ImplementedMethod : AllIcons.Gutter.OverridenMethod;
PsiElement range = aClass.getNameIdentifier();
if (range == null) range = aClass;
if (range == null) {
range = aClass;
}
MarkerType type = MarkerType.SUBCLASSED_CLASS;
LineMarkerInfo info = new LineMarkerInfo<PsiElement>(range, range.getTextRange(),
icon, Pass.UPDATE_OVERRIDEN_MARKERS, type.getTooltip(),
@@ -188,7 +239,7 @@ public class JavaLineMarkerProvider implements LineMarkerProvider {
}
}
private static void collectOverridingAccessors(final Set<PsiMethod> methods, Collection<LineMarkerInfo> result) {
private static void collectOverridingMethods(@NotNull final Collection<PsiMethod> methods, @NotNull Collection<LineMarkerInfo> result) {
final Set<PsiMethod> overridden = new HashSet<PsiMethod>();
Set<PsiClass> classes = new THashSet<PsiClass>();
for (PsiMethod method : methods) {
@@ -229,22 +280,9 @@ public class JavaLineMarkerProvider implements LineMarkerProvider {
ProgressManager.checkCanceled();
boolean overrides = !method.hasModifierProperty(PsiModifier.ABSTRACT);
final Icon icon = overrides ? AllIcons.Gutter.OverridenMethod : AllIcons.Gutter.ImplementedMethod;
PsiElement range;
if (method.isPhysical()) {
range = method.getNameIdentifier();
}
else {
final PsiElement navigationElement = method.getNavigationElement();
if (navigationElement instanceof PsiNameIdentifierOwner) {
range = ((PsiNameIdentifierOwner)navigationElement).getNameIdentifier();
}
else {
range = navigationElement;
}
}
if (range == null) range = method;
PsiElement range = getMethodRange(method);
final MarkerType type = MarkerType.OVERRIDDEN_METHOD;
final Icon icon = overrides ? AllIcons.Gutter.OverridenMethod : AllIcons.Gutter.ImplementedMethod;
LineMarkerInfo<PsiElement> info = new LineMarkerInfo<PsiElement>(range, range.getTextRange(),
icon, Pass.UPDATE_OVERRIDEN_MARKERS, type.getTooltip(),
type.getNavigationHandler(),
@@ -255,8 +293,8 @@ public class JavaLineMarkerProvider implements LineMarkerProvider {
}
private static class ArrowUpLineMarkerInfo extends MergeableLineMarkerInfo<PsiElement> {
private ArrowUpLineMarkerInfo(@NotNull PsiElement element, Icon icon, @NotNull MarkerType markerType) {
super(element, element.getTextRange(), icon, Pass.UPDATE_ALL, markerType.getTooltip(),
private ArrowUpLineMarkerInfo(@NotNull PsiElement element, @NotNull Icon icon, @NotNull MarkerType markerType, int passId) {
super(element, element.getTextRange(), icon, passId, markerType.getTooltip(),
markerType.getNavigationHandler(), GutterIconRenderer.Alignment.LEFT);
}
@@ -274,6 +312,7 @@ public class JavaLineMarkerProvider implements LineMarkerProvider {
return myIcon;
}
@NotNull
@Override
public Function<? super PsiElement, String> getCommonTooltip(@NotNull List<MergeableLineMarkerInfo> infos) {
return new Function<PsiElement, String>() {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -34,6 +34,7 @@ import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.*;
import com.intellij.psi.impl.FindSuperElementsHelper;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.search.PsiElementProcessorAdapter;
import com.intellij.psi.search.SearchScope;
@@ -45,6 +46,7 @@ import com.intellij.util.ArrayUtil;
import com.intellij.util.CommonProcessors;
import com.intellij.util.Function;
import com.intellij.util.NullableFunction;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -105,9 +107,9 @@ public class MarkerType {
});
@Nullable
public static String calculateOverridingMethodTooltip(PsiMethod method, boolean acceptSelf) {
private static String calculateOverridingMethodTooltip(@NotNull PsiMethod method, boolean acceptSelf) {
PsiMethod[] superMethods = composeSuperMethods(method, acceptSelf);
if (superMethods == null) return null;
if (superMethods.length == 0) return null;
PsiMethod superMethod = superMethods[0];
boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT);
@@ -121,10 +123,11 @@ public class MarkerType {
else{
key = sameSignature ? "method.overrides" : "method.overrides.in";
}
return composeText(superMethods, "", DaemonBundle.message(key), "GotoSuperMethod");
return composeText(superMethods, "", DaemonBundle.message(key), IdeActions.ACTION_GOTO_SUPER);
}
private static String composeText(PsiElement[] methods, String start, String pattern, String actionId) {
@NotNull
private static String composeText(@NotNull PsiElement[] methods, @NotNull String start, @NotNull String pattern, @NotNull String actionId) {
Shortcut[] shortcuts = ActionManager.getInstance().getAction(actionId).getShortcutSet().getShortcuts();
Shortcut shortcut = ArrayUtil.getFirstElement(shortcuts);
String postfix = "<br><div style='margin-top: 5px'><font size='2'>Click";
@@ -133,9 +136,9 @@ public class MarkerType {
return GutterIconTooltipHelper.composeText(Arrays.asList(methods), start, pattern, postfix);
}
public static void navigateToOverridingMethod(MouseEvent e, PsiMethod method, boolean acceptSelf) {
private static void navigateToOverridingMethod(MouseEvent e, @NotNull PsiMethod method, boolean acceptSelf) {
PsiMethod[] superMethods = composeSuperMethods(method, acceptSelf);
if (superMethods == null) return;
if (superMethods.length == 0) return;
boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature(superMethods);
PsiElementListNavigator.openTargets(e, superMethods,
DaemonBundle.message("navigation.title.super.method", method.getName()),
@@ -143,17 +146,23 @@ public class MarkerType {
new MethodCellRenderer(showMethodNames));
}
@Nullable
private static PsiMethod[] composeSuperMethods(PsiMethod method, boolean acceptSelf) {
PsiMethod[] superMethods = method.findSuperMethods(false);
@NotNull
private static PsiMethod[] composeSuperMethods(@NotNull PsiMethod method, boolean acceptSelf) {
PsiElement[] superElements = FindSuperElementsHelper.findSuperElements(method);
PsiMethod[] superMethods = ContainerUtil.map(superElements, new Function<PsiElement, PsiMethod>() {
@Override
public PsiMethod fun(PsiElement element) {
return (PsiMethod)element;
}
}, PsiMethod.EMPTY_ARRAY);
if (acceptSelf) {
superMethods = ArrayUtil.prepend(method, superMethods);
}
if (superMethods.length == 0) return null;
return superMethods;
}
private static PsiElement getParentMethod(PsiElement element) {
private static PsiElement getParentMethod(@NotNull PsiElement element) {
final PsiElement parent = element.getParent();
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(parent);
return interfaceMethod != null ? interfaceMethod : parent;
@@ -179,7 +188,7 @@ public class MarkerType {
}
});
public static String getOverriddenMethodTooltip(final PsiMethod method) {
private static String getOverriddenMethodTooltip(@NotNull PsiMethod method) {
PsiElementProcessor.CollectElementsWithLimit<PsiMethod> processor = new PsiElementProcessor.CollectElementsWithLimit<PsiMethod>(5);
OverridingMethodsSearch.search(method, true).forEach(new PsiElementProcessorAdapter<PsiMethod>(processor));
@@ -206,7 +215,7 @@ public class MarkerType {
return composeText(overridings, start, pattern, IdeActions.ACTION_GOTO_IMPLEMENTATION);
}
public static void navigateToOverriddenMethod(MouseEvent e, final PsiMethod method) {
private static void navigateToOverriddenMethod(MouseEvent e, @NotNull final PsiMethod method) {
if (DumbService.isDumb(method.getProject())) {
DumbService.getInstance(method.getProject()).showDumbModeNotification(
"Navigation to overriding classes is not possible during index update");
@@ -267,7 +276,7 @@ public class MarkerType {
}
});
public static String getSubclassedClassTooltip(PsiClass aClass) {
private static String getSubclassedClassTooltip(@NotNull PsiClass aClass) {
PsiElementProcessor.CollectElementsWithLimit<PsiClass> processor = new PsiElementProcessor.CollectElementsWithLimit<PsiClass>(5, new THashSet<PsiClass>());
ClassInheritorsSearch.search(aClass, true).forEach(new PsiElementProcessorAdapter<PsiClass>(processor));
@@ -298,7 +307,7 @@ public class MarkerType {
return composeText(subclasses, start, pattern, IdeActions.ACTION_GOTO_IMPLEMENTATION);
}
public static void navigateToSubclassedClass(MouseEvent e, final PsiClass aClass) {
private static void navigateToSubclassedClass(MouseEvent e, @NotNull final PsiClass aClass) {
if (DumbService.isDumb(aClass.getProject())) {
DumbService.getInstance(aClass.getProject()).showDumbModeNotification("Navigation to overriding methods is not possible during index update");
return;
@@ -331,7 +340,7 @@ public class MarkerType {
private final PsiClass myClass;
private final PsiClassOrFunctionalExpressionListCellRenderer myRenderer;
public SubclassUpdater(PsiClass aClass, PsiClassOrFunctionalExpressionListCellRenderer renderer) {
private SubclassUpdater(@NotNull PsiClass aClass, @NotNull PsiClassOrFunctionalExpressionListCellRenderer renderer) {
super(aClass.getProject(), SEARCHING_FOR_OVERRIDDEN_METHODS);
myClass = aClass;
myRenderer = renderer;
@@ -374,14 +383,13 @@ public class MarkerType {
}
});
}
}
private static class OverridingMethodsUpdater extends ListBackgroundUpdaterTask {
private final PsiMethod myMethod;
private final PsiElementListCellRenderer myRenderer;
public OverridingMethodsUpdater(PsiMethod method, PsiElementListCellRenderer renderer) {
private OverridingMethodsUpdater(@NotNull PsiMethod method, @NotNull PsiElementListCellRenderer renderer) {
super(method.getProject(), SEARCHING_FOR_OVERRIDING_METHODS);
myMethod = method;
myRenderer = renderer;
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.application.ApplicationManager;
@@ -112,6 +113,9 @@ public class AddMethodQualifierFix implements IntentionAction {
@Override
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
if (!FileModificationService.getInstance().preparePsiElementsForWrite(file)) {
return;
}
if (myCandidates.size() == 1 || UNIT_TEST_MODE) {
qualify(myCandidates.get(0), editor);
}
@@ -40,6 +40,14 @@ public class IfStatementSelectioner extends BasicSelectioner {
final PsiKeyword elseKeyword = statement.getElseElement();
if (elseKeyword != null) {
final PsiStatement then = statement.getThenBranch();
if (then != null) {
final TextRange thenRange = new TextRange(statement.getTextRange().getStartOffset(), then.getTextRange().getEndOffset());
if (thenRange.contains(cursorOffset)) {
result.addAll(expandToWholeLine(editorText, thenRange, false));
}
}
result.addAll(expandToWholeLine(editorText,
new TextRange(elseKeyword.getTextRange().getStartOffset(),
statement.getTextRange().getEndOffset()),
@@ -50,10 +58,13 @@ public class IfStatementSelectioner extends BasicSelectioner {
PsiIfStatement elseIf = (PsiIfStatement)branch;
final PsiKeyword element = elseIf.getElseElement();
if (element != null) {
result.addAll(expandToWholeLine(editorText,
new TextRange(elseKeyword.getTextRange().getStartOffset(),
elseIf.getThenBranch().getTextRange().getEndOffset()),
false));
final PsiStatement elseThen = elseIf.getThenBranch();
if (elseThen != null) {
result.addAll(expandToWholeLine(editorText,
new TextRange(elseKeyword.getTextRange().getStartOffset(),
elseThen.getTextRange().getEndOffset()),
false));
}
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -29,15 +29,11 @@ import com.intellij.psi.impl.FindSuperElementsHelper;
import com.intellij.psi.presentation.java.SymbolPresentationUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NotNull;
public class ShowSiblingsAction extends ShowImplementationsAction {
public ShowSiblingsAction() {
super();
}
@Override
public void performForContext(DataContext dataContext, final boolean invokedByShortcut) {
public void performForContext(@NotNull DataContext dataContext, final boolean invokedByShortcut) {
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
final PsiFile file = CommonDataKeys.PSI_FILE.getData(dataContext);
@@ -61,7 +57,7 @@ public class ShowSiblingsAction extends ShowImplementationsAction {
}
final NavigatablePsiElement[] superElements = (NavigatablePsiElement[])findSuperElements(element);
if (superElements == null || superElements.length == 0) return;
if (superElements.length == 0) return;
final boolean isMethod = superElements[0] instanceof PsiMethod;
final JBPopup popup = PsiElementListNavigator.navigateOrCreatePopup(superElements, "Choose super " + (isMethod ? "method" : "class or interface"), "Super " + (isMethod ? "methods" : "classes/interfaces"),
@@ -81,11 +77,11 @@ public class ShowSiblingsAction extends ShowImplementationsAction {
}
private void showSiblings(boolean invokedByShortcut,
Project project,
@NotNull Project project,
Editor editor,
PsiFile file,
boolean invokedFromEditor,
PsiElement element) {
@NotNull PsiElement element) {
final PsiElement[] impls = getSelfAndImplementations(editor, element, createImplementationsSearcher(), false);
final String text = SymbolPresentationUtil.getSymbolPresentableText(element);
showImplementations(impls, project, text, editor, file, element, invokedFromEditor, invokedByShortcut);
@@ -96,11 +92,11 @@ public class ShowSiblingsAction extends ShowImplementationsAction {
return false;
}
@Nullable
@NotNull
private static PsiElement[] findSuperElements(final PsiElement element) {
PsiNameIdentifierOwner parent = PsiTreeUtil.getParentOfType(element, PsiMethod.class, PsiClass.class);
if (parent == null) {
return null;
return PsiElement.EMPTY_ARRAY;
}
return FindSuperElementsHelper.findSuperElements(parent);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -32,7 +32,6 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class JavaGotoSuperHandler implements CodeInsightActionHandler {
@Override
@@ -41,7 +40,7 @@ public class JavaGotoSuperHandler implements CodeInsightActionHandler {
int offset = editor.getCaretModel().getOffset();
PsiElement[] superElements = findSuperElements(file, offset);
if (superElements == null || superElements.length == 0) return;
if (superElements.length == 0) return;
if (superElements.length == 1) {
PsiElement superElement = superElements[0].getNavigationElement();
final PsiFile containingFile = superElement.getContainingFile();
@@ -50,24 +49,25 @@ public class JavaGotoSuperHandler implements CodeInsightActionHandler {
if (virtualFile == null) return;
OpenFileDescriptor descriptor = new OpenFileDescriptor(project, virtualFile, superElement.getTextOffset());
FileEditorManager.getInstance(project).openTextEditor(descriptor, true);
} else {
if (superElements[0] instanceof PsiMethod) {
boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature((PsiMethod[])superElements);
PsiElementListNavigator.openTargets(editor, (PsiMethod[])superElements,
CodeInsightBundle.message("goto.super.method.chooser.title"),
CodeInsightBundle.message("goto.super.method.findUsages.title", ((PsiMethod)superElements[0]).getName()),
new MethodCellRenderer(showMethodNames));
}
else {
NavigationUtil.getPsiElementPopup(superElements, CodeInsightBundle.message("goto.super.class.chooser.title")).showInBestPositionFor(editor);
}
}
else if (superElements[0] instanceof PsiMethod) {
boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature((PsiMethod[])superElements);
PsiElementListNavigator.openTargets(editor, (PsiMethod[])superElements,
CodeInsightBundle.message("goto.super.method.chooser.title"),
CodeInsightBundle
.message("goto.super.method.findUsages.title", ((PsiMethod)superElements[0]).getName()),
new MethodCellRenderer(showMethodNames));
}
else {
NavigationUtil.getPsiElementPopup(superElements, CodeInsightBundle.message("goto.super.class.chooser.title"))
.showInBestPositionFor(editor);
}
}
@Nullable
private PsiElement[] findSuperElements(PsiFile file, int offset) {
@NotNull
private PsiElement[] findSuperElements(@NotNull PsiFile file, int offset) {
PsiElement element = getElement(file, offset);
if (element == null) return null;
if (element == null) return PsiElement.EMPTY_ARRAY;
final PsiElement psiElement = PsiTreeUtil.getParentOfType(element, PsiFunctionalExpression.class, PsiMember.class);
if (psiElement instanceof PsiFunctionalExpression) {
@@ -79,13 +79,13 @@ public class JavaGotoSuperHandler implements CodeInsightActionHandler {
final PsiNameIdentifierOwner parent = PsiTreeUtil.getNonStrictParentOfType(element, PsiMethod.class, PsiClass.class);
if (parent == null) {
return null;
return PsiElement.EMPTY_ARRAY;
}
return FindSuperElementsHelper.findSuperElements(parent);
}
protected PsiElement getElement(PsiFile file, int offset) {
protected PsiElement getElement(@NotNull PsiFile file, int offset) {
return file.findElementAt(offset);
}
@@ -50,7 +50,7 @@ public class FormatPostfixTemplate extends StringBasedPostfixTemplate {
}
@Override
protected boolean shouldRemoveParent() {
return false;
protected PsiElement getElementToRemove(PsiElement expr) {
return expr;
}
}
@@ -36,6 +36,7 @@ import com.intellij.ui.ListCellRendererWrapper;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.LinkedMultiMap;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -151,11 +152,11 @@ public class AddMethodsDialog extends DialogWrapper {
final DefaultComboBoxModel comboBoxModel = (DefaultComboBoxModel)myMethodNameCombo.getModel();
comboBoxModel.removeAllElements();
if (aClass == null) {
myMethodNameCombo.setEnabled(false);
enable(false);
}
else {
final List<PseudoLambdaReplaceTemplate> possibleTemplates = PseudoLambdaReplaceTemplate.getAllTemplates();
final MultiMap<String, PsiMethod> nameToMethod = new MultiMap<String, PsiMethod>();
final LinkedMultiMap<String, PsiMethod> nameToMethod = new LinkedMultiMap<String, PsiMethod>();
for (PsiMethod m : ContainerUtil.filter(aClass.getMethods(), new Condition<PsiMethod>() {
@Override
public boolean value(PsiMethod method) {
@@ -181,15 +182,27 @@ public class AddMethodsDialog extends DialogWrapper {
for (Map.Entry<String, Collection<PsiMethod>> entry : nameToMethod.entrySet()) {
comboBoxModel.addElement(entry.getValue());
}
myMethodNameCombo.setEnabled(true);
final boolean isSuitableMethodsFound = comboBoxModel.getSize() != 0;
enable(isSuitableMethodsFound);
}
}
});
myExamplePanel.setEnabled(false);
setOKActionEnabled(false);
init();
}
private void enable(boolean isEnabled) {
myMethodNameCombo.setEnabled(isEnabled);
myTemplatesCombo.setEnabled(isEnabled);
setOKActionEnabled(isEnabled);
myExamplePanel.setEnabled(isEnabled);
if (!isEnabled) {
myBeforeActionPanel.reset("", StdFileTypes.JAVA);
myAfterActionPanel.reset("", StdFileTypes.JAVA);
}
}
private void showTemplateExample(final PseudoLambdaReplaceTemplate template, final PsiMethod method) {
final PsiClass aClass = method.getContainingClass();
LOG.assertTrue(aClass != null);
@@ -19,17 +19,12 @@ import com.intellij.codeInsight.daemon.impl.quickfix.AddTypeArgumentsFix;
import com.intellij.codeInspection.AnonymousCanBeLambdaInspection;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.PsiDiamondTypeUtil;
import com.intellij.psi.impl.PsiSubstitutorImpl;
import com.intellij.psi.impl.source.PsiClassReferenceType;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.*;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.hash.HashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -116,7 +111,7 @@ class PseudoLambdaReplaceTemplate {
} else if (!(returnType instanceof PsiArrayType)) {
return null;
}
return validate(parameterTypes, returnType, method);
return validate(parameterTypes, returnType, null, method);
}
@Nullable
@@ -136,7 +131,9 @@ class PseudoLambdaReplaceTemplate {
if (argumentTypes.length != expectedParameters.length) {
return null;
}
return validate(argumentTypes, methodReturnType, expression);
final JavaResolveResult result = expression.getMethodExpression().advancedResolve(false);
final PsiSubstitutor methodSubstitutor = result.getSubstitutor();
return validate(argumentTypes, methodReturnType, methodSubstitutor, expression);
}
public String getStreamApiMethodName() {
@@ -151,7 +148,10 @@ class PseudoLambdaReplaceTemplate {
return myAcceptDefaultValue;
}
private ValidationInfo validate(final PsiType[] arguments, final PsiType methodReturnType, final PsiElement context) {
private ValidationInfo validate(final PsiType[] arguments,
final PsiType methodReturnType,
final @Nullable PsiSubstitutor methodSubstitutor,
final PsiElement context) {
int lambdaPosition = -1;
int defaultValuePosition = -1;
int iterablePosition = -1;
@@ -168,7 +168,7 @@ class PseudoLambdaReplaceTemplate {
for (int i = 0; i < arguments.length; i++) {
PsiType type = arguments[i];
if (isFunction(type, methodReturnType, context)) {
if (isFunction(type, methodReturnType, methodSubstitutor, context)) {
if (lambdaPosition == -1) {
lambdaPosition = i;
continue;
@@ -207,7 +207,7 @@ class PseudoLambdaReplaceTemplate {
return new ValidationInfo(lambdaPosition, iterablePosition, defaultValuePosition);
}
private boolean isFunction(PsiType type, PsiType baseMethodReturnType, PsiElement context) {
private boolean isFunction(PsiType type, PsiType baseMethodReturnType, PsiSubstitutor methodSubstitutor, PsiElement context) {
if (type instanceof PsiMethodReferenceType) {
final PsiMethodReferenceExpression expression = ((PsiMethodReferenceType)type).getExpression();
final PsiMethod resolvedMethod = (PsiMethod)expression.resolve();
@@ -219,20 +219,21 @@ class PseudoLambdaReplaceTemplate {
return false;
}
final PsiType returnType = LambdaUtil.getFunctionalInterfaceReturnType(expression);
return isSuitableLambdaRole(returnType, baseMethodReturnType, context);
return isSuitableLambdaRole(returnType, baseMethodReturnType, methodSubstitutor, context);
} else if (type instanceof PsiLambdaExpressionType) {
final PsiLambdaExpression expression = ((PsiLambdaExpressionType)type).getExpression();
final PsiType psiType = LambdaUtil.getFunctionalInterfaceReturnType(expression.getFunctionalInterfaceType());
return isSuitableLambdaRole(psiType, baseMethodReturnType, context);
} else if (isSuitableFunctionalType(type, baseMethodReturnType, context)) {
return isSuitableLambdaRole(psiType, baseMethodReturnType, methodSubstitutor, context);
} else if (isSuitableFunctionalType(type, baseMethodReturnType, methodSubstitutor, context)) {
return true;
}
return isJavaLangClassType(type) && myLambdaRole == LambdaRole.PREDICATE;
}
private boolean isSuitableLambdaRole(final PsiType lambdaReturnType,
final PsiType baseMethodReturnType,
final PsiElement context) {
private boolean isSuitableLambdaRole(PsiType lambdaReturnType,
PsiType baseMethodReturnType,
PsiSubstitutor methodSubstitutor,
PsiElement context) {
if (lambdaReturnType == null) {
return false;
}
@@ -244,6 +245,9 @@ class PseudoLambdaReplaceTemplate {
}
else {
LOG.assertTrue(myLambdaRole == LambdaRole.FUNCTION);
if (methodSubstitutor != null) {
lambdaReturnType = methodSubstitutor.substitute(lambdaReturnType);
}
if (baseMethodReturnType instanceof PsiClassType) {
final PsiClassType.ClassResolveResult resolveResult = ((PsiClassType)baseMethodReturnType).resolveGenerics();
final Map<PsiTypeParameter, PsiType> substitutionMap = resolveResult.getSubstitutor().getSubstitutionMap();
@@ -274,49 +278,44 @@ class PseudoLambdaReplaceTemplate {
return false;
}
private boolean isSuitableFunctionalType(final PsiType type, final PsiType baseMethodReturnType, final PsiElement context) {
private boolean isSuitableFunctionalType(final PsiType type,
final PsiType baseMethodReturnType,
final @Nullable PsiSubstitutor methodSubstitutor,
final PsiElement context) {
if (type instanceof PsiClassType) {
PsiClass targetClass = ((PsiClassType)type).resolve();
if (targetClass != null) {
if (targetClass instanceof PsiAnonymousClass) {
targetClass = ((PsiAnonymousClass)targetClass).getBaseClassType().resolve();
if (targetClass == null) {
final PsiClass resolvedClass = ((PsiClassType)type).resolve();
if (resolvedClass != null) {
if (resolvedClass instanceof PsiAnonymousClass) {
final PsiClass baseClass = ((PsiAnonymousClass)resolvedClass).getBaseClassType().resolve();
if (baseClass == null) {
return false;
}
}
if (!LambdaUtil.isFunctionalClass(targetClass)) {
return false;
}
PsiMethod method = LambdaUtil.getFunctionalInterfaceMethod(targetClass);
final PsiMethod[] methods = ((PsiClassType)type).resolve().findMethodsByName(method.getName(), false);
if (methods.length != 1) {
return false;
}
method = methods[0];
if (method == null) {
return false;
}
final PsiType psiType;
if (type instanceof PsiClassReferenceType) {
final PsiJavaCodeReferenceElement reference = ((PsiClassReferenceType)type).getReference();
final PsiClass resolvedClass = ((PsiClassReferenceType)type).resolve();
final PsiTypeParameter[] typeParameters = resolvedClass.getTypeParameters();
final PsiType[] substitutedTypeParameters = reference.getTypeParameters();
LOG.assertTrue(typeParameters.length == substitutedTypeParameters.length);
final Map<PsiTypeParameter, PsiType> substitutionMap = new HashMap<PsiTypeParameter, PsiType>();
for (int i = 0; i < typeParameters.length; i++) {
PsiTypeParameter parameter = typeParameters[i];
PsiType t = substitutedTypeParameters[i];
substitutionMap.put(parameter, t);
if (!LambdaUtil.isFunctionalClass(baseClass)) {
return false;
}
PsiSubstitutor substitutor = PsiSubstitutorImpl.createSubstitutor(substitutionMap);
psiType = substitutor.substitute(method.getReturnType());
PsiMethod superMethod = LambdaUtil.getFunctionalInterfaceMethod(baseClass);
if (superMethod == null) {
return false;
}
final PsiMethod[] methods = resolvedClass.findMethodsByName(superMethod.getName(), false);
PsiMethod method = null;
for (PsiMethod m : methods) {
if (PsiSuperMethodUtil.isSuperMethod(m, superMethod)) {
method = m;
}
}
if (method == null) {
return false;
}
final PsiType psiType = methodSubstitutor == null ? method.getReturnType() : methodSubstitutor.substitute(method.getReturnType());
return isSuitableLambdaRole(psiType, baseMethodReturnType, methodSubstitutor, context);
} else {
psiType = method.getReturnType();
if (!LambdaUtil.isFunctionalClass(resolvedClass)) {
return false;
}
return isSuitableLambdaRole(LambdaUtil.getFunctionalInterfaceReturnType(type), baseMethodReturnType, methodSubstitutor, context);
}
}
return isSuitableLambdaRole(psiType, baseMethodReturnType, context);
}
return false;
} else {
return false;
@@ -340,17 +339,19 @@ class PseudoLambdaReplaceTemplate {
int lambdaIndex = validationInfo.getLambdaPosition();
final PsiExpression[] expressions = expression.getArgumentList().getExpressions();
final PsiExpression iterableExpression = expressions[validationInfo.getIterablePosition()];
final String pipelineHead = createPipelineHeadText(iterableExpression, force);
if (pipelineHead == null) {
return expression;
}
PsiExpression lambdaExpression = expressions[lambdaIndex];
if (!force) {
lambdaExpression = convertClassTypeExpression(lambdaExpression);
lambdaExpression = convertToJavaLambda(lambdaExpression, myStreamApiMethodName);
lambdaExpression = convertToJavaLambda(lambdaExpression);
}
LOG.assertTrue(lambdaExpression != null);
final PsiExpression iterableExpression = expressions[validationInfo.getIterablePosition()];
final String pipelineHead = createPipelineHeadText(iterableExpression, lambdaExpression, force);
final String lambdaExpressionText;
final String elementText;
if (!StreamApiConstants.FAKE_FIND_MATCHED.equals(myStreamApiMethodName)) {
@@ -391,38 +392,6 @@ class PseudoLambdaReplaceTemplate {
return JavaPsiFacade.getElementFactory(project).createExpressionFromText(sb.toString(), null);
}
private static void convertNewExpression(PsiMethod containingMethod, PsiNewExpression newExpression, PsiClass expectedReturnClass) {
final String expectedReturnQName = expectedReturnClass.getQualifiedName();
LOG.assertTrue(expectedReturnQName != null);
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(newExpression.getProject());
PsiAnonymousClass anonymousClass = PsiTreeUtil.findChildOfType(newExpression, PsiAnonymousClass.class);
LOG.assertTrue(anonymousClass != null);
PsiJavaCodeReferenceElement referenceElement = PsiTreeUtil.findChildOfType(anonymousClass, PsiJavaCodeReferenceElement.class);
LOG.assertTrue(referenceElement != null);
final PsiReferenceParameterList parameterList = PsiTreeUtil.findChildOfType(referenceElement, PsiReferenceParameterList.class);
final PsiJavaCodeReferenceElement newCodeReferenceElement = factory.createReferenceFromText(expectedReturnClass.getQualifiedName()
+
(parameterList == null
? ""
: parameterList.getText()), null);
referenceElement.replace(newCodeReferenceElement);
final List<PsiMethod> methods = ContainerUtil.filter(anonymousClass.getMethods(), new Condition<PsiMethod>() {
@Override
public boolean value(PsiMethod method) {
return !"equals".equals(method.getName());
}
});
LOG.assertTrue(methods.size() == 1, methods);
final PsiMethod method = methods.get(0);
method.setName(expectedReturnClass.getMethods()[0].getName());
final PsiTypeElement element = containingMethod.getReturnTypeElement();
if (element != null) {
final PsiReferenceParameterList genericParameter = PsiTreeUtil.findChildOfType(element, PsiReferenceParameterList.class);
element.replace(
factory.createTypeElementFromText(expectedReturnQName + (genericParameter == null ? "" : genericParameter.getText()), null));
}
}
@Nullable
private static String findSuitableTailMethodForCollection(PsiMethod lambdaHandler) {
final PsiType type = lambdaHandler.getReturnType();
@@ -454,10 +423,7 @@ class PseudoLambdaReplaceTemplate {
return null;
}
private static PsiExpression convertToJavaLambda(PsiExpression expression, String streamApiMethodName) {
if (streamApiMethodName.equals(StreamApiConstants.FAKE_FIND_MATCHED)) {
streamApiMethodName = StreamApiConstants.FILTER;
}
private static PsiExpression convertToJavaLambda(PsiExpression expression) {
if (expression instanceof PsiMethodReferenceExpression) {
return expression;
}
@@ -473,72 +439,25 @@ class PseudoLambdaReplaceTemplate {
if (!(type instanceof PsiClassType)) {
return null;
}
final PsiClass lambdaClass = ((PsiClassType)type).resolve();
final PsiClassType.ClassResolveResult result = ((PsiClassType)type).resolveGenerics();
final PsiClass lambdaClass = result.getElement();
if (lambdaClass == null) {
return null;
}
final String methodName = lambdaClass.getMethods()[0].getName();
if (tryConvertPseudoLambdaToStreamApi(method, resolveStreamApiLambdaClass(expression.getProject(), streamApiMethodName))) {
return expression;
}
else {
return JavaPsiFacade.getElementFactory(expression.getProject())
.createExpressionFromText(expression.getText() + "::" + methodName, null);
}
final PsiMethod functionalInterfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(lambdaClass);
LOG.assertTrue(functionalInterfaceMethod != null);
final String methodName = functionalInterfaceMethod.getName();
return JavaPsiFacade.getElementFactory(expression.getProject()).createExpressionFromText(expression.getText() + "::" + methodName, null);
}
if (expression instanceof PsiReferenceExpression) {
final PsiType expressionType = expression.getType();
final PsiMethod method = LambdaUtil.getFunctionalInterfaceMethod(expressionType);
LOG.assertTrue(method != null);
return JavaPsiFacade.getElementFactory(expression.getProject()).createExpressionFromText(expression.getText() + "::" + method.getName(), null);
}
return AnonymousCanBeLambdaInspection.replacePsiElementWithLambda(expression, true);
}
@NotNull
private static PsiClass resolveStreamApiLambdaClass(Project project, String streamApiMethodName) {
final PsiClass javaUtilStream = JavaPsiFacade.getInstance(project)
.findClass(StreamApiConstants.JAVA_UTIL_STREAM_STREAM, GlobalSearchScope.notScope(GlobalSearchScope.projectScope(project)));
LOG.assertTrue(javaUtilStream != null);
final PsiMethod[] methods = javaUtilStream.findMethodsByName(streamApiMethodName, false);
LOG.assertTrue(methods.length == 1);
final PsiMethod method = methods[0];
final PsiParameter[] parameters = method.getParameterList().getParameters();
LOG.assertTrue(parameters.length == 1);
final PsiType type = parameters[0].getType();
LOG.assertTrue(type instanceof PsiClassType);
final PsiClass resolved = ((PsiClassType)type).resolve();
LOG.assertTrue(resolved != null);
return resolved;
}
private static boolean tryConvertPseudoLambdaToStreamApi(final @NotNull PsiMethod method, final @NotNull PsiClass expectedReturnClass) {
final PsiType currentReturnType = method.getReturnType();
if (!(currentReturnType instanceof PsiClassType)) {
LOG.error("pseudo-lambda return type must be class " + currentReturnType);
return true;
}
final PsiClass resolvedCurrentReturnType = ((PsiClassType)currentReturnType).resolve();
if (expectedReturnClass.getManager().areElementsEquivalent(expectedReturnClass, resolvedCurrentReturnType)) {
return true;
}
final PsiCodeBlock body = method.getBody();
Collection<PsiReturnStatement> returnStatements = PsiTreeUtil.findChildrenOfType(body, PsiReturnStatement.class);
returnStatements = ContainerUtil.filter(returnStatements, new Condition<PsiReturnStatement>() {
@Override
public boolean value(PsiReturnStatement statement) {
return PsiTreeUtil.getParentOfType(statement, PsiMethod.class) == method;
}
});
if (returnStatements.size() != 1) {
return false;
}
final PsiReturnStatement returnStatement = ContainerUtil.getFirstItem(returnStatements);
assert returnStatement != null;
final PsiExpression returnValue = returnStatement.getReturnValue();
if (returnValue instanceof PsiNewExpression) {
convertNewExpression(method, (PsiNewExpression)returnValue, expectedReturnClass);
return true;
}
else {
return false;
}
}
@NotNull
private static PsiExpression convertClassTypeExpression(PsiExpression expression) {
final PsiType type = expression.getType();
@@ -552,7 +471,7 @@ class PseudoLambdaReplaceTemplate {
return expression;
}
private static String createPipelineHeadText(PsiExpression collectionExpression, PsiExpression lambdaExpression, boolean force) {
private static String createPipelineHeadText(PsiExpression collectionExpression, boolean force) {
if (collectionExpression instanceof PsiNewExpression) {
final PsiDiamondType.DiamondInferenceResult diamondResolveResult =
PsiDiamondTypeImpl.resolveInferredTypesNoCheck((PsiNewExpression)collectionExpression, collectionExpression);
@@ -569,13 +488,20 @@ class PseudoLambdaReplaceTemplate {
final PsiType newType = copiedExpression.getType();
if (!currentType.equals(newType)) {
collectionExpression = AddTypeArgumentsFix.addTypeArguments(copiedExpression, currentType);
if (collectionExpression == null) {
return null;
}
}
}
final PsiType type = collectionExpression.getType();
if (type instanceof PsiClassType) {
final PsiClass resolved = ((PsiClassType)type).resolve();
LOG.assertTrue(resolved != null && resolved.getQualifiedName() != null, type);
return collectionExpression.getText() + ".stream()";
if (InheritanceUtil.isInheritor(resolved, CommonClassNames.JAVA_UTIL_COLLECTION)) {
return collectionExpression.getText() + ".stream()";
} else {
return "java.util.stream.StreamSupport.stream(" + collectionExpression.getText() + ".spliterator(), false)";
}
}
else if (type instanceof PsiArrayType) {
return CommonClassNames.JAVA_UTIL_ARRAYS + ".stream(" + collectionExpression.getText() + ")";
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -26,6 +26,7 @@ import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.impl.FindSuperElementsHelper;
import com.intellij.psi.presentation.java.SymbolPresentationUtil;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.search.searches.DeepestSuperMethodsSearch;
@@ -34,6 +35,7 @@ import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@@ -41,20 +43,24 @@ public class SuperMethodWarningUtil {
private SuperMethodWarningUtil() {}
@NotNull
public static PsiMethod[] checkSuperMethods(final PsiMethod method, String actionString) {
return checkSuperMethods(method, actionString, null);
public static PsiMethod[] checkSuperMethods(@NotNull PsiMethod method, @NotNull String actionString) {
return checkSuperMethods(method, actionString, Collections.<PsiElement>emptyList());
}
@NotNull
public static PsiMethod[] checkSuperMethods(final PsiMethod method, String actionString, Collection<PsiElement> ignore) {
public static PsiMethod[] checkSuperMethods(@NotNull PsiMethod method, @NotNull String actionString, @NotNull Collection<PsiElement> ignore) {
PsiClass aClass = method.getContainingClass();
if (aClass == null) return new PsiMethod[]{method};
final Collection<PsiMethod> superMethods = DeepestSuperMethodsSearch.search(method).findAll();
if (ignore != null) {
superMethods.removeAll(ignore);
}
superMethods.removeAll(ignore);
if (superMethods.isEmpty()) {
PsiMethod siblingSuperMethod = FindSuperElementsHelper.getSiblingInheritedViaSubClass(method);
if (siblingSuperMethod != null) {
superMethods.add(siblingSuperMethod);
}
}
if (superMethods.isEmpty()) return new PsiMethod[]{method};
@@ -85,7 +91,7 @@ public class SuperMethodWarningUtil {
}
public static PsiMethod checkSuperMethod(final PsiMethod method, String actionString) {
public static PsiMethod checkSuperMethod(@NotNull PsiMethod method, @NotNull String actionString) {
PsiClass aClass = method.getContainingClass();
if (aClass == null) return method;
@@ -110,10 +116,10 @@ public class SuperMethodWarningUtil {
return null;
}
public static void checkSuperMethod(final PsiMethod method,
final String actionString,
final PsiElementProcessor<PsiMethod> processor,
final Editor editor) {
public static void checkSuperMethod(@NotNull PsiMethod method,
@NotNull String actionString,
@NotNull final PsiElementProcessor<PsiMethod> processor,
@NotNull Editor editor) {
PsiClass aClass = method.getContainingClass();
if (aClass == null) {
processor.execute(method);
@@ -137,7 +143,7 @@ public class SuperMethodWarningUtil {
return;
}
final PsiMethod[] methods = new PsiMethod[]{superMethod, method};
final PsiMethod[] methods = {superMethod, method};
final String renameBase = actionString + " base method";
final String renameCurrent = actionString + " only current method";
final JBList list = new JBList(renameBase, renameCurrent);
@@ -148,6 +154,7 @@ public class SuperMethodWarningUtil {
.setResizable(false)
.setRequestFocus(true)
.setItemChoosenCallback(new Runnable() {
@Override
public void run() {
final Object value = list.getSelectedValue();
if (value instanceof String) {
@@ -816,7 +816,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
@Nullable
protected Wrap arrangeChildWrap(final ASTNode child, Wrap defaultWrap) {
return myWrapManager.arrangeChildWrap(child, myNode, getSettings(), defaultWrap, this);
return myWrapManager.arrangeChildWrap(child, myNode, mySettings, myJavaSettings, defaultWrap, this);
}
@NotNull
@@ -20,6 +20,7 @@ import com.intellij.formatting.Block;
import com.intellij.formatting.Wrap;
import com.intellij.lang.ASTNode;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
import com.intellij.psi.formatter.java.AbstractJavaBlock;
import com.intellij.psi.formatter.java.wrap.impl.JavaChildBlockWrapFactory;
import com.intellij.psi.formatter.java.wrap.impl.JavaChildWrapArranger;
@@ -78,10 +79,14 @@ public class JavaWrapManager {
* <code>null</code> otherwise
*/
@Nullable
public Wrap arrangeChildWrap(ASTNode child, ASTNode parent, CommonCodeStyleSettings settings, Wrap suggestedWrap,
public Wrap arrangeChildWrap(ASTNode child,
ASTNode parent,
CommonCodeStyleSettings settings,
JavaCodeStyleSettings javaSettings,
Wrap suggestedWrap,
AbstractJavaBlock reservedWrapsProvider)
{
return myChildArranger.arrange(child, parent, settings, suggestedWrap, reservedWrapsProvider);
return myChildArranger.arrange(child, parent, settings, javaSettings, suggestedWrap, reservedWrapsProvider);
}
/**
@@ -72,9 +72,9 @@ public class JavaChildWrapArranger {
public Wrap arrange(ASTNode child,
ASTNode parent,
CommonCodeStyleSettings settings,
JavaCodeStyleSettings javaSettings,
Wrap suggestedWrap,
AbstractJavaBlock reservedWrapsProvider) {
final JavaCodeStyleSettings javaSettings = settings.getRootSettings().getCustomSettings(JavaCodeStyleSettings.class);
ASTNode directParent = child.getTreeParent();
int role = ((CompositeElement)directParent).getChildRole(child);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,11 +23,16 @@ import com.intellij.psi.util.FileTypeUtils;
public class JavaVetoRenameCondition implements Condition<PsiElement> {
@Override
public boolean value(final PsiElement element) {
public boolean value(PsiElement element) {
if (element instanceof LightMethod) {
final PsiClass containingClass = ((LightMethod)element).getContainingClass();
PsiClass containingClass = ((LightMethod)element).getContainingClass();
if (containingClass != null && containingClass.isEnum()) return true;
}
if (element instanceof PsiReceiverParameter) {
return true;
}
return element instanceof PsiJavaFile &&
!FileTypeUtils.isInServerPageFile(element) &&
!JavaProjectRootsUtil.isOutsideJavaSourceRoot((PsiFile)element) &&
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,13 +20,14 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.spi.psi.SPIClassProviderReferenceElement;
import org.jetbrains.annotations.NotNull;
/**
* User: anna
*/
public class SPIGotoSuperHandler extends JavaGotoSuperHandler {
@Override
protected PsiElement getElement(PsiFile file, int offset) {
protected PsiElement getElement(@NotNull PsiFile file, int offset) {
final SPIClassProviderReferenceElement
providerElement = PsiTreeUtil.getParentOfType(super.getElement(file, offset), SPIClassProviderReferenceElement.class);
if (providerElement != null) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -61,7 +61,7 @@ public class JavaAllOverridingMethodsSearcher implements QueryExecutor<Pair<PsiM
PsiSubstitutor substitutor = null;
for (String name : methods.keySet()) {
if (inheritor.findMethodsByName(name, false).length == 0) continue;
if (inheritor.findMethodsByName(name, true).length == 0) continue;
for (PsiMethod method : methods.get(name)) {
if (method.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) &&
@@ -101,12 +101,14 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
return true;
}
Collection<PsiReferenceList> candidates = ApplicationManager.getApplication().runReadAction(new Computable<Collection<PsiReferenceList>>() {
@Override
public Collection<PsiReferenceList> compute() {
return JavaSuperClassNameOccurenceIndex.getInstance().get(searchKey, project, scope);
}
});
Collection<PsiReferenceList> candidates = MethodUsagesSearcher.resolveInReadAction(project,
new Computable<Collection<PsiReferenceList>>() {
@Override
public Collection<PsiReferenceList> compute() {
return JavaSuperClassNameOccurenceIndex
.getInstance().get(searchKey, project, scope);
}
});
Map<String, List<PsiClass>> classes = new HashMap<String, List<PsiClass>>();
@@ -118,7 +120,7 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
return referenceList.getParent();
}
});
if (!checkInheritance(p, aClass, candidate)) continue;
if (!checkInheritance(p, aClass, candidate, project)) continue;
String fqn = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Override
@@ -142,16 +144,19 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
}
if (p.includeAnonymous()) {
Collection<PsiAnonymousClass> anonymousCandidates = ApplicationManager.getApplication().runReadAction(new Computable<Collection<PsiAnonymousClass>>() {
@Override
public Collection<PsiAnonymousClass> compute() {
return JavaAnonymousClassBaseRefOccurenceIndex.getInstance().get(searchKey, project, scope);
}
});
Collection<PsiAnonymousClass> anonymousCandidates = MethodUsagesSearcher.resolveInReadAction(project,
new Computable<Collection<PsiAnonymousClass>>() {
@Override
public Collection<PsiAnonymousClass> compute() {
return JavaAnonymousClassBaseRefOccurenceIndex
.getInstance()
.get(searchKey, project, scope);
}
});
for (PsiAnonymousClass candidate : anonymousCandidates) {
ProgressIndicatorProvider.checkCanceled();
if (!checkInheritance(p, aClass, candidate)) continue;
if (!checkInheritance(p, aClass, candidate, project)) continue;
if (!consumer.process(candidate)) return false;
}
@@ -190,8 +195,8 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
return true;
}
private static boolean checkInheritance(final DirectClassInheritorsSearch.SearchParameters p, final PsiClass aClass, final PsiClass candidate) {
return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
private static boolean checkInheritance(final DirectClassInheritorsSearch.SearchParameters p, final PsiClass aClass, final PsiClass candidate, Project project) {
return MethodUsagesSearcher.resolveInReadAction(project, new Computable<Boolean>() {
@Override
public Boolean compute() {
return !p.isCheckInheritance() || candidate.isInheritor(aClass, false);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -17,6 +17,7 @@ package com.intellij.codeInsight;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.PsiAnnotation.TargetType;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -28,28 +29,27 @@ import java.util.Set;
* @author peter
*/
public class AnnotationTargetUtil {
public static final Set<PsiAnnotation.TargetType> DEFAULT_TARGETS = Collections.unmodifiableSet(ContainerUtil.newHashSet(
PsiAnnotation.TargetType.PACKAGE, PsiAnnotation.TargetType.TYPE, PsiAnnotation.TargetType.ANNOTATION_TYPE,
PsiAnnotation.TargetType.FIELD, PsiAnnotation.TargetType.METHOD, PsiAnnotation.TargetType.CONSTRUCTOR,
PsiAnnotation.TargetType.PARAMETER, PsiAnnotation.TargetType.LOCAL_VARIABLE));
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.AnnotationUtil");
private static final PsiAnnotation.TargetType[] PACKAGE_TARGETS = {PsiAnnotation.TargetType.PACKAGE};
private static final PsiAnnotation.TargetType[] TYPE_USE_TARGETS = {PsiAnnotation.TargetType.TYPE_USE};
private static final PsiAnnotation.TargetType[] ANNOTATION_TARGETS = {PsiAnnotation.TargetType.ANNOTATION_TYPE, PsiAnnotation.TargetType.TYPE, PsiAnnotation.TargetType.TYPE_USE};
private static final PsiAnnotation.TargetType[] TYPE_TARGETS = {PsiAnnotation.TargetType.TYPE, PsiAnnotation.TargetType.TYPE_USE};
private static final PsiAnnotation.TargetType[] TYPE_PARAMETER_TARGETS = {
PsiAnnotation.TargetType.TYPE_PARAMETER, PsiAnnotation.TargetType.TYPE_USE};
private static final PsiAnnotation.TargetType[] CONSTRUCTOR_TARGETS = {PsiAnnotation.TargetType.CONSTRUCTOR, PsiAnnotation.TargetType.TYPE_USE};
private static final PsiAnnotation.TargetType[] METHOD_TARGETS = {PsiAnnotation.TargetType.METHOD, PsiAnnotation.TargetType.TYPE_USE};
private static final PsiAnnotation.TargetType[] FIELD_TARGETS = {PsiAnnotation.TargetType.FIELD, PsiAnnotation.TargetType.TYPE_USE};
private static final PsiAnnotation.TargetType[] PARAMETER_TARGETS = {PsiAnnotation.TargetType.PARAMETER, PsiAnnotation.TargetType.TYPE_USE};
private static final PsiAnnotation.TargetType[] LOCAL_VARIABLE_TARGETS ={
PsiAnnotation.TargetType.LOCAL_VARIABLE, PsiAnnotation.TargetType.TYPE_USE};
public static final Set<TargetType> DEFAULT_TARGETS = ContainerUtil.immutableSet(
TargetType.PACKAGE, TargetType.TYPE, TargetType.ANNOTATION_TYPE, TargetType.FIELD, TargetType.METHOD, TargetType.CONSTRUCTOR,
TargetType.PARAMETER, TargetType.LOCAL_VARIABLE);
private static final TargetType[] PACKAGE_TARGETS = {TargetType.PACKAGE};
private static final TargetType[] TYPE_USE_TARGETS = {TargetType.TYPE_USE};
private static final TargetType[] ANNOTATION_TARGETS = {TargetType.ANNOTATION_TYPE, TargetType.TYPE, TargetType.TYPE_USE};
private static final TargetType[] TYPE_TARGETS = {TargetType.TYPE, TargetType.TYPE_USE};
private static final TargetType[] TYPE_PARAMETER_TARGETS = {TargetType.TYPE_PARAMETER, TargetType.TYPE_USE};
private static final TargetType[] CONSTRUCTOR_TARGETS = {TargetType.CONSTRUCTOR, TargetType.TYPE_USE};
private static final TargetType[] METHOD_TARGETS = {TargetType.METHOD, TargetType.TYPE_USE};
private static final TargetType[] FIELD_TARGETS = {TargetType.FIELD, TargetType.TYPE_USE};
private static final TargetType[] PARAMETER_TARGETS = {TargetType.PARAMETER, TargetType.TYPE_USE};
private static final TargetType[] LOCAL_VARIABLE_TARGETS = {TargetType.LOCAL_VARIABLE, TargetType.TYPE_USE};
@NotNull
public static PsiAnnotation.TargetType[] getTargetsForLocation(@Nullable PsiAnnotationOwner owner) {
public static TargetType[] getTargetsForLocation(@Nullable PsiAnnotationOwner owner) {
if (owner == null) {
return PsiAnnotation.TargetType.EMPTY_ARRAY;
return TargetType.EMPTY_ARRAY;
}
if (owner instanceof PsiType || owner instanceof PsiTypeElement) {
@@ -90,24 +90,27 @@ public class AnnotationTargetUtil {
if (element instanceof PsiLocalVariable) {
return LOCAL_VARIABLE_TARGETS;
}
if (element instanceof PsiReceiverParameter) {
return TYPE_USE_TARGETS;
}
}
return PsiAnnotation.TargetType.EMPTY_ARRAY;
return TargetType.EMPTY_ARRAY;
}
@Nullable
public static Set<PsiAnnotation.TargetType> extractRequiredAnnotationTargets(@Nullable PsiAnnotationMemberValue value) {
public static Set<TargetType> extractRequiredAnnotationTargets(@Nullable PsiAnnotationMemberValue value) {
if (value instanceof PsiReference) {
PsiAnnotation.TargetType targetType = translateTargetRef((PsiReference)value);
TargetType targetType = translateTargetRef((PsiReference)value);
if (targetType != null) {
return Collections.singleton(targetType);
}
}
else if (value instanceof PsiArrayInitializerMemberValue) {
Set <PsiAnnotation.TargetType> targets = ContainerUtil.newHashSet();
Set <TargetType> targets = ContainerUtil.newHashSet();
for (PsiAnnotationMemberValue initializer : ((PsiArrayInitializerMemberValue)value).getInitializers()) {
if (initializer instanceof PsiReference) {
PsiAnnotation.TargetType targetType = translateTargetRef((PsiReference)initializer);
TargetType targetType = translateTargetRef((PsiReference)initializer);
if (targetType != null) {
targets.add(targetType);
}
@@ -120,12 +123,12 @@ public class AnnotationTargetUtil {
}
@Nullable
private static PsiAnnotation.TargetType translateTargetRef(@NotNull PsiReference reference) {
private static TargetType translateTargetRef(@NotNull PsiReference reference) {
PsiElement field = reference.resolve();
if (field instanceof PsiEnumConstant) {
String name = ((PsiEnumConstant)field).getName();
try {
return PsiAnnotation.TargetType.valueOf(name);
return TargetType.valueOf(name);
}
catch (IllegalArgumentException e) {
LOG.warn("Unknown target: " + name);
@@ -15,10 +15,14 @@
*/
package com.intellij.psi;
import org.jetbrains.annotations.NotNull;
/**
* Represents a receiver parameter of a Java method (Java 8).
*
* @since 12.1
*/
public interface PsiReceiverParameter extends PsiVariable {
@NotNull
PsiThisExpression getIdentifier();
}
@@ -608,6 +608,22 @@ public class DeclarationParser {
}
}
if (typed) {
IElementType tokenType = builder.getTokenType();
if (tokenType == JavaTokenType.THIS_KEYWORD || tokenType == JavaTokenType.IDENTIFIER && builder.lookAhead(1) == JavaTokenType.DOT) {
PsiBuilder.Marker mark = builder.mark();
PsiBuilder.Marker expr = myParser.getExpressionParser().parse(builder);
if (expr != null && exprType(expr) == JavaElementType.THIS_EXPRESSION) {
mark.drop();
done(param, JavaElementType.RECEIVER_PARAMETER);
return param;
}
mark.rollbackTo();
}
}
if (expect(builder, JavaTokenType.IDENTIFIER)) {
if (!resource) {
eatBrackets(builder, typeInfo != null && typeInfo.isVarArg ? "expected.rparen" : null);
@@ -56,7 +56,8 @@ public class LocalsControlFlowPolicy implements ControlFlowPolicy {
if (codeFragment == null) return null;
if (myCodeFragment.getContainingFile() == codeFragment.getContainingFile() && // in order for jsp includes to work
!myCodeFragment.equals(codeFragment) &&
!(myCodeFragment.getParent() instanceof PsiLambdaExpression && codeFragment.equals(PsiTreeUtil.getParentOfType(myCodeFragment, PsiCodeBlock.class)))) {
!(myCodeFragment.getParent() instanceof PsiLambdaExpression &&
PsiTreeUtil.isAncestor(PsiTreeUtil.getParentOfType(myCodeFragment, PsiClass.class), codeFragment, false))) {
return null;
}
return (PsiVariable)refElement;
@@ -1,56 +0,0 @@
/*
* Copyright 2000-2012 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.psi.impl;
import com.intellij.psi.CommonClassNames;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.util.PsiSuperMethodUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public class FindSuperElementsHelper {
@Nullable
public static PsiElement[] findSuperElements(@NotNull PsiElement element) {
if (element instanceof PsiClass) {
PsiClass aClass = (PsiClass) element;
List<PsiClass> allSupers = new ArrayList<PsiClass>(Arrays.asList(aClass.getSupers()));
for (Iterator<PsiClass> iterator = allSupers.iterator(); iterator.hasNext();) {
PsiClass superClass = iterator.next();
if (CommonClassNames.JAVA_LANG_OBJECT.equals(superClass.getQualifiedName())) iterator.remove();
}
return allSupers.toArray(new PsiClass[allSupers.size()]);
} else if (element instanceof PsiMethod) {
PsiMethod method = (PsiMethod) element;
if (method.isConstructor()) {
PsiMethod constructorInSuper = PsiSuperMethodUtil.findConstructorInSuper(method);
if (constructorInSuper != null) {
return new PsiMethod[]{constructorInSuper};
}
} else {
return method.findSuperMethods(false);
}
}
return null;
}
}
@@ -15,7 +15,6 @@
*/
package com.intellij.psi.impl.source;
import com.intellij.lang.ASTNode;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.CompositePsiElement;
import com.intellij.psi.impl.source.tree.JavaElementType;
@@ -30,6 +29,11 @@ public class PsiReceiverParameterImpl extends CompositePsiElement implements Psi
super(JavaElementType.RECEIVER_PARAMETER);
}
@NotNull
public PsiThisExpression getIdentifier() {
return PsiTreeUtil.getRequiredChildOfType(this, PsiThisExpression.class);
}
@Nullable
@Override
public PsiModifierList getModifierList() {
@@ -100,13 +104,6 @@ public class PsiReceiverParameterImpl extends CompositePsiElement implements Psi
return getIdentifier().getTextOffset();
}
@NotNull
private PsiElement getIdentifier() {
ASTNode node = findChildByType(JavaTokenType.THIS_KEYWORD);
assert node != null : getChildren();
return node.getPsi();
}
@Override
public String toString() {
return "PsiReceiverParameter";
@@ -227,6 +227,19 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
psiSubstitutor = TypeConversionUtil.getClassSubstitutor(qContainingClass, paramClass, resolveResult.getSubstitutor());
LOG.assertTrue(psiSubstitutor != null);
}
else if (member instanceof PsiMethod && ((PsiMethod)member).isConstructor() || member instanceof PsiClass) {
//15.13.1
//If ClassType is a raw type, but is not a non-static member type of a raw type,
//the candidate notional member methods are those specified in §15.9.3 for a class instance creation expression that uses <>
//to elide the type arguments to a class.
final PsiResolveHelper helper = JavaPsiFacade.getInstance(myExpression.getProject()).getResolveHelper();
final PsiType[] paramTypes =
member instanceof PsiMethod ? ((PsiMethod)member).getSignature(PsiSubstitutor.EMPTY).getParameterTypes() : PsiType.EMPTY_ARRAY;
psiSubstitutor = helper.inferTypeArguments(qContainingClass.getTypeParameters(),
paramTypes,
signature.getParameterTypes(),
PsiUtil.getLanguageLevel(myExpression));
}
else {
psiSubstitutor = PsiSubstitutor.EMPTY;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,10 +19,7 @@ import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.impl.source.Constants;
import com.intellij.psi.impl.source.tree.ChildRole;
import com.intellij.psi.impl.source.tree.CompositeElement;
import com.intellij.psi.impl.source.tree.JavaSourceUtil;
import com.intellij.psi.impl.source.tree.TreeElement;
import com.intellij.psi.impl.source.tree.*;
import com.intellij.psi.tree.ChildRoleBase;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
@@ -32,7 +29,8 @@ import org.jetbrains.annotations.Nullable;
public class ParameterListElement extends CompositeElement implements Constants {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.ParameterListElement");
private static final TokenSet PARAMETER_SET = TokenSet.create(PARAMETER);
private static final TokenSet PARAMETER_SET = TokenSet.create(JavaElementType.PARAMETER, JavaElementType.RECEIVER_PARAMETER);
public ParameterListElement() {
super(PARAMETER_LIST);
@@ -50,8 +48,10 @@ public class ParameterListElement extends CompositeElement implements Constants
before = Boolean.FALSE;
}
}
TreeElement firstAdded = super.addInternal(first, last, anchor, before);
if (first == last && first.getElementType() == PARAMETER) {
if (first == last && PARAMETER_SET.contains(first.getElementType())) {
JavaSourceUtil.addSeparatingComma(this, first, PARAMETER_SET);
}
@@ -69,9 +69,11 @@ public class ParameterListElement extends CompositeElement implements Constants
public void deleteChildInternal(@NotNull ASTNode child) {
final TreeElement oldLastNodeInsideParens = getLastNodeInsideParens();
final TreeElement oldFirstNodeInsideParens = getFirstNodeInsideParens();
if (child.getElementType() == PARAMETER) {
if (PARAMETER_SET.contains(child.getElementType())) {
JavaSourceUtil.deleteSeparatingComma(this, child);
}
super.deleteChildInternal(child);
// We may want to fix trailing white space processing here - there is a following possible case:
@@ -79,10 +81,11 @@ public class ParameterListElement extends CompositeElement implements Constants
// *) 'arg2' is to be removed;
// We don't want to keep trailing white space then
TreeElement newLastNodeInsideParens = getLastNodeInsideParens();
if (newLastNodeInsideParens != null && newLastNodeInsideParens.getElementType() == WHITE_SPACE) {
if (newLastNodeInsideParens != null && oldLastNodeInsideParens != null && newLastNodeInsideParens.getElementType() == WHITE_SPACE) {
if (oldLastNodeInsideParens.getElementType() != WHITE_SPACE) {
deleteChildInternal(newLastNodeInsideParens);
} else {
}
else {
replaceChild(newLastNodeInsideParens, (ASTNode)oldLastNodeInsideParens.clone());
}
}
@@ -91,7 +94,8 @@ public class ParameterListElement extends CompositeElement implements Constants
if (newFirstNodeInsideParens != null && newFirstNodeInsideParens.getElementType() == WHITE_SPACE) {
if (oldFirstNodeInsideParens == null || oldFirstNodeInsideParens.getElementType() != WHITE_SPACE) {
deleteChildInternal(newFirstNodeInsideParens);
} else {
}
else {
replaceChild(newFirstNodeInsideParens, (ASTNode)oldFirstNodeInsideParens.clone());
}
}
@@ -126,7 +130,7 @@ public class ParameterListElement extends CompositeElement implements Constants
public int getChildRole(ASTNode child) {
LOG.assertTrue(child.getTreeParent() == this);
IElementType i = child.getElementType();
if (i == PARAMETER) {
if (PARAMETER_SET.contains((i))) {
return ChildRole.PARAMETER;
}
else if (i == COMMA) {
@@ -144,7 +148,7 @@ public class ParameterListElement extends CompositeElement implements Constants
}
/**
* @return last node before closing right paren if possible; <code>null</code> otherwise
* @return last node before closing right parenthesis if possible; <code>null</code> otherwise
*/
@Nullable
private TreeElement getLastNodeInsideParens() {
@@ -152,8 +156,8 @@ public class ParameterListElement extends CompositeElement implements Constants
return lastNode.getElementType() == RPARENTH ? lastNode.getTreePrev() : null;
}
/**
* @return first node after opening left paren if possible; <code>null</code> otherwise
/**
* @return first node after opening left parenthesis if possible; <code>null</code> otherwise
*/
@Nullable
private TreeElement getFirstNodeInsideParens() {
@@ -30,6 +30,12 @@ annotation.non.repeatable=The declaration of ''{0}'' does not have a valid java.
annotation.container.wrong.place=Container annotation ''{0}'' must not be present at the same time as the element it contains
annotation.container.not.applicable=Container annotation ''@{0}'' is not applicable to {1}
receiver.wrong.context=Receivers are not allowed outside of method parameter list
receiver.static.context=The receiver cannot be used in a static context
receiver.wrong.position=The receiver should be the first parameter
receiver.type.mismatch=The receiver type does not match the enclosing class type
receiver.name.mismatch=The receiver name does not match the enclosing class type
# These aren't unused.
# suppress inspection "UnusedProperty"
annotation.target.ANNOTATION_TYPE=annotation type
@@ -388,5 +394,6 @@ feature.extension.methods=Extension methods
feature.method.references=Method references
feature.lambda.expressions=Lambda expressions
feature.type.annotations=Type annotations
feature.type.receivers=Receiver parameters
insufficient.language.level={0} are not supported at this language level
bad.qualifier.in.super.method.reference=Bad type qualifier in default super call: redundant interface {0} is extended by {1}
@@ -1,19 +1,3 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.*;
import java.util.*;
@@ -47,6 +31,8 @@ class UnsupportedFeatures {
}
}
void f(<error descr="Receiver parameters are not supported at this language level">Object this</error>) { }
interface I {
<error descr="Extension methods are not supported at this language level">default void m() { }</error>
<error descr="Extension methods are not supported at this language level">static void m() { }</error>
@@ -0,0 +1,47 @@
import java.lang.annotation.*;
@interface A { }
@Target(ElementType.TYPE_USE)
@interface TA { }
class C {
@Override
public String toString(@TA C this) { return ""; }
@Override
public boolean equals(@TA C this, @TA Object other) { return false; }
@interface Anno { String f(Anno this); }
void m0() {
try (Object <error descr="Receivers are not allowed outside of method parameter list">this</error>) { }
Runnable r = (C <error descr="Receivers are not allowed outside of method parameter list">C.this</error>) -> { };
}
void m1a(<error descr="Modifier 'final' not allowed here">final</error> C this) { }
void m1b(<error descr="'@A' not applicable to type use">@A</error> C this) { }
void m2(@TA Object other, @TA C <error descr="The receiver should be the first parameter">this</error>) { }
void m3a(@TA <error descr="The receiver type does not match the enclosing class type">Object</error> this) { }
void m3b(@TA <error descr="The receiver type does not match the enclosing class type">int</error> this) { }
void m4a(C C.this) { }
void m4b(C <error descr="The receiver name does not match the enclosing class type">C.X.this</error>) { }
static void sm1(@TA Object <error descr="The receiver cannot be used in a static context">this</error>) { }
C(C <error descr="The receiver cannot be used in a static context">this</error>) { }
static class X {
X(X <error descr="The receiver cannot be used in a static context">this</error>) { }
}
class B {
B(C C.this) { }
B(<error descr="The receiver type does not match the enclosing class type">B</error> C.this, int p) { }
B(C <error descr="The receiver name does not match the enclosing class type">B.this</error>, long p) { }
B(C <error descr="The receiver name does not match the enclosing class type">this</error>, float p) { }
}
}
@@ -130,19 +130,4 @@ class Outer {
IntFunction<Super> f = Outer.<error descr="Annotations are not allowed here">@TA</error> This.super::getField;
}
}
//todo[r.sh]
/*public String toString(@TA C this) { return ""; }
public boolean equals(@TA C this, @TA C other) { return false; }
C(@TA C this, boolean b) { }
class Outer {
class Middle {
class Inner {
void innerMethod(@TA Outer.@TA Middle.@TA Inner this) { }
}
}
}*/
}
@@ -0,0 +1,6 @@
import java.util.*;
class Test {
public Optional<Set<String>> foo(Optional<Set<String>> args) {
return args.map(HashSet::new).map(Collections::unmodifiableSet);
}
}
@@ -0,0 +1,11 @@
package z;
interface I {
void <caret>run();
}
abstract class A {
public void run() {}
}
class Foo extends A implements I {
}
@@ -0,0 +1,11 @@
package z;
interface I {
void run();
}
abstract class A {
public void <caret>run() {}
}
class Foo extends A implements I {
}
@@ -0,0 +1,24 @@
import com.google.common.collect.Iterables;
import com.google.common.base.Function;
import java.lang.String;
import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Collectors;
class c {
void m() {
final Function<String, String> function = (Function<String, String>)new Function<String, String>() {
@Override
public String apply(String input) {
Collectors c;
ArrayList l;
System.out.println(input);
//do something
int i = 1;
return input;
}
};
Iterables.transfo<caret>rm(Collections.emptyList(), function);
}
}
@@ -0,0 +1,24 @@
import com.google.common.collect.Iterables;
import com.google.common.base.Function;
import java.lang.String;
import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Collectors;
class c {
void m() {
final Function<String, String> function = (Function<String, String>)new Function<String, String>() {
@Override
public String apply(String input) {
Collectors c;
ArrayList l;
System.out.println(input);
//do something
int i = 1;
return input;
}
};
Collections.<String>emptyList().stream().map(function::apply).collect(Collectors.toList());
}
}
@@ -6,13 +6,13 @@ import java.util.Collections;
class c {
void m() {
Collections.emptyList().stream().allMatch(getPredicate(100));
Collections.<String>emptyList().stream().allMatch(getPredicate(100)::apply);
}
public java.util.function.Predicate<String> getPredicate(final int param) {
return new java.util.function.Predicate<String>() {
public Predicate<String> getPredicate(final int param) {
return new Predicate<String>() {
@Override
public boolean test(String input) {
public boolean apply(String input) {
System.out.println("lambda param " + param);
return false;
}
@@ -6,9 +6,9 @@ import java.util.Collections;
class c {
void m() {
Iterables.f<caret>ind(Collections.emptyList(), new Predicate<Object>() {
Iterables.f<caret>ind(Collections.emptyList(), new Predicate<String>() {
@Override
public boolean apply(Object input) {
public boolean apply(String input) {
return true;
}
});
@@ -6,6 +6,6 @@ import java.util.Collections;
class c {
void m() {
Collections.emptyList().stream().filter(input -> true).findFirst().get();
Collections.<String>emptyList().stream().filter(input -> true).findFirst().get();
}
}
@@ -8,7 +8,7 @@ import java.util.stream.Collectors;
class c {
void m() {
Collections.emptyList().stream().map(input -> {
Collections.<String>emptyList().stream().map(input -> {
Collectors c;
ArrayList l;
System.out.println(input);
@@ -13,7 +13,7 @@ class c {
System.out.println(input);
//do something
int i = 1;
return input;
return input.intern();
}
});
}
@@ -12,6 +12,6 @@ class c {
System.out.println(input);
//do something
int i = 1;
return input;
return input.intern();
}).collect(Collectors.toList());
}
@@ -1,17 +1,21 @@
import com.google.common.collect.Iterables;
import com.google.common.base.Function;
import java.lang.Iterable;
import java.lang.String;
import java.util.ArrayList;
import java.util.Collections;
class c {
void m() {
Iterables.transf<caret>orm(new ArrayList<>(), getFunction())
Iterable<String> trnsfrmd = Iterables.transf<caret>orm(new ArrayList<>(), getFunction());
}
Function<String, String> getFunction() {
return new Function<String, String>() {
String apply(String s) {
return s.toString().toLowerCase().replace('c', 'h');
}
}
}
}
@@ -1,6 +1,7 @@
import com.google.common.collect.Iterables;
import com.google.common.base.Function;
import java.lang.Iterable;
import java.lang.String;
import java.util.ArrayList;
import java.util.Collections;
@@ -8,13 +9,14 @@ import java.util.stream.Collectors;
class c {
void m() {
Collections.emptyList().stream().map(input -> {
Collectors c;
ArrayList l;
System.out.println(input);
//do something
int i = 1;
return input;
}).collect(Collectors.toList())
Iterable<String> trnsfrmd = new ArrayList<String>().stream().map(getFunction()::apply).collect(Collectors.toList());
}
Function<String, String> getFunction() {
return new Function<String, String>() {
String apply(String s) {
return s.toString().toLowerCase().replace('c', 'h');
}
}
}
}
@@ -8,7 +8,7 @@ import java.util.stream.Collectors;
class c {
void m() {
Collections.emptyList().stream().map(input -> {
Collections.<String>emptyList().stream().map(input -> {
Collectors c;
ArrayList l;
System.out.println(input);
@@ -0,0 +1,178 @@
PsiJavaFile:Receiver.java
PsiJavaToken:LBRACE('{')
PsiWhiteSpace(' ')
PsiMethod:m1
PsiModifierList:
<empty list>
PsiTypeParameterList
<empty list>
PsiTypeElement:void
PsiKeyword:void('void')
PsiWhiteSpace(' ')
PsiIdentifier:m1('m1')
PsiParameterList:(C this)
PsiJavaToken:LPARENTH('(')
PsiReceiverParameter
PsiModifierList:
<empty list>
PsiTypeElement:C
PsiJavaCodeReferenceElement:C
PsiIdentifier:C('C')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiThisExpression:this
PsiReferenceParameterList
<empty list>
PsiKeyword:this('this')
PsiJavaToken:RPARENTH(')')
PsiReferenceList
<empty list>
PsiJavaToken:SEMICOLON(';')
PsiWhiteSpace(' ')
PsiMethod:m2
PsiModifierList:
<empty list>
PsiTypeParameterList
<empty list>
PsiTypeElement:void
PsiKeyword:void('void')
PsiWhiteSpace(' ')
PsiIdentifier:m2('m2')
PsiParameterList:(T T.this)
PsiJavaToken:LPARENTH('(')
PsiReceiverParameter
PsiModifierList:
<empty list>
PsiTypeElement:T
PsiJavaCodeReferenceElement:T
PsiIdentifier:T('T')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiThisExpression:T.this
PsiJavaCodeReferenceElement:T
PsiIdentifier:T('T')
PsiReferenceParameterList
<empty list>
PsiJavaToken:DOT('.')
PsiKeyword:this('this')
PsiJavaToken:RPARENTH(')')
PsiReferenceList
<empty list>
PsiJavaToken:SEMICOLON(';')
PsiWhiteSpace(' ')
PsiMethod:m3
PsiModifierList:
<empty list>
PsiTypeParameterList
<empty list>
PsiTypeElement:void
PsiKeyword:void('void')
PsiWhiteSpace(' ')
PsiIdentifier:m3('m3')
PsiParameterList:(X Y.Z)
PsiJavaToken:LPARENTH('(')
PsiParameter:Y
PsiModifierList:
<empty list>
PsiTypeElement:X
PsiJavaCodeReferenceElement:X
PsiIdentifier:X('X')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiIdentifier:Y('Y')
PsiErrorElement:',' expected
PsiJavaToken:DOT('.')
PsiJavaCodeReferenceElement:Z
PsiIdentifier:Z('Z')
PsiReferenceParameterList
<empty list>
PsiJavaToken:RPARENTH(')')
PsiReferenceList
<empty list>
PsiJavaToken:SEMICOLON(';')
PsiWhiteSpace(' ')
PsiField:f1
PsiModifierList:
<empty list>
PsiTypeElement:T
PsiJavaCodeReferenceElement:T
PsiIdentifier:T('T')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiIdentifier:f1('f1')
PsiWhiteSpace(' ')
PsiJavaToken:EQ('=')
PsiWhiteSpace(' ')
PsiLambdaExpression:(T this) -> { }
PsiParameterList:(T this)
PsiJavaToken:LPARENTH('(')
PsiReceiverParameter
PsiModifierList:
<empty list>
PsiTypeElement:T
PsiJavaCodeReferenceElement:T
PsiIdentifier:T('T')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiThisExpression:this
PsiReferenceParameterList
<empty list>
PsiKeyword:this('this')
PsiJavaToken:RPARENTH(')')
PsiWhiteSpace(' ')
PsiJavaToken:ARROW('->')
PsiWhiteSpace(' ')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiWhiteSpace(' ')
PsiJavaToken:RBRACE('}')
PsiJavaToken:SEMICOLON(';')
PsiWhiteSpace(' ')
PsiField:f2
PsiModifierList:
<empty list>
PsiTypeElement:T
PsiJavaCodeReferenceElement:T
PsiIdentifier:T('T')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiIdentifier:f2('f2')
PsiWhiteSpace(' ')
PsiJavaToken:EQ('=')
PsiWhiteSpace(' ')
PsiLambdaExpression:(T T.this) -> { }
PsiParameterList:(T T.this)
PsiJavaToken:LPARENTH('(')
PsiReceiverParameter
PsiModifierList:
<empty list>
PsiTypeElement:T
PsiJavaCodeReferenceElement:T
PsiIdentifier:T('T')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiThisExpression:T.this
PsiJavaCodeReferenceElement:T
PsiIdentifier:T('T')
PsiReferenceParameterList
<empty list>
PsiJavaToken:DOT('.')
PsiKeyword:this('this')
PsiJavaToken:RPARENTH(')')
PsiWhiteSpace(' ')
PsiJavaToken:ARROW('->')
PsiWhiteSpace(' ')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiWhiteSpace(' ')
PsiJavaToken:RBRACE('}')
PsiJavaToken:SEMICOLON(';')
PsiWhiteSpace(' ')
PsiJavaToken:RBRACE('}')
@@ -0,0 +1,9 @@
class Test {
void foo(Object o) {
try {
Runnable r = () -> {
<selection>System.out.println(o);</selection>
};
} catch (Throwable e) {}
}
}
@@ -0,0 +1,13 @@
class Test {
void foo(Object o) {
try {
Runnable r = () -> {
newMethod(o);
};
} catch (Throwable e) {}
}
private void newMethod(Object o) {
System.out.println(o);
}
}
@@ -23,40 +23,40 @@ import com.intellij.pom.java.LanguageLevel;
public class AnnotationsHighlightingTest extends LightDaemonAnalyzerTestCase {
private static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/annotations";
public void testWrongPlace() { doTest(false); }
public void testNotValueNameOmitted() { doTest(false); }
public void testCannotFindMethod() { doTest(false); }
public void testIncompatibleType1() { doTest(false); }
public void testIncompatibleType2() { doTest(false); }
public void testIncompatibleType3() { doTest(false); }
public void testIncompatibleType4() { doTest(false); }
public void testIncompatibleType5() { doTest(false); }
public void testMissingAttribute() { doTest(false); }
public void testDuplicateAnnotation() { doTest(false); }
public void testNonConstantInitializer() { doTest(false); }
public void testInvalidType() { doTest(false); }
public void testInapplicable() { doTest(false); }
public void testDuplicateAttribute() { doTest(false); }
public void testDuplicateTarget() { doTest(false); }
public void testPingPongAnnotationTypesDependencies() { doTest(false); }
public void testClashMethods() { doTest(false); }
public void testDupMethods() { doTest(false); }
public void testPrivateInaccessibleConstant() { doTest(false); }
public void testWrongPlace() { doTest(); }
public void testNotValueNameOmitted() { doTest(); }
public void testCannotFindMethod() { doTest(); }
public void testIncompatibleType1() { doTest(); }
public void testIncompatibleType2() { doTest(); }
public void testIncompatibleType3() { doTest(); }
public void testIncompatibleType4() { doTest(); }
public void testIncompatibleType5() { doTest(); }
public void testMissingAttribute() { doTest(); }
public void testDuplicateAnnotation() { doTest(); }
public void testNonConstantInitializer() { doTest(); }
public void testInvalidType() { doTest(); }
public void testInapplicable() { doTest(); }
public void testDuplicateAttribute() { doTest(); }
public void testDuplicateTarget() { doTest(); }
public void testPingPongAnnotationTypesDependencies() { doTest(); }
public void testClashMethods() { doTest(); }
public void testDupMethods() { doTest(); }
public void testPrivateInaccessibleConstant() { doTest(); }
public void testInvalidPackageAnnotationTarget() { doTest(BASE_PATH + "/package-info.java", false, false); }
public void testPackageAnnotationNotInPackageInfo() { doTest(); }
public void testInvalidPackageAnnotationTarget() { doTest(BASE_PATH + "/" + getTestName(true) + "/package-info.java", false, false); }
public void testPackageAnnotationNotInPackageInfo() { doTest(BASE_PATH + "/" + getTestName(true) + "/notPackageInfo.java", false, false); }
public void testTypeAnnotations() { doTest8(); }
public void testRepeatable() { doTest8(); }
public void testEnumValues() { doTest8(); }
public void testReceiverParameters() { doTest8(); }
public void testTypeAnnotations() { doTest8(false); }
public void testRepeatable() { doTest8(false); }
public void testEnumValues() { doTest8(false); }
private void doTest(boolean checkWarnings) {
private void doTest() {
setLanguageLevel(LanguageLevel.JDK_1_7);
doTest(BASE_PATH + "/" + getTestName(true) + ".java", checkWarnings, false);
doTest(BASE_PATH + "/" + getTestName(true) + ".java", false, false);
}
private void doTest8(boolean checkWarnings) {
private void doTest8() {
setLanguageLevel(LanguageLevel.JDK_1_8);
doTest(BASE_PATH + "/" + getTestName(true) + ".java", checkWarnings, false);
doTest(BASE_PATH + "/" + getTestName(true) + ".java", false, false);
}
}
@@ -13,20 +13,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.navigation;
package com.intellij.codeInsight.daemon.impl;
import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.CodeInsightActionHandler;
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
import com.intellij.codeInsight.daemon.LineMarkerInfo;
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl;
import com.intellij.ide.DataManager;
import com.intellij.lang.CodeInsightActions;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.actionSystem.Shortcut;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@@ -38,7 +39,7 @@ public class JavaGotoSuperTest extends LightDaemonAnalyzerTestCase {
return JavaTestUtil.getJavaTestDataPath();
}
protected String getBasePath() {
private static String getBasePath() {
return "/codeInsight/gotosuper/";
}
@@ -46,6 +47,13 @@ public class JavaGotoSuperTest extends LightDaemonAnalyzerTestCase {
doTest();
}
private void doTest() {
configureByFile(getBasePath() + getTestName(false) + ".java");
final CodeInsightActionHandler handler = CodeInsightActions.GOTO_SUPER.forLanguage(JavaLanguage.INSTANCE);
handler.invoke(getProject(), getEditor(), getFile());
checkResultByFile(getBasePath() + getTestName(false) + ".after.java");
}
public void testLambdaMarker() throws Exception {
configureByFile(getBasePath() + getTestName(false) + ".java");
int offset = myEditor.getCaretModel().getOffset();
@@ -67,10 +75,52 @@ public class JavaGotoSuperTest extends LightDaemonAnalyzerTestCase {
fail("Gutter expected");
}
private void doTest() throws Throwable {
configureByFile(getBasePath() + getTestName(false) + ".java");
final CodeInsightActionHandler handler = CodeInsightActions.GOTO_SUPER.forLanguage(JavaLanguage.INSTANCE);
handler.invoke(getProject(), getEditor(), getFile());
checkResultByFile(getBasePath() + getTestName(false) + ".after.java");
public void testSiblingInheritance() throws Throwable {
doTest();
}
public void testSiblingInheritanceLineMarkers() throws Throwable {
configureByFile(getBasePath() + "SiblingInheritance.java");
PsiJavaFile file = (PsiJavaFile)getFile();
PsiClass i = JavaPsiFacade.getInstance(getProject()).findClass("z.I", GlobalSearchScope.fileScope(file));
PsiClass a = JavaPsiFacade.getInstance(getProject()).findClass("z.A", GlobalSearchScope.fileScope(file));
PsiMethod iRun = i.getMethods()[0];
assertEquals("run", iRun.getName());
PsiMethod aRun = a.getMethods()[0];
assertEquals("run", aRun.getName());
doHighlighting();
Document document = getEditor().getDocument();
List<LineMarkerInfo> markers = DaemonCodeAnalyzerImpl.getLineMarkers(document, getProject());
assertTrue(markers.size() >= 2);
LineMarkerInfo iMarker = findMarkerWithElement(markers, iRun.getNameIdentifier());
assertSame(MarkerType.OVERRIDDEN_METHOD.getNavigationHandler(), iMarker.getNavigationHandler());
LineMarkerInfo aMarker = findMarkerWithElement(markers, aRun.getNameIdentifier());
assertSame(MarkerType.OVERRIDING_METHOD.getNavigationHandler(), aMarker.getNavigationHandler());
}
private static LineMarkerInfo findMarkerWithElement(List<LineMarkerInfo> markers, PsiElement psiMethod) {
LineMarkerInfo marker = ContainerUtil.find(markers, info -> {
return info.getElement().equals(psiMethod);
});
assertNotNull(markers.toString(), marker);
return marker;
}
public void testSiblingInheritanceGoDown() throws Throwable {
configureByFile(getBasePath() + "SiblingInheritance.after.java");
AnAction action = ActionManager.getInstance().getAction(IdeActions.ACTION_GOTO_IMPLEMENTATION);
AnActionEvent event = new AnActionEvent(
null,
DataManager.getInstance().getDataContextFromFocus().getResultSync(),
"",
action.getTemplatePresentation(),
ActionManager.getInstance(),
0);
action.update(event);
assertTrue(event.getPresentation().isEnabledAndVisible());
action.actionPerformed(event);
checkResultByFile(getBasePath() + "SiblingInheritance.java");
}
}
@@ -414,6 +414,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
doTest();
}
public void testRawClassTypeOnConstructorReference() throws Exception {
doTest();
}
private void doTest() {
doTest(false);
}
@@ -96,11 +96,11 @@ public class StaticPseudoFunctionalStyleMethodTest extends JavaCodeInsightFixtur
doTest();
}
public void _testTransformLambda() {
public void testTransformLambda() {
doTest();
}
public void _testTransformMethodCalling() {
public void testTransformMethodCalling() {
doTest();
}
@@ -108,6 +108,10 @@ public class StaticPseudoFunctionalStyleMethodTest extends JavaCodeInsightFixtur
doTest();
}
public void testLambdaIsVariable() {
doTest();
}
public void _testReplaceWithMethodReference() {
doTest();
}
@@ -131,7 +131,7 @@ public class RunConfigurableTest extends LightIdeaTestCase {
private void doExpand() {
List<DefaultMutableTreeNode> toExpand = new ArrayList<DefaultMutableTreeNode>();
RunConfigurable.collectNodesRecursively(myRoot, toExpand, FOLDER);
assertEquals(toExpand.size(), 5);
assertEquals(5, toExpand.size());
List<DefaultMutableTreeNode> toExpand2 = new ArrayList<DefaultMutableTreeNode>();
RunConfigurable.collectNodesRecursively(myRoot, toExpand2, CONFIGURATION_TYPE);
toExpand.addAll(toExpand2);
@@ -461,6 +461,10 @@ public class FindManagerTest extends DaemonAnalyzerTestCase {
assertEquals(text+"\n", getEditor().getDocument().getText());
}
public void testReplaceWithRegExp() {
doTestRegexpReplace("# Base", "(?<!^) ", " ", "# Base");
}
private void initProject(String folderName, final String... sourceDirs) {
final String testDir = JavaTestUtil.getJavaTestDataPath() + "/find/" + folderName;
ApplicationManager.getApplication().runWriteAction(() -> {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,6 @@
*/
package com.intellij.lang.java.parser.partial;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.java.parser.JavaParser;
import com.intellij.lang.java.parser.JavaParsingTestCase;
@@ -36,14 +35,7 @@ public class AnnotationParserTest extends JavaParsingTestCase {
public void testParameterizedAnnotation () { doParserTest("@Nullable<T>"); }
public void testFirstNameMissed() { doParserTest("@Anno(value1, param2=value2)"); }
private void doParserTest(final String text) {
doParserTest(text, new MyTestParser());
private void doParserTest(String text) {
doParserTest(text, builder -> JavaParser.INSTANCE.getDeclarationParser().parseAnnotations(builder));
}
private static class MyTestParser implements TestParser {
@Override
public void parse(final PsiBuilder builder) {
JavaParser.INSTANCE.getDeclarationParser().parseAnnotations(builder);
}
}
}
}
@@ -15,7 +15,6 @@
*/
package com.intellij.lang.java.parser.partial;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.java.parser.JavaParser;
import com.intellij.lang.java.parser.JavaParsingTestCase;
@@ -34,19 +33,12 @@ public class DeclarationParserTest extends JavaParsingTestCase {
public void testPines() { doParserTest("{ class A<T extends List<String>> extends List<List<Integer>> { } }"); }
public void testIncompleteAnnotation() { doParserTest("{ public class Foo { public void testSomething(); @Null } }"); }
public void testClassInit() { doParserTest("{ { /*comment*/ } }"); }
public void testAnnoDeclaration() { doParserTest("{ public @interface Annotation {} }"); }
public void testEnumSmartTypeCompletion() { doParserTest("{ @Preliminary(A.B\n#) public class TimeTravel {}\n" +
" @Preliminary(a=A.B\n#) public class TimeTravel {}\n" +
" @Preliminary(a=A.B\n#, b=c) public class TimeTravel {} }"); }
public void testTypeAnno() {
doParserTest("{ class C<@D T extends @F Object> extends @F Object {\n" +
" @F int @F[] method() throws @F Exception {\n" +
" a = this instanceof @F C;\n" +
" C<@F @G C> c = new @Q C<@F C>();\n" +
" c = (@F Object)c;\n" +
" Class c = @TA String.class;\n" +
" @F C.field++;\n" +
" }\n} }");
public void testEnumSmartTypeCompletion() {
doParserTest(
"{ @Preliminary(A.B\n#) public class TimeTravel {}\n" +
" @Preliminary(a=A.B\n#) public class TimeTravel {}\n" +
" @Preliminary(a=A.B\n#, b=c) public class TimeTravel {} }");
}
public void testEnumBody0() { doParserTest("{ ; }", false, true); }
@@ -59,6 +51,7 @@ public class DeclarationParserTest extends JavaParsingTestCase {
public void testEnumWithInitializedConstants() { doParserTest("{ A(10) { },\n B { void method() {} } }", false, true); }
public void testEnumWithoutConstants() { doParserTest("{ private A }", false, true); }
public void testAnnoDeclaration() { doParserTest("{ public @interface Annotation {} }"); }
public void testAnnoSimple() { doParserTest("{ int foo (); }", true, false); }
public void testAnnoDefault() { doParserTest("{ Class foo() default String.class; }", true, false); }
public void testAnnoNested() { doParserTest("{ @interface Inner { String bar () default \"<unspecified>\"; } }", true, false); }
@@ -66,6 +59,27 @@ public class DeclarationParserTest extends JavaParsingTestCase {
public void testAnnoOtherMembers() { doParserTest("{ int field;\n void m() {}\n class C {}\n interface I {} }", true, false); }
public void testAnnoLoop() { doParserTest("{ @@@ int i; }"); }
public void testTypeAnno() {
doParserTest(
"{ class C<@D T extends @F Object> extends @F Object {\n" +
" @F int @F[] method() throws @F Exception {\n" +
" a = this instanceof @F C;\n" +
" C<@F @G C> c = new @Q C<@F C>();\n" +
" c = (@F Object)c;\n" +
" Class c = @TA String.class;\n" +
" @F C.field++;\n" +
" }\n} }");
}
public void testReceiver() {
doParserTest(
"{ void m1(C this);" +
" void m2(T T.this);" +
" void m3(X Y.Z);" +
" T f1 = (T this) -> { };" +
" T f2 = (T T.this) -> { }; }");
}
public void testFieldSimple() { doParserTest("{ int field = 0; }"); }
public void testFieldMulti() { doParserTest("{ int field1 = 0, field2; }"); }
public void testUnclosedBracket() { doParserTest("{ int field[ }"); }
@@ -94,9 +108,13 @@ public class DeclarationParserTest extends JavaParsingTestCase {
public void testConstructorBrackets() { doParserTest("{ A() [] { } }"); }
public void testVarArgBrackets() { doParserTest("{ void foo(int... x[]); }"); }
public void testGenericMethod() { doParserTest("{ public static <E> test();\n" +
" <E> void test1();\n" +
" <E1 extends Integer, E2 extends Runnable> String test2(); }"); }
public void testGenericMethod() {
doParserTest(
"{ public static <E> test();\n" +
" <E> void test1();\n" +
" <E1 extends Integer, E2 extends Runnable> String test2(); }");
}
public void testGenericMethodErrors() { doParserTest("{ <Error sss /> test <error>(); }"); }
public void testErrors() { doParserTest("{ public static <error descr=\"2\">protected int f1 = 0; }"); }
public void testCompletionHack0() { doParserTest("{ <X IntelliJIdeaRulezz>\n String s = \"\"; }"); }
@@ -112,21 +130,6 @@ public class DeclarationParserTest extends JavaParsingTestCase {
}
private void doParserTest(String text, boolean isAnnotation, boolean isEnum) {
doParserTest(text, new MyTestParser(isAnnotation, isEnum));
doParserTest(text, builder -> JavaParser.INSTANCE.getDeclarationParser().parseClassBodyWithBraces(builder, isAnnotation, isEnum));
}
private static class MyTestParser implements TestParser {
private final boolean myAnnotation;
private final boolean myAnEnum;
public MyTestParser(boolean annotation, boolean anEnum) {
myAnnotation = annotation;
myAnEnum = anEnum;
}
@Override
public void parse(PsiBuilder builder) {
JavaParser.INSTANCE.getDeclarationParser().parseClassBodyWithBraces(builder, myAnnotation, myAnEnum);
}
}
}
}
@@ -15,7 +15,6 @@
*/
package com.intellij.lang.java.parser.partial;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.java.parser.JavaParser;
import com.intellij.lang.java.parser.JavaParsingTestCase;
@@ -150,13 +149,6 @@ public class ExpressionParserTest extends JavaParsingTestCase {
public void testAmbiguousLambdaExpression() { doParserTest("f( (x) < y , z > (w) -> v )"); }
private void doParserTest(String text) {
doParserTest(text, new MyTestParser());
doParserTest(text, builder -> JavaParser.INSTANCE.getExpressionParser().parse(builder));
}
private static class MyTestParser implements TestParser {
@Override
public void parse(final PsiBuilder builder) {
JavaParser.INSTANCE.getExpressionParser().parse(builder);
}
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,6 @@
*/
package com.intellij.lang.java.parser.partial;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.java.parser.JavaParser;
import com.intellij.lang.java.parser.JavaParsingTestCase;
@@ -40,14 +39,20 @@ public class FileParserTest extends JavaParsingTestCase {
public void testUnclosedImport2() { doParserTest("import java.awt."); }
public void testUnclosedImport3() { doParserTest("import static a"); }
public void testExtraSemicolons() { doParserTest("package p;;\n" +
"import a;;\n" +
"class C{};"); }
public void testExtraSemicolons() {
doParserTest(
"package p;;\n" +
"import a;;\n" +
"class C{};");
}
public void testFileWithClass() { doParserTest("package a;\n" +
"import b;\n" +
"public class C { }\n" +
"class D { }"); }
public void testFileWithClass() {
doParserTest(
"package a;\n" +
"import b;\n" +
"public class C { }\n" +
"class D { }");
}
public void testBindBefore0() { doParserTest("class A{\n // comment\n int field;\n}"); }
public void testBindBefore1() { doParserTest("class A{\n // comment\n\n int field;\n}"); }
@@ -61,14 +66,7 @@ public class FileParserTest extends JavaParsingTestCase {
public void testBindDocComment3() { doParserTest("class A {\n /** field comment */\n int f;\n}"); }
public void testBindDocComment4() { doParserTest("class A {\n /** field comment */\n// field comment\n int f;\n}"); }
private void doParserTest(final String text) {
doParserTest(text, new MyTestParser());
private void doParserTest(String text) {
doParserTest(text, builder -> JavaParser.INSTANCE.getFileParser().parse(builder));
}
private static class MyTestParser implements TestParser {
@Override
public void parse(final PsiBuilder builder) {
JavaParser.INSTANCE.getFileParser().parse(builder);
}
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,6 @@
*/
package com.intellij.lang.java.parser.partial;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.java.parser.JavaParser;
import com.intellij.lang.java.parser.JavaParsingTestCase;
import com.intellij.lang.java.parser.ReferenceParser;
@@ -56,39 +55,16 @@ public class ReferenceParserTest extends JavaParsingTestCase {
doTypeParamsParserTest("<any T>");
}
private void doRefParserTest(final String text, final boolean incomplete) {
doParserTest(text, new MyTestParser(incomplete));
}
private static class MyTestParser implements TestParser {
private final boolean myIncomplete;
public MyTestParser(boolean incomplete) {
myIncomplete = incomplete;
}
@Override
public void parse(final PsiBuilder builder) {
JavaParser.INSTANCE.getReferenceParser().parseJavaCodeReference(builder, myIncomplete, false, false, false);
}
private void doRefParserTest(String text, boolean incomplete) {
doParserTest(text, builder -> JavaParser.INSTANCE.getReferenceParser().parseJavaCodeReference(builder, incomplete, false, false, false));
}
private void doTypeParserTest(final String text) {
doParserTest(text, new MyTestParser2());
}
private static class MyTestParser2 implements TestParser {
@Override
public void parse(final PsiBuilder builder) {
JavaParser.INSTANCE.getReferenceParser().parseType(builder, ReferenceParser.ELLIPSIS | ReferenceParser.DIAMONDS | ReferenceParser.DISJUNCTIONS);
}
private void doTypeParserTest(String text) {
int flags = ReferenceParser.ELLIPSIS | ReferenceParser.DIAMONDS | ReferenceParser.DISJUNCTIONS;
doParserTest(text, builder -> JavaParser.INSTANCE.getReferenceParser().parseType(builder, flags));
}
private void doTypeParamsParserTest(final String text) {
doParserTest(text, new MyTestParser3());
private void doTypeParamsParserTest(String text) {
doParserTest(text, builder -> JavaParser.INSTANCE.getReferenceParser().parseTypeParameters(builder));
}
private static class MyTestParser3 implements TestParser {
@Override
public void parse(final PsiBuilder builder) {
JavaParser.INSTANCE.getReferenceParser().parseTypeParameters(builder);
}
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,6 @@
*/
package com.intellij.lang.java.parser.partial;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.java.parser.JavaParser;
import com.intellij.lang.java.parser.JavaParsingTestCase;
@@ -148,23 +147,11 @@ public class StatementParserTest extends JavaParsingTestCase {
public void testWhileIncomplete4() { doParserTest("while(cond)"); }
public void testWhileIncomplete5() { doParserTest("while() foo();"); }
private void doBlockParserTest(final String text) {
doParserTest(text, new MyBlockTestParser());
}
private static class MyBlockTestParser implements TestParser {
@Override
public void parse(final PsiBuilder builder) {
JavaParser.INSTANCE.getStatementParser().parseCodeBlockDeep(builder, true);
}
private void doBlockParserTest(String text) {
doParserTest(text, builder -> JavaParser.INSTANCE.getStatementParser().parseCodeBlockDeep(builder, true));
}
private void doParserTest(final String text) {
doParserTest(text, new MyStatementsTestParser());
private void doParserTest(String text) {
doParserTest(text, builder -> JavaParser.INSTANCE.getStatementParser().parseStatements(builder));
}
private static class MyStatementsTestParser implements TestParser {
@Override
public void parse(final PsiBuilder builder) {
JavaParser.INSTANCE.getStatementParser().parseStatements(builder);
}
}
}
}
@@ -371,7 +371,7 @@ public class JavaStubBuilderTest extends LightIdeaTestCase {
"\n" +
"class C<@A T extends @A C> implements @A I<@A T> {\n" +
" @TA T<@A T1, @A ? extends @A T2> f;\n" +
" @TA T m(/*@A C this,*/ @TA int p) throws @A E {\n" +
" @TA T m(@A C this, @TA int p) throws @A E {\n" +
" o.<@A1 C>m();\n" +
" new <T> @A2 C();\n" +
" C.@A3 B v = (@A4 C)v.new @A5 C();\n" +
@@ -27,13 +27,13 @@ import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.cache.CacheManager;
import com.intellij.psi.impl.cache.TodoCacheManager;
import com.intellij.psi.impl.cache.impl.id.IdIndex;
import com.intellij.psi.impl.cache.impl.todo.TodoIndex;
import com.intellij.psi.search.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.TodoAttributesUtil;
import com.intellij.psi.search.TodoPattern;
import com.intellij.psi.search.UsageSearchContext;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.indexing.FileBasedIndex;
import java.io.File;
import java.util.Arrays;
@@ -48,9 +48,6 @@ public class IdCacheTest extends CodeInsightTestCase{
protected void setUp() throws Exception {
super.setUp();
FileBasedIndex.getInstance().requestRebuild(IdIndex.NAME);
FileBasedIndex.getInstance().requestRebuild(TodoIndex.NAME);
String root = JavaTestUtil.getJavaTestDataPath()+ "/psi/impl/cache/";
PsiTestUtil.removeAllRoots(myModule, IdeaTestUtil.getMockJdk17());
@@ -34,7 +34,6 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.JavaPsiFacadeEx;
import com.intellij.psi.impl.PsiManagerImpl;
import com.intellij.psi.impl.cache.impl.id.IdIndex;
import com.intellij.psi.impl.cache.impl.todo.TodoIndex;
import com.intellij.psi.impl.cache.impl.todo.TodoIndexEntry;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageManagerImpl;
@@ -52,15 +51,7 @@ import java.io.File;
import java.util.*;
@PlatformTestCase.WrapInCommand
public class UpdateCacheTest extends PsiTestCase{
@Override
protected void setUp() throws Exception {
super.setUp();
FileBasedIndex.getInstance().requestRebuild(IdIndex.NAME);
FileBasedIndex.getInstance().requestRebuild(TodoIndex.NAME);
}
public class UpdateCacheTest extends PsiTestCase {
@Override
protected void setUpProject() throws Exception {
myProjectManager = ProjectManagerEx.getInstanceEx();
@@ -583,6 +583,10 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
public void testFromLambdaBodyToAnonymous() throws Exception {
doTest();
}
public void testFromLambdaBodyToToplevelInsideCodeBlock() throws Exception {
doTest();
}
public void testFromLambdaBodyWithReturn() throws Exception {
doTest();
+11
View File
@@ -0,0 +1,11 @@
<root>
<item name='org.hamcrest.SelfDescribing void describeTo(org.hamcrest.Description) 0'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='org.hamcrest.TypeSafeDiagnosingMatcher boolean matchesSafely(T, org.hamcrest.Description) 0'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='org.hamcrest.TypeSafeDiagnosingMatcher boolean matchesSafely(T, org.hamcrest.Description) 1'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>
@@ -1,5 +1,6 @@
package org.jetbrains.ide
import com.intellij.testFramework.FixtureRule
import com.intellij.util.Consumer
import com.intellij.util.concurrency.Semaphore
import com.intellij.util.net.NetUtils
@@ -1,19 +1,19 @@
package org.jetbrains.ide
import com.google.gson.stream.JsonWriter
import com.intellij.openapi.vfs.CharsetToolkit
import com.intellij.testFramework.FixtureRule
import io.netty.handler.codec.http.HttpResponseStatus
import org.junit.Rule
import org.junit.Test
import org.junit.rules.RuleChain
import org.hamcrest.CoreMatchers.equalTo
import org.jetbrains.ide.TestManager.TestDescriptor
import org.junit.Assert.assertThat
import java.net.URL
import java.net.HttpURLConnection
import com.google.gson.stream.JsonWriter
import java.io.OutputStreamWriter
import com.intellij.openapi.vfs.CharsetToolkit
import org.junit.Rule
import org.junit.Test
import org.junit.rules.RuleChain
import java.io.BufferedOutputStream
import java.io.OutputStreamWriter
import java.net.HttpURLConnection
import java.net.URL
public class RestApiTest {
private val fixtureManager = FixtureRule()
@@ -1,5 +1,7 @@
package org.jetbrains.ide
import com.intellij.openapi.application.invokeAndWaitIfNeed
import com.intellij.openapi.application.writeAction
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.ModuleRootModificationUtil
import com.intellij.openapi.util.io.FileUtilRt
@@ -63,10 +65,10 @@ class TestManager(val projectFixture: IdeaProjectTestFixture) : TestWatcher() {
}
invokeAndWaitIfNeed {
val normalizedFilePath = FileUtilRt.toSystemIndependentName(filePath)
val normalizedFilePath = FileUtilRt.toSystemIndependentName(filePath!!)
if (annotation!!.relativeToProject) {
val root = projectFixture.getProject().getBaseDir()
runWriteAction {
writeAction {
fileToDelete = root.findOrCreateChildData(this@TestManager, normalizedFilePath)
}
}
@@ -75,7 +77,7 @@ class TestManager(val projectFixture: IdeaProjectTestFixture) : TestWatcher() {
ModuleRootModificationUtil.updateModel(projectFixture.getModule()) { model ->
val contentEntry = model.getContentEntries()[0]
val contentRoot = contentEntry.getFile()!!
runWriteAction {
writeAction {
contentRoot.findChild(EXCLUDED_DIR_NAME)?.delete(this@TestManager)
fileToDelete = contentRoot.createChildDirectory(this@TestManager, EXCLUDED_DIR_NAME)
fileToDelete!!.createChildData(this@TestManager, normalizedFilePath)
@@ -87,7 +89,7 @@ class TestManager(val projectFixture: IdeaProjectTestFixture) : TestWatcher() {
}
else {
val root = ModuleRootManager.getInstance(projectFixture.getModule()).getSourceRoots()[0]
runWriteAction {
writeAction {
fileToDelete = root.findOrCreateChildData(this@TestManager, normalizedFilePath)
}
}
@@ -101,11 +103,11 @@ class TestManager(val projectFixture: IdeaProjectTestFixture) : TestWatcher() {
}
if (fileToDelete != null) {
invokeAndWaitIfNeed { runWriteAction { fileToDelete?.delete(this@TestManager) } }
invokeAndWaitIfNeed { writeAction { fileToDelete?.delete(this@TestManager) } }
fileToDelete = null
}
if (ioFileToDelete != null && !FileUtilRt.delete(ioFileToDelete)) {
if (ioFileToDelete != null && !FileUtilRt.delete(ioFileToDelete!!)) {
ioFileToDelete!!.deleteOnExit()
}
@@ -140,6 +140,7 @@ public interface PsiBuilder extends UserDataHolder, UserDataHolderUnprotected {
*
* @return the new marker instance.
*/
@NotNull
Marker precede();
/**
@@ -160,7 +161,7 @@ public interface PsiBuilder extends UserDataHolder, UserDataHolderUnprotected {
*
* @param type the type of the node in the AST tree.
*/
void done(IElementType type);
void done(@NotNull IElementType type);
/**
* Like {@linkplain #done(IElementType)}, but collapses all tokens between start and end markers
@@ -168,7 +169,7 @@ public interface PsiBuilder extends UserDataHolder, UserDataHolderUnprotected {
*
* @param type the type of the node in the AST tree.
*/
void collapse(IElementType type);
void collapse(@NotNull IElementType type);
/**
* Like {@linkplain #done(IElementType)}, but the marker is completed (end marker inserted)
@@ -178,7 +179,7 @@ public interface PsiBuilder extends UserDataHolder, UserDataHolderUnprotected {
* @param type the type of the node in the AST tree.
* @param before marker to complete this one before.
*/
void doneBefore(IElementType type, Marker before);
void doneBefore(@NotNull IElementType type, @NotNull Marker before);
/**
* Like {@linkplain #doneBefore(IElementType, Marker)}, but in addition an error element with given text
@@ -188,7 +189,7 @@ public interface PsiBuilder extends UserDataHolder, UserDataHolderUnprotected {
* @param before marker to complete this one before.
* @param errorMessage for error element.
*/
void doneBefore(IElementType type, Marker before, String errorMessage);
void doneBefore(@NotNull IElementType type, @NotNull Marker before, String errorMessage);
/**
* Completes this marker and labels it as error element with specified message. Before calling this method,
@@ -204,7 +205,7 @@ public interface PsiBuilder extends UserDataHolder, UserDataHolderUnprotected {
* @param message for error element.
* @param before marker to complete this one before.
*/
void errorBefore(String message, Marker before);
void errorBefore(String message, @NotNull Marker before);
/**
* Allows to define custom edge token binders instead of default ones. If any of parameters is null
@@ -222,6 +223,7 @@ public interface PsiBuilder extends UserDataHolder, UserDataHolderUnprotected {
*
* @return the new marker instance.
*/
@NotNull
Marker mark();
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -38,5 +38,5 @@ public interface PsiParser {
* @return the root of the resulting AST tree.
*/
@NotNull
ASTNode parse(IElementType root, PsiBuilder builder);
ASTNode parse(@NotNull IElementType root, @NotNull PsiBuilder builder);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
package com.intellij.lang;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@@ -31,6 +32,7 @@ public interface WhitespacesAndCommentsBinder {
* Provides an ability for the processor to get a text of any of given tokens.
*/
interface TokenTextGetter {
@NotNull
CharSequence get(int i);
}
@@ -46,8 +46,6 @@ public abstract class SchemesManager<T extends Scheme, E extends ExternalizableS
@Nullable
public abstract T findSchemeByName(@NotNull String schemeName);
public abstract void save();
public abstract void setCurrentSchemeName(@Nullable String schemeName);
@Nullable
@@ -60,6 +58,9 @@ public abstract class SchemesManager<T extends Scheme, E extends ExternalizableS
public abstract File getRootDirectory();
/**
* Must be called before {@link #loadSchemes}
*/
public void loadBundledScheme(@NotNull String resourceName, @NotNull Object requestor, @NotNull ThrowableConvertor<Element, T, Throwable> convertor) {
}
@@ -69,4 +70,11 @@ public abstract class SchemesManager<T extends Scheme, E extends ExternalizableS
public void setSchemes(@NotNull List<T> schemes, @Nullable Condition<T> removeCondition) {
}
/**
* Bundled / read-only (or overriding) scheme cannot be renamed or deleted.
*/
public boolean isMetadataEditable(@NotNull E scheme) {
return true;
}
}
+1
View File
@@ -11,5 +11,6 @@
<orderEntry type="library" name="picocontainer" level="project" />
<orderEntry type="module" module-name="boot" />
<orderEntry type="library" name="Guava" level="project" />
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
</component>
</module>
@@ -196,15 +196,18 @@ public class PluginManagerCore {
if (!plugins.isFile()) {
FileUtil.ensureCanCreateFile(plugins);
}
PrintWriter printWriter = new PrintWriter(new BufferedWriter(new FileWriter(plugins, append)));
writePluginsList(ids, new BufferedWriter(new FileWriter(plugins, append)));
}
public static void writePluginsList(@NotNull Collection<String> ids, @NotNull Writer writer) throws IOException {
try {
for (String id : ids) {
printWriter.println(id);
writer.write(id);
writer.write(LineSeparator.getSystemLineSeparator().getSeparatorString());
}
printWriter.flush();
}
finally {
printWriter.close();
writer.close();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -35,6 +35,7 @@ public abstract class DelegateMarker implements PsiBuilder.Marker {
return myDelegate;
}
@NotNull
@Override
public PsiBuilder.Marker precede() {
return myDelegate.precede();
@@ -51,22 +52,22 @@ public abstract class DelegateMarker implements PsiBuilder.Marker {
}
@Override
public void done(IElementType type) {
public void done(@NotNull IElementType type) {
myDelegate.done(type);
}
@Override
public void collapse(IElementType type) {
public void collapse(@NotNull IElementType type) {
myDelegate.collapse(type);
}
@Override
public void doneBefore(IElementType type, PsiBuilder.Marker before) {
public void doneBefore(@NotNull IElementType type, @NotNull PsiBuilder.Marker before) {
myDelegate.doneBefore(type, before);
}
@Override
public void doneBefore(IElementType type, PsiBuilder.Marker before, String errorMessage) {
public void doneBefore(@NotNull IElementType type, @NotNull PsiBuilder.Marker before, String errorMessage) {
myDelegate.doneBefore(type, before, errorMessage);
}
@@ -76,7 +77,7 @@ public abstract class DelegateMarker implements PsiBuilder.Marker {
}
@Override
public void errorBefore(String message, PsiBuilder.Marker before) {
public void errorBefore(String message, @NotNull PsiBuilder.Marker before) {
myDelegate.errorBefore(message, before);
}
@@ -101,6 +101,7 @@ public class PsiBuilderAdapter implements PsiBuilder {
return myDelegate.getCurrentOffset();
}
@NotNull
@Override
public Marker mark() {
return myDelegate.mark();
@@ -0,0 +1,38 @@
/*
* Copyright 2000-2015 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.application
import javax.swing.SwingUtilities
public inline fun writeAction(runnable: () -> Unit) {
val token = WriteAction.start()
try {
runnable()
}
finally {
token.finish()
}
}
public fun invokeAndWaitIfNeed(runnable: () -> Unit) {
val app = ApplicationManager.getApplication()
if (app == null) {
if (SwingUtilities.isEventDispatchThread()) runnable() else SwingUtilities.invokeAndWait(runnable)
}
else {
if (app.isDispatchThread()) runnable() else app.invokeAndWait(runnable, ModalityState.any())
}
}
@@ -1,705 +0,0 @@
/*
* Copyright 2000-2014 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.editor.impl;
import com.intellij.diagnostic.Dumpable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.impl.ApplicationInfoImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.LocalTimeCounter;
import com.intellij.util.text.CharArrayCharSequence;
import com.intellij.util.text.CharArrayUtil;
import com.intellij.util.text.CharSequenceBackedByArray;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author cdr
*/
abstract class CharArray implements CharSequenceBackedByArray, Dumpable {
private static final boolean CHECK_DOCUMENT_CONSISTENCY = ApplicationManager.getApplication() != null && ApplicationManager.getApplication().isUnitTestMode();
private static final Logger LOG = Logger.getInstance("#" + CharArray.class.getName());
@SuppressWarnings("UseOfArchaicSystemPropertyAccessors")
private static final boolean DISABLE_DEFERRED_PROCESSING = Boolean.getBoolean("idea.document.deny.deferred.changes");
@SuppressWarnings("UseOfArchaicSystemPropertyAccessors")
private static final boolean DEBUG_DEFERRED_PROCESSING = LOG.isDebugEnabled() || Boolean.getBoolean("idea.document.debug.bulk.processing");
/**
* We can't exclude possibility of situation when <code>'defer changes'</code> state is {@link #setDeferredChangeMode(boolean) entered}
* but not exited, hence, we want to perform automatic flushing if necessary in order to avoid memory leaks. This constant holds
* a value that defines that 'automatic flushing' criteria, i.e. every time number of stored deferred changes exceeds this value,
* they are automatically flushed.
*/
private static final int MAX_DEFERRED_CHANGES_NUMBER = 10000;
private final TextChangesStorage myDeferredChangesStorage;
private volatile int myStart; // start offset in myArray (used as an optimization when call substring())
private volatile int myCount;
private volatile CharSequence myOriginalSequence;
private volatile char[] myArray;
private volatile Reference<String> myStringRef; // buffers String value - for not to generate it every time
private volatile int myBufferSize;
private volatile int myDeferredShift;
private volatile boolean myDeferredChangeMode;
private volatile boolean myHasDeferredChanges;
// this lock is for mutual exclusion during read action access
// (some fields are changed in read action too)
private final Object lock = new String("myOriginalSequence");
// We had a problems with bulk document text processing, hence, debug facilities were introduced. The fields group below work with them.
// The main idea is to hold all history of bulk processing iteration in order to be able to retrieve it from client and reproduce the
// problem.
private final boolean myDebug = isDebug();
boolean isDebug() {
return DEBUG_DEFERRED_PROCESSING || CHECK_DOCUMENT_CONSISTENCY && !ApplicationInfoImpl.isInPerformanceTest();
}
/**
* Duplicate instance of the current char array that is used during debug processing as follows - apply every text change
* from the bulk changes group to this instance immediately in order to be able to check if the current 'deferred change-aware'
* instance functionally behaves at the same way as 'straightforward' one.
*/
private CharArray myDebugArray;
/**
* Holds deferred changes create during the current bulk processing iteration.
*/
private List<TextChangeImpl> myDebugDeferredChanges;
/**
* Document text on bulk processing start.
*/
private String myDebugTextOnBatchUpdateStart;
// bufferSize == 0 means unbounded
CharArray(final int bufferSize, @NotNull char[] data, int length) {
myBufferSize = bufferSize;
myDeferredChangesStorage = new TextChangesStorage();
myArray = Arrays.copyOf(data, length);
myCount = length;
if (myDebug) {
myDebugArray = new CharArray(bufferSize, data, length) {
@NotNull
@Override
protected DocumentEvent beforeChangedUpdate(int offset,
CharSequence oldString,
CharSequence newString,
boolean wholeTextReplaced) {
return CharArray.this.beforeChangedUpdate(offset, oldString, newString, wholeTextReplaced);
}
@Override
protected void afterChangedUpdate(@NotNull DocumentEvent event, long newModificationStamp) {
}
@Override
protected void assertWriteAccess() {
}
@Override
protected void assertReadAccess() {
}
@Override
boolean isDebug() {
return false;
}
};
myDebugDeferredChanges = new ArrayList<TextChangeImpl>();
}
assertConsistency();
}
public void setBufferSize(int bufferSize) {
assert bufferSize >= 0 : bufferSize;
myBufferSize = bufferSize;
assertConsistency();
}
private DocumentEvent startChange(int offset,
@Nullable CharSequence oldString,
@Nullable CharSequence newString,
boolean wholeTextReplaced) {
assert myStart == 0; // can't change substring
assertWriteAccess();
assertConsistency();
return beforeChangedUpdate(offset, oldString, newString, wholeTextReplaced);
}
@NotNull
protected abstract DocumentEvent beforeChangedUpdate(int offset,
@Nullable CharSequence oldString,
@Nullable CharSequence newString,
boolean wholeTextReplaced);
protected abstract void afterChangedUpdate(@NotNull DocumentEvent event, long newModificationStamp);
protected abstract void assertWriteAccess();
protected abstract void assertReadAccess();
private void setText(@NotNull CharSequence chars) {
assertConsistency();
myOriginalSequence = chars.toString();
myArray = null;
myStringRef = null;
myCount = chars.length();
assert myStart == 0; // can't change substring
myDeferredChangesStorage.clear();
myHasDeferredChanges = false;
trimToSize();
if (myDebug) {
myDebugArray.setText(chars);
myDebugDeferredChanges.clear();
}
assertConsistency();
}
private void assertConsistency() {
if (isDeferredChangeMode()) {
assert myOriginalSequence == null;
}
CharSequence originalSequence = myOriginalSequence;
int origLen = originalSequence == null ? -1 : originalSequence.length();
String string = com.intellij.reference.SoftReference.dereference(myStringRef);
int stringLen = string == null ? -1 : string.length();
assert origLen == stringLen || origLen==-1 || stringLen==-1;
int count = myCount + myDeferredShift;
assert count == origLen || origLen==-1;
assert count == stringLen || stringLen==-1;
if (!myDebug) return;
final CharSequence seqFromCharArray;
if (myArray != null) {
assert myCount <= myArray.length;
seqFromCharArray = new CharArrayCharSequence(myArray, myStart, myCount);
}
else {
seqFromCharArray = null;
}
if (seqFromCharArray != null && originalSequence != null) {
assert StringUtil.equals(seqFromCharArray, originalSequence);
}
if (!isDeferredChangeMode() && seqFromCharArray != null && string != null) {
assert StringUtil.equals(seqFromCharArray, string);
}
if (originalSequence != null && string != null) {
assert string.equals(originalSequence.toString());
}
myDebugArray.assertConsistency();
CharSequence str = com.intellij.reference.SoftReference.dereference(myStringRef);
if (str == null) {
if (myHasDeferredChanges) {
str = doSubString(0, myCount + myDeferredShift).toString();
}
else if (myOriginalSequence != null) {
str = myOriginalSequence.toString();
}
else {
str = seqFromCharArray;
}
}
assert count == str.length();
if (isDeferredChangeMode()) {
String expected = myDebugArray.toString();
checkStrings("toString()", expected, str);
}
}
public void replace(int startOffset,
int endOffset,
@NotNull CharSequence toDelete,
@NotNull CharSequence newString,
long newModificationStamp,
boolean wholeTextReplaced) {
final DocumentEvent event = startChange(startOffset, toDelete, newString, wholeTextReplaced);
startOffset += myStart;
endOffset += myStart;
doReplace(startOffset, endOffset, newString);
afterChangedUpdate(event, newModificationStamp);
assertConsistency();
}
private void doReplace(int startOffset, int endOffset, @NotNull CharSequence newString) {
prepareForModification();
if (isDeferredChangeMode()) {
storeChange(new TextChangeImpl(newString, startOffset, endOffset));
if (myDebug) {
myDebugArray.doReplace(startOffset, endOffset, newString);
}
}
else {
int newLength = newString.length();
int oldLength = endOffset - startOffset;
CharArrayUtil.getChars(newString, myArray, startOffset, Math.min(newLength, oldLength));
myStringRef = null;
if (newLength > oldLength) {
doInsert(newString.subSequence(oldLength, newLength), endOffset);
}
else if (newLength < oldLength) {
doRemove(startOffset + newLength, startOffset + oldLength);
}
}
}
public void remove(int startIndex, int endIndex, @NotNull CharSequence toDelete) {
DocumentEvent event = startChange(startIndex, toDelete, null, false);
startIndex += myStart;
endIndex += myStart;
doRemove(startIndex, endIndex);
afterChangedUpdate(event, LocalTimeCounter.currentTime());
assertConsistency();
}
private void doRemove(int startIndex, int endIndex) {
if (startIndex == endIndex) {
return;
}
prepareForModification();
if (isDeferredChangeMode()) {
storeChange(new TextChangeImpl("", startIndex, endIndex));
if (myDebug) {
myDebugArray.doRemove(startIndex, endIndex);
}
}
else {
if (endIndex < myCount) {
System.arraycopy(myArray, endIndex, myArray, startIndex, myCount - endIndex);
myStringRef = null;
}
myCount -= endIndex - startIndex;
}
}
public void insert(@NotNull CharSequence s, int startIndex) {
DocumentEvent event = startChange(startIndex, null, s, false);
startIndex += myStart;
doInsert(s, startIndex);
afterChangedUpdate(event, LocalTimeCounter.currentTime());
trimToSize();
assertConsistency();
}
private void doInsert(@NotNull CharSequence s, final int startIndex) {
prepareForModification();
if (isDeferredChangeMode()) {
storeChange(new TextChangeImpl(s, startIndex));
if (myDebug) {
myDebugArray.doInsert(s, startIndex);
}
}
else {
int insertLength = s.length();
myArray = resizeArray(myArray, myCount + insertLength);
if (startIndex < myCount) {
System.arraycopy(myArray, startIndex, myArray, startIndex + insertLength, myCount - startIndex);
}
CharArrayUtil.getChars(s, myArray, startIndex);
myCount += insertLength;
myStringRef = null;
}
}
/**
* Stores given change at collection of deferred changes (merging it with others if necessary) and updates current object
* state ({@link #length() length} etc).
*
* @param change new change to store
*/
private void storeChange(@NotNull TextChangeImpl change) {
if (!change.isWithinBounds(length())) {
LOG.error(
"Invalid change attempt detected - given change bounds are not within the current char array. Change: " +
change.getText().length()+":" + change.getStart()+"-" + change.getEnd(), dumpState());
return;
}
if (myDeferredChangesStorage.size() >= MAX_DEFERRED_CHANGES_NUMBER) {
flushDeferredChanged();
}
myDeferredChangesStorage.store(change);
myHasDeferredChanges = true;
myDeferredShift += change.getDiff();
if (myDebug) {
myDebugDeferredChanges.add(change);
}
}
private void prepareForModification() {
if (myOriginalSequence != null) {
myArray = new char[myOriginalSequence.length()];
CharArrayUtil.getChars(myOriginalSequence, myArray, 0);
myCount = myArray.length;
myOriginalSequence = null;
myStart = 0;
}
myStringRef = null;
assertConsistency();
}
@NotNull
public CharSequence getCharArray() {
assertConsistency();
CharSequence originalSequence = myOriginalSequence;
return originalSequence == null ? this : originalSequence;
}
@Override
@NotNull
public String toString() {
assertConsistency();
String str = com.intellij.reference.SoftReference.dereference(myStringRef);
if (str == null) {
if (myHasDeferredChanges) {
str = substring(0, length()).toString();
}
else {
str = myOriginalSequence == null ? new String(myArray, myStart, myCount) : myOriginalSequence.toString();
}
myStringRef = new SoftReference<String>(str);
}
return str;
}
@Override
public final int length() {
final int result = myCount + myDeferredShift;
if (myDebug && isDeferredChangeMode()) {
int expected = myDebugArray.length();
if (expected != result) {
dumpDebugInfo("Incorrect length() processing. Expected: '" + expected + "', actual: '" + result + "'");
}
}
return result;
}
@Override
public final char charAt(int i) {
if (i < 0 || i >= length()) {
throw new IndexOutOfBoundsException("Wrong offset: " + i + "; count:" + length());
}
i += myStart;
final char result;
if (!myHasDeferredChanges) {
if (myOriginalSequence != null) {
result = myOriginalSequence.charAt(i);
}
else {
result = myArray[i];
}
}
else {
result = myDeferredChangesStorage.charAt(myArray, i);
}
if (myDebug && isDeferredChangeMode()) {
char expected = myDebugArray.charAt(i);
if (expected != result) {
dumpDebugInfo("Incorrect charAt() processing for index " + i + ". Expected: '" + expected + "', actual: '" + result + "'");
}
}
return result;
}
@Override
@NotNull
public CharSequence subSequence(final int start, final int end) {
assertReadAccess();
assertConsistency();
if (start == 0 && end == length()) return this;
if (myOriginalSequence != null) {
return myOriginalSequence.subSequence(start, end);
}
flushDeferredChanged();
return new CharArrayCharSequence(myArray, start, end);
}
@Override
@NotNull
public char[] getChars() {
assertReadAccess();
assertConsistency();
char[] array = myArray;
CharSequence originalSequence = myOriginalSequence;
if (myHasDeferredChanges || originalSequence != null && array == null) {
// slow track
synchronized (lock) {
flushDeferredChanged();
array = myArray;
originalSequence = myOriginalSequence;
if (originalSequence != null && array == null) {
myArray = array = CharArrayUtil.fromSequence(originalSequence);
myStringRef = null;
}
}
assertConsistency();
}
return array;
}
@Override
public void getChars(@NotNull final char[] dst, final int dstOffset) {
assertReadAccess();
assertConsistency();
flushDeferredChanged();
if (myOriginalSequence == null) {
System.arraycopy(myArray, myStart, dst, dstOffset, length());
}
else {
CharArrayUtil.getChars(myOriginalSequence, dst, dstOffset);
}
if (myDebug && isDeferredChangeMode()) {
char[] expected = new char[dst.length];
myDebugArray.getChars(expected, dstOffset);
for (int i = dstOffset, j = myStart; i < dst.length && j < myArray.length; i++, j++) {
if (expected[i] != myArray[j]) {
dumpDebugInfo("getChars(char[], int). Given array of length " + dst.length + ", offset " + dstOffset + ". Found char '" + myArray[j] +
"' at index " + i + ", expected to find '" + expected[i] + "'");
break;
}
}
}
}
@NotNull
public CharSequence substring(final int start, final int end) {
assertReadAccess();
final CharSequence result = doSubString(start, end);
assertConsistency();
return result;
}
private CharSequence doSubString(int start, int end) {
if (start == end) return "";
final CharSequence result;
if (myOriginalSequence == null) {
result = myDeferredChangesStorage.substring(myArray, start + myStart, end + myStart);
}
else {
result = myOriginalSequence.subSequence(start, end);
}
return result;
}
@NotNull
private static char[] resizeArray(@NotNull char[] array, int newSize) {
if (newSize < array.length) {
return array;
}
int newArraySize = array.length;
if (newArraySize == 0) {
newArraySize = 16;
}
while (newArraySize <= newSize) {
newArraySize = newArraySize * 12 / 10 + 1;
}
char[] newArray = new char[newArraySize];
System.arraycopy(array, 0, newArray, 0, array.length);
return newArray;
}
private void trimToSize() {
if (myBufferSize != 0 && length() > myBufferSize) {
flushDeferredChanged();
// make a copy
int endIndex = myCount - myBufferSize;
String toDelete = getCharArray().subSequence(0, endIndex).toString();
remove(0, endIndex, toDelete);
}
}
/**
* @return <code>true</code> if this object is in the defer changes mode, see {@link #setDeferredChangeMode(boolean)};
*/
public boolean isDeferredChangeMode() {
return myDeferredChangeMode;
}
public boolean hasDeferredChanges() {
return myHasDeferredChanges;
}
/**
* There is a possible case that client of this class wants to perform great number of modifications in a short amount of time
* (e.g. end-user performs formatting of the document backed by the object of the current class). It may result in significant
* performance degradation is the changes are performed one by one (every time the change is applied tail content is shifted to
* the left or right). So, we may want to optimize that by avoiding actual array modification until information about
* all target changes is provided and perform array data moves only after that.
* <p/>
* This method allows to define that <code>'defer changes'</code> mode usages, i.e. expected usage pattern is as follows:
* <pre>
* <ol>
* <li>
* Client of this class enters <code>'defer changes'</code> mode (calls this method with <code>'true'</code> argument).
* That means that all subsequent changes will not actually modify backed array data and will be stored separately;
* </li>
* <li>
* Number of target changes are applied to the current object via standard API
* ({@link #insert(CharSequence, int) insert},
* {@link #remove(int, int, CharSequence) remove} and
* {@link #replace(int, int, java.lang.CharSequence, java.lang.CharSequence, long, boolean)});
* </li>
* <li>
* Client of this class indicates that <code>'massive change time'</code> is over by calling this method with <code>'false'</code>
* argument. That flushes all deferred changes (if any) to the backed data array and makes every subsequent change to
* be immediate flushed to the backed array;
* </li>
* </ol>
* </pre>
* <p/>
* <b>Note:</b> we can't exclude possibility that <code>'defer changes'</code> mode is started but inadvertently not ended
* (due to programming error, unexpected exception etc). Hence, this class is free to automatically end
* <code>'defer changes'</code> mode when necessary in order to avoid memory leak with infinite deferred changes storing.
*
* @param deferredChangeMode flag that defines if <code>'defer changes'</code> mode should be used by the current object
*/
public void setDeferredChangeMode(boolean deferredChangeMode) {
if (!DISABLE_DEFERRED_PROCESSING) {
if (deferredChangeMode) {
if (myDebug) {
myDebugArray.setText(myDebugTextOnBatchUpdateStart = toString());
myDebugDeferredChanges.clear();
}
prepareForModification();
}
else {
flushDeferredChanged();
}
myDeferredChangeMode = deferredChangeMode;
}
assertConsistency();
}
private void flushDeferredChanged() {
List<TextChangeImpl> changes = myDeferredChangesStorage.getChanges();
if (changes.isEmpty()) {
return;
}
synchronized (lock) {
char[] beforeMerge = null;
if (myDebug) {
beforeMerge = new char[myArray.length];
System.arraycopy(myArray, 0, beforeMerge, 0, myArray.length);
}
BulkChangesMerger changesMerger = BulkChangesMerger.INSTANCE;
final boolean inPlace;
if (myArray.length < length()) {
myArray = changesMerger.mergeToCharArray(myArray, myCount, changes);
inPlace = false;
}
else {
changesMerger.mergeInPlace(myArray, myCount, changes);
inPlace = true;
}
myCount += myDeferredShift;
myDeferredShift = 0;
myDeferredChangesStorage.clear();
myHasDeferredChanges = false;
myDeferredChangeMode = false;
myStringRef = null;
if (myDebug) {
for (int i = 0, max = length(); i < max; i++) {
if (myArray[i] != myDebugArray.myArray[i]) {
dumpDebugInfo("flushDeferredChanged(). Index " + i + ", expected: '" + myDebugArray.myArray[i]+"', actual '" +
myArray[i]+"'. Text before merge: '" + Arrays.toString(beforeMerge)+"', merge inplace: "+inPlace);
break;
}
}
}
}
assertConsistency();
}
@Override
@NonNls
@NotNull
public String dumpState() {
return "deferred changes mode: " + isDeferredChangeMode()+", length: " + length()+" (data array length: " + myCount+
", deferred shift: " + myDeferredShift+"); view offsets: [" + myStart+"; "+myCount+"]; deferred changes: "+myDeferredChangesStorage;
}
private void checkStrings(@NonNls @NotNull String operation, @NotNull String expected, @NotNull CharSequence actual) {
if (StringUtil.equals(expected, actual)) {
return;
}
for (int i = 0, max = Math.min(expected.length(), actual.length()); i < max; i++) {
if (actual.charAt(i) != expected.charAt(i)) {
dumpDebugInfo(
"Incorrect " +
operation+" processing. Expected length: " +
expected.length()+", actual length: " +
actual.length()+". Unmatched symbol at " +
i+" - expected: '" +
expected.charAt(i)+"', " +
"actual: '" +
actual.charAt(i)+"', expected document: '" +
expected+"', actual document: '" +
actual+"'"
);
return;
}
}
dumpDebugInfo("Incorrect " + operation+" processing. Expected length: " + expected.length()+", actual length: " +
actual.length()+", expected: '" + expected+"', actual: '" + actual+"'");
}
private void dumpDebugInfo(@NonNls @NotNull String problem) {
LOG.error(
"Incorrect CharArray processing detected: " + problem +
". Start: " + myStart
+ ", count: " + myCount + ", text on batch update start: " +
myDebugTextOnBatchUpdateStart + ", deferred changes history: " +
myDebugDeferredChanges + ", current deferred changes: " + myDeferredChangesStorage
);
}
}
@@ -48,10 +48,6 @@ public class EmptySchemesManager extends SchemesManager {
return null;
}
@Override
public void save() {
}
@Override
public void setCurrentSchemeName(String schemeName) {
}
@@ -178,14 +178,15 @@ public class SingleRootFileViewProvider extends UserDataHolderBase implements Fi
psiFile = PsiUtilCore.NULL_PSI_FILE;
}
boolean set = myPsiFile.compareAndSet(null, psiFile);
if (!set) {
if (!set && psiFile != PsiUtilCore.NULL_PSI_FILE) {
PsiFile alreadyCreated = myPsiFile.get();
if (alreadyCreated == psiFile) {
LOG.error(this + ".createFile() must create new file instance but got the same: " + psiFile);
}
if (psiFile instanceof PsiFileImpl) {
if (myPsiFile.get() == psiFile) {
LOG.error(this + ".createFile() must create new file instance but got the same: " + psiFile);
}
((PsiFileImpl)psiFile).markInvalidated();
}
psiFile = myPsiFile.get();
psiFile = alreadyCreated;
}
}
return psiFile == PsiUtilCore.NULL_PSI_FILE ? null : psiFile;
@@ -23,6 +23,7 @@ import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.diff.DiffBundle;
import com.intellij.openapi.project.DefaultProjectFactory;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -57,8 +58,7 @@ public class DiffApplication extends ApplicationStarterBase {
if (file1 == null) throw new Exception("Can't find file " + path1);
if (file2 == null) throw new Exception("Can't find file " + path2);
file1.refresh(false, true);
file2.refresh(false, true);
VfsUtil.markDirtyAndRefresh(false, false, false, file1, file2);
DiffRequest request = DiffRequestFactory.getInstance().createFromFiles(null, file1, file2);
Project project = DefaultProjectFactory.getInstance().getDefaultProject();
@@ -346,8 +346,8 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
EditorHighlighter highlighter2 = DiffUtil.initEditorHighlighter(project, content2, text2);
if (highlighter1 == null && highlighter2 == null) return null;
if (highlighter1 == null) highlighter1 = DiffUtil.initEmptyEditorHighlighter(project, text1);
if (highlighter2 == null) highlighter2 = DiffUtil.initEmptyEditorHighlighter(project, text2);
if (highlighter1 == null) highlighter1 = DiffUtil.initEmptyEditorHighlighter(text1);
if (highlighter2 == null) highlighter2 = DiffUtil.initEmptyEditorHighlighter(text2);
return new UnifiedEditorHighlighter(myDocument, highlighter1, highlighter2, ranges, textLength);
}
@@ -107,7 +107,7 @@ public class DiffUtil {
}
@NotNull
public static EditorHighlighter initEmptyEditorHighlighter(@Nullable Project project, @NotNull CharSequence text) {
public static EditorHighlighter initEmptyEditorHighlighter(@NotNull CharSequence text) {
EditorHighlighter highlighter = createEmptyEditorHighlighter();
highlighter.setText(text);
return highlighter;
@@ -216,10 +216,6 @@ public class DiffUtil {
scrollToCaret(editor, animated);
}
public static void scrollToPoint(@Nullable Editor editor, @NotNull Point point) {
scrollToPoint(editor, point, false);
}
public static void scrollToPoint(@Nullable Editor editor, @NotNull Point point, boolean animated) {
if (editor == null) return;
if (!animated) editor.getScrollingModel().disableAnimation();
@@ -876,14 +872,6 @@ public class DiffUtil {
return holder;
}
public static <T> UserDataHolderBase createUserDataHolder(@NotNull Key<T> key1, @Nullable T value1,
@NotNull Key<T> key2, @Nullable T value2) {
UserDataHolderBase holder = new UserDataHolderBase();
holder.putUserData(key1, value1);
holder.putUserData(key2, value2);
return holder;
}
public static boolean isUserDataFlagSet(@NotNull Key<Boolean> key, UserDataHolder... holders) {
for (UserDataHolder holder : holders) {
if (holder == null) continue;
@@ -1039,9 +1027,5 @@ public class DiffUtil {
this(ignorePolicy.getComparisonPolicy(), highlightPolicy.isFineFragments(), highlightPolicy.isShouldSquash(),
ignorePolicy.isShouldTrimChunks());
}
public DiffConfig() {
this(IgnorePolicy.DEFAULT, HighlightPolicy.BY_LINE);
}
}
}
@@ -26,10 +26,13 @@ import javax.swing.*;
/**
* Interface which should be implemented in order to draw icons in the gutter area and handle events
* for them. Gutter icons are drawn to the left of the folding area and can be used, for example,
* to mark implemented or overridden methods.
* to mark implemented or overridden methods.<p/>
*
* Daemon code analyzer checks newly arrived gutter icon renderer against the old one and if they are equal, does not redraw the icon.
* So it is highly advisable to override hashCode()/equals() methods to avoid icon flickering when old gutter renderer gets replaced with the new.
* So it is highly advisable to override hashCode()/equals() methods to avoid icon flickering when old gutter renderer gets replaced with the new.<p/>
*
* During indexing, click handlers are only invoked for renderers implementing {@link com.intellij.openapi.project.DumbAware}.
*
* @author max
* @see RangeHighlighter#setGutterIconRenderer(GutterIconRenderer)
*/
@@ -312,7 +312,7 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
}
// we failed to run read action in job launcher thread
// run read action in our thread instead to wait for a write action to complete and resume parallel processing
ApplicationManager.getApplication().runReadAction(EmptyRunnable.getInstance());
DumbService.getInstance(myManager.getProject()).runReadActionInSmartMode(EmptyRunnable.getInstance());
files = failedList;
}
return completed;
@@ -347,7 +347,10 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
ApplicationUtil.tryRunReadAction(new Computable<Void>() {
@Override
public Void compute() {
if (myManager.getProject().isDisposed()) throw new ProcessCanceledException();
final Project project = myManager.getProject();
if (project.isDisposed()) throw new ProcessCanceledException();
if (DumbService.isDumb(project)) throw new ApplicationUtil.CannotRunReadActionException();
List<PsiFile> psiRoots = file.getViewProvider().getAllFiles();
Set<PsiFile> processed = new THashSet<PsiFile>(psiRoots.size() * 2, (float)0.5);
for (final PsiFile psiRoot : psiRoots) {
@@ -20,6 +20,7 @@ import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.ShortcutSet;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.event.MouseEvent;
@@ -28,10 +29,10 @@ import java.awt.event.MouseEvent;
* @author Dmitry Avdeev
*/
public class NavigateAction<T extends PsiElement> extends AnAction {
private LineMarkerInfo<T> myInfo;
private final LineMarkerInfo<T> myInfo;
public NavigateAction(String text,
LineMarkerInfo<T> info,
public NavigateAction(@NotNull String text,
@NotNull LineMarkerInfo<T> info,
@Nullable String originalActionId) {
super(text);
myInfo = info;
@@ -41,7 +42,7 @@ public class NavigateAction<T extends PsiElement> extends AnAction {
}
}
public NavigateAction(LineMarkerInfo<T> info) {
public NavigateAction(@NotNull LineMarkerInfo<T> info) {
myInfo = info;
}
@@ -56,7 +57,8 @@ public class NavigateAction<T extends PsiElement> extends AnAction {
}
}
public static <T extends PsiElement> LineMarkerInfo<T> setNavigateAction(LineMarkerInfo<T> info, String text, @Nullable String originalActionId) {
@NotNull
public static <T extends PsiElement> LineMarkerInfo<T> setNavigateAction(@NotNull LineMarkerInfo<T> info, @NotNull String text, @Nullable String originalActionId) {
NavigateAction<T> action = new NavigateAction<T>(text, info, originalActionId);
info.setNavigateAction(action);
return info;
@@ -161,6 +161,20 @@ public interface RunnerAndConfigurationSettings {
*/
boolean isEditBeforeRun();
/**
* Sets the "Before launch: Activate tool window" flag (for activation tool window Run/Debug etc.)
*
* @param b if true, the tool window will be activated before launching this configuration.
*/
void setActivateToolWindowBeforeRun(boolean activate);
/**
* Returns the "Before launch: Activate tool window" flag (for activation tool window Run/Debug etc.)
*
* @return if true (it's default value), the tool window will be activated before launching this configuration.
*/
boolean isActivateToolWindowBeforeRun();
/**
* Sets the "Single instance only" flag (meaning that only one instance of this run configuration can be run at the same time).
*
@@ -16,10 +16,7 @@
package com.intellij.execution.runners;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionResult;
import com.intellij.execution.Executor;
import com.intellij.execution.RunManager;
import com.intellij.execution.*;
import com.intellij.execution.configurations.*;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.options.SettingsEditor;
@@ -72,6 +69,10 @@ abstract class BaseProgramRunner<Settings extends RunnerSettings> implements Pro
static RunContentDescriptor postProcess(@NotNull ExecutionEnvironment environment, @Nullable RunContentDescriptor descriptor, @Nullable Callback callback) {
if (descriptor != null) {
descriptor.setExecutionId(environment.getExecutionId());
RunnerAndConfigurationSettings settings = environment.getRunnerAndConfigurationSettings();
if (settings != null) {
descriptor.setActivateToolWindowWhenAdded(settings.isActivateToolWindowBeforeRun());
}
}
if (callback != null) {
callback.processStarted(descriptor);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -37,6 +37,7 @@ import com.intellij.ui.popup.HintUpdateSupply;
import com.intellij.usages.UsageView;
import com.intellij.util.Consumer;
import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -88,12 +89,12 @@ public class PsiElementListNavigator {
}
@Nullable
public static JBPopup navigateOrCreatePopup(final NavigatablePsiElement[] targets,
public static JBPopup navigateOrCreatePopup(@NotNull final NavigatablePsiElement[] targets,
final String title,
final String findUsagesTitle,
final ListCellRenderer listRenderer,
@Nullable final ListBackgroundUpdaterTask listUpdaterTask,
final Consumer<Object[]> consumer) {
@NotNull final Consumer<Object[]> consumer) {
if (targets.length == 0) return null;
if (targets.length == 1) {
consumer.consume(targets);

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