Merge remote-tracking branch 'origin/master'

This commit is contained in:
Roman Shevchenko
2016-11-23 15:08:24 +01:00
163 changed files with 1462 additions and 930 deletions
+1 -1
View File
@@ -321,6 +321,6 @@ class TeamCityBuildLocator {
String getDownloadUrl(String buildNumber) {
String encodedBuildNumber = URLEncoder.encode(buildNumber, "UTF-8")
return "$host/guestAuth/repository/download/$buildTypeId/$encodedBuildNumber/kotlin-plugin-${encodedBuildNumber}-IJ2016.3-1.zip"
return "$host/guestAuth/repository/download/$buildTypeId/$encodedBuildNumber/kotlin-plugin-1.0.5-release-IJ2016.3-2.zip"
}
}
@@ -139,7 +139,7 @@ public class JavaParametersUtil {
parameters.configureByProject(project, classPathType, createProjectJdk(project, jreHome));
}
private static Sdk createModuleJdk(final Module module, boolean productionOnly, @Nullable String jreHome) throws CantRunException {
public static Sdk createModuleJdk(final Module module, boolean productionOnly, @Nullable String jreHome) throws CantRunException {
return jreHome == null ? JavaParameters.getValidJdkToRunModule(module, productionOnly) : createAlternativeJdk(jreHome);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@ import com.intellij.codeInsight.editorActions.DeclarationJoinLinesHandler;
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
import com.intellij.codeInspection.RemoveInitializerFix;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
@@ -100,6 +101,11 @@ public class JoinDeclarationAndAssignmentAction extends PsiElementBaseIntentionA
return null;
}
@Override
public boolean startInWriteAction() {
return false;
}
@Override
public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return;
@@ -112,8 +118,10 @@ public class JoinDeclarationAndAssignmentAction extends PsiElementBaseIntentionA
if (initializer != null && assignmentExpression.getOperationTokenType() == JavaTokenType.EQ) {
RemoveInitializerFix.sideEffectAwareRemove(project, initializer, initializer, variable);
}
final PsiExpression initializerExpression = DeclarationJoinLinesHandler.getInitializerExpression(variable, assignmentExpression);
variable.setInitializer(initializerExpression);
assignmentExpression.delete();
WriteAction.run(() -> {
final PsiExpression initializerExpression = DeclarationJoinLinesHandler.getInitializerExpression(variable, assignmentExpression);
variable.setInitializer(initializerExpression);
assignmentExpression.delete();
});
}
}
@@ -17,6 +17,7 @@ package com.intellij.codeInspection;
import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.PsiEquivalenceUtil;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil;
import com.intellij.codeInspection.util.LambdaGenerationUtil;
import com.intellij.codeInspection.util.OptionalUtil;
@@ -33,10 +34,9 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.psi.util.PsiUtil;
import com.siyeh.ig.psiutils.BoolUtils;
import com.siyeh.ig.psiutils.CommentTracker;
import com.siyeh.ig.psiutils.ControlFlowUtils;
import com.siyeh.ig.psiutils.EquivalenceChecker;
import com.siyeh.ig.psiutils.ExpressionUtils;
import one.util.streamex.StreamEx;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -55,6 +55,18 @@ public class OptionalIsPresentInspection extends BaseJavaBatchLocalInspectionToo
new TernaryCase()
};
private enum ProblemType {
WARNING, INFO, NONE;
void registerProblem(ProblemsHolder holder, PsiExpression condition, OptionalIfPresentCase scenario) {
if(this != NONE) {
holder.registerProblem(condition, "Can be replaced with single expression in functional style",
this == INFO ? ProblemHighlightType.INFORMATION : ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
new OptionalIfPresentFix(scenario));
}
}
}
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
@@ -100,10 +112,7 @@ public class OptionalIsPresentInspection extends BaseJavaBatchLocalInspectionToo
void check(PsiExpression condition, PsiVariable optionalVariable, PsiElement thenElement, PsiElement elseElement) {
for (OptionalIfPresentCase scenario : CASES) {
if (scenario.isApplicable(optionalVariable, thenElement, elseElement)) {
holder.registerProblem(condition, "Can be replaced with single expression in functional style",
new OptionalIfPresentFix(scenario));
}
scenario.getProblemType(optionalVariable, thenElement, elseElement).registerProblem(holder, condition, scenario);
}
}
};
@@ -162,13 +171,16 @@ public class OptionalIsPresentInspection extends BaseJavaBatchLocalInspectionToo
ExpressionUtils.isReferenceTo(methodExpression.getQualifierExpression(), variable);
}
@Contract("_, null, _ -> false")
static boolean isOptionalLambdaCandidate(PsiVariable optionalVariable, PsiExpression lambdaCandidate, PsiExpression falseExpression) {
if (lambdaCandidate == null) return false;
if (ExpressionUtils.isReferenceTo(lambdaCandidate, optionalVariable) && OptionalUtil.isOptionalEmptyCall(falseExpression)) return true;
if (!ExceptionUtil.getThrownCheckedExceptions(lambdaCandidate).isEmpty()) return false;
@NotNull
static ProblemType getTypeByLambdaCandidate(PsiVariable optionalVariable, PsiElement lambdaCandidate, PsiExpression falseExpression) {
if (lambdaCandidate == null) return ProblemType.NONE;
if (lambdaCandidate instanceof PsiReferenceExpression &&
((PsiReferenceExpression)lambdaCandidate).isReferenceTo(optionalVariable) && OptionalUtil.isOptionalEmptyCall(falseExpression)) {
return ProblemType.WARNING;
}
if (!ExceptionUtil.getThrownCheckedExceptions(lambdaCandidate).isEmpty()) return ProblemType.NONE;
Ref<Boolean> hasOptionalReference = new Ref<>(Boolean.FALSE);
return PsiTreeUtil.processElements(lambdaCandidate, e -> {
boolean hasNoBadRefs = PsiTreeUtil.processElements(lambdaCandidate, e -> {
if (!(e instanceof PsiReferenceExpression)) return true;
PsiElement element = ((PsiReferenceExpression)e).resolve();
if (!(element instanceof PsiVariable)) return true;
@@ -178,11 +190,14 @@ public class OptionalIsPresentInspection extends BaseJavaBatchLocalInspectionToo
return isOptionalGetCall(e.getParent().getParent(), optionalVariable);
}
return HighlightControlFlowUtil.isEffectivelyFinal((PsiVariable)element, lambdaCandidate, null);
}) && hasOptionalReference.get();
});
if(!hasNoBadRefs) return ProblemType.NONE;
if(hasOptionalReference.get() && lambdaCandidate instanceof PsiExpression) return ProblemType.WARNING;
return ProblemType.INFO;
}
@NotNull
static String generateOptionalLambda(PsiElementFactory factory, PsiVariable optionalVariable, PsiExpression trueValue) {
static String generateOptionalLambda(PsiElementFactory factory, CommentTracker ct, PsiVariable optionalVariable, PsiElement trueValue) {
PsiType type = optionalVariable.getType();
JavaCodeStyleManager javaCodeStyleManager = JavaCodeStyleManager.getInstance(trueValue.getProject());
SuggestedNameInfo info = javaCodeStyleManager.suggestVariableName(VariableKind.PARAMETER, null, null, type);
@@ -190,16 +205,23 @@ public class OptionalIsPresentInspection extends BaseJavaBatchLocalInspectionToo
info = javaCodeStyleManager.suggestVariableName(VariableKind.PARAMETER, "value", null, type);
}
String paramName = javaCodeStyleManager.suggestUniqueVariableName(info, trueValue, true).names[0];
if(trueValue instanceof PsiExpressionStatement) {
trueValue = ((PsiExpressionStatement)trueValue).getExpression();
}
ct.markUnchanged(trueValue);
PsiElement copy = trueValue.copy();
for (PsiElement getCall : PsiTreeUtil.collectElements(copy, e -> isOptionalGetCall(e, optionalVariable))) {
PsiElement result = getCall.replace(factory.createIdentifier(paramName));
if (copy == getCall) copy = result;
}
if(copy instanceof PsiStatement && !(copy instanceof PsiBlockStatement)) {
return paramName + "->{" + copy.getText()+"}";
}
return paramName + "->" + copy.getText();
}
static String generateOptionalUnwrap(PsiElementFactory factory,
PsiVariable optionalVariable,
CommentTracker ct, PsiVariable optionalVariable,
PsiExpression trueValue,
PsiExpression falseValue,
PsiType targetType) {
@@ -210,10 +232,14 @@ public class OptionalIsPresentInspection extends BaseJavaBatchLocalInspectionToo
if (ExpressionUtils.isReferenceTo(falseValue, optionalVariable)) {
falseValue = factory.createExpressionFromText(CommonClassNames.JAVA_UTIL_OPTIONAL + ".empty()", falseValue);
}
String lambdaText = generateOptionalLambda(factory, optionalVariable, trueValue);
String lambdaText = generateOptionalLambda(factory, ct, optionalVariable, trueValue);
PsiLambdaExpression lambda = (PsiLambdaExpression)factory.createExpressionFromText(lambdaText, trueValue);
return OptionalUtil.generateOptionalUnwrap(optionalVariable.getName(), lambda.getParameterList().getParameters()[0],
(PsiExpression)lambda.getBody(), falseValue, targetType, true);
(PsiExpression)lambda.getBody(), ct.markUnchanged(falseValue), targetType, true);
}
static boolean isSimpleOrUnchecked(PsiExpression expression) {
return ExpressionUtils.isSimpleExpression(expression) || LambdaGenerationUtil.canBeUncheckedLambda(expression);
}
static class OptionalIfPresentFix implements LocalQuickFix {
@@ -252,24 +278,17 @@ public class OptionalIsPresentInspection extends BaseJavaBatchLocalInspectionToo
thenElement = invert ? ((PsiConditionalExpression)cond).getElseExpression() : ((PsiConditionalExpression)cond).getThenExpression();
elseElement = invert ? ((PsiConditionalExpression)cond).getThenExpression() : ((PsiConditionalExpression)cond).getElseExpression();
} else return;
if (!myScenario.isApplicable(optionalVariable, thenElement, elseElement)) return;
if (myScenario.getProblemType(optionalVariable, thenElement, elseElement) == ProblemType.NONE) return;
if (!FileModificationService.getInstance().preparePsiElementForWrite(element.getContainingFile())) return;
PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
PsiElement parent = cond.getParent();
StreamEx.of(cond, thenElement, elseElement).nonNull()
.flatCollection(st -> PsiTreeUtil.findChildrenOfType(st, PsiComment.class))
.distinct()
.forEach(comment -> {
parent.addBefore(comment, cond);
comment.delete();
});
String replacementText = myScenario.generateReplacement(factory, optionalVariable, thenElement, elseElement);
if (thenElement != null && !PsiTreeUtil.isAncestor(cond, thenElement, true)) thenElement.delete();
if (elseElement != null && !PsiTreeUtil.isAncestor(cond, elseElement, true)) elseElement.delete();
CommentTracker ct = new CommentTracker();
String replacementText = myScenario.generateReplacement(factory, ct, optionalVariable, thenElement, elseElement);
if (thenElement != null && !PsiTreeUtil.isAncestor(cond, thenElement, true)) ct.delete(thenElement);
if (elseElement != null && !PsiTreeUtil.isAncestor(cond, elseElement, true)) ct.delete(elseElement);
PsiElement replacement = cond instanceof PsiExpression ?
factory.createExpressionFromText(replacementText, cond) :
factory.createStatementFromText(replacementText, cond);
PsiElement result = cond.replace(replacement);
PsiElement result = ct.replaceAndRestoreComments(cond, replacement);
LambdaCanBeMethodReferenceInspection.replaceAllLambdasWithMethodReferences(result);
PsiDiamondTypeUtil.removeRedundantTypeArguments(result);
CodeStyleManager.getInstance(project).reformat(result);
@@ -277,28 +296,27 @@ public class OptionalIsPresentInspection extends BaseJavaBatchLocalInspectionToo
}
interface OptionalIfPresentCase {
boolean isApplicable(PsiVariable optionalVariable, PsiElement trueElement, PsiElement falseElement);
ProblemType getProblemType(PsiVariable optionalVariable, PsiElement trueElement, PsiElement falseElement);
String generateReplacement(PsiElementFactory factory,
PsiVariable optionalVariable,
CommentTracker ct, PsiVariable optionalVariable,
PsiElement trueElement,
PsiElement falseElement);
}
static class ReturnCase implements OptionalIfPresentCase {
@Override
public boolean isApplicable(PsiVariable optionalVariable, PsiElement trueElement, PsiElement falseElement) {
if (!(trueElement instanceof PsiReturnStatement) || !(falseElement instanceof PsiReturnStatement)) return false;
public ProblemType getProblemType(PsiVariable optionalVariable, PsiElement trueElement, PsiElement falseElement) {
if (!(trueElement instanceof PsiReturnStatement) || !(falseElement instanceof PsiReturnStatement)) return ProblemType.NONE;
PsiExpression falseValue = ((PsiReturnStatement)falseElement).getReturnValue();
if (!ExpressionUtils.isSimpleExpression(falseValue) &&
!LambdaGenerationUtil.canBeUncheckedLambda(falseValue)) return false;
PsiExpression trueValue = ((PsiReturnStatement)trueElement).getReturnValue();
return isOptionalLambdaCandidate(optionalVariable, trueValue, falseValue);
if (!isSimpleOrUnchecked(falseValue)) return ProblemType.NONE;
return getTypeByLambdaCandidate(optionalVariable, trueValue, falseValue);
}
@Override
public String generateReplacement(PsiElementFactory factory,
PsiVariable optionalVariable,
CommentTracker ct, PsiVariable optionalVariable,
PsiElement trueElement,
PsiElement falseElement) {
PsiExpression trueValue = ((PsiReturnStatement)trueElement).getReturnValue();
@@ -306,30 +324,29 @@ public class OptionalIsPresentInspection extends BaseJavaBatchLocalInspectionToo
LOG.assertTrue(trueValue != null);
LOG.assertTrue(falseValue != null);
return "return " +
generateOptionalUnwrap(factory, optionalVariable, trueValue, falseValue, PsiTypesUtil.getMethodReturnType(trueElement)) +
generateOptionalUnwrap(factory, ct, optionalVariable, trueValue, falseValue, PsiTypesUtil.getMethodReturnType(trueElement)) +
";";
}
}
static class AssignmentCase implements OptionalIfPresentCase {
@Override
public boolean isApplicable(PsiVariable optionalVariable, PsiElement trueElement, PsiElement falseElement) {
public ProblemType getProblemType(PsiVariable optionalVariable, PsiElement trueElement, PsiElement falseElement) {
PsiAssignmentExpression trueAssignment = ExpressionUtils.getAssignment(trueElement);
PsiAssignmentExpression falseAssignment = ExpressionUtils.getAssignment(falseElement);
if (trueAssignment == null ||
falseAssignment == null ||
!EquivalenceChecker.getCanonicalPsiEquivalence()
.expressionsAreEquivalent(trueAssignment.getLExpression(), falseAssignment.getLExpression()) ||
!isOptionalLambdaCandidate(optionalVariable, trueAssignment.getRExpression(), falseAssignment.getRExpression())) {
return false;
if (trueAssignment == null || falseAssignment == null) return ProblemType.NONE;
PsiExpression falseVal = falseAssignment.getRExpression();
PsiExpression trueVal = trueAssignment.getRExpression();
if (PsiEquivalenceUtil.areElementsEquivalent(trueAssignment.getLExpression(), falseAssignment.getLExpression()) &&
isSimpleOrUnchecked(falseVal)) {
return getTypeByLambdaCandidate(optionalVariable, trueVal, falseVal);
}
return ExpressionUtils.isSimpleExpression(falseAssignment.getRExpression()) ||
LambdaGenerationUtil.canBeUncheckedLambda(falseAssignment.getRExpression());
return ProblemType.NONE;
}
@Override
public String generateReplacement(PsiElementFactory factory,
PsiVariable optionalVariable,
CommentTracker ct, PsiVariable optionalVariable,
PsiElement trueElement,
PsiElement falseElement) {
PsiAssignmentExpression trueAssignment = ExpressionUtils.getAssignment(trueElement);
@@ -340,49 +357,51 @@ public class OptionalIsPresentInspection extends BaseJavaBatchLocalInspectionToo
PsiExpression trueValue = trueAssignment.getRExpression();
PsiExpression falseValue = falseAssignment.getRExpression();
LOG.assertTrue(falseValue != null);
return lValue.getText() + " = " + generateOptionalUnwrap(factory, optionalVariable, trueValue, falseValue, lValue.getType()) + ";";
return lValue.getText() + " = " + generateOptionalUnwrap(factory, ct, optionalVariable, trueValue, falseValue, lValue.getType()) + ";";
}
}
static class TernaryCase implements OptionalIfPresentCase {
@Override
public boolean isApplicable(PsiVariable optionalVariable, PsiElement trueElement, PsiElement falseElement) {
if(!(trueElement instanceof PsiExpression) || !(falseElement instanceof PsiExpression)) return false;
public ProblemType getProblemType(PsiVariable optionalVariable, PsiElement trueElement, PsiElement falseElement) {
if(!(trueElement instanceof PsiExpression) || !(falseElement instanceof PsiExpression)) return ProblemType.NONE;
PsiExpression trueExpression = (PsiExpression)trueElement;
PsiExpression falseExpression = (PsiExpression)falseElement;
return isOptionalLambdaCandidate(optionalVariable, trueExpression, falseExpression) &&
(ExpressionUtils.isSimpleExpression(falseExpression) || LambdaGenerationUtil.canBeUncheckedLambda(falseExpression));
return (isSimpleOrUnchecked(falseExpression)) ?
getTypeByLambdaCandidate(optionalVariable, trueExpression, falseExpression) : ProblemType.NONE;
}
@Override
public String generateReplacement(PsiElementFactory factory,
PsiVariable optionalVariable,
CommentTracker ct, PsiVariable optionalVariable,
PsiElement trueElement,
PsiElement falseElement) {
PsiExpression ternary = PsiTreeUtil.getParentOfType(trueElement, PsiConditionalExpression.class);
LOG.assertTrue(ternary != null);
PsiExpression trueExpression = (PsiExpression)trueElement;
PsiExpression falseExpression = (PsiExpression)falseElement;
return generateOptionalUnwrap(factory, optionalVariable, trueExpression, falseExpression, ternary.getType());
return generateOptionalUnwrap(factory, ct, optionalVariable, trueExpression, falseExpression, ternary.getType());
}
}
static class ConsumerCase implements OptionalIfPresentCase {
@Override
public boolean isApplicable(PsiVariable optionalVariable, PsiElement trueElement, PsiElement falseElement) {
if (falseElement != null && !(falseElement instanceof PsiEmptyStatement)) return false;
if (!(trueElement instanceof PsiExpressionStatement)) return false;
PsiExpression expression = ((PsiExpressionStatement)trueElement).getExpression();
return isOptionalLambdaCandidate(optionalVariable, expression, null) && !isOptionalGetCall(expression, optionalVariable);
public ProblemType getProblemType(PsiVariable optionalVariable, PsiElement trueElement, PsiElement falseElement) {
if (falseElement != null && !(falseElement instanceof PsiEmptyStatement)) return ProblemType.NONE;
if (trueElement instanceof PsiExpressionStatement) {
PsiExpression expression = ((PsiExpressionStatement)trueElement).getExpression();
if(isOptionalGetCall(expression, optionalVariable)) return ProblemType.NONE;
trueElement = expression;
}
return getTypeByLambdaCandidate(optionalVariable, trueElement, null);
}
@Override
public String generateReplacement(PsiElementFactory factory,
PsiVariable optionalVariable,
CommentTracker ct, PsiVariable optionalVariable,
PsiElement trueElement,
PsiElement falseElement) {
PsiExpression expression = ((PsiExpressionStatement)trueElement).getExpression();
return optionalVariable.getName() + ".ifPresent(" + generateOptionalLambda(factory, optionalVariable, expression) + ");";
return optionalVariable.getName() + ".ifPresent(" + generateOptionalLambda(factory, ct, optionalVariable, trueElement) + ");";
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@ package com.intellij.codeInspection;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.editorActions.DeclarationJoinLinesHandler;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
@@ -49,11 +50,14 @@ public class RemoveAssignmentFix extends RemoveInitializerFix {
final PsiElement gParent = parent.getParent();
if ((gParent instanceof PsiExpression || gParent instanceof PsiExpressionList || gParent instanceof PsiReturnStatement) && rExpression != null) {
if (!FileModificationService.getInstance().prepareFileForWrite(gParent.getContainingFile())) return;
if (gParent instanceof PsiParenthesizedExpression) {
gParent.replace(rExpression);
} else {
parent.replace(rExpression);
}
PsiExpression finalRExpr = rExpression;
WriteAction.run(() -> {
if (gParent instanceof PsiParenthesizedExpression) {
gParent.replace(finalRExpr);
} else {
parent.replace(finalRExpr);
}
});
return;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,14 +18,13 @@ package com.intellij.codeInspection;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.daemon.impl.quickfix.RemoveUnusedVariableFix;
import com.intellij.codeInsight.daemon.impl.quickfix.RemoveUnusedVariableUtil;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiExpressionTrimRenderer;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
@@ -50,6 +49,11 @@ public class RemoveInitializerFix implements LocalQuickFix {
sideEffectAwareRemove(project, (PsiExpression)psiInitializer, psiInitializer, variable);
}
@Override
public boolean startInWriteAction() {
return false;
}
public static void sideEffectAwareRemove(Project project,
PsiExpression psiInitializer,
PsiElement elementToDelete,
@@ -59,7 +63,7 @@ public class RemoveInitializerFix implements LocalQuickFix {
final PsiElement declaration = variable.getParent();
final List<PsiElement> sideEffects = new ArrayList<>();
boolean hasSideEffects = RemoveUnusedVariableUtil.checkSideEffects(psiInitializer, variable, sideEffects);
RemoveUnusedVariableUtil.RemoveMode res = RemoveUnusedVariableUtil.RemoveMode.DELETE_ALL;
RemoveUnusedVariableUtil.RemoveMode res;
if (hasSideEffects) {
hasSideEffects = PsiUtil.isStatement(psiInitializer);
PsiTypeElement typeElement = variable.getTypeElement();
@@ -71,7 +75,10 @@ public class RemoveInitializerFix implements LocalQuickFix {
PsiExpressionTrimRenderer.render(psiInitializer)
);
}
try {
else {
res = RemoveUnusedVariableUtil.RemoveMode.DELETE_ALL;
}
WriteAction.run(() -> {
if (res == RemoveUnusedVariableUtil.RemoveMode.DELETE_ALL) {
elementToDelete.delete();
}
@@ -81,14 +88,12 @@ public class RemoveInitializerFix implements LocalQuickFix {
final PsiElement parent = elementToDelete.getParent();
if (parent instanceof PsiExpressionStatement) {
parent.replace(statementFromText);
} else {
}
else {
declaration.getParent().addBefore(statementFromText, declaration);
elementToDelete.delete();
}
}
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
});
}
}
@@ -29,8 +29,11 @@ import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
* @author peter
@@ -83,8 +86,7 @@ public class ReferenceChainLink {
List<PsiMember> candidates = new ArrayList<>();
AtomicInteger count = new AtomicInteger();
Processor<PsiMember> processor = member -> {
if (canBeAccessible(placeFile, member) && (!(member instanceof PsiMethod) ||
ApproximateResolver.canHaveArgCount((PsiMethod)member, argCount))) {
if (!(member instanceof PsiMethod && !ApproximateResolver.canHaveArgCount((PsiMethod)member, argCount))) {
candidates.add(member);
}
return count.incrementAndGet() < 42;
@@ -112,7 +114,7 @@ public class ReferenceChainLink {
return null;
}
return candidates;
return candidates.stream().filter(candidate -> canBeAccessible(placeFile, candidate)).collect(Collectors.toList());
}
private static boolean canBeAccessible(VirtualFile placeFile, PsiMember member) {
@@ -16,6 +16,9 @@
package com.intellij.psi.impl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.ExtensionPoint;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.extensions.SimpleSmartExtensionPoint;
import com.intellij.openapi.progress.ProgressIndicatorProvider;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
@@ -48,7 +51,7 @@ import java.util.concurrent.ConcurrentMap;
public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
private static final Logger LOG = Logger.getInstance(JavaPsiFacadeImpl.class);
private final PsiElementFinder[] myElementFinders;
private final SimpleSmartExtensionPoint<PsiElementFinder> myElementFinders;
private final PsiConstantEvaluationHelper myConstantEvaluationHelper;
private final ConcurrentMap<String, PsiPackage> myPackageCache = ContainerUtil.createConcurrentSoftValueMap();
private final ConcurrentMap<GlobalSearchScope, Map<String, PsiClass>> myClassCache = ContainerUtil.createConcurrentWeakKeySoftValueMap();
@@ -82,7 +85,13 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
}
DummyHolderFactory.setFactory(new JavaDummyHolderFactory());
myElementFinders = calcFinders();
myElementFinders = new SimpleSmartExtensionPoint<PsiElementFinder>(Collections.<PsiElementFinder>emptyList()) {
@NotNull
@Override
protected ExtensionPoint<PsiElementFinder> getExtensionPoint() {
return Extensions.getArea(myProject).getExtensionPoint(PsiElementFinder.EP_NAME);
}
};
}
@Override
@@ -115,7 +124,7 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
return null;
}
PsiElementFinder[] finders = finders();
List<PsiElementFinder> finders = finders();
Condition<PsiClass> classesFilter = getFilterFromFinders(scope, finders);
for (PsiElementFinder finder : finders) {
@@ -156,7 +165,7 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
return findClassesInDumbMode(qualifiedName, scope);
}
PsiElementFinder[] finders = finders();
List<PsiElementFinder> finders = finders();
Condition<PsiClass> classesFilter = getFilterFromFinders(scope, finders);
List<PsiClass> result = null;
@@ -171,7 +180,7 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
return result == null || result.isEmpty() ? PsiClass.EMPTY_ARRAY : result.toArray(new PsiClass[result.size()]);
}
private static Condition<PsiClass> getFilterFromFinders(@NotNull GlobalSearchScope scope, @NotNull PsiElementFinder[] finders) {
private static Condition<PsiClass> getFilterFromFinders(@NotNull GlobalSearchScope scope, @NotNull List<PsiElementFinder> finders) {
Condition<PsiClass> filter = null;
for (PsiElementFinder finder : finders) {
Condition<PsiClass> finderFilter = finder.getClassesFilter(scope);
@@ -187,13 +196,8 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
return dumbService.isDumb() && dumbService.isAlternativeResolveEnabled();
}
private PsiElementFinder[] finders() {
return myElementFinders;
}
@NotNull
protected PsiElementFinder[] calcFinders() {
return myProject.getExtensions(PsiElementFinder.EP_NAME);
private List<PsiElementFinder> finders() {
return myElementFinders.getExtensions();
}
@Override
@@ -220,14 +224,8 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
}
@NotNull
private PsiElementFinder[] filteredFinders() {
DumbService dumbService = DumbService.getInstance(getProject());
PsiElementFinder[] finders = finders();
if (dumbService.isDumb()) {
List<PsiElementFinder> list = dumbService.filterByDumbAwareness(finders);
finders = list.toArray(new PsiElementFinder[list.size()]);
}
return finders;
private List<PsiElementFinder> filteredFinders() {
return DumbService.getInstance(getProject()).filterByDumbAwareness(finders());
}
@Override
@@ -259,7 +257,7 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
@NotNull
public PsiClass[] getClasses(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
PsiElementFinder[] finders = filteredFinders();
List<PsiElementFinder> finders = filteredFinders();
Condition<PsiClass> classesFilter = getFilterFromFinders(scope, finders);
List<PsiClass> result = null;
@@ -35,10 +35,7 @@ import com.intellij.psi.impl.java.stubs.PsiJavaFileStub;
import com.intellij.psi.impl.source.resolve.ClassResolverProcessor;
import com.intellij.psi.impl.source.resolve.SymbolCollectingProcessor;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.scope.ElementClassHint;
import com.intellij.psi.scope.JavaScopeProcessorEvent;
import com.intellij.psi.scope.NameHint;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.scope.*;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.*;
@@ -348,11 +345,7 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava
// check in current package
final PsiPackage aPackage = JavaPsiFacade.getInstance(myManager.getProject()).findPackage(getPackageName());
if (aPackage != null) {
if (!aPackage.processDeclarations(processor, state, null, place)) {
return false;
}
}
if (aPackage != null && !processPackageDeclarations(processor, state, place, aPackage)) return false;
// on-demand processing
for (PsiImportStatement statement : importStatements) {
@@ -414,6 +407,31 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava
return true;
}
private static boolean processPackageDeclarations(PsiScopeProcessor processor,
@NotNull ResolveState state,
PsiElement place,
@NotNull PsiPackage aPackage) {
if (!aPackage.getQualifiedName().isEmpty()) {
processor = new DelegatingScopeProcessor(processor) {
@Nullable
@Override
public <T> T getHint(@NotNull Key<T> hintKey) {
if (hintKey == ElementClassHint.KEY) {
//noinspection unchecked
return (T)new ElementClassHint() {
@Override
public boolean shouldProcess(DeclarationKind kind) {
return kind == DeclarationKind.CLASS;
}
};
}
return super.getHint(hintKey);
}
};
}
return aPackage.processDeclarations(processor, state, null, place);
}
@NotNull
private static PsiSubstitutor createRawSubstitutor(PsiClass containingClass) {
return JavaPsiFacade.getElementFactory(containingClass.getProject()).createRawSubstitutor(containingClass);
@@ -421,7 +439,7 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava
private static boolean processOnDemandTarget(PsiElement target, PsiScopeProcessor processor, ResolveState substitutor, PsiElement place) {
if (target instanceof PsiPackage) {
if (!target.processDeclarations(processor, substitutor, null, place)) {
if (!processPackageDeclarations(processor, substitutor, place, (PsiPackage)target)) {
return false;
}
}
@@ -436,7 +454,7 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava
}
}
else {
LOG.assertTrue(false);
LOG.error(target);
}
return true;
}
@@ -15,6 +15,7 @@
*/
package com.intellij.psi.impl.source.resolve.graphInference.constraints;
import com.intellij.codeInsight.daemon.impl.analysis.JavaGenericsUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceVariable;
@@ -51,7 +52,7 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
final PsiType type = myExpression.getType();
session.registerIncompatibleErrorMessage((type != null ? type.getPresentableText() : myExpression.getText()) + " is not compatible with " + session.getPresentableText(myT));
}
else if (TypeCompatibilityConstraint.isUncheckedConversion(myT, exprType)) {
else if (TypeCompatibilityConstraint.isUncheckedConversion(myT, exprType) && !JavaGenericsUtil.isReifiableType(myT)) {
session.setErasedDuringApplicabilityCheck();
}
return assignmentCompatible;
@@ -1,3 +1,4 @@
import java.util.function.Consumer;
class Test {
private static AG<AE> foo(Class clz) {
return (AG<AE>) foo1(clz);
@@ -15,3 +16,39 @@ class Test {
}
class Test1 {
static class D<T> {
public D(Consumer<T> c, Class<?> cl) {
}
static <M> D<M> create(Consumer<M> c, Class<?> ck) {
return new D<>(c, ck);
}
}
{
Class c = D.class;
D<String> d = new D<>(s -> s.isEmpty(), c);
D<String> d1 = D.create(s -> s.isEmpty(), c);
}
}
class Test2 {
static class D<T> {
public D(Consumer<T> c, Class<? extends String> cl) {
}
static <M> D<M> create(Consumer<M> c, Class<? extends String> ck) {
return new D<>(c, ck);
}
}
{
Class c = D.class;
D<String> d = new D<>(s -> s.<error descr="Cannot resolve method 'isEmpty()'">isEmpty</error>(), c);
D<String> d1 = D.create(s -> s.<error descr="Cannot resolve method 'isEmpty()'">isEmpty</error>(), c);
}
}
@@ -1,4 +1,4 @@
// "Replace lambda with method reference" "true"
// "Replace lambda with method reference (may change semantics)" "true"
class Example {
public void m() {
}
@@ -1,4 +1,4 @@
// "Replace lambda with method reference" "true"
// "Replace lambda with method reference (may change semantics)" "true"
import java.util.*;
import java.util.function.Predicate;
@@ -1,4 +1,4 @@
// "Replace lambda with method reference" "true"
// "Replace lambda with method reference (may change semantics)" "true"
class Example {
public void m() {
}
@@ -1,4 +1,4 @@
// "Replace lambda with method reference" "true"
// "Replace lambda with method reference (may change semantics)" "true"
import java.util.*;
import java.util.function.Predicate;
@@ -0,0 +1,15 @@
// "Replace Optional.isPresent() condition with functional style expression" "INFORMATION"
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.Optional;
public class Main<T> {
public static <A extends Annotation> Optional<A> findAnnotation(Optional<? extends AnnotatedElement> element) {
return element.<Optional<A>>map(annotatedElement -> Optional.empty()).orElseGet(() -> findAnnotation((AnnotatedElement) null));
}
private static <A extends Annotation> Optional<A> findAnnotation(AnnotatedElement element) {
return Optional.empty();
}
}
@@ -3,13 +3,14 @@
import java.util.*;
public class Main {
public void testOptional(Optional<String> str) {
String val;
// line comment
// another line comment
//before trim
/* block comment *//*block comment*/
val = str.map(String::trim).orElse("");
System.out.println(val);
}
public void testOptional(Optional<String> str) {
String val;
// line comment
// another line comment
/* block comment */
/*block comment*/
//before trim
val = str.map(String::trim).orElse("");
System.out.println(val);
}
}
@@ -1,4 +1,4 @@
// "Replace Optional.isPresent() condition with functional style expression" "true"
// "Replace Optional.isPresent() condition with functional style expression" "GENERIC_ERROR_OR_WARNING"
import java.util.*;
@@ -0,0 +1,12 @@
// "Replace Optional.isPresent() condition with functional style expression" "INFORMATION"
import java.util.Optional;
public class Main {
public void test(Optional<String> opt) {
opt.ifPresent(s -> {
if (s.equals("abc"))
System.out.println(s);
});
}
}
@@ -0,0 +1,13 @@
// "Replace Optional.isPresent() condition with functional style expression" "INFORMATION"
import java.util.*;
public class Main {
public void testOptional(Optional<String> str) {
str.ifPresent(s -> {
System.out.println(s);
// once again!
System.out.println(s);
});
}
}
@@ -11,7 +11,10 @@ public class Main {
}
public Number testOptionalComments(Optional<MyList> strList) {
/* optional is present *//*return something *//*too big*//* optional is absent *//* return null*/
return strList.map(myList -> myList.size() > 1 ? myList.get(1) : 1.0).orElse(null);
/* optional is present */
/*return something */
/* optional is absent */
/* return null*/
return strList.map(myList -> myList.size() > /*too big*/ 1 ? myList.get(1) : 1.0).orElse(null);
}
}
@@ -1,4 +1,4 @@
// "Replace Optional.isPresent() condition with functional style expression" "false"
// "Replace Optional.isPresent() condition with functional style expression" "INFORMATION"
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
@@ -3,16 +3,16 @@
import java.util.*;
public class Main {
public void testOptional(Optional<String> str) {
String val;
if (str.isPrese<caret>nt()) {
val = // line comment
// another line comment
str.get()//before trim
.trim() /* block comment *//*block comment*/;
} else {
val = "";
public void testOptional(Optional<String> str) {
String val;
if (str.isPrese<caret>nt()) {
val = // line comment
// another line comment
str.get()//before trim
.trim() /* block comment *//*block comment*/;
} else {
val = "";
}
System.out.println(val);
}
System.out.println(val);
}
}
@@ -1,4 +1,4 @@
// "Replace Optional.isPresent() condition with functional style expression" "true"
// "Replace Optional.isPresent() condition with functional style expression" "GENERIC_ERROR_OR_WARNING"
import java.util.*;
@@ -0,0 +1,12 @@
// "Replace Optional.isPresent() condition with functional style expression" "INFORMATION"
import java.util.Optional;
public class Main {
public void test(Optional<String> opt) {
if(opt.isPres<caret>ent()) {
if(opt.get().equals("abc"))
System.out.println(opt.get());
}
}
}
@@ -1,4 +1,4 @@
// "Replace Optional.isPresent() condition with functional style expression" "false"
// "Replace Optional.isPresent() condition with functional style expression" "INFORMATION"
import java.util.*;
@@ -6,6 +6,7 @@ public class Main {
public void testOptional(Optional<String> str) {
if (str.isPrese<caret>nt()) {
System.out.println(str.get());
// once again!
System.out.println(str.get());
}
}
@@ -1,4 +1,4 @@
// "Wrap 4th parameter using 'Arrays.asList'" "true"
// "Wrap 4th parameter using 'Arrays.asList()'" "true"
import java.util.Arrays;
import java.util.List;
@@ -1,4 +1,4 @@
// "Wrap using 'Arrays.asList'" "true"
// "Wrap using 'Arrays.asList()'" "true"
import java.util.Arrays;
import java.util.List;
@@ -1,4 +1,4 @@
// "Wrap 4th parameter using 'Arrays.asList'" "true"
// "Wrap 4th parameter using 'Arrays.asList()'" "true"
import java.util.List;
public class Test {
@@ -1,4 +1,4 @@
// "Wrap using 'Arrays.asList'" "false"
// "Wrap using 'Arrays.asList()'" "false"
import java.util.LinkedList;
public class Test {
@@ -1,4 +1,4 @@
// "Wrap using 'Arrays.asList'" "false"
// "Wrap using 'Arrays.asList()'" "false"
import java.util.LinkedList;
public class Test {
@@ -1,4 +1,4 @@
// "Wrap using 'Arrays.asList'" "true"
// "Wrap using 'Arrays.asList()'" "true"
import java.util.List;
public class Test {
@@ -1,4 +1,4 @@
// "Wrap using 'Long.parseLong'" "true"
// "Wrap using 'Long.parseLong()'" "true"
public class Test {
private long lo = Long.parseLong("42");
}
@@ -1,4 +1,4 @@
// "Wrap using 'Long.parseLong'" "true"
// "Wrap using 'Long.parseLong()'" "true"
public class Test {
void ba() {
fa(Long.parseLong("42"));
@@ -1,4 +1,4 @@
// "Wrap using 'Long.parseLong'" "true"
// "Wrap using 'Long.parseLong()'" "true"
public class Test {
void ba(long l) {
fa(l, Long.parseLong("42"));
@@ -1,4 +1,4 @@
// "Wrap using 'Long.valueOf'" "true"
// "Wrap using 'Long.valueOf()'" "true"
public class Test {
private Long lo = Long.valueOf("42");
}
@@ -1,4 +1,4 @@
// "Wrap using 'Long.valueOf'" "true"
// "Wrap using 'Long.valueOf()'" "true"
public class Test {
void ba() {
fa(Long.valueOf("42"));
@@ -1,4 +1,4 @@
// "Wrap using 'Long.valueOf'" "true"
// "Wrap using 'Long.valueOf()'" "true"
public class Test {
void ba(Long l) {
fa(l, Long.valueOf("42"));
@@ -1,4 +1,4 @@
// "Wrap using 'Long.valueOf'" "true"
// "Wrap using 'Long.valueOf()'" "true"
public class Test {
void ba() {
fa(Long.valueOf("42"));
@@ -1,4 +1,4 @@
// "Wrap using 'Long.parseLong'" "true"
// "Wrap using 'Long.parseLong()'" "true"
public class Test {
private long l<caret>o = "42";
}
@@ -1,4 +1,4 @@
// "Wrap using 'Long.parseLong'" "true"
// "Wrap using 'Long.parseLong()'" "true"
public class Test {
void ba() {
fa("4<caret>2");
@@ -1,4 +1,4 @@
// "Wrap using 'Long.parseLong'" "true"
// "Wrap using 'Long.parseLong()'" "true"
public class Test {
void ba(long l) {
fa(l, "4<caret>2");
@@ -1,4 +1,4 @@
// "Wrap using 'Long.valueOf'" "true"
// "Wrap using 'Long.valueOf()'" "true"
public class Test {
private Long l<caret>o = "42";
}
@@ -1,4 +1,4 @@
// "Wrap using 'Long.valueOf'" "true"
// "Wrap using 'Long.valueOf()'" "true"
public class Test {
void ba() {
fa("4<caret>2");
@@ -1,4 +1,4 @@
// "Wrap using 'Long.valueOf'" "true"
// "Wrap using 'Long.valueOf()'" "true"
public class Test {
void ba(Long l) {
fa(l, "4<caret>2");
@@ -1,4 +1,4 @@
// "Wrap using 'Long.valueOf'" "true"
// "Wrap using 'Long.valueOf()'" "true"
public class Test {
void ba() {
fa("4<caret>2");
@@ -0,0 +1,8 @@
import javax.*;
class Foo {
{
<ref>foo.bar.goo d;
}
}
@@ -15,6 +15,7 @@
*/
package com.intellij.index;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.indexing.*;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.EnumeratorStringDescriptor;
@@ -75,7 +76,7 @@ public class StringIndex {
}
public List<String> getFilesByWord(@NotNull String word) throws StorageException {
return myIndex.getData(word).toValueList();
return ContainerUtil.collect(myIndex.getData(word).getValueIterator());
}
public void update(final String path, @Nullable String content, @Nullable String oldContent) throws StorageException {
@@ -17,6 +17,7 @@ package com.intellij.psi.resolve;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
@@ -31,8 +32,14 @@ import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.testFramework.ResolveTestCase;
import com.intellij.util.containers.ContainerUtil;
import org.easymock.IArgumentMatcher;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Set;
import static org.easymock.EasyMock.*;
public class ResolveClassTest extends ResolveTestCase {
public void testFQName() throws Exception {
@@ -268,4 +275,41 @@ public class ResolveClassTest extends ResolveTestCase {
private PsiReference configure() throws Exception {
return configureByFile("class/" + getTestName(false) + ".java");
}
public void testNoSubpackagesAccess() throws Exception {
PsiElementFinder mock = createMockFinder();
PlatformTestUtil.registerExtension(Extensions.getArea(getProject()), PsiElementFinder.EP_NAME, mock, getTestRootDisposable());
PsiReference reference = configure();
assertNull(reference.resolve());
reference.getVariants();
verify(mock);
}
private static PsiElementFinder createMockFinder() {
Set<String> ignoredMethods = ContainerUtil.newHashSet("getClassesFilter", "processPackageDirectories", "getClasses");
Method[] methods = ContainerUtil.findAllAsArray(PsiElementFinder.class.getDeclaredMethods(), m -> !ignoredMethods.contains(m.getName()));
PsiElementFinder mock = createMockBuilder(PsiElementFinder.class).addMockedMethods(methods).createMock();
expect(mock.findClasses(anyObject(), anyObject())).andReturn(PsiClass.EMPTY_ARRAY).anyTimes();
expect(mock.findPackage(eq("foo"))).andReturn(null);
expect(mock.getSubPackages(rootPackage(), anyObject())).andReturn(PsiPackage.EMPTY_ARRAY);
replay(mock);
return mock;
}
private static PsiPackage rootPackage() {
reportMatcher(new IArgumentMatcher() {
@Override
public boolean matches(Object argument) {
return "PsiPackage:".equals(String.valueOf(argument));
}
@Override
public void appendTo(StringBuffer buffer) {
buffer.append("PsiPackage:");
}
});
return null;
}
}
@@ -16,6 +16,8 @@
package com.intellij.codeInsight.daemon.quickFix;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ex.QuickFixWrapper;
import com.intellij.lang.Commenter;
import com.intellij.lang.LanguageCommenters;
import com.intellij.lang.injection.InjectedLanguageManager;
@@ -40,10 +42,12 @@ import static org.junit.Assert.fail;
public class ActionHint {
final String myExpectedText;
final boolean myShouldPresent;
final ProblemHighlightType myHighlightType;
private ActionHint(String expectedText, boolean shouldPresent) {
private ActionHint(String expectedText, boolean shouldPresent, ProblemHighlightType severity) {
myExpectedText = expectedText;
myShouldPresent = shouldPresent;
myHighlightType = severity;
}
/**
@@ -79,11 +83,25 @@ public class ActionHint {
@Nullable
public IntentionAction findAndCheck(Collection<IntentionAction> actions, Supplier<String> infoSupplier) {
IntentionAction result = actions.stream().filter(t -> t.getText().equals(myExpectedText)).findFirst().orElse(null);
if(result == null && myShouldPresent) {
fail("Action with text '" + myExpectedText + "' not found\nAvailable actions: " +
actions.stream().map(IntentionAction::getText).collect(Collectors.joining(", ", "[", "]\n")) +
infoSupplier.get());
} else if(result != null && !myShouldPresent) {
if(myShouldPresent) {
if(result == null) {
fail("Action with text '" + myExpectedText + "' not found\nAvailable actions: " +
actions.stream().map(IntentionAction::getText).collect(Collectors.joining(", ", "[", "]\n")) +
infoSupplier.get());
} else if(myHighlightType != null) {
if(!(result instanceof QuickFixWrapper)) {
fail("Action with text '" + myExpectedText + "' is not a LocalQuickFix, but " + result.getClass().getName() +
"\nExpected LocalQuickFix with ProblemHighlightType=" + myHighlightType + "\n" +
infoSupplier.get());
}
ProblemHighlightType actualType = ((QuickFixWrapper)result).getHighlightType();
if(actualType != myHighlightType) {
fail("Action with text '" + myExpectedText + "' has wrong ProblemHighlightType.\nExpected: " + myHighlightType +
"\nActual: " + actualType + "\n" + infoSupplier.get());
}
}
}
else if(result != null) {
fail("Action with text '" + myExpectedText + "' is present, but should not\n" + infoSupplier.get());
}
return result;
@@ -93,8 +111,13 @@ public class ActionHint {
* Parse given file with given contents extracting ActionHint of it.
* <p>
* Currently the following syntax is supported:
* // "quick-fix name or intention text" "true|false"
* (replace // with line comment prefix in the corresponding language if necessary)
* </p>
* {@code // "quick-fix name or intention text" "true|false|<ProblemHighlightType>"}
* <p>
* (replace // with line comment prefix in the corresponding language if necessary).
* If {@link ProblemHighlightType} enum value is specified instead of true/false
* (e.g. {@code "INFORMATION"}), then
* it's expected that the action is present and it's a quick-fix with given highlight type.
* </p>
*
* @param file PsiFile associated with contents (used to determine the language)
@@ -114,11 +137,15 @@ public class ActionHint {
assert comment != null : commenter;
// "quick fix action text to perform" "should be available"
Pattern pattern = Pattern.compile("^" + Pattern.quote(comment) + " \"(.*)\" \"(true|false)\".*", Pattern.DOTALL);
Pattern pattern = Pattern.compile("^" + Pattern.quote(comment) + " \"(.*)\" \"(\\w+)\".*", Pattern.DOTALL);
Matcher matcher = pattern.matcher(contents);
TestCase.assertTrue("No comment found in " + file.getVirtualFile(), matcher.matches());
final String text = matcher.group(1);
final boolean actionShouldBeAvailable = Boolean.parseBoolean(matcher.group(2));
return new ActionHint(text, actionShouldBeAvailable);
String state = matcher.group(2);
if(state.equals("true") || state.equals("false")) {
return new ActionHint(text, Boolean.parseBoolean(state), null);
} else {
return new ActionHint(text, true, ProblemHighlightType.valueOf(state));
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.QuickFix;
import com.intellij.openapi.command.undo.UndoUtil;
import com.intellij.openapi.diagnostic.Logger;
@@ -29,6 +30,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;
/**
* @author max
@@ -104,6 +106,11 @@ public class QuickFixWrapper implements IntentionAction {
return (LocalQuickFix)myDescriptor.getFixes()[myFixNumber];
}
@TestOnly
public ProblemHighlightType getHighlightType() {
return myDescriptor.getHighlightType();
}
public String toString() {
return getText();
}
@@ -85,7 +85,7 @@ class LibraryLicensesListGenerator {
LibraryLicense lib = it.key
String moduleName = it.value
def name = lib.url != null ? "[$lib.name|$lib.url]" : lib.name
def license = lib.libraryLicenseUrl != null ? "[$lib.license|$lib.licenseUrl]" : lib.license
def license = lib.libraryLicenseUrl != null ? "[$lib.license|$lib.libraryLicenseUrl]" : lib.license
projectBuilder.info(" $lib.name (in module $moduleName)")
lines << "|$name| ${lib.version ?: ""}|$license|".toString()
}
@@ -31,6 +31,7 @@ import com.intellij.openapi.diagnostic.catchAndLog
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectCoreUtil
import com.intellij.openapi.project.impl.ProjectImpl
import com.intellij.openapi.project.impl.ProjectManagerImpl.UnableToSaveProjectNotification
import com.intellij.openapi.project.impl.ProjectStoreClassProvider
@@ -255,7 +256,7 @@ abstract class ProjectStoreBase(override final val project: ProjectImpl) : Compo
}
override fun isProjectFile(file: VirtualFile): Boolean {
if (!file.isInLocalFileSystem) {
if (!file.isInLocalFileSystem || !ProjectCoreUtil.isProjectOrWorkspaceFile(file, file.fileType)) {
return false
}
@@ -213,7 +213,8 @@ public abstract class CustomFoldingBuilder extends FoldingBuilderEx implements P
}
public final boolean isCustomFoldingCandidate(@NotNull PsiElement element) {
return isCustomFoldingCandidate(element.getNode());
ASTNode node = element.getNode();
return node != null && isCustomFoldingCandidate(node);
}
/**
@@ -17,12 +17,8 @@
package com.intellij.util.indexing;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.VoidDataExternalizer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
/**
* A specialization of FileBasedIndexExtension allowing to create a mapping [DataObject -> List of files containing this object]
@@ -30,24 +26,15 @@ import java.io.IOException;
*/
public abstract class ScalarIndexExtension<K> extends FileBasedIndexExtension<K, Void>{
public static final DataExternalizer<Void> VOID_DATA_EXTERNALIZER = new VoidDataExternalizer();
/**
* To remove in IDEA 2018.1. Use {@link VoidDataExternalizer.INSTANCE}
*/
@Deprecated
public static final DataExternalizer<Void> VOID_DATA_EXTERNALIZER = VoidDataExternalizer.INSTANCE;
@NotNull
@Override
public final DataExternalizer<Void> getValueExternalizer() {
return VOID_DATA_EXTERNALIZER;
}
private static class VoidDataExternalizer implements DataExternalizer<Void> {
@Override
public void save(@NotNull final DataOutput out, final Void value) throws IOException {
}
@Override
@Nullable
public Void read(@NotNull final DataInput in) throws IOException {
return null;
}
return VoidDataExternalizer.INSTANCE;
}
}
@@ -66,7 +66,6 @@ import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.search.GlobalSearchScope;
@@ -420,13 +419,11 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
}
private void addFlushRequest(@NotNull MyFlushRunnable flushRunnable, final int millis) {
StartupManager.getInstance(myProject).runWhenProjectIsInitialized(() -> {
synchronized (myCurrentRequests) {
if (!myFlushAlarm.isDisposed() && myCurrentRequests.add(flushRunnable)) {
myFlushAlarm.addRequest(flushRunnable, millis, getStateForUpdate());
}
synchronized (myCurrentRequests) {
if (!myFlushAlarm.isDisposed() && myCurrentRequests.add(flushRunnable)) {
myFlushAlarm.addRequest(flushRunnable, millis, getStateForUpdate());
}
});
}
}
@Override
@@ -373,13 +373,14 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
return;
}
String text = "";
//if (myEditor != null) {
// text = myEditor.getSelectionModel().getSelectedText();
// text = text == null ? "" : text.trim();
//}
if (myEditor != null) {
text = myEditor.getSelectionModel().getSelectedText();
text = text == null ? "" : text.trim();
}
search.setText(text);
search.getTextEditor().setForeground(UIUtil.getLabelForeground());
search.selectText();
//titleIndex = new TitleIndexes();
editor.setColumns(SEARCH_FIELD_COLUMNS);
myFocusComponent = e.getOppositeComponent();
@@ -52,7 +52,6 @@ import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.*;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.SystemInfo;
@@ -139,7 +138,6 @@ public abstract class ChooseByNameBase {
private final ListUpdater myListUpdater = new ListUpdater();
private boolean myDisposedFlag = false;
private ActionCallback myPostponedOkAction;
private final String[][] myNames = new String[2][];
private volatile CalcElementsThread myCalcElementsThread;
@@ -163,15 +161,10 @@ public abstract class ChooseByNameBase {
private ShortcutSet myCheckBoxShortcut;
protected boolean myInitIsDone;
static final boolean ourLoadNamesEachTime = FileBasedIndex.ourEnableTracingOfKeyHashToVirtualFileMapping;
private boolean myFixLostTyping = true;
private boolean myAlwaysHasMore = false;
private Point myFocusPoint;
public boolean checkDisposed() {
if (myDisposedFlag && myPostponedOkAction != null && !myPostponedOkAction.isProcessed()) {
myPostponedOkAction.setRejected();
}
return myDisposedFlag;
}
@@ -569,7 +562,6 @@ public abstract class ChooseByNameBase {
myTextField.getDocument().addDocumentListener(new DocumentAdapter() {
@Override
protected void textChanged(DocumentEvent e) {
clearPostponedOkAction(false);
rebuildList(false);
}
});
@@ -777,12 +769,10 @@ public abstract class ChooseByNameBase {
if (checkDisposed()) return;
if (closeForbidden(ok)) return;
if (postponeCloseWhenListReady(ok)) return;
cancelListUpdater();
close(ok);
clearPostponedOkAction(ok);
myListModel.removeAll();
}
@@ -797,36 +787,15 @@ public abstract class ChooseByNameBase {
final CalcElementsThread calcElementsThread = myCalcElementsThread;
if (calcElementsThread != null) {
calcElementsThread.cancel();
backgroundCalculationFinished(Collections.emptyList(), 0);
myCalcElementsThread = null;
}
myListUpdater.cancelAll();
}
private boolean postponeCloseWhenListReady(boolean ok) {
if (!isToFixLostTyping()) return false;
final String text = getTrimmedText();
if (ok && myCalcElementsThread != null && !text.isEmpty()) {
myPostponedOkAction = new ActionCallback();
IdeFocusManager.getInstance(myProject).typeAheadUntil(myPostponedOkAction);
return true;
}
return false;
}
@NotNull public String getTrimmedText() {
return StringUtil.trimLeading(StringUtil.notNullize(myTextField.getText()));
}
public void setFixLostTyping(boolean fixLostTyping) {
myFixLostTyping = fixLostTyping;
}
protected boolean isToFixLostTyping() {
return myFixLostTyping && Registry.is("actionSystem.fixLostTyping");
}
@NotNull
private synchronized String[] ensureNamesLoaded(boolean checkboxState) {
String[] cached = getNamesSync(checkboxState);
@@ -1038,7 +1007,6 @@ public abstract class ChooseByNameBase {
myTextField.setForeground(JBColor.red);
myListUpdater.cancelAll();
hideList();
clearPostponedOkAction(false);
return;
}
@@ -1046,7 +1014,6 @@ public abstract class ChooseByNameBase {
Object[] newElements = elements.toArray();
List<ModelDiff.Cmd> commands = ModelDiff.createDiffCmds(myListModel, oldElements, newElements);
if (commands == null) {
myListUpdater.doPostponedOkIfNeeded();
return; // Nothing changed
}
@@ -1168,9 +1135,6 @@ public abstract class ChooseByNameBase {
if (!myCommands.isEmpty()) {
myAlarm.addRequest(this, DELAY);
}
else {
doPostponedOkIfNeeded();
}
if (!checkDisposed()) {
showList();
myTextFieldPanel.repositionHint();
@@ -1184,31 +1148,11 @@ public abstract class ChooseByNameBase {
}, DELAY);
}
private void doPostponedOkIfNeeded() {
if (myPostponedOkAction != null) {
if (getChosenElement() != null) {
doClose(true);
}
clearPostponedOkAction(checkDisposed());
}
}
}
private void clearPostponedOkAction(boolean success) {
if (myPostponedOkAction != null) {
if (success) {
myPostponedOkAction.setDone();
}
else {
myPostponedOkAction.setRejected();
}
}
myPostponedOkAction = null;
}
@Deprecated
public boolean hasPostponedAction() {
return myPostponedOkAction != null;
return false;
}
protected abstract void showList();
@@ -1646,10 +1590,6 @@ public abstract class ChooseByNameBase {
myListSizeIncreasing = listSizeIncreasing;
}
public boolean isAlwaysHasMore() {
return myAlwaysHasMore;
}
/**
* Display <tt>...</tt> item at the end of the list regardless of whether it was filled up or not.
* This option can be useful in cases, when it can't be said beforehand, that the next call to {@link ChooseByNameItemProvider}
@@ -24,9 +24,7 @@ import com.intellij.codeInsight.hint.HintUtil;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.ex.*;
import com.intellij.icons.AllIcons;
import com.intellij.ide.CommonActionsManager;
import com.intellij.ide.DefaultTreeExpander;
import com.intellij.ide.TreeExpander;
import com.intellij.ide.*;
import com.intellij.ide.ui.search.SearchUtil;
import com.intellij.ide.ui.search.SearchableOptionsRegistrar;
import com.intellij.lang.annotation.HighlightSeverity;
@@ -36,6 +34,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.options.ex.Settings;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
@@ -71,10 +70,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.event.*;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
@@ -93,6 +89,7 @@ public class SingleInspectionProfilePanel extends JPanel {
@NonNls private static final String EMPTY_HTML = "<html><body></body></html>";
private static final float DIVIDER_PROPORTION_DEFAULT = 0.5f;
public static final String SETTINGS = "settings://";
private final Map<HighlightDisplayKey, ToolDescriptors> myInitialToolDescriptors = new THashMap<>();
private final InspectionConfigTreeNode myRoot =
@@ -1041,7 +1038,25 @@ public class SingleInspectionProfilePanel extends JPanel {
myBrowser = new JEditorPane(UIUtil.HTML_MIME, EMPTY_HTML);
myBrowser.setEditable(false);
myBrowser.setBorder(IdeBorderFactory.createEmptyBorder(5, 5, 5, 5));
myBrowser.addHyperlinkListener(BrowserHyperlinkListener.INSTANCE);
myBrowser.addHyperlinkListener(new HyperlinkAdapter() {
@Override
protected void hyperlinkActivated(HyperlinkEvent e) {
String description = e.getDescription();
if (description.startsWith(SETTINGS)) {
String configId = description.substring(SETTINGS.length());
DataContext context = DataManager.getInstance().getDataContextFromFocus().getResult();
if (context != null) {
Settings settings = Settings.KEY.getData(context);
if (settings != null) {
settings.select(settings.find(configId));
}
}
}
else {
BrowserUtil.browse(description);
}
}
});
initToolStates();
fillTreeData(myProfileFilter != null ? myProfileFilter.getFilter() : null, true);
@@ -26,7 +26,6 @@ import org.jetbrains.annotations.Nullable;
import java.io.DataOutput;
import java.io.IOException;
import java.util.List;
/**
* @author Eugene Zhuravlev
@@ -82,24 +81,6 @@ class ChangeTrackingValueContainer<Value> extends UpdatableValueContainer<Value>
return getMergedData().getValueIterator();
}
@NotNull
@Override
public List<Value> toValueList() {
return getMergedData().toValueList();
}
@NotNull
@Override
public IntPredicate getValueAssociationPredicate(Value value) {
return getMergedData().getValueAssociationPredicate(value);
}
@NotNull
@Override
public IntIterator getInputIdsIterator(final Value value) {
return getMergedData().getInputIdsIterator(value);
}
public void dropMergedData() {
myMerged = null;
}
@@ -164,7 +145,7 @@ class ChangeTrackingValueContainer<Value> extends UpdatableValueContainer<Value>
}
});
}
setNeedsCompacting(fromDisk.needsCompacting());
setNeedsCompacting(((UpdatableValueContainer)fromDisk).needsCompacting());
myMerged = newMerged;
return newMerged;
@@ -914,9 +914,9 @@ public class FileBasedIndexImpl extends FileBasedIndex {
@NotNull K dataKey,
@Nullable VirtualFile restrictToFile,
@NotNull GlobalSearchScope scope,
@NotNull Processor<ValueContainer.ValueIterator<V>> valueProcessor) {
@NotNull Processor<ValueIteratorImpl<V>> valueProcessor) {
final Boolean result = processExceptions(indexId, restrictToFile, scope,
index -> valueProcessor.process(index.getData(dataKey).getValueIterator()));
index -> valueProcessor.process((ValueIteratorImpl<V>)index.getData(dataKey).getValueIterator()));
return result == null || result.booleanValue();
}
@@ -1053,10 +1053,10 @@ public class FileBasedIndexImpl extends FileBasedIndex {
}
@Nullable
private static <K, V, I> TIntHashSet collectInputIdsContainingAllKeys(@NotNull UpdatableIndex<K, V, I> index,
private static <K, V, I> TIntHashSet collectInputIdsContainingAllKeys(@NotNull InvertedIndex<K, V, I> index,
@NotNull Collection<K> dataKeys,
@Nullable Condition<V> valueChecker,
@Nullable ValueContainer.IntPredicate idChecker)
@Nullable IntPredicate idChecker)
throws StorageException {
TIntHashSet mainIntersection = null;
@@ -1065,7 +1065,7 @@ public class FileBasedIndexImpl extends FileBasedIndex {
final TIntHashSet copy = new TIntHashSet();
final ValueContainer<V> container = index.getData(dataKey);
for (final ValueContainer.ValueIterator<V> valueIt = container.getValueIterator(); valueIt.hasNext(); ) {
for (ValueIteratorImpl<V> valueIt = (ValueIteratorImpl<V>)container.getValueIterator(); valueIt.hasNext(); ) {
final V value = valueIt.next();
if (valueChecker != null && !valueChecker.value(value)) {
continue;
@@ -1085,7 +1085,7 @@ public class FileBasedIndexImpl extends FileBasedIndex {
}
else {
mainIntersection.forEach(new TIntProcedure() {
final ValueContainer.IntPredicate predicate = valueIt.getValueAssociationPredicate();
final IntPredicate predicate = valueIt.getValueAssociationPredicate();
@Override
public boolean execute(int id) {
@@ -1107,7 +1107,7 @@ public class FileBasedIndexImpl extends FileBasedIndex {
@NotNull
public static <K, V, I> ValueContainer.IntIterator collectInputIdsContainingAllKeys(@NotNull UpdatableIndex<K, V, I> index,
public static <K, V, I> ValueContainer.IntIterator collectInputIdsContainingAllKeys(@NotNull InvertedIndex<K, V, I> index,
@NotNull Collection<K> dataKeys)
throws StorageException {
TIntHashSet result = collectInputIdsContainingAllKeys(index, dataKeys, null, null);
@@ -73,7 +73,7 @@ class FileId2ValueMapping<Value> {
valueContainer.removeValue(inputId, mapped);
}
if (DebugAssertions.EXTRA_SANITY_CHECKS && myOnePerFileValidationEnabled) {
for (final ValueContainer.ValueIterator<Value> valueIterator = valueContainer.getValueIterator(); valueIterator.hasNext();) {
for (final ValueIteratorImpl<Value> valueIterator = valueContainer.getValueIterator(); valueIterator.hasNext();) {
valueIterator.next();
DebugAssertions.assertTrue(!valueIterator.getValueAssociationPredicate().contains(inputId));
}
@@ -0,0 +1,23 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.util.indexing;
/**
* Created by Maxim.Mossienko on 11/22/2016.
*/
public interface IntPredicate {
boolean contains(int id);
}
@@ -16,8 +16,9 @@
package com.intellij.util.indexing;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -27,25 +28,15 @@ import java.util.concurrent.locks.Lock;
* @author Eugene Zhuravlev
* Date: Dec 10, 2007
*/
public interface UpdatableIndex<Key, Value, Input> extends AbstractIndex<Key,Value> {
public interface UpdatableIndex<Key, Value, Input> extends InvertedIndex<Key,Value, Input> {
void clear() throws StorageException;
void flush() throws StorageException;
/**
* @param inputId *positive* id of content.
*/
@NotNull
Computable<Boolean> update(int inputId, @Nullable Input content);
boolean processAllKeys(@NotNull Processor<Key> processor, @NotNull GlobalSearchScope scope, @Nullable IdFilter idFilter) throws StorageException;
@NotNull
Lock getReadLock();
@NotNull
Lock getWriteLock();
void dispose();
void setIndexedStateForFile(int fileId, @NotNull VirtualFile file);
void resetIndexedStateForFile(int fileId);
@@ -25,4 +25,14 @@ public abstract class UpdatableValueContainer<T> extends ValueContainer<T>{
public abstract void addValue(int inputId, T value);
public abstract void removeAssociatedValue(int inputId);
private volatile boolean myNeedsCompacting;
boolean needsCompacting() {
return myNeedsCompacting;
}
void setNeedsCompacting(boolean value) {
myNeedsCompacting = value;
}
}
@@ -31,8 +31,6 @@ import org.jetbrains.annotations.Nullable;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@@ -86,7 +84,7 @@ class ValueContainerImpl<Value> extends UpdatableValueContainer<Value> implement
if (myInputIdMapping == null) return;
List<Object> fileSetObjects = null;
List<Value> valueObjects = null;
for (final ValueIterator<Value> valueIterator = getValueIterator(); valueIterator.hasNext();) {
for (final ValueIteratorImpl<Value> valueIterator = getValueIterator(); valueIterator.hasNext();) {
final Value value = valueIterator.next();
if (valueIterator.getValueAssociationPredicate().contains(inputId)) {
@@ -144,10 +142,10 @@ class ValueContainerImpl<Value> extends UpdatableValueContainer<Value> implement
@NotNull
@Override
public ValueIterator<Value> getValueIterator() {
public ValueIteratorImpl<Value> getValueIterator() {
if (myInputIdMapping != null) {
if (!(myInputIdMapping instanceof THashMap)) {
return new ValueIterator<Value>() {
return new ValueIteratorImpl<Value>() {
private Value value = (Value)myInputIdMapping;
@NotNull
@@ -186,7 +184,7 @@ class ValueContainerImpl<Value> extends UpdatableValueContainer<Value> implement
}
};
} else {
return new ValueIterator<Value>() {
return new ValueIteratorImpl<Value>() {
private Value current;
private Object currentValue;
private final THashMap<Value, Object> myMapping = ((THashMap<Value, Object>)myInputIdMapping);
@@ -235,7 +233,7 @@ class ValueContainerImpl<Value> extends UpdatableValueContainer<Value> implement
}
}
static class EmptyValueIterator<Value> extends EmptyIterator<Value> implements ValueIterator<Value> {
static class EmptyValueIterator<Value> extends EmptyIterator<Value> implements ValueIteratorImpl<Value> {
@NotNull
@Override
@@ -257,24 +255,6 @@ class ValueContainerImpl<Value> extends UpdatableValueContainer<Value> implement
private static final EmptyValueIterator emptyIterator = new EmptyValueIterator();
@NotNull
@Override
public List<Value> toValueList() {
if (myInputIdMapping == null) {
return Collections.emptyList();
} else if (myInputIdMapping instanceof THashMap) {
return new ArrayList<>(((THashMap<Value, Object>)myInputIdMapping).keySet());
} else {
return new SmartList<>((Value)myInputIdMapping);
}
}
@NotNull
@Override
public IntPredicate getValueAssociationPredicate(Value value) {
return getPredicateOutOfFileSetObject(getFileSetObject(value));
}
private static @NotNull IntPredicate getPredicateOutOfFileSetObject(@Nullable Object input) {
if (input == null) return EMPTY_PREDICATE;
@@ -291,12 +271,6 @@ class ValueContainerImpl<Value> extends UpdatableValueContainer<Value> implement
return ((ChangeBufferingList)input).intPredicate();
}
@NotNull
@Override
public IntIterator getInputIdsIterator(Value value) {
return getIntIteratorOutOfFileSetObject(getFileSetObject(value));
}
private static @NotNull IntIterator getIntIteratorOutOfFileSetObject(@Nullable Object input) {
if (input == null) return EMPTY_ITERATOR;
if (input instanceof Integer){
@@ -436,7 +410,7 @@ class ValueContainerImpl<Value> extends UpdatableValueContainer<Value> implement
public void saveTo(DataOutput out, DataExternalizer<Value> externalizer) throws IOException {
DataInputOutputUtil.writeINT(out, size());
for (final ValueIterator<Value> valueIterator = getValueIterator(); valueIterator.hasNext();) {
for (final ValueIteratorImpl<Value> valueIterator = getValueIterator(); valueIterator.hasNext();) {
final Value value = valueIterator.next();
externalizer.save(out, value);
Object fileSetObject = valueIterator.getFileSetObject();
@@ -0,0 +1,28 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.util.indexing;
import org.jetbrains.annotations.NotNull;
/**
* Created by Maxim.Mossienko on 11/22/2016.
*/
interface ValueIteratorImpl<Value> extends ValueContainer.ValueIterator<Value> {
@NotNull
IntPredicate getValueAssociationPredicate();
Object getFileSetObject();
}
@@ -16,6 +16,7 @@
package com.intellij.util.indexing.containers;
import com.intellij.util.indexing.DebugAssertions;
import com.intellij.util.indexing.IntPredicate;
import com.intellij.util.indexing.ValueContainer;
import gnu.trove.TIntProcedure;
@@ -266,10 +267,10 @@ public class ChangeBufferingList implements Cloneable {
return intContainer.size() == 0;
}
public ValueContainer.IntPredicate intPredicate() {
final ValueContainer.IntPredicate predicate = getRandomAccessContainer().intPredicate();
public IntPredicate intPredicate() {
final IntPredicate predicate = getRandomAccessContainer().intPredicate();
if (checkSet != null) {
return new ValueContainer.IntPredicate() {
return new IntPredicate() {
@Override
public boolean contains(int id) {
boolean answer = predicate.contains(id);
@@ -16,6 +16,7 @@
package com.intellij.util.indexing.containers;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.indexing.IntPredicate;
import com.intellij.util.indexing.ValueContainer;
/**
@@ -126,8 +127,8 @@ class IdBitSet implements Cloneable, RandomAccessIntContainer {
}
@Override
public ValueContainer.IntPredicate intPredicate() {
return new ValueContainer.IntPredicate() {
public IntPredicate intPredicate() {
return new IntPredicate() {
@Override
public boolean contains(int id) {
return IdBitSet.this.contains(id);
@@ -15,6 +15,7 @@
*/
package com.intellij.util.indexing.containers;
import com.intellij.util.indexing.IntPredicate;
import com.intellij.util.indexing.ValueContainer;
import gnu.trove.TIntHashSet;
@@ -36,8 +37,8 @@ public class IdSet extends TIntHashSet implements RandomAccessIntContainer {
}
@Override
public ValueContainer.IntPredicate intPredicate() {
return new ValueContainer.IntPredicate() {
public IntPredicate intPredicate() {
return new IntPredicate() {
@Override
public boolean contains(int id) {
return IdSet.this.contains(id);
@@ -15,6 +15,7 @@
*/
package com.intellij.util.indexing.containers;
import com.intellij.util.indexing.IntPredicate;
import com.intellij.util.indexing.ValueContainer;
/**
@@ -25,7 +26,7 @@ interface RandomAccessIntContainer {
boolean add(int value);
boolean remove(int value);
ValueContainer.IntIterator intIterator();
ValueContainer.IntPredicate intPredicate();
IntPredicate intPredicate();
void compact();
int size();
@@ -15,6 +15,7 @@
*/
package com.intellij.util.indexing.containers;
import com.intellij.util.indexing.IntPredicate;
import com.intellij.util.indexing.ValueContainer;
import gnu.trove.TIntProcedure;
@@ -94,8 +95,8 @@ public class SortedIdSet implements Cloneable, RandomAccessIntContainer {
}
@Override
public ValueContainer.IntPredicate intPredicate() {
return new ValueContainer.IntPredicate() {
public IntPredicate intPredicate() {
return new IntPredicate() {
@Override
public boolean contains(int id) {
@@ -36,7 +36,6 @@ import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ex.ProjectEx;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.EmptyRunnable;
@@ -66,7 +65,6 @@ public class UndoManagerImpl extends UndoManager implements ProjectComponent, Ap
@Nullable private final ProjectEx myProject;
private final CommandProcessor myCommandProcessor;
private final StartupManager myStartupManager;
private UndoProvider[] myUndoProviders;
private CurrentEditorProvider myEditorProvider;
@@ -101,29 +99,21 @@ public class UndoManagerImpl extends UndoManager implements ProjectComponent, Ap
return Registry.intValue("undo.documentUndoLimit");
}
public UndoManagerImpl(Application application, CommandProcessor commandProcessor) {
this(application, null, commandProcessor, null);
public UndoManagerImpl(CommandProcessor commandProcessor) {
this(null, commandProcessor);
}
public UndoManagerImpl(Application application,
@Nullable ProjectEx project,
CommandProcessor commandProcessor,
StartupManager startupManager) {
public UndoManagerImpl(@Nullable ProjectEx project, CommandProcessor commandProcessor) {
myProject = project;
myCommandProcessor = commandProcessor;
myStartupManager = startupManager;
init(application);
if (myProject == null || !myProject.isDefault()) {
runStartupActivity();
}
myMerger = new CommandMerger(this);
}
private void init(@NotNull Application application) {
if (myProject == null || application.isUnitTestMode() && !myProject.isDefault()) {
initialize();
}
}
@Override
@NotNull
public String getComponentName() {
@@ -141,9 +131,6 @@ public class UndoManagerImpl extends UndoManager implements ProjectComponent, Ap
@Override
public void projectOpened() {
if (!ApplicationManager.getApplication().isUnitTestMode()) {
initialize();
}
}
@Override
@@ -158,15 +145,6 @@ public class UndoManagerImpl extends UndoManager implements ProjectComponent, Ap
public void dispose() {
}
private void initialize() {
if (myProject == null) {
runStartupActivity();
}
else {
myStartupManager.registerStartupActivity(this::runStartupActivity);
}
}
private void runStartupActivity() {
myEditorProvider = new FocusBasedCurrentEditorProvider();
CommandListener commandListener = new CommandAdapter() {
@@ -53,7 +53,7 @@ class RunnableActionsTest : PlatformTestCase() {
private val myPerProjectModalDialog = Dialog(null, "Per-project modal dialog", Dialog.ModalityType.DOCUMENT_MODAL)
private val myApplicationModalDialog = Dialog(null, "Owned dialog", Dialog.ModalityType.DOCUMENT_MODAL)
fun testModalityStateChangedListener () {
fun _testModalityStateChangedListener () {
val enteringOrder = booleanArrayOf(true, true, false, false)
val enteringIndex = AtomicInteger(-1)
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,8 +16,7 @@
package com.intellij.util.indexing;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.Processor;
import com.intellij.openapi.util.Computable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -25,9 +24,19 @@ import org.jetbrains.annotations.Nullable;
* @author Eugene Zhuravlev
* Date: Dec 24, 2007
*/
public interface AbstractIndex<Key, Value> {
public interface InvertedIndex<Key, Value, Input> {
@NotNull
ValueContainer<Value> getData(@NotNull Key key) throws StorageException;
boolean processAllKeys(@NotNull Processor<Key> processor, @NotNull GlobalSearchScope scope, @Nullable IdFilter idFilter) throws StorageException;
/**
* @param inputId *positive* id of content.
*/
@NotNull
Computable<Boolean> update(int inputId, @Nullable Input content);
void flush() throws StorageException;
void clear() throws StorageException;
void dispose();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,7 +22,6 @@ import org.jetbrains.annotations.NotNull;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
/**
* @author Eugene Zhuravlev
@@ -41,35 +40,16 @@ public abstract class ValueContainer<Value> {
IntIterator createCopyInInitialState();
}
public interface IntPredicate {
boolean contains(int id);
}
@NotNull
public abstract IntIterator getInputIdsIterator(Value value);
@NotNull
public abstract IntPredicate getValueAssociationPredicate(Value value);
@NotNull
public abstract ValueIterator<Value> getValueIterator();
public interface ValueIterator<Value> extends Iterator<Value> {
@NotNull
IntIterator getInputIdsIterator();
@NotNull
IntPredicate getValueAssociationPredicate();
Object getFileSetObject();
}
@NotNull
public abstract List<Value> toValueList();
public abstract int size();
public interface ContainerAction<T> {
boolean perform(int id, T value);
}
@@ -84,15 +64,5 @@ public abstract class ValueContainer<Value> {
return true;
}
private volatile boolean myNeedsCompacting;
boolean needsCompacting() {
return myNeedsCompacting;
}
void setNeedsCompacting(boolean value) {
myNeedsCompacting = value;
}
public abstract void saveTo(DataOutput out, DataExternalizer<Value> externalizer) throws IOException;
}
@@ -0,0 +1,37 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.util.io;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class VoidDataExternalizer implements DataExternalizer<Void> {
public static final VoidDataExternalizer INSTANCE = new VoidDataExternalizer();
@Override
public void save(@NotNull final DataOutput out, final Void value) throws IOException {
}
@Override
@Nullable
public Void read(@NotNull final DataInput in) throws IOException {
return null;
}
}
@@ -18,9 +18,9 @@ package com.intellij.vcs.log.data.index;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.util.text.TrigramBuilder;
import com.intellij.util.indexing.DataIndexer;
import com.intellij.util.indexing.ScalarIndexExtension;
import com.intellij.util.indexing.StorageException;
import com.intellij.util.indexing.ValueContainer;
import com.intellij.util.io.VoidDataExternalizer;
import com.intellij.vcs.log.VcsFullCommitDetails;
import com.intellij.vcs.log.impl.FatalErrorHandler;
import gnu.trove.THashMap;
@@ -38,7 +38,7 @@ public class VcsLogMessagesTrigramIndex extends VcsLogFullDetailsIndex<Void> {
public VcsLogMessagesTrigramIndex(@NotNull String logId,
@NotNull FatalErrorHandler fatalErrorHandler,
@NotNull Disposable disposableParent) throws IOException {
super(logId, TRIGRAMS, getVersion(), new TrigramMessageIndexer(), ScalarIndexExtension.VOID_DATA_EXTERNALIZER,
super(logId, TRIGRAMS, getVersion(), new TrigramMessageIndexer(), VoidDataExternalizer.INSTANCE,
fatalErrorHandler, disposableParent);
}
@@ -20,8 +20,8 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.Consumer;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.indexing.DataIndexer;
import com.intellij.util.indexing.ScalarIndexExtension;
import com.intellij.util.indexing.StorageException;
import com.intellij.util.io.VoidDataExternalizer;
import com.intellij.vcs.log.VcsFullCommitDetails;
import com.intellij.vcs.log.VcsUser;
import com.intellij.vcs.log.data.VcsUserRegistryImpl;
@@ -45,7 +45,7 @@ public class VcsLogUserIndex extends VcsLogFullDetailsIndex<Void> {
@NotNull VcsUserRegistryImpl userRegistry,
@NotNull FatalErrorHandler consumer,
@NotNull Disposable disposableParent) throws IOException {
super(logId, USERS, getVersion(), new UserIndexer(userRegistry), ScalarIndexExtension.VOID_DATA_EXTERNALIZER,
super(logId, USERS, getVersion(), new UserIndexer(userRegistry), VoidDataExternalizer.INSTANCE,
consumer, disposableParent);
myUserRegistry = userRegistry;
((UserIndexer)myIndexer).setFatalErrorConsumer(e -> consumer.consume(this, e));
@@ -90,11 +90,17 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp
final PsiExpression candidate =
canBeMethodReferenceProblem(expression.getParameterList().getParameters(), functionalInterfaceType, null, methodRefCandidate);
if (candidate != null) {
ProblemHighlightType errorOrWarning = checkQualifier(methodRefCandidate) ? ProblemHighlightType.GENERIC_ERROR_OR_WARNING
: ProblemHighlightType.INFORMATION;
PsiExpression qualifier =
methodRefCandidate instanceof PsiMethodCallExpression ? ((PsiMethodCallExpression)methodRefCandidate).getMethodExpression().getQualifierExpression()
: methodRefCandidate instanceof PsiNewExpression
? ((PsiNewExpression)methodRefCandidate).getQualifier()
: null;
boolean safeQualifier = checkQualifier(qualifier);
ProblemHighlightType errorOrWarning = safeQualifier ? ProblemHighlightType.GENERIC_ERROR_OR_WARNING
: ProblemHighlightType.INFORMATION;
holder.registerProblem(InspectionProjectProfileManager.isInformationLevel(getShortName(), expression) ? expression : candidate,
"Can be replaced with method reference",
errorOrWarning, new ReplaceWithMethodRefFix());
errorOrWarning, new ReplaceWithMethodRefFix(safeQualifier ? "" : " (may change semantics)"));
}
}
}
@@ -308,7 +314,7 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp
return tryConvertToMethodReference(lambda, candidate);
}
public static boolean checkQualifier(PsiElement qualifier) {
public static boolean checkQualifier(@Nullable PsiElement qualifier) {
if (qualifier == null) {
return true;
}
@@ -564,6 +570,19 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp
}
private static class ReplaceWithMethodRefFix implements LocalQuickFix {
private String mySuffix;
public ReplaceWithMethodRefFix(String suffix) {
mySuffix = suffix;
}
@Nls
@NotNull
@Override
public String getName() {
return getFamilyName() + mySuffix;
}
@NotNull
@Override
public String getFamilyName() {
@@ -110,7 +110,7 @@ public class UnicodeUnescapeIntention extends Intention {
/**
* see JLS 3.3. Unicode Escapes
*/
private static int indexOfUnicodeEscape(@NotNull String text, int offset) {
static int indexOfUnicodeEscape(@NotNull String text, int offset) {
final int length = text.length();
for (int i = 0; i < length; i++) {
final char c = text.charAt(i);
@@ -143,6 +143,8 @@ public class UnicodeUnescapeIntention extends Intention {
StringUtil.isHexDigit(text.charAt(nextChar + 3))) {
final int escapeEnd = nextChar + 4;
if (offset <= escapeEnd) {
final char d = (char)Integer.parseInt(text.substring(nextChar, nextChar + 4), 16);
if (d == '\r') return -1; // carriage return not allowed
return i;
}
}
@@ -0,0 +1 @@
// \u000D<caret>
@@ -29,6 +29,7 @@ public class UnicodeUnescapeIntentionTest extends IPPTestCase {
public void testSurrogatePairs2() { doTest(); }
public void testNoException() { assertIntentionNotAvailable(); }
public void testU() { assertIntentionNotAvailable(); }
public void testNoCarriageReturn() { assertIntentionNotAvailable(); }
@Override
protected String getRelativePath() {
@@ -26,6 +26,7 @@ import com.intellij.openapi.vcs.VcsNotifier;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import git4idea.GitUtil;
import git4idea.commands.*;
import git4idea.config.GitVcsSettings;
@@ -38,6 +39,7 @@ import javax.swing.event.HyperlinkEvent;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import static git4idea.util.GitUIUtil.code;
import static java.util.Arrays.stream;
@@ -53,8 +55,6 @@ import static java.util.Arrays.stream;
*/
class GitCheckoutOperation extends GitBranchOperation {
public static final String ROLLBACK_PROPOSAL_FORMAT = "You may rollback (checkout back to previous branch) not to let branches diverge.";
@NotNull private final String myStartPointReference;
private final boolean myDetach;
private final boolean myRefShouldBeValid;
@@ -192,8 +192,15 @@ class GitCheckoutOperation extends GitBranchOperation {
@NotNull
@Override
protected String getRollbackProposal() {
Collection<String> distinctPrevBranches = getSuccessfulRepositories().stream().
map(myCurrentHeads::get).
distinct().
collect(Collectors.toList());
String previousBranch = distinctPrevBranches.size() == 1 ? ContainerUtil.getFirstItem(distinctPrevBranches) : "previous branch";
String rollBackProposal = "You may rollback (checkout back to " + previousBranch + ") not to let branches diverge.";
return "However checkout has succeeded for the following " + repositories() + ":<br/>" +
successfulRepositoriesJoined() + "<br/>" + ROLLBACK_PROPOSAL_FORMAT;
successfulRepositoriesJoined() + "<br/>" +
rollBackProposal;
}
@NotNull
@@ -17,9 +17,10 @@ package org.jetbrains.plugins.gradle.config;
import com.intellij.compiler.options.CompileStepBeforeRun;
import com.intellij.compiler.options.CompileStepBeforeRunNoErrorCheck;
import com.intellij.execution.*;
import com.intellij.execution.CantRunException;
import com.intellij.execution.Location;
import com.intellij.execution.RunManagerEx;
import com.intellij.execution.configurations.JavaParameters;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.externalSystem.psi.search.ExternalModuleBuildGlobalSearchScope;
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
@@ -172,12 +173,10 @@ public class GradleScriptType extends GroovyRunnableScriptType {
}
@Override
public boolean ensureRunnerConfigured(@Nullable Module module, RunProfile profile, Executor executor, final Project project) throws ExecutionException {
if (project != null && profile instanceof GroovyScriptRunConfiguration) {
GroovyScriptRunConfiguration configuration = (GroovyScriptRunConfiguration)profile;
String parameters = configuration.getProgramParameters();
if (parameters != null) {
// TODO den implement
public void ensureRunnerConfigured(@NotNull GroovyScriptRunConfiguration configuration) {
String parameters = configuration.getProgramParameters();
if (parameters != null) {
// TODO den implement
// GradleTasksList list = GradleUtil.getToolWindowElement(GradleTasksList.class, project, ExternalSystemDataKeys.RECENT_TASKS_LIST);
// if (list != null) {
// ExternalSystemTaskDescriptor descriptor = new ExternalSystemTaskDescriptor(parameters, null);
@@ -185,7 +184,6 @@ public class GradleScriptType extends GroovyRunnableScriptType {
// list.setFirst(descriptor);
// GradleLocalSettings.getInstance(project).setRecentTasks(list.getModel().getTasks());
// }
}
}
final GradleInstallationManager libraryManager = ServiceManager.getService(GradleInstallationManager.class);
// TODO den implement
@@ -203,7 +201,6 @@ public class GradleScriptType extends GroovyRunnableScriptType {
// return false;
// }
// }
return true;
}
@Override
@@ -15,6 +15,7 @@
*/
package org.jetbrains.plugins.groovy.lang.psi.util;
import com.intellij.openapi.project.DumbService;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiMethodUtil;
import com.intellij.psi.util.PsiTreeUtil;
@@ -27,6 +28,7 @@ public class GroovyRunnerPsiUtil {
@Nullable
public static PsiClass getRunningClass(@Nullable PsiElement element) {
if (element == null) return null;
if (DumbService.isDumb(element.getProject())) return null;
final PsiFile file = element.getContainingFile();
if (!(file instanceof GroovyFile)) return null;
@@ -16,19 +16,16 @@
package org.jetbrains.plugins.groovy.gant;
import com.intellij.execution.CantRunException;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.JavaParameters;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.configurations.RuntimeConfigurationException;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.libraries.LibraryUtil;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import icons.JetgroovyIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
@@ -55,20 +52,13 @@ public class GantRunner extends GroovyScriptRunner {
}
@Override
public boolean ensureRunnerConfigured(@Nullable Module module, RunProfile profile, Executor executor, final Project project) {
if (GantUtils.getSDKInstallPath(module, project).isEmpty()) {
int result = Messages
.showOkCancelDialog("Gant is not configured. Do you want to configure it?", "Configure Gant SDK",
JetgroovyIcons.Groovy.Gant_16x16);
if (result == Messages.OK) {
ShowSettingsUtil.getInstance().editConfigurable(project, new GantConfigurable(project));
}
if (GantUtils.getSDKInstallPath(module, project).isEmpty()) {
return false;
}
public void ensureRunnerConfigured(@NotNull GroovyScriptRunConfiguration configuration) throws RuntimeConfigurationException {
Project project = configuration.getProject();
if (GantUtils.getSDKInstallPath(configuration.getModule(), project).isEmpty()) {
RuntimeConfigurationException e = new RuntimeConfigurationException("Gant is not configured");
e.setQuickFix(() -> ShowSettingsUtil.getInstance().editConfigurable(project, new GantConfigurable(project)));
throw e;
}
return true;
}
private static String getGantConfPath(final String gantHome) {
@@ -17,14 +17,10 @@
package org.jetbrains.plugins.groovy.runner;
import com.intellij.execution.CantRunException;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.JavaParameters;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.runners.ExecutionUtil;
import com.intellij.execution.configurations.RuntimeConfigurationException;
import com.intellij.execution.util.ScriptFileUtil;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ui.configuration.ClasspathEditor;
import com.intellij.openapi.roots.ui.configuration.ModulesConfigurator;
import com.intellij.openapi.util.Comparing;
@@ -52,17 +48,17 @@ public class DefaultGroovyScriptRunner extends GroovyScriptRunner {
}
@Override
public boolean ensureRunnerConfigured(@Nullable Module module, RunProfile profile, Executor executor, final Project project) throws ExecutionException {
public void ensureRunnerConfigured(@NotNull GroovyScriptRunConfiguration configuration) throws RuntimeConfigurationException {
Module module = configuration.getModule();
if (module == null) {
throw new ExecutionException("Module is not specified");
throw new RuntimeConfigurationException("Module is not specified");
}
if (LibrariesUtil.getGroovyHomePath(module) == null) {
ExecutionUtil.handleExecutionError(project, executor.getToolWindowId(), profile, new ExecutionException("Groovy is not configured"));
ModulesConfigurator.showDialog(module.getProject(), module.getName(), ClasspathEditor.NAME);
return false;
RuntimeConfigurationException e = new RuntimeConfigurationException("Groovy is not configured for module '" + module.getName() + "'");
e.setQuickFix(() -> ModulesConfigurator.showDialog(module.getProject(), module.getName(), ClasspathEditor.NAME));
throw e;
}
return true;
}
@Override
@@ -1,104 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.groovy.runner.GroovyRunConfigurationEditor">
<grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="9" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="9" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="329"/>
<xy x="20" y="20" width="500" height="354"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<vspacer id="41261">
<component id="dec50" class="com.intellij.openapi.ui.LabeledComponent" binding="myScriptPathComponent" default-binding="true">
<constraints>
<grid row="8" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<componentClass value="com.intellij.openapi.ui.TextFieldWithBrowseButton"/>
<labelLocation value="West"/>
<text value="Script path"/>
<verifyInputWhenFocusTarget value="false"/>
</properties>
</component>
<component id="2fdc8" class="com.intellij.execution.ui.CommonJavaParametersPanel" binding="myCommonJavaParametersPanel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<vspacer id="e3ad0">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false">
<preferred-size width="-1" height="10"/>
</grid>
</constraints>
</vspacer>
<component id="3b65f" class="com.intellij.ui.RawCommandLineEditor" binding="myVMParameters">
<component id="9b09" class="com.intellij.openapi.ui.LabeledComponent" binding="myModulesComboBoxComponent">
<constraints>
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<component id="3d033" class="com.intellij.ui.RawCommandLineEditor" binding="myParameters" default-binding="true">
<constraints>
<grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<grid id="27781" binding="scriptPathPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children/>
</grid>
<grid id="4852" binding="workDirPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints>
<grid row="5" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children/>
</grid>
<component id="39213" class="com.intellij.execution.configuration.EnvironmentVariablesComponent" binding="myEnvVariables">
<constraints>
<grid row="4" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<componentClass value="com.intellij.application.options.ModulesComboBox"/>
<labelLocation value="West"/>
<text value="Module"/>
</properties>
</component>
<component id="5f62b" class="com.intellij.ui.components.JBLabel" binding="myScriptParametersLabel">
<component id="9cee8" class="com.intellij.execution.ui.JrePathEditor" binding="myJrePathEditor">
<constraints>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Script parameters:"/>
</properties>
</component>
<component id="c5c05" class="javax.swing.JLabel">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="VM options:"/>
</properties>
</component>
<component id="86e25" class="javax.swing.JLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="d1e7d"/>
<text value="Module:"/>
</properties>
</component>
<component id="d1e7d" class="com.intellij.application.options.ModulesComboBox" binding="myModulesBox">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<component id="5194" class="javax.swing.JLabel">
<vspacer id="f5fd3">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false">
<preferred-size width="-1" height="10"/>
</grid>
</constraints>
<properties>
<text value="Script path:"/>
</properties>
</component>
<component id="ae9d1" class="javax.swing.JLabel">
<constraints>
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Working directory:"/>
</properties>
</component>
</vspacer>
<component id="c934c" class="javax.swing.JCheckBox" binding="myDebugCB" default-binding="true">
<constraints>
<grid row="6" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="6" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<selected value="false"/>
@@ -107,12 +66,17 @@
</component>
<component id="62ce7" class="javax.swing.JCheckBox" binding="myAddClasspathCB">
<constraints>
<grid row="7" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="7" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Add module &amp;classpath to the runner"/>
</properties>
</component>
<vspacer id="41261">
<constraints>
<grid row="8" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
</children>
</grid>
</form>
@@ -17,116 +17,123 @@
package org.jetbrains.plugins.groovy.runner;
import com.intellij.application.options.ModulesComboBox;
import com.intellij.execution.configuration.EnvironmentVariablesComponent;
import com.intellij.ide.util.BrowseFilesListener;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.execution.ui.CommonJavaParametersPanel;
import com.intellij.execution.ui.DefaultJreSelector.SdkFromModuleDependencies;
import com.intellij.execution.ui.JrePathEditor;
import com.intellij.execution.util.ScriptFileUtil;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.ui.LabeledComponent;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.FieldPanel;
import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.PanelWithAnchor;
import com.intellij.ui.RawCommandLineEditor;
import com.intellij.ui.components.JBLabel;
import com.intellij.util.ui.UIUtil;
import kotlin.jvm.functions.Function0;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.GroovyFileType;
import javax.swing.*;
import java.awt.*;
import javax.swing.event.DocumentEvent;
public class GroovyRunConfigurationEditor extends SettingsEditor<GroovyScriptRunConfiguration> implements PanelWithAnchor {
private ModulesComboBox myModulesBox;
private JPanel myMainPanel;
private RawCommandLineEditor myVMParameters;
private RawCommandLineEditor myParameters;
private JPanel scriptPathPanel;
private JPanel workDirPanel;
private LabeledComponent<TextFieldWithBrowseButton> myScriptPathComponent;
private CommonJavaParametersPanel myCommonJavaParametersPanel;
private LabeledComponent<ModulesComboBox> myModulesComboBoxComponent;
private JrePathEditor myJrePathEditor;
private JCheckBox myDebugCB;
private EnvironmentVariablesComponent myEnvVariables;
private JBLabel myScriptParametersLabel;
private JCheckBox myAddClasspathCB;
private final JTextField scriptPathField;
private final JTextField workDirField;
private JComponent anchor;
public GroovyRunConfigurationEditor() {
private JComponent myAnchor;
scriptPathField = new JTextField();
final BrowseFilesListener scriptBrowseListener = new BrowseFilesListener(scriptPathField,
"Script Path",
"Specify path to script",
new FileChooserDescriptor(true, false, false, false, false, false) {
@Override
public boolean isFileSelectable(VirtualFile file) {
return file.getFileType() == GroovyFileType.GROOVY_FILE_TYPE;
public GroovyRunConfigurationEditor(@NotNull Project project) {
final TextFieldWithBrowseButton scriptPath = myScriptPathComponent.getComponent();
scriptPath.addBrowseFolderListener(
"Script Path", "Specify path to script", project,
FileChooserDescriptorFactory.createSingleFileDescriptor(GroovyFileType.GROOVY_FILE_TYPE)
);
final ModulesComboBox modulesComboBox = myModulesComboBoxComponent.getComponent();
modulesComboBox.addActionListener(e -> myCommonJavaParametersPanel.setModuleContext(modulesComboBox.getSelectedModule()));
ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
Function0<Boolean> productionOnly = () -> {
VirtualFile script = ScriptFileUtil.findScriptFileByPath(scriptPath.getText());
return script != null && !fileIndex.isInTestSourceContent(script);
};
myJrePathEditor.setDefaultJreSelector(new SdkFromModuleDependencies(modulesComboBox, productionOnly) {
@Override
public void addChangeListener(@NotNull Runnable listener) {
super.addChangeListener(listener);
scriptPath.getChildComponent().getDocument().addDocumentListener(
new DocumentAdapter() {
@Override
protected void textChanged(DocumentEvent e) {
listener.run();
}
}
});
final FieldPanel scriptFieldPanel = new FieldPanel(scriptPathField, null, null, scriptBrowseListener, null);
scriptPathPanel.setLayout(new BorderLayout());
scriptPathPanel.add(scriptFieldPanel, BorderLayout.CENTER);
workDirField = new JTextField();
final BrowseFilesListener workDirBrowseFilesListener = new BrowseFilesListener(workDirField,
"Working directory",
"Specify working directory",
BrowseFilesListener.SINGLE_DIRECTORY_DESCRIPTOR);
final FieldPanel workDirFieldPanel = new FieldPanel(workDirField, null, null, workDirBrowseFilesListener, null);
workDirPanel.setLayout(new BorderLayout());
workDirPanel.add(workDirFieldPanel, BorderLayout.CENTER);
setAnchor(myEnvVariables.getLabel());
);
}
});
myAnchor = UIUtil.mergeComponentsWithAnchor(
myScriptPathComponent,
myCommonJavaParametersPanel,
myModulesComboBoxComponent,
myJrePathEditor
);
}
@Override
public void resetEditorFrom(@NotNull GroovyScriptRunConfiguration configuration) {
myVMParameters.setDialogCaption("VM Options");
myVMParameters.setText(configuration.getVMParameters());
myScriptPathComponent.getComponent().setText(configuration.getScriptPath());
myCommonJavaParametersPanel.reset(configuration);
myParameters.setDialogCaption("Script Parameters");
myParameters.setText(configuration.getProgramParameters());
myModulesComboBoxComponent.getComponent().setModules(configuration.getValidModules());
myModulesComboBoxComponent.getComponent().setSelectedModule(configuration.getConfigurationModule().getModule());
myJrePathEditor.setPathOrName(configuration.getAlternativeJrePath(), configuration.isAlternativeJrePathEnabled());
scriptPathField.setText(configuration.getScriptPath());
workDirField.setText(configuration.getWorkDir());
myDebugCB.setEnabled(true);
myDebugCB.setSelected(configuration.isDebugEnabled());
myAddClasspathCB.setSelected(configuration.isAddClasspathToTheRunner());
myModulesBox.setModules(configuration.getValidModules());
myModulesBox.setSelectedModule(configuration.getModule());
myEnvVariables.setEnvs(configuration.getEnvs());
}
@Override
public void applyEditorTo(@NotNull GroovyScriptRunConfiguration configuration) throws ConfigurationException {
configuration.setModule(myModulesBox.getSelectedModule());
configuration.setVMParameters(myVMParameters.getText());
configuration.setScriptPath(myScriptPathComponent.getComponent().getText().trim());
myCommonJavaParametersPanel.applyTo(configuration);
configuration.setModule(myModulesComboBoxComponent.getComponent().getSelectedModule());
configuration.setAlternativeJrePathEnabled(myJrePathEditor.isAlternativeJreSelected());
configuration.setAlternativeJrePath(myJrePathEditor.getJrePathOrName());
configuration.setDebugEnabled(myDebugCB.isSelected());
configuration.setAddClasspathToTheRunner(myAddClasspathCB.isSelected());
configuration.setProgramParameters(myParameters.getText());
configuration.setScriptPath(scriptPathField.getText().trim());
configuration.setWorkDir(workDirField.getText().trim());
configuration.setEnvs(myEnvVariables.getEnvs());
}
@Override
@NotNull
public JComponent createEditor() {
myDebugCB.setEnabled(true);
myDebugCB.setSelected(false);
return myMainPanel;
}
@Override
public JComponent getAnchor() {
return anchor;
return myAnchor;
}
@Override
public void setAnchor(JComponent anchor) {
this.anchor = anchor;
myScriptParametersLabel.setAnchor(anchor);
myEnvVariables.setAnchor(anchor);
myAnchor = anchor;
myScriptPathComponent.setAnchor(anchor);
myCommonJavaParametersPanel.setAnchor(anchor);
myModulesComboBoxComponent.setAnchor(anchor);
myJrePathEditor.setAnchor(anchor);
}
}
@@ -15,16 +15,19 @@
*/
package org.jetbrains.plugins.groovy.runner;
import com.intellij.execution.*;
import com.intellij.execution.CommonJavaRunConfigurationParameters;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor;
import com.intellij.execution.ExternalizablePath;
import com.intellij.execution.configurations.*;
import com.intellij.execution.process.OSProcessHandler;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.util.JavaParametersUtil;
import com.intellij.execution.util.ProgramParametersUtil;
import com.intellij.execution.util.ScriptFileUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.options.SettingsEditor;
@@ -36,6 +39,7 @@ import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.JDOMExternalizer;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
@@ -71,7 +75,6 @@ import java.util.Map;
public class GroovyScriptRunConfiguration extends ModuleBasedConfiguration<RunConfigurationModule>
implements CommonJavaRunConfigurationParameters, RefactoringListenerProvider {
private static final Logger LOG = Logger.getInstance(GroovyScriptRunConfiguration.class);
private String vmParams;
private String workDir;
private boolean isDebugEnabled;
@@ -81,28 +84,23 @@ public class GroovyScriptRunConfiguration extends ModuleBasedConfiguration<RunCo
private final Map<String, String> envs = new LinkedHashMap<>();
public boolean passParentEnv = true;
private boolean myAlternativeJrePathEnabled;
private @Nullable String myAlternativeJrePath;
public GroovyScriptRunConfiguration(final String name, final Project project, final ConfigurationFactory factory) {
super(name, new RunConfigurationModule(project), factory);
workDir = PathUtil.getLocalPath(project.getBaseDir());
}
public void setWorkDir(String dir) {
workDir = dir;
}
public String getWorkDir() {
return workDir;
}
@Nullable
public Module getModule() {
return getConfigurationModule().getModule();
return ObjectUtils.chooseNotNull(getConfigurationModule().getModule(), ContainerUtil.getFirstItem(getValidModules()));
}
@Override
public Collection<Module> getValidModules() {
Module[] modules = ModuleManager.getInstance(getProject()).getModules();
final GroovyScriptRunner scriptRunner = findConfiguration();
final GroovyScriptRunner scriptRunner = getScriptRunner();
if (scriptRunner == null) {
return Arrays.asList(modules);
}
@@ -118,21 +116,20 @@ public class GroovyScriptRunConfiguration extends ModuleBasedConfiguration<RunCo
}
@Nullable
private GroovyScriptRunner findConfiguration() {
final VirtualFile scriptFile = getScriptFile();
if (scriptFile == null) {
return null;
}
private GroovyScriptRunner getScriptRunner() {
final VirtualFile scriptFile = ScriptFileUtil.findScriptFileByPath(getScriptPath());
if (scriptFile == null) return null;
final PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(scriptFile);
if (!(psiFile instanceof GroovyFile)) {
return null;
if (!(psiFile instanceof GroovyFile)) return null;
final GroovyFile groovyFile = (GroovyFile)psiFile;
if (groovyFile.isScript()) {
return GroovyScriptUtil.getScriptType(groovyFile).getRunner();
}
if (!((GroovyFile)psiFile).isScript()) {
else {
return new DefaultGroovyScriptRunner();
}
return GroovyScriptUtil.getScriptType((GroovyFile)psiFile).getRunner();
}
@Override
@@ -150,6 +147,9 @@ public class GroovyScriptRunConfiguration extends ModuleBasedConfiguration<RunCo
isAddClasspathToTheRunner = Boolean.parseBoolean(JDOMExternalizer.readString(element, "addClasspath"));
envs.clear();
JDOMExternalizer.readMap(element, envs, null, "env");
myAlternativeJrePathEnabled = JDOMExternalizer.readBoolean(element, "alternativeJrePathEnabled");
myAlternativeJrePath = JDOMExternalizer.readString(element, "alternativeJrePath");
}
@Override
@@ -163,26 +163,20 @@ public class GroovyScriptRunConfiguration extends ModuleBasedConfiguration<RunCo
JDOMExternalizer.write(element, "debug", isDebugEnabled);
if (isAddClasspathToTheRunner) JDOMExternalizer.write(element, "addClasspath", true);
JDOMExternalizer.writeMap(element, envs, null, "env");
if (myAlternativeJrePathEnabled) {
JDOMExternalizer.write(element, "alternativeJrePathEnabled", true);
if (StringUtil.isNotEmpty(myAlternativeJrePath)) JDOMExternalizer.write(element, "alternativeJrePath", myAlternativeJrePath);
}
}
@Override
public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment environment) throws ExecutionException {
final VirtualFile script = getScriptFile();
if (script == null) {
throw new CantRunException("Cannot find script " + scriptPath);
}
final VirtualFile scriptFile = ScriptFileUtil.findScriptFileByPath(getScriptPath());
assert scriptFile != null;
final GroovyScriptRunner scriptRunner = findConfiguration();
if (scriptRunner == null) {
throw new CantRunException("Unknown script type " + scriptPath);
}
final Module module = ObjectUtils.chooseNotNull(getModule(), ContainerUtil.getFirstItem(getValidModules()));
if (!scriptRunner.ensureRunnerConfigured(module, this, executor, getProject())) {
return null;
}
final boolean tests = ProjectRootManager.getInstance(getProject()).getFileIndex().isInTestSourceContent(script);
final GroovyScriptRunner scriptRunner = getScriptRunner();
assert scriptRunner != null;
return new JavaCommandLineState(environment) {
@NotNull
@@ -206,9 +200,18 @@ public class GroovyScriptRunConfiguration extends ModuleBasedConfiguration<RunCo
@Override
protected JavaParameters createJavaParameters() throws ExecutionException {
JavaParameters params = createJavaParametersWithSdk(module);
final Module module = getModule();
final boolean tests = ProjectRootManager.getInstance(getProject()).getFileIndex().isInTestSourceContent(scriptFile);
String jrePath = isAlternativeJrePathEnabled() ? getAlternativeJrePath() : null;
JavaParameters params = new JavaParameters();
params.setUseClasspathJar(true);
params.setDefaultCharset(getProject());
params.setJdk(
module == null ? JavaParametersUtil.createProjectJdk(getProject(), jrePath)
: JavaParametersUtil.createModuleJdk(module, !tests, jrePath)
);
ProgramParametersUtil.configureConfiguration(params, GroovyScriptRunConfiguration.this);
scriptRunner.configureCommandLine(params, module, tests, script, GroovyScriptRunConfiguration.this);
scriptRunner.configureCommandLine(params, module, tests, scriptFile, GroovyScriptRunConfiguration.this);
return params;
}
@@ -281,29 +284,28 @@ public class GroovyScriptRunConfiguration extends ModuleBasedConfiguration<RunCo
return params;
}
@Nullable
private VirtualFile getScriptFile() {
return ScriptFileUtil.findScriptFileByPath(scriptPath);
}
@Nullable
private PsiClass getScriptClass() {
final VirtualFile scriptFile = getScriptFile();
if (scriptFile == null) return null;
final PsiFile file = PsiManager.getInstance(getProject()).findFile(scriptFile);
return GroovyRunnerPsiUtil.getRunningClass(file);
}
@Override
@NotNull
public SettingsEditor<? extends RunConfiguration> getConfigurationEditor() {
return new GroovyRunConfigurationEditor();
return new GroovyRunConfigurationEditor(getProject());
}
@Override
public void checkConfiguration() throws RuntimeConfigurationException {
super.checkConfiguration();
final PsiClass toRun = getScriptClass();
final String scriptPath = getScriptPath();
final VirtualFile script = ScriptFileUtil.findScriptFileByPath(scriptPath);
if (script == null) throw new RuntimeConfigurationException("Cannot find script " + scriptPath);
final GroovyScriptRunner scriptRunner = getScriptRunner();
if (scriptRunner == null) throw new RuntimeConfigurationException("Unknown script type " + scriptPath);
scriptRunner.ensureRunnerConfigured(this);
final PsiFile file = PsiManager.getInstance(getProject()).findFile(script);
final PsiClass toRun = GroovyRunnerPsiUtil.getRunningClass(file);
if (toRun == null) {
throw new RuntimeConfigurationWarning(GroovyBundle.message("class.does.not.exist"));
}
@@ -315,6 +317,7 @@ public class GroovyScriptRunConfiguration extends ModuleBasedConfiguration<RunCo
else {
throw new RuntimeConfigurationWarning(GroovyBundle.message("script.file.is.not.groovy.file"));
}
JavaParametersUtil.checkAlternativeJRE(this);
}
@Override
@@ -329,23 +332,23 @@ public class GroovyScriptRunConfiguration extends ModuleBasedConfiguration<RunCo
@Override
public boolean isAlternativeJrePathEnabled() {
return false;
return myAlternativeJrePathEnabled;
}
@Override
public void setAlternativeJrePathEnabled(boolean enabled) {
throw new UnsupportedOperationException();
public void setAlternativeJrePathEnabled(boolean alternativeJrePathEnabled) {
myAlternativeJrePathEnabled = alternativeJrePathEnabled;
}
@Nullable
@Override
public String getAlternativeJrePath() {
throw new UnsupportedOperationException();
return myAlternativeJrePath;
}
@Override
public void setAlternativeJrePath(String path) {
throw new UnsupportedOperationException();
public void setAlternativeJrePath(@Nullable String alternativeJrePath) {
myAlternativeJrePath = alternativeJrePath;
}
@Override
@@ -130,7 +130,7 @@ public class GroovyScriptRunConfigurationProducer extends RuntimeConfigurationPr
final PsiFile file = aClass.getContainingFile().getOriginalFile();
final PsiDirectory dir = file.getContainingDirectory();
if (dir != null) {
configuration.setWorkDir(dir.getVirtualFile().getPath());
configuration.setWorkingDirectory(dir.getVirtualFile().getPath());
}
final VirtualFile vFile = file.getVirtualFile();
if (vFile == null) return null;
@@ -16,12 +16,9 @@
package org.jetbrains.plugins.groovy.runner;
import com.intellij.execution.CantRunException;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.JavaParameters;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.configurations.RuntimeConfigurationException;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdkType;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.OrderEnumerator;
@@ -47,7 +44,7 @@ public abstract class GroovyScriptRunner {
public abstract boolean isValidModule(@NotNull Module module);
public abstract boolean ensureRunnerConfigured(@Nullable Module module, RunProfile profile, Executor executor, final Project project) throws ExecutionException;
public abstract void ensureRunnerConfigured(@NotNull GroovyScriptRunConfiguration configuration) throws RuntimeConfigurationException;
public abstract void configureCommandLine(JavaParameters params, @Nullable Module module, boolean tests, VirtualFile script,
GroovyScriptRunConfiguration configuration) throws CantRunException;
@@ -89,11 +89,7 @@ class TaskItemProvider implements ChooseByNameItemProvider, Disposable {
}
catch (TimeoutException ignore) {
}
if (base.hasPostponedAction()) {
future.cancel(true);
return true;
}
}
}
myFutureReference.compareAndSet(future, null);
// Exclude *all* cached and local issues, not only those returned by TaskSearchSupport.getLocalAndCachedTasks().
@@ -50,20 +50,20 @@ public class CCRefactoringElementListenerProvider implements RefactoringElementL
static class CCRenameListener extends RefactoringElementAdapter {
private String myElementName;
private String myElementRelativePath;
public CCRenameListener(PsiElement element) {
if (element instanceof PsiFile) {
PsiFile psiFile = (PsiFile)element;
myElementName = psiFile.getName();
myElementRelativePath = StudyUtils.pathRelativeToTask(psiFile.getVirtualFile());
}
}
@Override
protected void elementRenamedOrMoved(@NotNull PsiElement newElement) {
if (newElement instanceof PsiFile && myElementName != null) {
if (newElement instanceof PsiFile && myElementRelativePath != null) {
PsiFile psiFile = (PsiFile)newElement;
tryToRenameTaskFile(psiFile, myElementName);
tryToRenameTaskFile(psiFile, myElementRelativePath);
}
}
@@ -107,7 +107,7 @@ public class CCRefactoringElementListenerProvider implements RefactoringElementL
});
taskFiles.remove(oldName);
taskFiles.put(file.getName(), taskFile);
taskFiles.put(StudyUtils.pathRelativeToTask(file.getVirtualFile()), taskFile);
CCUtils.createResourceFile(file.getVirtualFile(), course, taskDir.getVirtualFile());
}
@@ -266,7 +266,7 @@ public class CCUtils {
}
for (Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
String name = entry.getKey();
VirtualFile answerFile = taskDir.findChild(name);
VirtualFile answerFile = taskDir.findFileByRelativePath(name);
if (answerFile == null) {
continue;
}

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