Merge remote-tracking branch 'origin/master' into amakeev/symlinks

This commit is contained in:
Anton Makeev
2016-08-31 17:25:44 +02:00
198 changed files with 3069 additions and 1877 deletions
@@ -97,6 +97,12 @@ public final class RegExpCompletionContributor extends CompletionContributor {
final ElementPattern<PsiElement> propertyNamePattern
= psiElement().afterLeaf(psiElement().withText("{").afterLeaf(propertyPattern));
extend(CompletionType.BASIC, propertyNamePattern, new PropertyNameCompletionProvider());
final PsiElementPattern.Capture<PsiElement> namedCharacterPattern = psiElement().withText("N");
extend(CompletionType.BASIC, psiElement().afterLeaf(namedCharacterPattern),
new NamedCharacterCompletionProvider(true));
extend(CompletionType.BASIC, psiElement().afterLeaf(psiElement(RegExpTT.LBRACE).afterLeaf(namedCharacterPattern)),
new NamedCharacterCompletionProvider(false));
}
}
@@ -15,11 +15,11 @@
*/
package org.intellij.lang.regexp;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.ClassExtension;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.FileContextUtil;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.intellij.lang.regexp.psi.*;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
@@ -51,36 +51,19 @@ public final class RegExpLanguageHosts extends ClassExtension<RegExpLanguageHost
@Contract("null -> null")
@Nullable
private static RegExpLanguageHost findRegExpHost(@Nullable final PsiElement element) {
if (ApplicationManager.getApplication().isUnitTestMode() && myHost != null) {
return myHost;
}
if (element == null) {
return null;
}
PsiLanguageInjectionHost injectionHost = InjectedLanguageManager.getInstance(element.getProject()).getInjectionHost(element);
final RegExpLanguageHost host = getRegExpHost(injectionHost);
if (host != null) {
return host;
if (ApplicationManager.getApplication().isUnitTestMode() && myHost != null) {
return myHost;
}
final PsiFile file = element.getContainingFile();
final SmartPsiElementPointer pointer = file.getUserData(FileContextUtil.INJECTED_IN_ELEMENT);
if (pointer == null) {
return null;
final PsiElement context = file.getContext();
if (context instanceof RegExpLanguageHost) {
return (RegExpLanguageHost)context;
}
final PsiElement pointerElement = pointer.getElement();
if (pointerElement == null) {
return null;
}
return getRegExpHost(pointerElement);
}
@Nullable
private static RegExpLanguageHost getRegExpHost(@Nullable PsiElement languageInjectionHostElement) {
if (languageInjectionHostElement instanceof RegExpLanguageHost) {
return (RegExpLanguageHost)languageInjectionHostElement;
}
if (languageInjectionHostElement != null) {
return INSTANCE.forClass(languageInjectionHostElement.getClass());
if (context != null) {
return INSTANCE.forClass(context.getClass());
}
return null;
}
@@ -171,7 +154,6 @@ public final class RegExpLanguageHosts extends ClassExtension<RegExpLanguageHost
public boolean supportsNamedCharacters(@NotNull final RegExpNamedCharacter namedCharacter) {
final RegExpLanguageHost host = findRegExpHost(namedCharacter);
System.out.println("host = " + host);
return host != null && host.supportsNamedCharacters(namedCharacter);
}
@@ -33,14 +33,16 @@ public class UnicodeCharacterNames {
try {
final Class<?> aClass = Class.forName("java.lang.CharacterName");
final Method initNamePool = ReflectionUtil.getDeclaredMethod(aClass, "initNamePool");
final int[][] lookup2d = ReflectionUtil.getField(aClass, null, int[][].class, "lookup");
if (initNamePool != null && lookup2d != null) { // jdk 8
byte[] namePool = (byte[])initNamePool.invoke(null);
if (initNamePool != null) { // jdk 8
byte[] namePool = (byte[])initNamePool.invoke(null); // initializes "lookup" field
final int[][] lookup2d = ReflectionUtil.getStaticFieldValue(aClass, int[][].class, "lookup");
if (lookup2d == null) {
return;
}
for (int[] indexes : lookup2d) {
if (indexes != null) {
for (int index : indexes) {
if (index != 0) {
;
final String name = new String(namePool, index >>> 8, index & 0xff, AsciiUtil.ASCII_CHARSET);
consumer.accept(name);
}
@@ -15,9 +15,11 @@
*/
package org.intellij.lang.regexp;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.openapi.application.PathManager;
import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import java.io.File;
import java.util.ArrayList;
@@ -57,6 +59,17 @@ public class RegExpCompletionTest extends CodeInsightFixtureTestCase {
myFixture.checkResult("[[:^alpha:]<caret>");
}
public void testNamedCharacter() {
myFixture.configureByText(RegExpFileType.INSTANCE, "\\\\N{SMILE<caret>}");
final LookupElement[] elements = myFixture.completeBasic();
final List<String> strings = ContainerUtil.map(elements, LookupElement::getLookupString);
assertEquals(Arrays.asList("SMILE", "SMILING FACE WITH SMILING EYES", "SMILING FACE WITH HEART-SHAPED EYES",
"SMILING CAT FACE WITH HEART-SHAPED EYES", "SMILING FACE WITH OPEN MOUTH AND SMILING EYES",
"SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES", "CAT FACE WITH WRY SMILE",
"GRINNING CAT FACE WITH SMILING EYES", "GRINNING FACE WITH SMILING EYES",
"KISSING FACE WITH SMILING EYES"), strings);
}
public void testBackSlashVariants() throws Throwable {
List<String> nameList =
new ArrayList<>(Arrays.asList("d", "D", "s", "S", "w", "W", "b", "B", "A", "G", "Z", "z", "Q", "E",
@@ -65,6 +65,12 @@ abstract class BuildContext {
abstract boolean includeBreakGenLibraries()
/**
* If the method returns {@code false} 'idea.jars.nocopy' property will be set to {@code true} in idea.properties by default. Otherwise it
* won't be set and the IDE will copy library *.jar files to avoid their locking when running under Windows.
*/
abstract boolean shouldIDECopyJarsByDefault()
abstract void patchInspectScript(String path)
abstract String getAdditionalJvmArguments()
@@ -178,6 +178,7 @@ class CommunityRepositoryModules {
plugin("course-creator"),
plugin("course-creator-python"),
plugin("ipnb"),
plugin("IntelliLang-python")
plugin("IntelliLang-python"),
plugin("python-rest")
]
}
@@ -78,7 +78,7 @@ abstract class WindowsDistributionCustomizer {
/**
* The returned name will be used to create links on Desktop
*/
String fullNameIncludingEditionAndVendor(ApplicationInfoProperties applicationInfo) { applicationInfo.shortCompanyName + " " + applicationInfo.productName }
String fullNameIncludingEditionAndVendor(ApplicationInfoProperties applicationInfo) { applicationInfo.shortCompanyName + " " + fullNameIncludingEdition(applicationInfo) }
String uninstallFeedbackPageUrl(ApplicationInfoProperties applicationInfo) {
return null
@@ -259,8 +259,18 @@ class BuildContextImpl extends BuildContext {
@Override
boolean includeBreakGenLibraries() {
return isJavaSupportedInProduct()
}
@Override
boolean shouldIDECopyJarsByDefault() {
return isJavaSupportedInProduct()
}
private boolean isJavaSupportedInProduct() {
def productLayout = productProperties.productLayout
return productLayout.mainJarName == null || //todo[nik] remove this condition later
return productLayout.mainJarName == null ||
//todo[nik] remove this condition later; currently build scripts for IDEA don't fully migrated to the new scheme
productLayout.includedPlatformModules.contains("execution-impl")
}
@@ -84,7 +84,7 @@ class BuildTasksImpl extends BuildTasks {
@Override
void buildSearchableOptions(String targetModuleName, List<String> modulesToIndex, List<String> pathsToLicenses) {
buildSearchableOptions(new File(buildContext.projectBuilder.moduleOutput(buildContext.findModule(targetModuleName))), modulesToIndex, pathsToLicenses)
buildSearchableOptions(new File(buildContext.projectBuilder.moduleOutput(buildContext.findRequiredModule(targetModuleName))), modulesToIndex, pathsToLicenses)
}
//todo[nik] do we need 'cp' and 'jvmArgs' parameters?
@@ -143,6 +143,14 @@ class BuildTasksImpl extends BuildTasks {
File originalFile = new File("$buildContext.paths.communityHome/bin/idea.properties")
String text = originalFile.text
if (!buildContext.shouldIDECopyJarsByDefault()) {
text += """
#---------------------------------------------------------------------
# IDE can copy library .jar files to prevent their locking. Set this property to 'false' to enable copying.
#---------------------------------------------------------------------
idea.jars.nocopy=true
"""
}
buildContext.productProperties.additionalIDEPropertiesFilePaths.each {
text += "\n" + new File(it).text
}
@@ -79,6 +79,7 @@ class DistributionJARsBuilder {
exclude(name: "tips/**")
exclude(name: "tips")
exclude(name: "search/**")
exclude(name: "**/icon-robots.txt")
}
def productLayout = buildContext.productProperties.productLayout
@@ -146,7 +147,8 @@ class DistributionJARsBuilder {
List<String> getPlatformModules() {
(platform.moduleJars.values() as List<String>) +
["java-runtime" /*required to build searchable options index*/, "updater"]
["java-runtime", "platform-main", /*required to build searchable options index*/
"updater", buildContext.productProperties.productLayout.mainModule]
}
@@ -16,8 +16,13 @@
package com.intellij.debugger.actions;
import com.intellij.debugger.SourcePosition;
import com.intellij.debugger.engine.DebuggerUtils;
import com.intellij.debugger.engine.SuspendContextImpl;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilderImpl;
import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator;
import com.intellij.debugger.engine.events.DebuggerContextCommandImpl;
import com.intellij.debugger.impl.DebuggerContextImpl;
import com.intellij.debugger.impl.DebuggerSession;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.jdi.MethodBytecodeUtil;
@@ -36,6 +41,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.util.DocumentUtil;
import com.intellij.util.Range;
import com.intellij.util.ThreeState;
import com.intellij.util.containers.OrderedSet;
import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
import com.sun.jdi.Location;
@@ -68,7 +74,7 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler {
@Override
public void threadAction(@NotNull SuspendContextImpl suspendContext) {
List<SmartStepTarget> targets = ApplicationManager.getApplication().runReadAction(
(Computable<List<SmartStepTarget>>)() -> findSmartStepTargets(position, suspendContext));
(Computable<List<SmartStepTarget>>)() -> findSmartStepTargets(position, suspendContext, getDebuggerContext()));
DebuggerUIUtil.invokeLater(() -> {
if (targets.isEmpty()) {
doStepInto(session, Registry.is("debugger.single.smart.step.force"), null);
@@ -93,7 +99,9 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler {
throw new IllegalStateException("Should not be used");
}
protected List<SmartStepTarget> findSmartStepTargets(final SourcePosition position, @Nullable SuspendContextImpl suspendContext) {
protected List<SmartStepTarget> findSmartStepTargets(final SourcePosition position,
@Nullable SuspendContextImpl suspendContext,
@NotNull DebuggerContextImpl debuggerContext) {
final int line = position.getLine();
if (line < 0) {
return Collections.emptyList(); // the document has been changed
@@ -174,38 +182,78 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler {
@Override
public void visitField(PsiField field) {
TextRange range = field.getTextRange();
if (lineRange.intersects(range)) {
//textRange.set(textRange.get().union(range));
if (checkTextRange(field, false)) {
super.visitField(field);
}
}
@Override
public void visitMethod(PsiMethod method) {
TextRange range = method.getTextRange();
if (lineRange.intersects(range)) {
//textRange.set(textRange.get().union(range));
if (checkTextRange(method, false)) {
super.visitMethod(method);
}
}
@Override
public void visitStatement(PsiStatement statement) {
TextRange range = statement.getTextRange();
if (lineRange.intersects(range)) {
textRange.set(textRange.get().union(range));
if (checkTextRange(statement, true)) {
super.visitStatement(statement);
}
}
@Override
public void visitIfStatement(PsiIfStatement statement) {
visitConditional(statement.getCondition(), statement.getThenBranch(), statement.getElseBranch());
}
@Override
public void visitConditionalExpression(PsiConditionalExpression expression) {
visitConditional(expression.getCondition(), expression.getThenExpression(), expression.getElseExpression());
}
private void visitConditional(@Nullable PsiElement condition,
@Nullable PsiElement thenBranch,
@Nullable PsiElement elseBranch) {
if (condition != null) {
condition.accept(this);
}
ThreeState conditionRes = evaluateCondition(condition);
if (conditionRes != ThreeState.NO && thenBranch != null) {
thenBranch.accept(this);
}
if (conditionRes != ThreeState.YES && elseBranch != null) {
elseBranch.accept(this);
}
}
private ThreeState evaluateCondition(@Nullable PsiElement condition) {
if (condition != null && !DebuggerUtils.hasSideEffects(condition)) {
try {
ExpressionEvaluator evaluator = EvaluatorBuilderImpl.getInstance().build(condition, position);
return ThreeState.fromBoolean(DebuggerUtilsEx.evaluateBoolean(evaluator, debuggerContext.createEvaluationContext()));
}
catch (EvaluateException e) {
LOG.info(e);
}
}
return ThreeState.UNSURE;
}
@Override
public void visitExpression(PsiExpression expression) {
checkTextRange(expression, true);
super.visitExpression(expression);
}
boolean checkTextRange(PsiElement expression, boolean expand) {
TextRange range = expression.getTextRange();
if (lineRange.intersects(range)) {
textRange.set(textRange.get().union(range));
if (expand) {
textRange.set(textRange.get().union(range));
}
return true;
}
super.visitExpression(expression);
return false;
}
public void visitExpressionList(PsiExpressionList expressionList) {
@@ -25,6 +25,8 @@ import com.intellij.debugger.SourcePosition;
import com.intellij.debugger.engine.*;
import com.intellij.debugger.engine.evaluation.*;
import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilder;
import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator;
import com.intellij.debugger.engine.evaluation.expression.UnBoxingEvaluator;
import com.intellij.debugger.engine.requests.RequestManagerImpl;
import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
import com.intellij.debugger.requests.Requestor;
@@ -865,6 +867,14 @@ public abstract class DebuggerUtilsEx extends DebuggerUtils {
return PsiParameter.EMPTY_ARRAY;
}
public static boolean evaluateBoolean(ExpressionEvaluator evaluator, EvaluationContextImpl context) throws EvaluateException {
Object value = UnBoxingEvaluator.unbox(evaluator.evaluate(context), context);
if (!(value instanceof BooleanValue)) {
throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.boolean.expected"));
}
return ((BooleanValue)value).booleanValue();
}
public static boolean intersects(@NotNull TextRange range, @NotNull PsiElement elem) {
TextRange elemRange = elem.getTextRange();
return elemRange != null && elemRange.intersects(range);
@@ -25,8 +25,8 @@ import com.intellij.debugger.engine.*;
import com.intellij.debugger.engine.evaluation.*;
import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilderImpl;
import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator;
import com.intellij.debugger.engine.evaluation.expression.UnBoxingEvaluator;
import com.intellij.debugger.engine.events.SuspendContextCommandImpl;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.jdi.StackFrameProxyImpl;
import com.intellij.debugger.jdi.ThreadReferenceProxyImpl;
import com.intellij.debugger.requests.ClassPrepareRequestor;
@@ -371,13 +371,7 @@ public abstract class Breakpoint<P extends JavaBreakpointProperties> implements
return EvaluatorBuilderImpl.build(getCondition(), contextPsiElement, contextSourcePosition, project);
}
});
Object value = UnBoxingEvaluator.unbox(evaluator.evaluate(context), context);
if (!(value instanceof BooleanValue)) {
throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.boolean.expected"));
}
if (!((BooleanValue)value).booleanValue()) {
return false;
}
return DebuggerUtilsEx.evaluateBoolean(evaluator, context);
}
catch (EvaluateException ex) {
if (ex.getCause() instanceof VMDisconnectedException) {
@@ -387,7 +381,6 @@ public abstract class Breakpoint<P extends JavaBreakpointProperties> implements
DebuggerBundle.message("error.failed.evaluating.breakpoint.condition", getCondition(), ex.getMessage())
);
}
return true;
}
protected String calculateEventClass(EvaluationContextImpl context, LocatableEvent event) throws EvaluateException {
@@ -423,11 +423,14 @@ public abstract class DebuggerUtils {
}
}
public static boolean hasSideEffects(PsiElement element) {
public static boolean hasSideEffects(@Nullable PsiElement element) {
return hasSideEffectsOrReferencesMissingVars(element, null);
}
public static boolean hasSideEffectsOrReferencesMissingVars(PsiElement element, @Nullable final Set<String> visibleLocalVariables) {
public static boolean hasSideEffectsOrReferencesMissingVars(@Nullable PsiElement element, @Nullable final Set<String> visibleLocalVariables) {
if (element == null) {
return false;
}
final Ref<Boolean> rv = new Ref<>(Boolean.FALSE);
element.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
@@ -112,7 +112,7 @@ public class JUnitUtil {
if (psiMethod.hasModifierProperty(PsiModifier.STATIC) && SUITE_METHOD_NAME.equals(psiMethod.getName())) return false;
if (!psiMethod.getName().startsWith("test")) return false;
PsiClass testCaseClass = getTestCaseClassOrNull(location);
return testCaseClass != null && psiMethod.getContainingClass().isInheritor(testCaseClass, true);
return testCaseClass != null && psiMethod.getContainingClass().isInheritor(testCaseClass, true) && PsiType.VOID.equals(psiMethod.getReturnType());
}
public static boolean isTestCaseInheritor(final PsiClass aClass) {
@@ -33,6 +33,10 @@ public abstract class JavaSourceRootDetector extends ProjectStructureDetector {
@Override
public DirectoryProcessingResult detectRoots(@NotNull File dir, @NotNull File[] children, @NotNull File base,
@NotNull List<DetectedProjectRoot> result) {
if (dir.getName().equals("node_modules")) {
return DirectoryProcessingResult.SKIP_CHILDREN;
}
final String fileExtension = getFileExtension();
for (File child : children) {
if (child.isFile() && FileUtilRt.extensionEquals(child.getName(), fileExtension)) {
@@ -45,6 +45,16 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns
private static final String EMPTY_SET_METHOD = "emptySet";
private static final String SINGLETON_LIST_METHOD = "singletonList";
private static final String SINGLETON_METHOD = "singleton";
private static final String COLLECT_METHOD = "collect";
private static final String COUNTING_COLLECTOR = "counting";
private static final String MIN_BY_COLLECTOR = "minBy";
private static final String MAX_BY_COLLECTOR = "maxBy";
private static final String MAPPING_COLLECTOR = "mapping";
private static final String REDUCING_COLLECTOR = "reducing";
private static final String SUMMING_INT_COLLECTOR = "summingInt";
private static final String SUMMING_LONG_COLLECTOR = "summingLong";
private static final String SUMMING_DOUBLE_COLLECTOR = "summingDouble";
@Override
public boolean isEnabledByDefault() {
@@ -95,6 +105,44 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns
holder.registerProblem(methodCall, null, fix.getMessage(), fix);
}
}
else if (isCallOf(method, CommonClassNames.JAVA_UTIL_STREAM_STREAM, COLLECT_METHOD, 1)) {
PsiElement parameter = methodCall.getArgumentList().getExpressions()[0];
if(parameter instanceof PsiMethodCallExpression) {
PsiMethodCallExpression collectorCall = (PsiMethodCallExpression)parameter;
PsiMethod collectorMethod = collectorCall.resolveMethod();
ReplaceCollectorFix fix = null;
if(isCallOf(collectorMethod, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, COUNTING_COLLECTOR, 0)) {
fix = new ReplaceCollectorFix(COUNTING_COLLECTOR, "count()", false);
} else if(isCallOf(collectorMethod, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, MIN_BY_COLLECTOR, 1)) {
fix = new ReplaceCollectorFix(MIN_BY_COLLECTOR, "min({1})", true);
} else if(isCallOf(collectorMethod, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, MAX_BY_COLLECTOR, 1)) {
fix = new ReplaceCollectorFix(MAX_BY_COLLECTOR, "max({1})", true);
} else if(isCallOf(collectorMethod, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, MAPPING_COLLECTOR, 2)) {
fix = new ReplaceCollectorFix(MAPPING_COLLECTOR, "map({1}).collect({2})", false);
} else if(isCallOf(collectorMethod, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, REDUCING_COLLECTOR, 1)) {
fix = new ReplaceCollectorFix(REDUCING_COLLECTOR, "reduce({1})", true);
} else if(isCallOf(collectorMethod, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, REDUCING_COLLECTOR, 2)) {
fix = new ReplaceCollectorFix(REDUCING_COLLECTOR, "reduce({1}, {2})", false);
} else if(isCallOf(collectorMethod, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, REDUCING_COLLECTOR, 3)) {
fix = new ReplaceCollectorFix(REDUCING_COLLECTOR, "map({2}).reduce({1}, {3})", false);
} else if(isCallOf(collectorMethod, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, SUMMING_INT_COLLECTOR, 1)) {
fix = new ReplaceCollectorFix(SUMMING_INT_COLLECTOR, "mapToInt({1}).sum()", false);
} else if(isCallOf(collectorMethod, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, SUMMING_LONG_COLLECTOR, 1)) {
fix = new ReplaceCollectorFix(SUMMING_LONG_COLLECTOR, "mapToLong({1}).sum()", false);
} else if(isCallOf(collectorMethod, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, SUMMING_DOUBLE_COLLECTOR, 1)) {
fix = new ReplaceCollectorFix(SUMMING_DOUBLE_COLLECTOR, "mapToDouble({1}).sum()", false);
}
if (fix != null &&
collectorCall.getArgumentList().getExpressions().length == collectorMethod.getParameterList().getParametersCount()) {
TextRange range = methodCall.getTextRange();
PsiElement nameElement = methodCall.getMethodExpression().getReferenceNameElement();
if(nameElement != null) {
range = new TextRange(nameElement.getTextOffset(), range.getEndOffset());
}
holder.registerProblem(methodCall, range.shiftRight(-methodCall.getTextOffset()), fix.getMessage(), fix);
}
}
}
else {
final String name;
if (isCallOf(method, CommonClassNames.JAVA_UTIL_STREAM_STREAM, FOR_EACH_METHOD, 1)) {
@@ -390,4 +438,87 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns
}
}
}
private static class ReplaceCollectorFix implements LocalQuickFix {
private final String myCollector;
private final String myStreamSequence;
private final String myStreamSequenceStripped;
private final boolean myChangeSemantics;
public ReplaceCollectorFix(String collector, String streamSequence, boolean changeSemantics) {
myCollector = collector;
myStreamSequence = streamSequence;
myStreamSequenceStripped = streamSequence.replaceAll("\\([^)]+\\)", "()");
myChangeSemantics = changeSemantics;
}
@Nls
@NotNull
@Override
public String getName() {
return getFamilyName();
}
@Nls
@NotNull
@Override
public String getFamilyName() {
return "Replace Stream.collect(" + myCollector +
"()) with Stream." + myStreamSequenceStripped +
(myChangeSemantics ? " (may change semantics when result is null)" : "");
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PsiElement element = descriptor.getStartElement();
if (element instanceof PsiMethodCallExpression) {
PsiMethodCallExpression collectCall = (PsiMethodCallExpression)element;
PsiExpression qualifierExpression = collectCall.getMethodExpression().getQualifierExpression();
if (qualifierExpression != null) {
PsiElement parameter = collectCall.getArgumentList().getExpressions()[0];
if (parameter instanceof PsiMethodCallExpression) {
PsiMethodCallExpression collectorCall = (PsiMethodCallExpression)parameter;
PsiExpression[] collectorArgs = collectorCall.getArgumentList().getExpressions();
String result = myStreamSequence;
for(int i=0; i<collectorArgs.length; i++) {
result = result.replace("{"+(i+1)+"}", collectorArgs[i].getText());
}
if (!FileModificationService.getInstance().preparePsiElementForWrite(element.getContainingFile())) return;
PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
PsiExpression replacement = factory.createExpressionFromText(
qualifierExpression.getText() + "." + result, collectCall);
PsiElement expression = collectCall.replace(replacement);
// Replacements like .collect(counting()) -> .count() change the result type from boxed to primitive
// In rare cases it's necessary to add cast to return back to boxed type
// example:
// List<Integer> intList; List<String> stringList;
// intList.remove(stringList.stream().collect(summingInt(String::length)) -- remove given element
// intList.remove(stringList.stream().mapToInt(String::length).sum()) -- remove element by index
if(expression instanceof PsiExpression) {
PsiType type = ((PsiExpression)expression).getType();
if(type instanceof PsiPrimitiveType) {
PsiClassType boxedType = ((PsiPrimitiveType)type).getBoxedType(expression);
if(boxedType != null) {
PsiExpression castExpression =
factory.createExpressionFromText("(" + boxedType.getCanonicalText() + ") " + expression.getText(), expression);
PsiElement cast = expression.replace(castExpression);
if (cast instanceof PsiTypeCastExpression && RedundantCastUtil.isCastRedundant((PsiTypeCastExpression)cast)) {
RedundantCastUtil.removeCast((PsiTypeCastExpression)cast);
}
}
}
}
}
}
}
}
@NotNull
String getMessage() {
return "Stream.collect(" + myCollector +
"()) can be replaced with Stream." + myStreamSequenceStripped + "()" +
(myChangeSemantics ? " (may change semantics when result is null)" : "");
}
}
}
@@ -126,13 +126,8 @@ public class AllClassesGetter {
public static final InsertHandler<JavaPsiClassReferenceElement> INSERT_FQN = (context, item) -> {
final String qName = item.getQualifiedName();
if (qName != null) {
int start = context.getTailOffset() - 1;
while (start >= 0) {
final char ch = context.getDocument().getCharsSequence().charAt(start);
if (!Character.isJavaIdentifierPart(ch) && ch != '.') break;
start--;
}
context.getDocument().replaceString(start + 1, context.getTailOffset(), qName);
int start = JavaCompletionUtil.findQualifiedNameStart(context);
context.getDocument().replaceString(start, context.getTailOffset(), qName);
LOG.assertTrue(context.getTailOffset() >= 0);
}
};
@@ -7,7 +7,10 @@ import com.intellij.codeInsight.generation.OverrideImplementExploreUtil;
import com.intellij.codeInsight.generation.OverrideImplementUtil;
import com.intellij.codeInsight.generation.PsiGenerationInfo;
import com.intellij.codeInsight.intention.impl.TypeExpression;
import com.intellij.codeInsight.lookup.*;
import com.intellij.codeInsight.lookup.Lookup;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementDecorator;
import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
import com.intellij.codeInsight.template.*;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.application.ApplicationManager;
@@ -260,6 +263,8 @@ public class ConstructorInsertHandler implements InsertHandler<LookupElementDeco
private static Runnable createOverrideRunnable(final Editor editor, final PsiFile file, final Project project) {
return () -> {
TemplateManager.getInstance(project).finishTemplate(editor);
PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
final PsiAnonymousClass
aClass = PsiTreeUtil.findElementOfClassAtOffset(file, editor.getCaretModel().getOffset(), PsiAnonymousClass.class, false);
@@ -16,7 +16,6 @@
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.AutoPopupController;
import com.intellij.codeInsight.ExpectedTypeInfo;
import com.intellij.codeInsight.ExpectedTypesProvider;
import com.intellij.codeInsight.lookup.Lookup;
import com.intellij.codeInsight.lookup.LookupElement;
@@ -34,6 +33,7 @@ import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.javadoc.PsiDocTag;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import static com.intellij.psi.codeStyle.JavaCodeStyleSettings.*;
@@ -159,18 +159,17 @@ class JavaClassNameInsertHandler implements InsertHandler<JavaPsiClassReferenceE
final PsiElement prevElement = FilterPositionUtil.searchNonSpaceNonCommentBack(ref);
if (prevElement != null && prevElement.getParent() instanceof PsiNewExpression) {
for (ExpectedTypeInfo info : ExpectedTypesProvider.getExpectedTypes((PsiExpression)prevElement.getParent(), true)) {
if (info.getType() instanceof PsiArrayType) {
return false;
}
}
return true;
return !isArrayTypeExpected((PsiExpression)prevElement.getParent());
}
return false;
}
static boolean isArrayTypeExpected(PsiExpression expr) {
return ContainerUtil.exists(ExpectedTypesProvider.getExpectedTypes(expr, true),
info -> info.getType() instanceof PsiArrayType);
}
private static boolean insertingAnnotation(InsertionContext context, LookupElement item) {
final Object obj = item.getObject();
if (!(obj instanceof PsiClass) || !((PsiClass)obj).isAnnotationType()) return false;
@@ -226,12 +226,8 @@ public class JavaCompletionContributor extends CompletionContributor {
PrefixMatcher matcher = result.getPrefixMatcher();
PsiElement parent = position.getParent();
if (JavaModuleCompletion.isModuleFile(position.getContainingFile())) {
JavaModuleCompletion.addVariants(position, element -> {
if (element.getLookupString().startsWith(result.getPrefixMatcher().getPrefix())) {
result.addElement(element);
}
});
if (JavaModuleCompletion.isModuleFile(parameters.getOriginalFile())) {
JavaModuleCompletion.addVariants(position, result);
result.stopHere();
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.
@@ -528,10 +528,7 @@ public class JavaCompletionUtil {
.accepts(reference),
JavaClassNameInsertHandler.JAVA_CLASS_INSERT_HANDLER,
Conditions.alwaysTrue());
if (JavaClassNameCompletionContributor.AFTER_NEW.accepts(reference)) {
return JBIterable.from(classItems).flatMap(i -> JavaConstructorCallElement.wrap(i, reference.getElement()));
}
return classItems;
return JBIterable.from(classItems).flatMap(i -> JavaConstructorCallElement.wrap(i, reference.getElement()));
}
}
@@ -544,11 +541,7 @@ public class JavaCompletionUtil {
if (completion instanceof PsiClass) {
JavaPsiClassReferenceElement classItem =
JavaClassNameCompletionContributor.createClassLookupItem((PsiClass)completion, true).setSubstitutor(substitutor);
if (JavaClassNameCompletionContributor.AFTER_NEW.accepts(reference)) {
return JavaConstructorCallElement.wrap(classItem, reference.getElement());
}
return Collections.singletonList(classItem);
return JavaConstructorCallElement.wrap(classItem, reference.getElement());
}
if (completion instanceof PsiMethod) {
JavaMethodCallElement item = new JavaMethodCallElement((PsiMethod)completion).setQualifierSubstitutor(substitutor);
@@ -935,4 +928,14 @@ public class JavaCompletionUtil {
}
return false;
}
}
public static int findQualifiedNameStart(@NotNull InsertionContext context) {
int start = context.getTailOffset() - 1;
while (start >= 0) {
char ch = context.getDocument().getCharsSequence().charAt(start);
if (!Character.isJavaIdentifierPart(ch) && ch != '.') break;
start--;
}
return start + 1;
}
}
@@ -20,7 +20,11 @@ import com.intellij.codeInsight.lookup.LookupElementDecorator;
import com.intellij.codeInsight.lookup.LookupElementPresentation;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.JBIterable;
import org.jetbrains.annotations.NotNull;
@@ -42,6 +46,10 @@ public class JavaConstructorCallElement extends JavaMethodCallElement {
myType = type.get();
setQualifierSubstitutor(myType.resolveGenerics().getSubstitutor());
markClassItemWrapped(classItem);
}
private void markClassItemWrapped(@NotNull LookupElement classItem) {
LookupElement delegate = classItem;
while (true) {
delegate.putUserData(WRAPPING_CONSTRUCTOR_CALL, this);
@@ -65,19 +73,24 @@ public class JavaConstructorCallElement extends JavaMethodCallElement {
@Override
public void renderElement(LookupElementPresentation presentation) {
myClassItem.renderElement(presentation);
String itemText = presentation.getItemText();
super.renderElement(presentation);
presentation.setItemText(itemText);
String tailText = StringUtil.notNullize(presentation.getTailText());
int genericsEnd = tailText.lastIndexOf('>') + 1;
presentation.clearTail();
presentation.appendTailText(tailText.substring(0, genericsEnd), false);
presentation.appendTailText(MemberLookupHelper.getMethodParameterString(getObject(), getSubstitutor()), false);
presentation.appendTailText(tailText.substring(genericsEnd), true);
}
static List<? extends LookupElement> wrap(JavaPsiClassReferenceElement classItem, PsiElement position) {
static List<? extends LookupElement> wrap(@NotNull JavaPsiClassReferenceElement classItem, @NotNull PsiElement position) {
PsiClass psiClass = classItem.getObject();
return wrap(classItem, psiClass, position, () -> JavaPsiFacade.getElementFactory(psiClass.getProject()).createType(psiClass, PsiSubstitutor.EMPTY));
}
static List<? extends LookupElement> wrap(LookupElement classItem, PsiClass psiClass, PsiElement position, Supplier<PsiClassType> type) {
if (Registry.is("java.completion.show.constructors") && JavaClassNameCompletionContributor.AFTER_NEW.accepts(position)) {
static List<? extends LookupElement> wrap(@NotNull LookupElement classItem, @NotNull PsiClass psiClass,
@NotNull PsiElement position, @NotNull Supplier<PsiClassType> type) {
if (Registry.is("java.completion.show.constructors") && isConstructorCallPlace(position)) {
PsiMethod[] constructors = psiClass.getConstructors();
if (constructors.length > 0) {
return JBIterable.of(constructors).
@@ -89,6 +102,14 @@ public class JavaConstructorCallElement extends JavaMethodCallElement {
return Collections.singletonList(classItem);
}
private static boolean isConstructorCallPlace(@NotNull PsiElement position) {
return CachedValuesManager.getCachedValue(position, () -> {
boolean result = JavaClassNameCompletionContributor.AFTER_NEW.accepts(position) &&
!JavaClassNameInsertHandler.isArrayTypeExpected(PsiTreeUtil.getParentOfType(position, PsiNewExpression.class));
return CachedValueProvider.Result.create(result, position);
});
}
static boolean isWrapped(LookupElement element) {
return element.getUserData(WRAPPING_CONSTRUCTOR_CALL) != null;
}
@@ -22,10 +22,15 @@ import com.intellij.codeInsight.template.Template;
import com.intellij.codeInsight.template.TemplateManager;
import com.intellij.codeInsight.template.impl.ConstantNode;
import com.intellij.codeInsight.template.impl.MacroCallNode;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
import com.intellij.codeInsight.template.macro.CompleteMacro;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.util.ClassConditionKey;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
@@ -170,7 +175,7 @@ public class JavaMethodCallElement extends LookupItem<PsiMethod> implements Type
}
}
if (hasParams && Registry.is("java.completion.argument.live.template")) {
if (hasParams && context.getCompletionChar() != Lookup.COMPLETE_STATEMENT_SELECT_CHAR && Registry.is("java.completion.argument.live.template")) {
startArgumentLiveTemplate(context, method);
}
}
@@ -187,7 +192,8 @@ public class JavaMethodCallElement extends LookupItem<PsiMethod> implements Type
qualifyMethodCall(file, startOffset, document);
}
private static void startArgumentLiveTemplate(InsertionContext context, PsiMethod method) {
public static final Key<JavaMethodCallElement> ARGUMENT_TEMPLATE_ACTIVE = Key.create("ARGUMENT_TEMPLATE_ACTIVE");
private void startArgumentLiveTemplate(InsertionContext context, PsiMethod method) {
TemplateManager manager = TemplateManager.getInstance(method.getProject());
Template template = manager.createTemplate("", "");
PsiParameter[] parameters = method.getParameterList().getParameters();
@@ -199,7 +205,18 @@ public class JavaMethodCallElement extends LookupItem<PsiMethod> implements Type
template.addVariable(name, new MacroCallNode(new CompleteMacro()), new ConstantNode(name), true);
}
manager.startTemplate(context.getEditor(), template);
Editor editor = context.getEditor();
manager.startTemplate(editor, template);
TemplateState templateState = TemplateManagerImpl.getTemplateState(editor);
if (templateState == null) return;
editor.putUserData(ARGUMENT_TEMPLATE_ACTIVE, this);
Disposer.register(templateState, () -> {
if (editor.getUserData(ARGUMENT_TEMPLATE_ACTIVE) == this) {
editor.putUserData(ARGUMENT_TEMPLATE_ACTIVE, null);
}
});
}
private boolean shouldInsertTypeParameters() {
@@ -19,21 +19,22 @@ import com.intellij.codeInsight.TailType;
import com.intellij.codeInsight.completion.JavaKeywordCompletion.OverrideableSpace;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.module.impl.scopes.ModulesScope;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.impl.file.impl.JavaFileManager;
import com.intellij.psi.impl.java.stubs.index.JavaModuleNameIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
import java.util.function.Predicate;
import static com.intellij.codeInsight.completion.JavaKeywordCompletion.createKeyword;
class JavaModuleCompletion {
@@ -41,7 +42,13 @@ class JavaModuleCompletion {
return PsiUtil.isLanguageLevel9OrHigher(file) && PsiJavaModule.MODULE_INFO_FILE.equals(file.getName());
}
static void addVariants(@NotNull PsiElement position, @NotNull Consumer<LookupElement> result) {
static void addVariants(@NotNull PsiElement position, @NotNull CompletionResultSet resultSet) {
Consumer<LookupElement> result = element -> {
if (element.getLookupString().startsWith(resultSet.getPrefixMatcher().getPrefix())) {
resultSet.addElement(element);
}
};
if (position instanceof PsiIdentifier) {
PsiElement context = position.getParent();
if (context instanceof PsiErrorElement) context = context.getParent();
@@ -52,11 +59,14 @@ class JavaModuleCompletion {
else if (context instanceof PsiJavaModule) {
addModuleStatementKeywords(position, result);
}
else if (context instanceof PsiProvidesStatement) {
addProvidesStatementKeywords(position, result);
}
else if (context instanceof PsiJavaModuleReferenceElement) {
addModuleReferences(context, result);
}
else if (context instanceof PsiJavaCodeReferenceElement) {
addCodeReferences(context, result);
addCodeReferences(context, result, resultSet);
}
}
}
@@ -74,6 +84,10 @@ class JavaModuleCompletion {
result.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.PROVIDES), TailType.HUMBLE_SPACE_BEFORE_WORD));
}
private static void addProvidesStatementKeywords(PsiElement position, Consumer<LookupElement> result) {
result.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.WITH), TailType.HUMBLE_SPACE_BEFORE_WORD));
}
private static void addModuleReferences(PsiElement context, Consumer<LookupElement> result) {
PsiJavaModule host = PsiTreeUtil.getParentOfType(context, PsiJavaModule.class);
if (host != null) {
@@ -90,24 +104,81 @@ class JavaModuleCompletion {
}
}
private static void addCodeReferences(PsiElement context, Consumer<LookupElement> result) {
PsiElement statement = PsiTreeUtil.skipParentsOfType(context, PsiJavaCodeReferenceElement.class);
private static void addCodeReferences(PsiElement context, Consumer<LookupElement> result, CompletionResultSet resultSet) {
PsiElement statement = context.getParent();
if (statement instanceof PsiExportsStatement) {
Module module = ModuleUtilCore.findModuleForPsiElement(context);
PsiPackage topPackage = ServiceManager.getService(context.getProject(), JavaFileManager.class).findPackage("");
PsiPackage topPackage = JavaPsiFacade.getInstance(context.getProject()).findPackage("");
if (module != null && topPackage != null) {
processPackage(topPackage, new ModulesScope(module), result);
}
}
else if (statement instanceof PsiUsesStatement) {
processClasses(context.getProject(), null, resultSet, SERVICE_FILTER, TailType.SEMICOLON);
}
else if (statement instanceof PsiProvidesStatement) {
PsiJavaCodeReferenceElement intRef = ((PsiProvidesStatement)statement).getInterfaceReference();
if (context == intRef) {
processClasses(context.getProject(), null, resultSet, SERVICE_FILTER, TailType.HUMBLE_SPACE_BEFORE_WORD);
}
else if (context == ((PsiProvidesStatement)statement).getImplementationReference() && intRef != null) {
PsiElement service = intRef.resolve();
Module module = ModuleUtilCore.findModuleForPsiElement(context);
if (service instanceof PsiClass && module != null) {
Predicate<PsiClass> filter = psiClass -> !psiClass.hasModifierProperty(PsiModifier.ABSTRACT) &&
InheritanceUtil.isInheritorOrSelf(psiClass, (PsiClass)service, true);
processClasses(context.getProject(), new ModulesScope(module), resultSet, filter, TailType.SEMICOLON);
}
}
}
}
private static void processPackage(PsiPackage pkg, ModulesScope scope, Consumer<LookupElement> result) {
String packageName = pkg.getQualifiedName();
if (packageName.indexOf('.') > 0 && !PsiUtil.isPackageEmpty(pkg.getDirectories(scope), packageName)) {
result.consume(new OverrideableSpace(LookupElementBuilder.create(packageName), TailType.SEMICOLON));
if (isQualified(packageName) && !PsiUtil.isPackageEmpty(pkg.getDirectories(scope), packageName)) {
result.consume(new OverrideableSpace(lookupElement(pkg), TailType.SEMICOLON));
}
for (PsiPackage subPackage : pkg.getSubPackages(scope)) {
processPackage(subPackage, scope, result);
}
}
private static final Predicate<PsiClass> SERVICE_FILTER =
psiClass -> !psiClass.isEnum() && psiClass.hasModifierProperty(PsiModifier.PUBLIC);
private static void processClasses(Project project,
GlobalSearchScope scope,
CompletionResultSet resultSet,
Predicate<PsiClass> filter,
TailType tail) {
GlobalSearchScope _scope = scope != null ? scope : ProjectScope.getAllScope(project);
AllClassesGetter.processJavaClasses(resultSet.getPrefixMatcher(), project, _scope, psiClass -> {
if (isQualified(psiClass.getQualifiedName()) && filter.test(psiClass)) {
resultSet.addElement(new OverrideableSpace(lookupElement(psiClass), tail));
}
return true;
});
}
private static LookupElementBuilder lookupElement(PsiNamedElement e) {
LookupElementBuilder lookup = LookupElementBuilder.create(e).withInsertHandler(FQN_INSERT_HANDLER);
String fqn = e instanceof PsiClass ? ((PsiClass)e).getQualifiedName() : ((PsiQualifiedNamedElement)e).getQualifiedName();
return fqn != null ? lookup.withPresentableText(fqn) : lookup;
}
private static boolean isQualified(String name) {
return name != null && name.indexOf('.') > 0;
}
private static final InsertHandler<LookupElement> FQN_INSERT_HANDLER = new InsertHandler<LookupElement>() {
@Override
public void handleInsert(InsertionContext context, LookupElement item) {
Object e = item.getObject();
String fqn = e instanceof PsiClass ? ((PsiClass)e).getQualifiedName() : ((PsiQualifiedNamedElement)e).getQualifiedName();
if (fqn != null) {
int start = JavaCompletionUtil.findQualifiedNameStart(context);
context.getDocument().replaceString(start, context.getTailOffset(), fqn);
}
}
};
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 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.
@@ -42,6 +42,10 @@ import static com.intellij.patterns.PsiJavaPatterns.psiElement;
public class JavaNoVariantsDelegator extends CompletionContributor {
@Override
public void fillCompletionVariants(@NotNull final CompletionParameters parameters, @NotNull final CompletionResultSet result) {
if (JavaModuleCompletion.isModuleFile(parameters.getOriginalFile())) {
return;
}
final JavaCompletionSession session = new JavaCompletionSession(result);
ResultTracker tracker = new ResultTracker(result) {
@Override
@@ -20,6 +20,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiFormatUtil;
import com.intellij.psi.util.PsiFormatUtilBase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
@@ -78,9 +79,7 @@ public class MemberLookupHelper {
final String params = myMergedOverloads
? "(...)"
: myMember instanceof PsiMethod
? PsiFormatUtil.formatMethod((PsiMethod)myMember, substitutor,
PsiFormatUtilBase.SHOW_PARAMETERS,
PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_TYPE)
? getMethodParameterString((PsiMethod)myMember, substitutor)
: "";
presentation.clearTail();
presentation.appendTailText(params, false);
@@ -96,5 +95,9 @@ public class MemberLookupHelper {
}
}
@NotNull
static String getMethodParameterString(@NotNull PsiMethod method, @NotNull PsiSubstitutor substitutor) {
return PsiFormatUtil.formatMethod(method, substitutor,
PsiFormatUtilBase.SHOW_PARAMETERS, PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_TYPE);
}
}
@@ -16,10 +16,13 @@
package com.intellij.codeInsight.template.macro;
import com.intellij.codeInsight.completion.JavaCompletionUtil;
import com.intellij.codeInsight.completion.JavaMethodCallElement;
import com.intellij.codeInsight.completion.SmartCompletionDecorator;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.template.ExpressionContext;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.util.ClassConditionKey;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiPackage;
import java.util.List;
@@ -34,6 +37,12 @@ public class JavaTemplateCompletionProcessor implements TemplateCompletionProces
if (elements != null && elements.size() == 1 && elements.get(0) instanceof PsiPackage) {
return false;
}
Editor editor = context.getEditor();
if (editor != null && editor.getUserData(JavaMethodCallElement.ARGUMENT_TEMPLATE_ACTIVE) != null) {
return item.as(ClassConditionKey.create(SmartCompletionDecorator.class)) != null;
}
return true;
}
}
@@ -15,7 +15,6 @@
*/
package com.intellij.codeInspection.deadCode;
import com.intellij.codeInspection.CommonProblemDescriptor;
import com.intellij.codeInspection.GlobalJavaInspectionContext;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.ex.*;
@@ -24,6 +23,7 @@ import com.intellij.codeInspection.reference.RefEntity;
import com.intellij.codeInspection.reference.RefJavaElement;
import com.intellij.codeInspection.ui.InspectionNode;
import com.intellij.codeInspection.ui.InspectionResultsView;
import com.intellij.codeInspection.ui.InspectionTree;
import com.intellij.codeInspection.ui.InspectionTreeNode;
import com.intellij.codeInspection.util.RefFilter;
import com.intellij.openapi.actionSystem.AnActionEvent;
@@ -43,7 +43,7 @@ public class DummyEntryPointsPresentation extends UnusedDeclarationPresentation
}
@Override
public QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements, CommonProblemDescriptor[] allowedDescriptors) {
public QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements, InspectionTree tree) {
if (myQuickFixActions == null) {
myQuickFixActions = new QuickFixAction[]{new MoveEntriesToSuspicious(getToolWrapper())};
}
@@ -67,6 +67,7 @@ import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;
import javax.swing.tree.TreePath;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
@@ -182,7 +183,7 @@ public class UnusedDeclarationPresentation extends DefaultInspectionToolPresenta
}
@Override
public QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements, CommonProblemDescriptor[] allowedDescriptors) {
public QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements, InspectionTree tree) {
boolean showFixes = false;
for (RefEntity element : refElements) {
if (!getIgnoredRefElements().contains(element) && element.isValid()) {
@@ -192,8 +193,23 @@ public class UnusedDeclarationPresentation extends DefaultInspectionToolPresenta
}
if (showFixes) {
final QuickFixAction[] fixes = super.getQuickFixes(refElements, allowedDescriptors);
return fixes != null ? ArrayUtil.mergeArrays(fixes, myQuickFixActions) : myQuickFixActions;
final TreePath[] paths = tree.getSelectionPaths();
if (paths != null) {
int count = 0;
for (TreePath path : paths) {
final Object component = path.getLastPathComponent();
if (component instanceof ProblemDescriptionNode) {
count++;
}
}
if (count > 0) {
final QuickFixAction[] fixes = super.getQuickFixes(refElements, tree);
if (fixes != null) {
return count == paths.length ? fixes : ArrayUtil.mergeArrays(fixes, myQuickFixActions);
}
}
}
return myQuickFixActions;
}
return QuickFixAction.EMPTY;
}
@@ -23,6 +23,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.PathManager
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.Inlay
import com.intellij.openapi.project.Project
@@ -35,6 +36,10 @@ class ReportMissingOrExcessiveInlineHint : AnAction() {
private val text = "Report Missing or Excessive Inline Hint"
private val description = "Text line at caret will be anonymously reported to our servers"
companion object {
private val LOG = Logger.getInstance(ReportMissingOrExcessiveInlineHint::class.java)
}
init {
val presentation = templatePresentation
presentation.text = text
@@ -85,12 +90,14 @@ class ReportMissingOrExcessiveInlineHint : AnAction() {
}
private fun trySendFileInBackground() {
LOG.debug("File: ${file.path} Length: ${file.length()}")
if (!file.exists() || file.length() == 0L) return
ApplicationManager.getApplication().executeOnPooledThread {
val text = file.readText()
LOG.debug("File text $text")
if (StatsSender.send(text)) {
file.delete()
LOG.debug("File deleted")
}
}
}
@@ -63,9 +63,10 @@ class ConstructorReferencesSearchHelper {
DumbService.getInstance(project).runReadActionInSmartMode(new Computable<Void>() {
@Override
public Void compute() {
constructorCanBeCalledImplicitly[0] = constructor.getParameterList().getParametersCount() == 0;
final PsiParameter[] parameters = constructor.getParameterList().getParameters();
constructorCanBeCalledImplicitly[0] = parameters.length == 0;
if (!constructorCanBeCalledImplicitly[0]) {
constructorCanBeCalledImplicitly[0] = hasDefaultConstructorWithVarargParameter(containingClass);
constructorCanBeCalledImplicitly[0] = parameters.length == 1 && parameters[0].isVarArgs();
}
isEnum[0] = containingClass.isEnum();
isUnder18[0] = PsiUtil.getLanguageLevel(containingClass).isAtLeast(LanguageLevel.JDK_1_8);
@@ -127,17 +128,6 @@ class ConstructorReferencesSearchHelper {
return ClassInheritorsSearch.search(containingClass, searchScope, false).forEach(processor2);
}
private static boolean hasDefaultConstructorWithVarargParameter(@NotNull PsiClass containingClass) {
final PsiMethod[] constructors = containingClass.getConstructors();
for (PsiMethod ctr : constructors) {
final PsiParameter[] parameters = ctr.getParameterList().getParameters();
if (parameters.length == 1 && parameters[0].isVarArgs()) {
return true;
}
}
return false;
}
private static boolean processEnumReferences(@NotNull final Processor<PsiReference> processor,
@NotNull final PsiMethod constructor,
@NotNull final Project project,
@@ -21,13 +21,19 @@ import com.intellij.psi.JavaTokenType;
import com.intellij.psi.PsiKeyword;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
import static com.intellij.lang.PsiBuilderUtil.expect;
import static com.intellij.lang.java.parser.JavaParserUtil.error;
import static com.intellij.lang.java.parser.JavaParserUtil.semicolon;
public class ModuleParser {
private static final Set<String> STATEMENT_KEYWORDS =
ContainerUtil.newHashSet(PsiKeyword.REQUIRES, PsiKeyword.EXPORTS, PsiKeyword.USES, PsiKeyword.PROVIDES);
public static void parseModule(@NotNull PsiBuilder builder) {
PsiBuilder.Marker module = builder.mark();
mapAndAdvance(builder, JavaTokenType.MODULE_KEYWORD);
@@ -225,7 +231,15 @@ public class ModuleParser {
}
}
else if (!hasError) {
error(builder, JavaErrorMessages.message("expected.with"));
IElementType next = builder.getTokenType();
if (next == JavaTokenType.IDENTIFIER && !STATEMENT_KEYWORDS.contains(builder.getTokenText())) {
PsiBuilder.Marker marker = builder.mark();
builder.advanceLexer();
marker.error(JavaErrorMessages.message("expected.with"));
}
else {
error(builder, JavaErrorMessages.message("expected.with"));
}
hasError = true;
}
@@ -20,7 +20,6 @@ import com.intellij.psi.*;
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
import com.intellij.psi.impl.java.stubs.PsiClassStub;
import com.intellij.psi.impl.source.tree.ChildRole;
import com.intellij.psi.impl.source.tree.SharedImplUtil;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.reference.SoftReference;
import com.intellij.util.IncorrectOperationException;
@@ -66,7 +65,7 @@ public class PsiAnonymousClassImpl extends PsiClassImpl implements PsiAnonymousC
@Override
@NotNull
public PsiClassType getBaseClassType() {
final PsiClassStub stub = getStub();
final PsiClassStub stub = getGreenStub();
if (stub == null) {
myCachedBaseType = null;
return getTypeByTree();
@@ -192,7 +191,7 @@ public class PsiAnonymousClassImpl extends PsiClassImpl implements PsiAnonymousC
@Override
public boolean isInQualifiedNew() {
final PsiClassStub stub = getStub();
final PsiClassStub stub = getGreenStub();
if (stub != null) {
return stub.isAnonymousInQualifiedNew();
}
@@ -242,7 +242,7 @@ public class PsiClassImpl extends JavaStubPsiElement<PsiClassStub<?>> implements
@Override
@Nullable
public PsiClass getContainingClass() {
final PsiClassStub stub = getStub();
final PsiClassStub stub = getGreenStub();
if (stub != null) {
StubElement parent = stub.getParentStub();
return parent instanceof PsiClassStub ? ((PsiClassStub<?>)parent).getPsi() : null;
@@ -540,7 +540,7 @@ public class PsiClassImpl extends JavaStubPsiElement<PsiClassStub<?>> implements
private static boolean isAnonymousOrLocal(PsiClass aClass) {
if (aClass instanceof PsiAnonymousClass) return true;
final PsiClassStub stub = ((PsiClassImpl)aClass).getStub();
final PsiClassStub stub = ((PsiClassImpl)aClass).getGreenStub();
if (stub != null) {
final StubElement parentStub = stub.getParentStub();
return !(parentStub instanceof PsiClassStub || parentStub instanceof PsiFileStub);
@@ -174,7 +174,7 @@ public class PsiEnumConstantImpl extends JavaStubPsiElement<PsiFieldStub> implem
@Override
@NotNull
public String getName() {
final PsiFieldStub stub = getStub();
final PsiFieldStub stub = getGreenStub();
if (stub != null) {
return stub.getName();
}
@@ -194,7 +194,7 @@ public class PsiEnumConstantImpl extends JavaStubPsiElement<PsiFieldStub> implem
@Override
public boolean isDeprecated() {
final PsiFieldStub stub = getStub();
final PsiFieldStub stub = getGreenStub();
if (stub != null) {
return stub.isDeprecated();
}
@@ -104,7 +104,7 @@ public class PsiFieldImpl extends JavaStubPsiElement<PsiFieldStub> implements Ps
@Override
@NotNull
public String getName() {
final PsiFieldStub stub = getStub();
final PsiFieldStub stub = getGreenStub();
if (stub != null) {
return stub.getName();
}
@@ -185,7 +185,7 @@ public class PsiFieldImpl extends JavaStubPsiElement<PsiFieldStub> implements Ps
private PsiField findFirstFieldInDeclaration() {
if (getSelfModifierList() != null) return this;
final PsiFieldStub stub = getStub();
final PsiFieldStub stub = getGreenStub();
if (stub != null) {
final List siblings = stub.getParentStub().getChildrenStubs();
final int idx = siblings.indexOf(stub);
@@ -226,7 +226,7 @@ public class PsiFieldImpl extends JavaStubPsiElement<PsiFieldStub> implements Ps
// avoids stub-to-AST switch if possible,
// returns the light generated initializer literal expression if stored in stubs, the regular initializer if wasn't
public PsiExpression getDetachedInitializer() {
final PsiFieldStub stub = getStub();
final PsiFieldStub stub = getGreenStub();
PsiExpression initializer;
if (stub == null) {
initializer = getInitializer();
@@ -251,7 +251,7 @@ public class PsiFieldImpl extends JavaStubPsiElement<PsiFieldStub> implements Ps
@Override
public boolean hasInitializer() {
PsiFieldStub stub = getStub();
PsiFieldStub stub = getGreenStub();
if (stub != null) {
return stub.getInitializerText() != null;
}
@@ -299,7 +299,7 @@ public class PsiFieldImpl extends JavaStubPsiElement<PsiFieldStub> implements Ps
@Override
public boolean isDeprecated() {
final PsiFieldStub stub = getStub();
final PsiFieldStub stub = getGreenStub();
if (stub != null) {
return stub.isDeprecated() || stub.hasDeprecatedAnnotation() && PsiImplUtil.isDeprecatedByAnnotation(this);
}
@@ -309,7 +309,7 @@ public class PsiFieldImpl extends JavaStubPsiElement<PsiFieldStub> implements Ps
@Override
public PsiDocComment getDocComment(){
final PsiFieldStub stub = getStub();
final PsiFieldStub stub = getGreenStub();
if (stub != null && !stub.hasDocComment()) return null;
CompositeElement treeElement = getNode();
@@ -40,7 +40,7 @@ public abstract class PsiImportStatementBaseImpl extends JavaStubPsiElement<PsiI
@Override
public boolean isOnDemand(){
final PsiImportStatementStub stub = getStub();
final PsiImportStatementStub stub = getGreenStub();
if (stub != null) {
return stub.isOnDemand();
}
@@ -42,7 +42,7 @@ public class PsiImportStatementImpl extends PsiImportStatementBaseImpl implement
@Override
public String getQualifiedName() {
PsiImportStatementStub stub = getStub();
PsiImportStatementStub stub = getGreenStub();
if (stub != null) {
return stub.getImportReferenceText();
}
@@ -38,7 +38,7 @@ public class PsiJavaFileImpl extends PsiJavaFileBaseImpl {
@Nullable
@Override
public PsiJavaModule getModuleDeclaration() {
PsiJavaFileStub stub = (PsiJavaFileStub)getStub();
PsiJavaFileStub stub = (PsiJavaFileStub)getGreenStub();
if (stub != null) {
return stub.getModule();
}
@@ -43,7 +43,7 @@ public class PsiJavaModuleImpl extends JavaStubPsiElement<PsiJavaModuleStub> imp
@NotNull
@Override
public String getModuleName() {
PsiJavaModuleStub stub = getStub();
PsiJavaModuleStub stub = getGreenStub();
if (stub != null) {
return stub.getName();
}
@@ -20,6 +20,7 @@ import com.intellij.navigation.ItemPresentation;
import com.intellij.navigation.ItemPresentationProviders;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.ui.Queryable;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.*;
import com.intellij.psi.impl.ElementPresentationUtil;
@@ -136,7 +137,7 @@ public class PsiMethodImpl extends JavaStubPsiElement<PsiMethodStub> implements
@NotNull
public String getName() {
final String name;
final PsiMethodStub stub = getStub();
final PsiMethodStub stub = getGreenStub();
if (stub != null) {
name = stub.getName();
}
@@ -241,7 +242,7 @@ public class PsiMethodImpl extends JavaStubPsiElement<PsiMethodStub> implements
@Override
public boolean isDeprecated() {
final PsiMethodStub stub = getStub();
final PsiMethodStub stub = getGreenStub();
if (stub != null) {
return stub.isDeprecated() || stub.hasDeprecatedAnnotation() && PsiImplUtil.isDeprecatedByAnnotation(this);
}
@@ -251,7 +252,7 @@ public class PsiMethodImpl extends JavaStubPsiElement<PsiMethodStub> implements
@Override
public PsiDocComment getDocComment() {
final PsiMethodStub stub = getStub();
final PsiMethodStub stub = getGreenStub();
if (stub != null && !stub.hasDocComment()) return null;
return (PsiDocComment)getNode().findChildByRoleAsPsiElement(ChildRole.DOC_COMMENT);
@@ -259,7 +260,7 @@ public class PsiMethodImpl extends JavaStubPsiElement<PsiMethodStub> implements
@Override
public boolean isConstructor() {
final PsiMethodStub stub = getStub();
final PsiMethodStub stub = getGreenStub();
if (stub != null) {
return stub.isConstructor();
}
@@ -269,7 +270,7 @@ public class PsiMethodImpl extends JavaStubPsiElement<PsiMethodStub> implements
@Override
public boolean isVarArgs() {
final PsiMethodStub stub = getStub();
final PsiMethodStub stub = getGreenStub();
if (stub != null) {
return stub.isVarArgs();
}
@@ -113,7 +113,7 @@ public class PsiParameterImpl extends JavaStubPsiElement<PsiParameterStub> imple
@Override
@NotNull
public final String getName() {
PsiParameterStub stub = getStub();
PsiParameterStub stub = getGreenStub();
if (stub != null) {
return stub.getName();
}
@@ -269,7 +269,7 @@ public class PsiParameterImpl extends JavaStubPsiElement<PsiParameterStub> imple
@Override
public boolean isVarArgs() {
final PsiParameterStub stub = getStub();
final PsiParameterStub stub = getGreenStub();
if (stub != null) {
return stub.isParameterTypeEllipsis();
}
@@ -59,7 +59,7 @@ public class PsiParameterListImpl extends JavaStubPsiElement<PsiParameterListStu
@Override
public int getParametersCount() {
final PsiParameterListStub stub = getStub();
final PsiParameterListStub stub = getGreenStub();
if (stub != null) {
return stub.getChildrenStubs().size();
}
@@ -47,7 +47,7 @@ public class PsiReferenceListImpl extends JavaStubPsiElement<PsiClassReferenceLi
@Override
@NotNull
public PsiClassType[] getReferencedTypes() {
PsiClassReferenceListStub stub = getStub();
PsiClassReferenceListStub stub = getGreenStub();
if (stub != null) {
return stub.getReferencedTypes();
}
@@ -98,7 +98,7 @@ public class PsiLiteralExpressionImpl
}
public IElementType getLiteralElementType() {
PsiLiteralStub stub = getStub();
PsiLiteralStub stub = getGreenStub();
if (stub != null) return stub.getLiteralType();
return getNode().getFirstChildNode().getElementType();
@@ -111,7 +111,7 @@ public class PsiLiteralExpressionImpl
@Override
public String getText() {
PsiLiteralStub stub = getStub();
PsiLiteralStub stub = getGreenStub();
if (stub != null) return stub.getLiteralText();
return super.getText();
@@ -103,7 +103,7 @@ public class PsiNameValuePairImpl extends JavaStubPsiElement<PsiNameValuePairStu
@Override
@Nullable
public PsiAnnotationMemberValue getDetachedValue() {
PsiNameValuePairStub stub = getStub();
PsiNameValuePairStub stub = getGreenStub();
if (stub != null) {
String text = stub.getValue();
PsiAnnotationMemberValue result = SoftReference.dereference(myDetachedValue);
@@ -0,0 +1,10 @@
// "Replace Stream.collect(counting()) with Stream.count()" "true"
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public long count(List<String> data) {
return data.stream().filter(x -> x.startsWith("xyz")).count();
}
}
@@ -0,0 +1,10 @@
// "Replace Stream.collect(mapping()) with Stream.map().collect()" "true"
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public List<Integer> sizes(List<String> data) {
return data.stream().filter(x -> x.startsWith("xyz")).map(String::length).collect(Collectors.toList());
}
}
@@ -0,0 +1,10 @@
// "Replace Stream.collect(maxBy()) with Stream.max() (may change semantics when result is null)" "true"
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public String max(List<String> data) {
return data.stream().filter(x -> x.startsWith("xyz")).max(String.CASE_INSENSITIVE_ORDER).orElse("");
}
}
@@ -0,0 +1,10 @@
// "Replace Stream.collect(minBy()) with Stream.min() (may change semantics when result is null)" "true"
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public Optional<String> min(List<String> data) {
return data.stream().filter(x -> x.startsWith("xyz")).min(String.CASE_INSENSITIVE_ORDER);
}
}
@@ -0,0 +1,10 @@
// "Replace Stream.collect(reducing()) with Stream.reduce() (may change semantics when result is null)" "true"
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public Optional<String> concat(List<String> data) {
return data.stream().filter(x -> x.startsWith("xyz")).reduce(String::concat);
}
}
@@ -0,0 +1,10 @@
// "Replace Stream.collect(reducing()) with Stream.reduce()" "true"
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public String concat(List<String> data) {
return data.stream().filter(x -> x.startsWith("xyz")).reduce("", String::concat);
}
}
@@ -0,0 +1,10 @@
// "Replace Stream.collect(reducing()) with Stream.map().reduce()" "true"
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public int sum(List<String> data) {
return data.stream().filter(x -> x.startsWith("xyz")).map(String::length).reduce(0, Integer::sum);
}
}
@@ -0,0 +1,10 @@
// "Replace Stream.collect(summingInt()) with Stream.mapToInt().sum()" "true"
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public void remove(List<Integer> ints, List<String> data) {
ints.remove((Integer) data.stream().mapToInt(String::length).sum());
}
}
@@ -0,0 +1,10 @@
// "Replace Stream.collect(summingLong()) with Stream.mapToLong().sum()" "true"
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public void remove(List<Integer> ints, List<String> data) {
ints.remove(data.stream().mapToLong(String::length).sum());
}
}
@@ -0,0 +1,10 @@
// "Replace Stream.collect(counting()) with Stream.count()" "true"
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public long count(List<String> data) {
return data.stream().filter(x -> x.startsWith("xyz")).collect(Collectors.<caret>counting());
}
}
@@ -0,0 +1,10 @@
// "Replace Stream.collect(mapping()) with Stream.map().collect()" "true"
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public List<Integer> sizes(List<String> data) {
return data.stream().filter(x -> x.startsWith("xyz")).collect(Collectors.mapping(Str<caret>ing::length, Collectors.toList()));
}
}
@@ -0,0 +1,10 @@
// "Replace Stream.collect(maxBy()) with Stream.max() (may change semantics when result is null)" "true"
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public String max(List<String> data) {
return data.stream().filter(x -> x.startsWith("xyz")).collect(Collectors.maxBy(String.CASE_INSENSIT<caret>IVE_ORDER)).orElse("");
}
}
@@ -0,0 +1,10 @@
// "Replace Stream.collect(minBy()) with Stream.min() (may change semantics when result is null)" "true"
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public Optional<String> min(List<String> data) {
return data.stream().filter(x -> x.startsWith("xyz")).collect(Collectors.minBy(Str<caret>ing.CASE_INSENSITIVE_ORDER));
}
}
@@ -0,0 +1,10 @@
// "Replace Stream.collect(reducing()) with Stream.reduce() (may change semantics when result is null)" "true"
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public Optional<String> concat(List<String> data) {
return data.stream().filter(x -> x.startsWith("xyz")).colle<caret>ct(Collectors.reducing(String::concat));
}
}
@@ -0,0 +1,10 @@
// "Replace Stream.collect(reducing()) with Stream.reduce()" "true"
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public String concat(List<String> data) {
return data.stream().filter(x -> x.startsWith("xyz")).colle<caret>ct(Collectors.reducing("", String::concat));
}
}
@@ -0,0 +1,10 @@
// "Replace Stream.collect(reducing()) with Stream.map().reduce()" "true"
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public int sum(List<String> data) {
return data.stream().filter(x -> x.startsWith("xyz")).colle<caret>ct(Collectors.reducing(0, String::length, Integer::sum));
}
}
@@ -0,0 +1,10 @@
// "Replace Stream.collect(summingInt()) with Stream.mapToInt().sum()" "true"
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public void remove(List<Integer> ints, List<String> data) {
ints.remove(data.stream().collect(Collectors<caret>.summingInt(String::length)));
}
}
@@ -0,0 +1,10 @@
// "Replace Stream.collect(summingLong()) with Stream.mapToLong().sum()" "true"
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public void remove(List<Integer> ints, List<String> data) {
ints.remove(data.stream().collect(Collectors<caret>.summingLong(String::length)));
}
}
@@ -0,0 +1,21 @@
PsiJavaFile:Provides7.java
PsiJavaModule:M
PsiKeyword:module('module')
PsiWhiteSpace(' ')
PsiJavaModuleReference
PsiIdentifier:M('M')
PsiWhiteSpace(' ')
PsiJavaToken:LBRACE('{')
PsiWhiteSpace(' ')
PsiProvidesStatement
PsiKeyword:provides('provides')
PsiWhiteSpace(' ')
PsiJavaCodeReferenceElement:Spi
PsiIdentifier:Spi('Spi')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiErrorElement:'with' expected
PsiIdentifier:_('_')
PsiWhiteSpace(' ')
PsiJavaToken:RBRACE('}')
@@ -33,7 +33,22 @@ class ModuleCompletionTest : LightFixtureCompletionTestCase() {
addFile("pkg/empty/package-info.java", "package pkg.empty;")
addFile("pkg/main/C.java", "package pkg.main;\nclass C { }")
addFile("pkg/other/C.groovy", "package pkg.other\nclass C { }")
variants("module M { exports pkg.<caret> }", "pkg.main", "pkg.other")
variants("module M { exports pkg.<caret> }", "main", "other")
complete("module M { exports pkg.o<caret> }", "module M { exports pkg.other;<caret> }")
}
fun testUses() {
addFile("pkg/main/MySvc.java", "package pkg.main;\npublic class MySvc { }")
addFile("pkg/main/MySvcImpl.java", "package pkg.main;\nclass MySvcImpl extends MySvc { }")
complete("module M { uses MyS<caret> }", "module M { uses pkg.main.MySvc;<caret> }")
}
fun testProvides() {
addFile("pkg/main/MySvc.java", "package pkg.main;\npublic class MySvc { }")
addFile("pkg/main/MySvcImpl.java", "package pkg.main;\nclass MySvcImpl extends MySvc { }")
complete("module M { provides MyS<caret> }", "module M { provides pkg.main.MySvc <caret> }")
complete("module M { provides pkg.main.MySvc <caret> }", "module M { provides pkg.main.MySvc with <caret> }")
complete("module M { provides pkg.main.MySvc with MSI<caret> }", "module M { provides pkg.main.MySvc with pkg.main.MySvcImpl;<caret> }")
}
//<editor-fold desc="Helpers.">
@@ -69,6 +69,7 @@ public class ModuleParserTest extends JavaParsingTestCase {
public void testProvides4() { doParserTest("module M { provides Spi with ; }"); }
public void testProvides5() { doParserTest("module M { provides Spi with Impl }"); }
public void testProvides6() { doParserTest("module M { provides Spi with Impl; }"); }
public void testProvides7() { doParserTest("module M { provides Spi _ }"); }
private void doParserTest(String text) {
doParserTest(text, builder -> JavaParser.INSTANCE.getFileParser().parse(builder));
@@ -15,12 +15,14 @@
*/
package com.intellij.refactoring.typeMigration.rules;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.refactoring.typeMigration.TypeConversionDescriptorBase;
import com.intellij.refactoring.typeMigration.TypeEvaluator;
import com.intellij.refactoring.typeMigration.TypeMigrationLabeler;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.ig.controlflow.UnnecessaryReturnInspection;
import com.siyeh.ig.fixes.DeleteUnnecessaryStatementFix;
import com.siyeh.ig.psiutils.SideEffectChecker;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -43,10 +45,11 @@ public class VoidConversionRule extends TypeConversionRule {
@Override
public PsiExpression replace(PsiExpression expression, @NotNull TypeEvaluator evaluator) throws IncorrectOperationException {
final PsiElement parent = expression.getParent();
final Project project = expression.getProject();
if (parent instanceof PsiReturnStatement) {
expression.delete();
if (UnnecessaryReturnInspection.isReturnRedundant((PsiReturnStatement)parent, false, null)) {
parent.delete();
final PsiReturnStatement replaced = (PsiReturnStatement)parent.replace(JavaPsiFacade.getElementFactory(project).createStatementFromText("return;", null));
if (UnnecessaryReturnInspection.isReturnRedundant(replaced, false, null)) {
DeleteUnnecessaryStatementFix.deleteUnnecessaryStatement(replaced);
}
}
return null;
@@ -28,6 +28,7 @@ import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* In-memory representation of JVM *.class file produced by a compiler.
@@ -84,7 +85,7 @@ public class CompiledClass extends UserDataHolderBase{
}
@NotNull
public Collection<String> getSourceFilesPaths() {
public List<String> getSourceFilesPaths() {
return ContainerUtil.map(mySourceFiles, new Function<File, String>() {
@Override
public String fun(File file) {
@@ -20,6 +20,7 @@ import com.intellij.compiler.instrumentation.InstrumentationClassFinder;
import com.intellij.compiler.instrumentation.InstrumenterClassWriter;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Key;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.ModuleChunk;
import org.jetbrains.jps.incremental.*;
@@ -72,7 +73,7 @@ public abstract class BaseInstrumentingBuilder extends ClassProcessingBuilder {
LOG.info(e);
final String message = e.getMessage();
if (message != null) {
context.processMessage(new CompilerMessage(getPresentableName(), message, compiledClass.getSourceFilesPaths(), BuildMessage.Kind.ERROR));
context.processMessage(new CompilerMessage(getPresentableName(), BuildMessage.Kind.ERROR, message, ContainerUtil.getFirstItem(compiledClass.getSourceFilesPaths())));
}
else {
context.processMessage(new CompilerMessage(getPresentableName(), e));
@@ -93,9 +93,9 @@ public class NotNullInstrumentingBuilder extends BaseInstrumentingBuilder{
}
}) + ": " + e.getMessage();
context.processMessage(new CompilerMessage(getPresentableName(),
BuildMessage.Kind.ERROR,
msg,
compiledClass.getSourceFilesPaths(),
BuildMessage.Kind.ERROR));
ContainerUtil.getFirstItem(compiledClass.getSourceFilesPaths())));
}
return null;
}
@@ -16,16 +16,12 @@
package org.jetbrains.jps.incremental.messages;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.PrintStream;
import java.util.Collection;
import java.util.Collections;
/**
* @author Eugene Zhuravlev
@@ -37,28 +33,24 @@ public class CompilerMessage extends BuildMessage {
private final long myProblemBeginOffset;
private final long myProblemEndOffset;
private final long myProblemLocationOffset;
private final Collection<String> mySourcePaths;
private final String mySourcePath;
private final long myLine;
private final long myColumn;
public CompilerMessage(@NotNull String compilerName, @NotNull Throwable internalError) {
this(compilerName, Kind.ERROR, getTextFromThrowable(internalError));
this(compilerName, Kind.ERROR, getTextFromThrowable(internalError), null, -1L, -1L, -1L, -1L, -1L);
}
public CompilerMessage(@NotNull String compilerName, Kind kind, String messageText) {
this(compilerName, kind, messageText, (String)null, -1L, -1L, -1L, -1L, -1L);
}
public CompilerMessage(@NotNull String compilerName, String messageText, Collection<String> sourcePaths, Kind kind) {
this(compilerName, kind, messageText, sourcePaths, -1L, -1L, -1L, -1L, -1L);
this(compilerName, kind, messageText, null, -1L, -1L, -1L, -1L, -1L);
}
public CompilerMessage(@NotNull String compilerName, Kind kind, String messageText, String sourcePath) {
this(compilerName, messageText, sourcePath == null ? Collections.<String>emptyList() : Collections.singleton(sourcePath), kind);
this(compilerName, kind, messageText, sourcePath, -1L, -1L, -1L, -1L, -1L);
}
public CompilerMessage(@NotNull String compilerName, Kind kind, String messageText,
@NotNull Collection<String> sourcePaths,
@Nullable String sourcePath,
long problemBeginOffset,
long problemEndOffset,
long problemLocationOffset,
@@ -69,34 +61,11 @@ public class CompilerMessage extends BuildMessage {
myProblemBeginOffset = problemBeginOffset;
myProblemEndOffset = problemEndOffset;
myProblemLocationOffset = problemLocationOffset;
mySourcePaths = ContainerUtil.map(sourcePaths, new Function<String, String>() {
@Override
public String fun(String s) {
return s.replace(File.separatorChar, '/');
}
});
mySourcePath = sourcePath != null && !sourcePath.isEmpty()? sourcePath.replace(File.separatorChar, '/') : null;
myLine = locationLine;
myColumn = locationColumn;
}
public CompilerMessage(@NotNull String compilerName, Kind kind, String messageText,
@Nullable String sourcePath,
long problemBeginOffset,
long problemEndOffset,
long problemLocationOffset,
long locationLine,
long locationColumn) {
this(compilerName,
kind,
messageText,
sourcePath == null ? Collections.<String>emptyList() : Collections.singleton(sourcePath),
problemBeginOffset,
problemEndOffset,
problemLocationOffset,
locationLine,
locationColumn);
}
@NotNull
public String getCompilerName() {
return myCompilerName;
@@ -104,7 +73,7 @@ public class CompilerMessage extends BuildMessage {
@Nullable
public String getSourcePath() {
return mySourcePaths.size() == 1 ? ContainerUtil.getFirstItem(mySourcePaths) : null;
return mySourcePath;
}
public long getLine() {
@@ -130,16 +99,7 @@ public class CompilerMessage extends BuildMessage {
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append(getCompilerName()).append(":").append(getKind().name()).append(":").append(super.toString());
String result;
if (mySourcePaths.isEmpty()) {
result = null;
}
else if (mySourcePaths.size() == 1) {
result = ContainerUtil.getFirstItem(mySourcePaths);
} else {
result = mySourcePaths.toString();
}
final String path = result;
final String path = getSourcePath();
if (path != null) {
builder.append("; file: ").append(path);
final long line = getLine();
@@ -121,8 +121,7 @@ public class JsonSchemaDefinitionResolver {
if (parSchema.getId() != null) {
schemaFile = JsonSchemaService.Impl.getEx(myElement.getProject()).getSchemaFileById(parSchema.getId());
}
return resolveInSomeSchema(definitionAddress.substring(1) + PROPERTIES + propertyName, myElement.getProject(), parSchema.getId(),
schemaFile != null ? GlobalSearchScope.fileScope(myElement.getProject(), schemaFile) : null);
return resolveInSomeSchema(definitionAddress.substring(1) + PROPERTIES + propertyName, myElement.getProject(), parSchema.getId(), schemaFile);
} else {
String relative = splitter.getRelativePath();
if (StringUtil.isEmptyOrSpaces(relative)) {
@@ -139,19 +138,20 @@ public class JsonSchemaDefinitionResolver {
if (myRef == null) initializeName();
if (myRef == null) return null;
GlobalSearchScope filter = null;
VirtualFile filter = null;
if (mySchemaId != null && myRef.startsWith("#/")) {
filter = GlobalSearchScope.fileScope(myElement.getContainingFile());
filter = myElement.getContainingFile().getVirtualFile();
}
else {
final JsonSchemaServiceEx schemaServiceEx = JsonSchemaService.Impl.getEx(myElement.getProject());
final Collection<Pair<VirtualFile, String>> pairs = schemaServiceEx.getSchemaFilesByFile(myElement.getContainingFile().getVirtualFile());
if (pairs != null && ! pairs.isEmpty()) {
for (Pair<VirtualFile, String> pair : pairs) {
final PsiElement element = resolveInSomeSchema(myRef, myElement.getProject(), pair.getSecond(),
GlobalSearchScope.fileScope(myElement.getProject(), pair.getFirst()));
final PsiElement element = resolveInSomeSchema(myRef, myElement.getProject(), pair.getSecond(), pair.getFirst());
if (element != null) return element;
}
// if not in schema file
if (mySchemaId == null) return null;
}
}
return resolveInSomeSchema(myRef, myElement.getProject(), mySchemaId, filter);
@@ -161,10 +161,13 @@ public class JsonSchemaDefinitionResolver {
private static PsiElement resolveInSomeSchema(@NotNull String referenceName,
@NotNull final Project project,
@Nullable final String schemaId,
final @Nullable GlobalSearchScope filter) {
final @Nullable VirtualFile filterFile) {
final Ref<Pair<VirtualFile, Integer>> reference = new Ref<>();
final FileBasedIndex index = FileBasedIndex.getInstance();
final GlobalSearchScope fileScope = filterFile == null ? null : GlobalSearchScope.fileScope(project, filterFile);
final GlobalSearchScope enlarged = fileScope != null && JsonSchemaResourcesRootsProvider.ourFiles.getValue().contains(filterFile) ? fileScope :
JsonSchemaResourcesRootsProvider.enlarge(project, fileScope == null ? GlobalSearchScope.allScope(project) : fileScope);
index.processValues(JsonSchemaFileIndex.PROPERTIES_INDEX, referenceName, null, new FileBasedIndex.ValueProcessor<Integer>() {
@Override
public boolean process(VirtualFile file, Integer value) {
@@ -176,7 +179,7 @@ public class JsonSchemaDefinitionResolver {
reference.set(Pair.create(file, value));
return false;
}
}, JsonSchemaResourcesRootsProvider.enlarge(project, filter == null ? GlobalSearchScope.allScope(project) : filter));
}, enlarged);
if (!reference.isNull()) {
final Pair<VirtualFile, Integer> pair = reference.get();
@@ -35,7 +35,7 @@ import java.util.Map;
*/
public class JsonSchemaFileIndex extends FileBasedIndexExtension<String, Integer> {
public static final ID<String, Integer> PROPERTIES_INDEX = ID.create("json.schema.properties.index");
public static final int VERSION = 4;
public static final int VERSION = 5;
private IntInlineKeyDescriptor myKeyDescriptor = new IntInlineKeyDescriptor();
@NotNull
@@ -159,6 +159,11 @@ public class SeverityRegistrar implements Comparator<HighlightSeverity> {
read.add(severity);
}
}
myOrderMap = ensureAllStandardIncluded(read, knownSeverities);
severitiesChanged();
}
private OrderMap ensureAllStandardIncluded(List<HighlightSeverity> read, final List<HighlightSeverity> knownSeverities) {
OrderMap orderMap = fromList(read);
if (orderMap.isEmpty()) {
orderMap = fromList(knownSeverities);
@@ -182,8 +187,7 @@ public class SeverityRegistrar implements Comparator<HighlightSeverity> {
}
orderMap = fromList(list);
}
myOrderMap = orderMap;
severitiesChanged();
return orderMap;
}
public void writeExternal(Element element) {
@@ -345,7 +349,7 @@ public class SeverityRegistrar implements Comparator<HighlightSeverity> {
}
public void setOrder(@NotNull List<HighlightSeverity> orderList) {
myOrderMap = fromList(orderList);
myOrderMap = ensureAllStandardIncluded(orderList, getDefaultOrder());
myReadOrder = null;
severitiesChanged();
}
@@ -21,6 +21,7 @@ import com.intellij.codeInspection.ex.InspectionToolRegistrar
import com.intellij.configurationStore.SchemeDataHolder
import com.intellij.configurationStore.SchemeManagerIprProvider
import com.intellij.configurationStore.digest
import com.intellij.configurationStore.wrapState
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.PersistentStateComponent
@@ -32,7 +33,6 @@ import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.project.ProjectManagerListener
import com.intellij.openapi.startup.StartupActivity
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.JDOMUtil
import com.intellij.openapi.util.text.StringUtil
import com.intellij.packageDependencies.DependencyValidationManager
import com.intellij.profile.Profile
@@ -209,6 +209,23 @@ class ProjectInspectionProfileManager(val project: Project,
}
}
@Synchronized override fun getState(): Element? {
val result = Element("settings")
schemeManagerIprProvider?.writeState(result)
val state = this.state
state.projectProfile = schemeManager.currentSchemeName
XmlSerializer.serializeInto(state, result, skipDefaultsSerializationFilter)
if (!result.children.isEmpty()) {
result.addContent(Element("version").setAttribute("value", VERSION))
}
severityRegistrar.writeExternal(result)
return wrapState(result)
}
@Synchronized override fun loadState(state: Element) {
val data = state.getChild("settings")
@@ -250,29 +267,6 @@ class ProjectInspectionProfileManager(val project: Project,
}
}
@Synchronized override fun getState(): Element? {
val result = Element("settings")
schemeManagerIprProvider?.writeState(result)
val state = this.state
state.projectProfile = schemeManager.currentSchemeName
XmlSerializer.serializeInto(state, result, skipDefaultsSerializationFilter)
if (!result.children.isEmpty()) {
result.addContent(Element("version").setAttribute("value", VERSION))
}
severityRegistrar.writeExternal(result)
if (JDOMUtil.isEmpty(result)) {
result.name = "state"
return result
}
else {
return Element("state").addContent(result)
}
}
override fun getScopesManager() = scopeManager
@Synchronized override fun getProfiles(): Collection<Profile> {
@@ -370,12 +370,16 @@ class SchemeManagerImpl<T : Scheme, MUTABLE_SCHEME : T>(val fileSpec: String,
override fun updateDigest(scheme: MUTABLE_SCHEME) {
try {
externalInfo.digest = (processor.writeScheme(scheme) as Element).digest()
updateDigest(processor.writeScheme(scheme) as Element)
}
catch (e: WriteExternalException) {
LOG.error("Cannot update digest", e)
}
}
override fun updateDigest(data: Element) {
externalInfo.digest = data.digest()
}
}
private fun loadScheme(fileName: String, input: InputStream, schemes: MutableList<T>, filesToDelete: MutableSet<String>? = null): MUTABLE_SCHEME? {
@@ -438,7 +442,7 @@ class SchemeManagerImpl<T : Scheme, MUTABLE_SCHEME : T>(val fileSpec: String,
XmlPullParser.START_TAG -> {
if (!isUseOldFileNameSanitize || parser.name != "component") {
var name: String? = null
if (isUseOldFileNameSanitize && parser.name == "profile") {
if (isUseOldFileNameSanitize && (parser.name == "profile" || parser.name == "copyright")) {
eventType = parser.next()
findName@ while (eventType != XmlPullParser.END_DOCUMENT) {
when (eventType) {
@@ -0,0 +1,44 @@
/*
* 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.diagnostic;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class ImplementationConflictException extends RuntimeException {
@NotNull
private final Collection<Class<?>> myConflictingClasses;
public ImplementationConflictException(String message, Throwable cause, @NotNull Object ...implementationObjects) {
super(message, cause);
final List<Class<?>> classes = new ArrayList<Class<?>>();
for (Object object : implementationObjects) {
classes.add(object.getClass());
}
myConflictingClasses = Collections.unmodifiableList(classes);
}
@NotNull
public Collection<Class<?>> getConflictingClasses() {
return myConflictingClasses;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 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.
@@ -15,6 +15,7 @@
*/
package com.intellij.lang;
import com.intellij.diagnostic.ImplementationConflictException;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeRegistry;
@@ -24,7 +25,6 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -33,12 +33,10 @@ import java.util.concurrent.ConcurrentMap;
/**
* The base class for all programming language support implementations. Specific language implementations should inherit from this class
* and its register instance wrapped with {@link com.intellij.openapi.fileTypes.LanguageFileType} instance through
* <code>FileTypeManager.getInstance().registerFileType</code>
* and its register instance wrapped with {@link LanguageFileType} instance via {@code FileTypeManager.getInstance().registerFileType()}.
* There should be exactly one instance of each Language.
* It is usually created when creating {@link com.intellij.openapi.fileTypes.LanguageFileType} and can be retrieved later
* with {@link #findInstance(Class)}.
* For the list of standard languages, see {@link com.intellij.lang.StdLanguages}.
* It is usually created when creating {@link LanguageFileType} and can be retrieved later with {@link #findInstance(Class)}.
* For the list of standard languages, see {@code com.intellij.lang.StdLanguages}.
*/
public abstract class Language extends UserDataHolderBase {
private static final Logger LOG = Logger.getInstance("#com.intellij.lang.Language");
@@ -46,14 +44,15 @@ public abstract class Language extends UserDataHolderBase {
private static final Map<Class<? extends Language>, Language> ourRegisteredLanguages = ContainerUtil.newConcurrentMap();
private static final ConcurrentMap<String, List<Language>> ourRegisteredMimeTypes = ContainerUtil.newConcurrentMap();
private static final Map<String, Language> ourRegisteredIDs = ContainerUtil.newConcurrentMap();
private final Language myBaseLanguage;
private final String myID;
private final String[] myMimeTypes;
private final List<Language> myDialects = ContainerUtil.createLockFreeCopyOnWriteList();
public static final Language ANY = new Language("") {
@Override
public String toString() {
//noinspection HardCodedStringLiteral
return "Language: ANY";
}
@@ -64,28 +63,31 @@ public abstract class Language extends UserDataHolderBase {
}
};
protected Language(@NotNull @NonNls String ID) {
protected Language(@NotNull String ID) {
this(ID, ArrayUtil.EMPTY_STRING_ARRAY);
}
protected Language(@NotNull @NonNls final String ID, @NotNull @NonNls final String... mimeTypes) {
protected Language(@NotNull String ID, @NotNull String... mimeTypes) {
this(null, ID, mimeTypes);
}
protected Language(@Nullable Language baseLanguage, @NotNull @NonNls final String ID, @NotNull @NonNls final String... mimeTypes) {
protected Language(@Nullable Language baseLanguage, @NotNull String ID, @NotNull String... mimeTypes) {
myBaseLanguage = baseLanguage;
myID = ID;
myMimeTypes = mimeTypes;
Class<? extends Language> langClass = getClass();
Language prev = ourRegisteredLanguages.put(langClass, this);
if (prev != null) {
LOG.error("Language of '" + langClass + "' is already registered: " + prev);
LOG.error(new ImplementationConflictException("Language of '" + langClass + "' is already registered: " + prev, null, prev, this));
return;
}
prev = ourRegisteredIDs.put(ID, this);
if (prev != null) {
LOG.error("Language with ID '" + ID + "' is already registered: " + prev.getClass());
LOG.error(new ImplementationConflictException("Language with ID '" + ID + "' is already registered: " + prev.getClass(), null, prev, this));
}
for (String mimeType : mimeTypes) {
if (StringUtil.isEmpty(mimeType)) {
continue;
@@ -96,6 +98,7 @@ public abstract class Language extends UserDataHolderBase {
}
languagesByMimeType.add(this);
}
if (baseLanguage != null) {
baseLanguage.myDialects.add(this);
}
@@ -129,10 +132,8 @@ public abstract class Language extends UserDataHolderBase {
return result == null ? Collections.<Language>emptyList() : Collections.unmodifiableCollection(result);
}
@Override
public String toString() {
//noinspection HardCodedStringLiteral
return "Language: " + myID;
}
@@ -228,4 +229,4 @@ public abstract class Language extends UserDataHolderBase {
myBaseLanguage = null;
myMimeTypes = null;
}
}
}
@@ -102,41 +102,58 @@ public interface Module extends ComponentManager, AreaInstance, Disposable {
String getOptionValue(@NotNull String key);
/**
* Returns module scope including sources and tests, excluding libraries and dependencies.
*
* @return scope including sources and tests, excluding libraries and dependencies.
* @return module scope including source and tests, excluding libraries and dependencies.
*/
@NotNull
GlobalSearchScope getModuleScope();
/**
* @param includeTests whether to include test source
* @return module scope including source and, optionally, tests, excluding libraries and dependencies.
*/
@NotNull
GlobalSearchScope getModuleScope(boolean includeTests);
/**
* Returns module scope including sources, tests, and libraries, excluding dependencies.
*
* @return scope including sources, tests, and libraries, excluding dependencies.
* @return module scope including source, tests, and libraries, excluding dependencies.
*/
@NotNull
GlobalSearchScope getModuleWithLibrariesScope();
/**
* Returns module scope including sources, tests, and dependencies, excluding libraries.
*
* @return scope including sources, tests, and dependencies, excluding libraries.
* @return module scope including source, tests, and dependencies, excluding libraries.
*/
@NotNull
GlobalSearchScope getModuleWithDependenciesScope();
/**
* @return a scope that includes everything in module content roots, without any dependencies or libraries
*/
@NotNull
GlobalSearchScope getModuleContentScope();
/**
* @return a scope that includes everything under the content roots of this module and its dependencies, with test source
*/
@NotNull
GlobalSearchScope getModuleContentWithDependenciesScope();
/**
* @param includeTests whether test source and test dependencies should be included
* @return a scope including module source and dependencies with libraries
*/
@NotNull
GlobalSearchScope getModuleWithDependenciesAndLibrariesScope(boolean includeTests);
/**
* @return a scope including everything under the content roots of this module and all modules that depend on it, directly or indirectly (via exported dependencies), excluding test source and resources
*/
@NotNull
GlobalSearchScope getModuleWithDependentsScope();
/**
* @return same as {@link #getModuleWithDependentsScope()}, but with test source/resources included
*/
@NotNull
GlobalSearchScope getModuleTestsWithDependentsScope();
@NotNull
@@ -383,11 +383,10 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements
private void registerComponents(@NotNull ComponentConfig config) {
ClassLoader loader = config.getClassLoader();
try {
final Class<?> interfaceClass = Class.forName(config.getInterfaceClass(), true, loader);
final Class<?> implementationClass = Comparing.equal(config.getInterfaceClass(), config.getImplementationClass())
?
interfaceClass
: StringUtil.isEmpty(config.getImplementationClass()) ? null : Class.forName(config.getImplementationClass(), true, loader);
Class<?> interfaceClass = Class.forName(config.getInterfaceClass(), true, loader);
Class<?> implementationClass = Comparing.equal(config.getInterfaceClass(), config.getImplementationClass()) ? interfaceClass :
StringUtil.isEmpty(config.getImplementationClass()) ? null :
Class.forName(config.getImplementationClass(), true, loader);
MutablePicoContainer picoContainer = getPicoContainer();
if (config.options != null && Boolean.parseBoolean(config.options.get("overrides"))) {
ComponentAdapter oldAdapter = picoContainer.getComponentAdapterOfType(interfaceClass);
@@ -398,8 +397,8 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements
}
// implementationClass == null means we want to unregister this component
if (implementationClass != null) {
picoContainer.registerComponent(new ComponentConfigComponentAdapter(interfaceClass, implementationClass, config.getPluginId(),
config.options != null && Boolean.parseBoolean(config.options.get("workspace"))));
boolean ws = config.options != null && Boolean.parseBoolean(config.options.get("workspace"));
picoContainer.registerComponent(new ComponentConfigComponentAdapter(interfaceClass, implementationClass, config.getPluginId(), ws));
}
}
catch (Throwable t) {
@@ -522,4 +521,4 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements
return "ComponentConfigAdapter[" + getComponentKey() + "]: implementation=" + getComponentImplementation() + ", plugin=" + myPluginId;
}
}
}
}
@@ -115,12 +115,8 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable {
private void refresh() {
int maxIndex = mySeverityRegistrar.getSeverityMaxIndex();
if (errorCount != null && maxIndex == errorCount.length) return;
int[] newErrors = new int[maxIndex+1];
if (errorCount != null) {
System.arraycopy(errorCount, 0, newErrors, 0, Math.min(errorCount.length, newErrors.length));
}
errorCount = newErrors;
if (errorCount != null && maxIndex + 1 == errorCount.length) return;
errorCount = new int[maxIndex + 1];
}
static void setOrRefreshErrorStripeRenderer(@NotNull EditorMarkupModel editorMarkupModel,
@@ -334,7 +330,7 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable {
Icon icon = AllIcons.General.InspectionsOK;
for (int i = status.errorCount.length - 1; i >= 0; i--) {
if (status.errorCount[i] != 0) {
if (status.errorCount[i] > 0) {
icon = SeverityRegistrar.getSeverityRegistrar(project).getRendererIconByIndex(i);
break;
}
@@ -56,4 +56,10 @@ public abstract class TemplateManager {
@Nullable
public abstract Template getActiveTemplate(@NotNull Editor editor);
/**
* Finished a live template in the given editor, if it's present
* @return whether a live template was present
*/
public abstract boolean finishTemplate(@NotNull Editor editor);
}
@@ -521,6 +521,16 @@ public class TemplateManagerImpl extends TemplateManager implements Disposable {
return templateState != null ? templateState.getTemplate() : null;
}
@Override
public boolean finishTemplate(@NotNull Editor editor) {
TemplateState state = getTemplateState(editor);
if (state != null) {
state.gotoEnd();
return true;
}
return false;
}
public static boolean isApplicable(PsiFile file, int offset, TemplateImpl template) {
return isApplicable(template, getApplicableContextTypes(file, offset));
}
@@ -31,16 +31,16 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.progress.EmptyProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.SequentialModalProgressTask;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
@@ -74,39 +74,45 @@ public class CleanupInspectionIntention implements IntentionAction, HighPriority
@Override
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
if (!FileModificationService.getInstance().preparePsiElementForWrite(file)) return;
final List<ProblemDescriptor> descriptions =
ProgressManager.getInstance().runProcess(() -> {
InspectionManager inspectionManager = InspectionManager.getInstance(project);
return InspectionEngine.runInspectionOnFile(file, myToolWrapper, inspectionManager.createNewGlobalContext(false));
}, new EmptyProgressIndicator());
Collections.sort(descriptions, new Comparator<CommonProblemDescriptor>() {
@Override
public int compare(final CommonProblemDescriptor o1, final CommonProblemDescriptor o2) {
final ProblemDescriptorBase d1 = (ProblemDescriptorBase)o1;
final ProblemDescriptorBase d2 = (ProblemDescriptorBase)o2;
final int offset2 = d2.getTextRange().getStartOffset();
final int offset1 = d1.getTextRange().getStartOffset();
return offset2 < offset1 ? -1 : offset1 == offset2 ? 0 : 1;
}
if (!descriptions.isEmpty() && !FileModificationService.getInstance().preparePsiElementForWrite(file)) return;
final AbstractPerformFixesTask fixesTask = applyFixes(project, "Apply Fixes", descriptions, myQuickfixClass);
if (!fixesTask.isApplicableFixFound()) {
HintManager.getInstance().showErrorHint(editor, "Unfortunately '" + myText + "' is currently not available for batch mode\n User interaction is required for each problem found");
}
}
public static AbstractPerformFixesTask applyFixes(@NotNull Project project,
@NotNull String presentationText,
@NotNull List<ProblemDescriptor> descriptions,
@Nullable Class quickfixClass) {
Collections.sort(descriptions, (o1, o2) -> {
final ProblemDescriptorBase d1 = (ProblemDescriptorBase)o1;
final ProblemDescriptorBase d2 = (ProblemDescriptorBase)o2;
return -PsiUtilCore.compareElementsByPosition(d1.getPsiElement(), d2.getPsiElement());
});
final String templatePresentationText = "Apply Fixes";
final SequentialModalProgressTask progressTask =
new SequentialModalProgressTask(project, templatePresentationText, true);
final boolean isBatch = BatchQuickFix.class.isAssignableFrom(myQuickfixClass);
final AbstractPerformFixesTask fixesTask = createTask(project, descriptions.toArray(new ProblemDescriptor[descriptions.size()]), progressTask, isBatch);
new SequentialModalProgressTask(project, presentationText, true);
final boolean isBatch = quickfixClass != null && BatchQuickFix.class.isAssignableFrom(quickfixClass);
final AbstractPerformFixesTask fixesTask = isBatch ?
new PerformBatchFixesTask(project, descriptions.toArray(ProblemDescriptor.EMPTY_ARRAY), progressTask, quickfixClass) :
new PerformFixesTask(project, descriptions.toArray(ProblemDescriptor.EMPTY_ARRAY), progressTask, quickfixClass);
CommandProcessor.getInstance().executeCommand(project, () -> {
CommandProcessor.getInstance().markCurrentCommandAsGlobal(project);
progressTask.setMinIterationTime(200);
progressTask.setTask(fixesTask);
ProgressManager.getInstance().run(progressTask);
}, templatePresentationText, null);
if (!fixesTask.isApplicableFixFound()) {
HintManager.getInstance().showErrorHint(editor, "Unfortunately '" + myText + "' is currently not available for batch mode\n User interaction is required for each problem found");
}
}, presentationText, null);
return fixesTask;
}
@Override
@@ -120,23 +126,16 @@ public class CleanupInspectionIntention implements IntentionAction, HighPriority
return false;
}
@NotNull
private AbstractPerformFixesTask createTask(@NotNull Project project,
ProblemDescriptor[] descriptions,
SequentialModalProgressTask progressTask,
boolean isBatch) {
return isBatch ?
new PerformBatchFixesTask(project, descriptions, progressTask) :
new PerformFixesTask(project, descriptions, progressTask);
}
private abstract class AbstractPerformFixesTask extends PerformFixesModalTask {
private static abstract class AbstractPerformFixesTask extends PerformFixesModalTask {
private boolean myApplicableFixFound = false;
protected final Class myQuickfixClass;
public AbstractPerformFixesTask(@NotNull Project project,
@NotNull CommonProblemDescriptor[] descriptors,
@NotNull SequentialModalProgressTask task) {
@NotNull CommonProblemDescriptor[] descriptors,
@NotNull SequentialModalProgressTask task,
@Nullable Class quickfixClass) {
super(project, descriptors, task);
myQuickfixClass = quickfixClass;
}
protected abstract void collectFix(QuickFix fix, ProblemDescriptor descriptor, Project project);
@@ -146,7 +145,7 @@ public class CleanupInspectionIntention implements IntentionAction, HighPriority
final QuickFix[] fixes = descriptor.getFixes();
if (fixes != null && fixes.length > 0) {
for (final QuickFix fix : fixes) {
if (fix != null && fix.getClass().isAssignableFrom(myQuickfixClass)) {
if (fix != null && (myQuickfixClass == null || fix.getClass().isAssignableFrom(myQuickfixClass))) {
final ProblemDescriptor problemDescriptor = (ProblemDescriptor)descriptor;
final PsiElement element = problemDescriptor.getPsiElement();
if (element != null && element.isValid()) {
@@ -164,14 +163,15 @@ public class CleanupInspectionIntention implements IntentionAction, HighPriority
}
}
private class PerformBatchFixesTask extends AbstractPerformFixesTask {
private static class PerformBatchFixesTask extends AbstractPerformFixesTask {
private final List<ProblemDescriptor> myBatchModeDescriptors = new ArrayList<>();
private boolean myApplied = false;
public PerformBatchFixesTask(@NotNull Project project,
@NotNull CommonProblemDescriptor[] descriptors,
@NotNull SequentialModalProgressTask task) {
super(project, descriptors, task);
@NotNull SequentialModalProgressTask task,
@NotNull Class quickfixClass) {
super(project, descriptors, task, quickfixClass);
}
@Override
@@ -204,11 +204,12 @@ public class CleanupInspectionIntention implements IntentionAction, HighPriority
}
}
private class PerformFixesTask extends AbstractPerformFixesTask {
private static class PerformFixesTask extends AbstractPerformFixesTask {
public PerformFixesTask(@NotNull Project project,
@NotNull CommonProblemDescriptor[] descriptors,
@NotNull SequentialModalProgressTask task) {
super(project, descriptors, task);
@NotNull SequentialModalProgressTask task,
@Nullable Class quickFixClass) {
super(project, descriptors, task, quickFixClass);
}
@Override
@@ -20,10 +20,10 @@ import com.intellij.analysis.AnalysisScope;
import com.intellij.analysis.AnalysisUIOptions;
import com.intellij.analysis.PerformAnalysisInBackgroundOption;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.HighlightInfoProcessor;
import com.intellij.codeInsight.daemon.impl.LocalInspectionsPass;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.actions.CleanupInspectionIntention;
import com.intellij.codeInspection.lang.GlobalInspectionContextExtension;
import com.intellij.codeInspection.reference.RefElement;
import com.intellij.codeInspection.reference.RefEntity;
@@ -47,7 +47,6 @@ import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.application.TransactionGuard;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.components.PathMacroManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
@@ -77,8 +76,9 @@ import com.intellij.psi.util.PsiUtilCore;
import com.intellij.ui.GuiUtils;
import com.intellij.ui.content.*;
import com.intellij.util.*;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.*;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
import com.intellij.util.ui.UIUtil;
import gnu.trove.THashSet;
import org.jdom.Element;
@@ -92,6 +92,7 @@ import java.io.IOException;
import java.io.OutputStreamWriter;
import java.lang.reflect.Constructor;
import java.util.*;
import java.util.Queue;
import java.util.concurrent.*;
public class GlobalInspectionContextImpl extends GlobalInspectionContextBase implements GlobalInspectionContext {
@@ -889,8 +890,6 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
final ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator();
final List<LocalInspectionToolWrapper> lTools = new ArrayList<>();
final LinkedHashMap<PsiFile, List<HighlightInfo>> results = new LinkedHashMap<>();
final SearchScope searchScope = scope.toSearchScope();
final TextRange range;
if (searchScope instanceof LocalSearchScope) {
@@ -909,47 +908,66 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
assert tools != null;
return tools.getTool().getTool() instanceof CleanupLocalInspectionTool;
});
List<ProblemDescriptor> descriptors = new ArrayList<>();
Set<PsiFile> files = new HashSet<>();
boolean includeDoNotShow = includeDoNotShow(profile);
scope.accept(new PsiElementVisitor() {
private int myCount;
@Override
public void visitFile(PsiFile file) {
if (progressIndicator != null) {
progressIndicator.setFraction((double)++myCount / fileCount);
}
if (isBinary(file)) return;
for (final Tools tools : inspectionTools) {
final InspectionToolWrapper tool = tools.getEnabledTool(file, includeDoNotShow);
if (tool instanceof LocalInspectionToolWrapper) {
lTools.add((LocalInspectionToolWrapper)tool);
tool.initialize(GlobalInspectionContextImpl.this);
final RefManagerImpl refManager = (RefManagerImpl)getRefManager();
refManager.inspectionReadActionStarted();
try {
scope.accept(new PsiElementVisitor() {
private int myCount;
@Override
public void visitFile(PsiFile file) {
if (progressIndicator != null) {
progressIndicator.setFraction((double)++myCount / fileCount);
}
}
if (!lTools.isEmpty()) {
final LocalInspectionsPass pass = new LocalInspectionsPass(file, PsiDocumentManager.getInstance(getProject()).getDocument(file), range != null ? range.getStartOffset() : 0,
range != null ? range.getEndOffset() : file.getTextLength(), LocalInspectionsPass.EMPTY_PRIORITY_RANGE, true,
HighlightInfoProcessor.getEmpty());
Runnable runnable = () -> pass.doInspectInBatch(GlobalInspectionContextImpl.this, InspectionManager.getInstance(getProject()), lTools);
ApplicationManager.getApplication().runReadAction(runnable);
final List<HighlightInfo> infos = pass.getInfos();
if (searchScope instanceof LocalSearchScope) {
for (Iterator<HighlightInfo> iterator = infos.iterator(); iterator.hasNext(); ) {
final HighlightInfo info = iterator.next();
final TextRange infoRange = new TextRange(info.getStartOffset(), info.getEndOffset());
if (!((LocalSearchScope)searchScope).containsRange(file, infoRange)) {
iterator.remove();
}
if (isBinary(file)) return;
for (final Tools tools : inspectionTools) {
final InspectionToolWrapper tool = tools.getEnabledTool(file, includeDoNotShow);
if (tool instanceof LocalInspectionToolWrapper) {
lTools.add((LocalInspectionToolWrapper)tool);
tool.initialize(GlobalInspectionContextImpl.this);
}
}
if (!infos.isEmpty()) {
results.put(file, infos);
if (!lTools.isEmpty()) {
final LocalInspectionsPass pass = new LocalInspectionsPass(file, PsiDocumentManager.getInstance(getProject()).getDocument(file), range != null ? range.getStartOffset() : 0,
range != null ? range.getEndOffset() : file.getTextLength(), LocalInspectionsPass.EMPTY_PRIORITY_RANGE, true,
HighlightInfoProcessor.getEmpty());
Runnable runnable = () -> pass.doInspectInBatch(GlobalInspectionContextImpl.this, InspectionManager.getInstance(getProject()), lTools);
ApplicationManager.getApplication().runReadAction(runnable);
List<ProblemDescriptor> localDescriptors = new ArrayList<>();
for (LocalInspectionToolWrapper tool : lTools) {
for (CommonProblemDescriptor descriptor : getPresentation(tool).getProblemDescriptors()) {
if (descriptor instanceof ProblemDescriptor) {
localDescriptors.add((ProblemDescriptor)descriptor);
}
}
}
if (searchScope instanceof LocalSearchScope) {
for (Iterator<ProblemDescriptor> iterator = localDescriptors.iterator(); iterator.hasNext(); ) {
final ProblemDescriptor descriptor = iterator.next();
final TextRange infoRange = descriptor instanceof ProblemDescriptorBase ? ((ProblemDescriptorBase)descriptor).getTextRange() : null;
if (infoRange != null && !((LocalSearchScope)searchScope).containsRange(file, infoRange)) {
iterator.remove();
}
}
}
if (!localDescriptors.isEmpty()) {
descriptors.addAll(localDescriptors);
files.add(file);
}
}
}
}
});
});
}
finally {
refManager.inspectionReadActionFinished();
}
if (results.isEmpty()) {
if (files.isEmpty()) {
GuiUtils.invokeLaterIfNeeded(() -> {
if (commandName != null) {
NOTIFICATION_GROUP.createNotification(InspectionsBundle.message("inspection.no.problems.message", scope.getFileCount(), scope.getDisplayName()), MessageType.INFO).notify(getProject());
@@ -961,21 +979,8 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
return;
}
Runnable runnable = () -> {
if (!FileModificationService.getInstance().preparePsiElementsForWrite(results.keySet())) return;
final String title = "Code Cleanup";
final SequentialModalProgressTask progressTask = new SequentialModalProgressTask(getProject(), title, true);
progressTask.setMinIterationTime(200);
progressTask.setTask(new SequentialCleanupTask(getProject(), results, progressTask));
CommandProcessor.getInstance().executeCommand(getProject(), () -> {
if (commandName != null) {
CommandProcessor.getInstance().markCurrentCommandAsGlobal(getProject());
}
ProgressManager.getInstance().run(progressTask);
if (postRunnable != null) {
ApplicationManager.getApplication().invokeLater(postRunnable);
}
}, title, null);
if (!FileModificationService.getInstance().preparePsiElementsForWrite(files)) return;
CleanupInspectionIntention.applyFixes(getProject(), "Code Cleanup", descriptors, null);
};
TransactionGuard.submitTransaction(getProject(), runnable);
}
@@ -20,6 +20,7 @@
*/
package com.intellij.codeInspection.ex;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInspection.CommonProblemDescriptor;
import com.intellij.codeInspection.QuickFix;
import com.intellij.codeInspection.reference.RefDirectory;
@@ -279,21 +280,25 @@ public abstract class InspectionRVContentProvider {
continue;
}
}
for (RefElementNode parentNode : parentNodes) {
final List<ProblemDescriptionNode> nodes = new ArrayList<>();
TreeUtil.traverse(parentNode, new TreeUtil.Traverse() {
@Override
public boolean accept(final Object node) {
if (node instanceof ProblemDescriptionNode) {
nodes.add((ProblemDescriptionNode)node);
//allow unused declaration to have structure at file level even when there are unused parameters
if (!HighlightInfoType.UNUSED_SYMBOL_SHORT_NAME.equals(toolWrapper.getShortName())) {
for (RefElementNode parentNode : parentNodes) {
final List<ProblemDescriptionNode> nodes = new ArrayList<>();
TreeUtil.traverse(parentNode, new TreeUtil.Traverse() {
@Override
public boolean accept(final Object node) {
if (node instanceof ProblemDescriptionNode) {
nodes.add((ProblemDescriptionNode)node);
}
return true;
}
return true;
});
if (nodes.isEmpty()) continue;
parentNode.removeAllChildren();
for (ProblemDescriptionNode node : nodes) {
parentNode.add(node);
}
});
if (nodes.isEmpty()) continue; //FilteringInspectionTool == DeadCode
parentNode.removeAllChildren();
for (ProblemDescriptionNode node : nodes) {
parentNode.add(node);
}
}
for (RefElementNode node : parentNodes) {
@@ -81,7 +81,7 @@ public class InspectionRVContentProviderImpl extends InspectionRVContentProvider
public QuickFixAction[] getQuickFixes(@NotNull final InspectionToolWrapper toolWrapper, @NotNull final InspectionTree tree) {
final RefEntity[] refEntities = tree.getSelectedElements();
InspectionToolPresentation presentation = tree.getContext().getPresentation(toolWrapper);
return refEntities.length == 0 ? null : presentation.getQuickFixes(refEntities, tree.getSelectedDescriptors());
return refEntities.length == 0 ? null : presentation.getQuickFixes(refEntities, tree);
}
@@ -1,93 +0,0 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInspection.ex;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiFile;
import com.intellij.util.SequentialModalProgressTask;
import com.intellij.util.SequentialTask;
import java.util.*;
class SequentialCleanupTask implements SequentialTask {
private static final Logger LOG = Logger.getInstance(SequentialCleanupTask.class);
private final Project myProject;
private final List<Pair<PsiFile, HighlightInfo>> myResults = new ArrayList<>();
private final SequentialModalProgressTask myProgressTask;
private int myCount = 0;
public SequentialCleanupTask(Project project, LinkedHashMap<PsiFile, List<HighlightInfo>> results, SequentialModalProgressTask task) {
myProject = project;
for (Map.Entry<PsiFile, List<HighlightInfo>> entry : results.entrySet()) {
PsiFile file = entry.getKey();
List<HighlightInfo> infos = entry.getValue();
// sort from bottom to top
Collections.sort(infos, (info1, info2) -> info2.getStartOffset() - info1.getStartOffset());
for (HighlightInfo info : infos) {
myResults.add(Pair.create(file, info));
}
}
myProgressTask = task;
}
@Override
public void prepare() {}
@Override
public boolean isDone() {
return myCount > myResults.size() - 1;
}
@Override
public boolean iteration() {
final Pair<PsiFile, HighlightInfo> pair = myResults.get(myCount++);
final ProgressIndicator indicator = myProgressTask.getIndicator();
if (indicator != null) {
indicator.setFraction((double) myCount/myResults.size());
indicator.setText("Processing " + pair.first.getName());
}
for (final Pair<HighlightInfo.IntentionActionDescriptor, TextRange> actionRange : pair.second.quickFixActionRanges) {
final AccessToken token = WriteAction.start();
try {
actionRange.getFirst().getAction().invoke(myProject, null, pair.first);
}
catch (ProcessCanceledException e) {
throw e;
}
catch (Exception e) {
LOG.error(e);
}
finally {
token.finish();
}
}
return true;
}
@Override
public void stop() {}
}
@@ -618,8 +618,8 @@ public class DefaultInspectionToolPresentation implements ProblemDescriptionsPro
@Override
@Nullable
public QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements, CommonProblemDescriptor[] allowedDescriptors) {
return extractActiveFixes(refElements, getProblemElements(), allowedDescriptors);
public QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements, InspectionTree tree) {
return extractActiveFixes(refElements, getProblemElements(), tree != null ? tree.getSelectedDescriptors() : null);
}
@Override
@@ -80,7 +80,7 @@ public interface InspectionToolPresentation extends ProblemDescriptionsProcessor
@NotNull
Set<RefModule> getModuleProblems();
@Nullable
QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements, @Nullable CommonProblemDescriptor[] descriptors);
QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements, @Nullable InspectionTree tree);
@NotNull
Map<RefEntity, CommonProblemDescriptor[]> getProblemElements();
@NotNull
@@ -52,7 +52,7 @@ public class FileTemplateSettings extends FileTemplatesLoader implements Persist
@Nullable
@Override
public Element getState() {
Element element = null;
Element element = new Element("fileTemplateSettings");
for (FTManager manager : getAllManagers()) {
Element templatesGroup = null;
for (FileTemplateBase template : manager.getAllTemplates(true)) {
@@ -75,9 +75,6 @@ public class FileTemplateSettings extends FileTemplatesLoader implements Persist
if (templatesGroup == null) {
templatesGroup = new Element(getXmlElementGroupName(manager));
if (element == null) {
element = new Element("fileTemplateSettings");
}
element.addContent(templatesGroup);
}
templatesGroup.addContent(templateElement);
@@ -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,13 +22,13 @@ import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowFactoryEx;
import com.intellij.openapi.wm.ToolWindowFactory;
import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
public class ProjectViewToolWindowFactory implements ToolWindowFactoryEx, DumbAware {
public class ProjectViewToolWindowFactory implements ToolWindowFactory, DumbAware {
@Override
public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
((ProjectViewImpl) ProjectView.getInstance(project)).setupImpl(toolWindow);
@@ -667,9 +667,7 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable
@Override
public JComponent getPreferredFocusedComponent() {
final InspectionProfileImpl inspectionProfile = myProfiles.getProfilesComboBox().getSelectedProfile();
SingleInspectionProfilePanel panel = getProfilePanel(inspectionProfile);
return panel == null ? null : panel.getPreferredFocusedComponent();
return myProfilePanelHolder;
}
private void showProfile(InspectionProfileImpl profile) {
@@ -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.
@@ -23,8 +23,24 @@ import org.jetbrains.annotations.NotNull;
* Performs lazy initialization of a toolwindow registered in plugin.xml.
*
* @author yole
* @author Konstantin Bulenkov
* @see ToolWindowEP
*/
public interface ToolWindowFactory {
void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow);
/**
* Perform additional initialisation routine here
* @param window Tool Window
*/
default void init(ToolWindow window) {}
/**
* Tool Window saves its state on project close and restore on when project opens
* In some cases, it is useful to postpone Tool Window activation until user explicitly activates it.
* Example: Tool Window initialisation takes huge amount of time and makes project loading slower.
* @return {@code true} if Tool Window should not be activated on start even if was opened previously.
* {@code false} otherwise.
*/
default boolean isDoNotActivateOnStart() {return false;}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 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,7 +17,7 @@ package com.intellij.openapi.wm;
/**
* @author Dennis.Ushakov
* @deprecated use {@link ToolWindowFactory}
*/
public interface ToolWindowFactoryEx extends ToolWindowFactory {
void init(ToolWindow window);
}
@@ -0,0 +1,66 @@
/*
* 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.diagnostic;
import com.intellij.diagnostic.errordialog.PluginConflictDialog;
import com.intellij.ide.plugins.cl.PluginClassLoader;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.wm.WindowManager;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public enum PluginConflictReporter {
INSTANCE;
public void reportConflictByClasses(@NotNull Collection<Class<?>> conflictingClasses) {
final Set<PluginId> foundPlugins = new HashSet<>();
boolean hasConflictWithPlatform = false;
if (conflictingClasses.size() < 2) {
throw new IllegalArgumentException("The conflict should has been caused by at least two classes");
}
for (Class<?> aClass : conflictingClasses) {
final ClassLoader classLoader = aClass.getClassLoader();
if (classLoader instanceof PluginClassLoader) {
foundPlugins.add(((PluginClassLoader)classLoader).getPluginId());
}
else {
hasConflictWithPlatform = true;
}
}
if (foundPlugins.isEmpty()) {
Logger.getInstance(PluginConflictReporter.class).warn("The conflict has not come from PluginClassLoader");
return;
}
boolean finalHasConflictWithPlatform = hasConflictWithPlatform;
ApplicationManager.getApplication().invokeLater(() -> {
final JFrame frame = WindowManager.getInstance().findVisibleFrame();
if (frame != null) {
new PluginConflictDialog(frame, new ArrayList<>(foundPlugins), finalHasConflictWithPlatform).show();
}
});
}
}
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.diagnostic.errordialog.PluginConflictDialog">
<grid id="27dc6" binding="myContentPane" layout-manager="GridLayoutManager" row-count="4" 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="400"/>
</constraints>
<properties>
<preferredSize width="400" height="-1"/>
</properties>
<border type="none"/>
<children>
<component id="94dfc" class="com.intellij.ui.components.JBLabel" binding="myTopMessageLabel">
<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"/>
</constraints>
<properties/>
</component>
<grid id="99a5b" binding="myConflictingPluginsListPanel" custom-create="true" layout-manager="FlowLayout" hgap="5" vgap="5" flow-align="0">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children/>
</grid>
<component id="d6b86" class="com.intellij.ui.components.JBLabel" binding="myBottomMessageLabel">
<constraints>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<vspacer id="a4d4f">
<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"/>
</constraints>
</vspacer>
</children>
</grid>
</form>
@@ -0,0 +1,242 @@
/*
* 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.diagnostic.errordialog;
import com.intellij.diagnostic.DiagnosticBundle;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.ide.plugins.PluginManagerConfigurable;
import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBRadioButton;
import com.intellij.util.ui.JBEmptyBorder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class PluginConflictDialog extends DialogWrapper {
public static final int WIDTH = 510;
@NotNull
private final List<PluginId> myConflictingPlugins;
private final boolean myIsConflictWithPlatform;
@Nullable
private final List<JBRadioButton> myRadioButtons;
private JPanel myContentPane;
private JBLabel myTopMessageLabel;
private JPanel myConflictingPluginsListPanel;
private JBLabel myBottomMessageLabel;
public PluginConflictDialog(@NotNull Component parent,
@NotNull List<PluginId> conflictingPlugins,
boolean isConflictWithPlatform) {
super(parent, false);
myConflictingPlugins = conflictingPlugins;
myIsConflictWithPlatform = isConflictWithPlatform;
if (myIsConflictWithPlatform) {
myRadioButtons = null;
}
else {
myRadioButtons = new ArrayList<>();
}
$$$setupUI$$$();
setTitle(DiagnosticBundle.message("error.dialog.conflict.plugin.title"));
init();
myTopMessageLabel.setText(getTopMessageText(conflictingPlugins, isConflictWithPlatform));
myBottomMessageLabel.setText(DiagnosticBundle.message("error.dialog.conflict.plugin.footer"));
myTopMessageLabel.setPreferredSize(new Dimension(WIDTH, (int)myTopMessageLabel.getPreferredSize().getHeight()));
myContentPane.setPreferredSize(new Dimension(WIDTH, (int)myContentPane.getMinimumSize().getHeight()));
}
private static String getTopMessageText(@NotNull List<PluginId> conflictingPlugins, boolean isConflictWithPlatform) {
final int pluginsNumber = conflictingPlugins.size();
if (isConflictWithPlatform) {
return DiagnosticBundle.message("error.dialog.conflict.plugin.header.platform", pluginsNumber);
}
else {
final List<String> names = conflictingPlugins.stream()
.map(PluginConflictDialog::getPluginNameOrId)
.map(s -> "<b>" + s + "</b>")
.collect(Collectors.toList());
return DiagnosticBundle.message("error.dialog.conflict.plugin.header.each.other",
StringUtil.join(names.subList(0, pluginsNumber - 1), ", "),
names.get(pluginsNumber - 1));
}
}
private void $$$setupUI$$$() {
}
@Nullable
@Override
protected JComponent createCenterPanel() {
return myContentPane;
}
private void createUIComponents() {
final ButtonGroup buttonGroup = new ButtonGroup();
myConflictingPluginsListPanel = new JPanel(new GridLayout(0, 1));
final List<JPanel> pluginDescriptions = myConflictingPlugins.stream()
.map(plugin -> getChooserPanelForPlugin(buttonGroup, plugin))
.collect(Collectors.toList());
if (!myIsConflictWithPlatform) {
pluginDescriptions.add(0, getChooserPanelForPlugin(buttonGroup, null));
}
for (JPanel panel : pluginDescriptions) {
myConflictingPluginsListPanel.add(panel);
}
setUpDefaultSelection();
}
@NotNull
private JPanel getChooserPanelForPlugin(@NotNull ButtonGroup buttonGroup, @Nullable PluginId plugin) {
final JPanel panel = new JPanel(new BorderLayout());
if (!myIsConflictWithPlatform) {
assert myRadioButtons != null;
final JBRadioButton radioButton = new JBRadioButton();
myRadioButtons.add(radioButton);
buttonGroup.add(radioButton);
panel.add(radioButton, BorderLayout.WEST);
panel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
radioButton.setSelected(true);
}
});
}
final JPanel descriptionPanel;
if (plugin != null) {
descriptionPanel = getPluginDescriptionPanel(plugin, !myIsConflictWithPlatform);
}
else {
descriptionPanel = getDisableAllPanel();
}
descriptionPanel.setBorder(new JBEmptyBorder(10, myIsConflictWithPlatform ? 10 : 0, 10, 20));
panel.add(descriptionPanel, BorderLayout.CENTER);
return panel;
}
private void setUpDefaultSelection() {
if (myIsConflictWithPlatform) {
return;
}
assert myRadioButtons != null && myRadioButtons.size() == myConflictingPlugins.size() + 1;
for (int i = 0; i < myConflictingPlugins.size(); i++) {
final IdeaPluginDescriptor pluginDescriptor = PluginManager.getPlugin(myConflictingPlugins.get(i));
if (pluginDescriptor != null
&& (pluginDescriptor.isBundled() || StringUtil.equalsIgnoreCase(pluginDescriptor.getVendor(), "JetBrains"))) {
myRadioButtons.get(i).setSelected(true);
return;
}
}
myRadioButtons.get(myRadioButtons.size() - 1).setSelected(true);
}
@NotNull
private static JPanel getPluginDescriptionPanel(@NotNull PluginId plugin, boolean addUseWord) {
final JPanel panel = new JPanel(new BorderLayout());
final IdeaPluginDescriptor pluginDescriptor = PluginManager.getPlugin(plugin);
if (pluginDescriptor == null) {
panel.add(new JBLabel(plugin.getIdString()), BorderLayout.CENTER);
return panel;
}
final StringBuilder sb = new StringBuilder("<html>");
if (addUseWord) {
sb.append("Use ");
}
sb.append(pluginDescriptor.getName());
if (pluginDescriptor.getVendor() != null) {
sb.append(" by ").append(pluginDescriptor.getVendor());
}
sb.append("</html>");
panel.add(new JBLabel(sb.toString()));
return panel;
}
@NotNull
private static String getPluginNameOrId(@NotNull PluginId pluginId) {
final IdeaPluginDescriptor pluginDescriptor = PluginManager.getPlugin(pluginId);
if (pluginDescriptor == null) {
return pluginId.getIdString();
}
else {
return pluginDescriptor.getName();
}
}
@NotNull
private static JPanel getDisableAllPanel() {
final JPanel panel = new JPanel(new BorderLayout());
panel.add(new JBLabel(DiagnosticBundle.message("error.dialog.conflict.plugin.disable.all")));
return panel;
}
@NotNull
@Override
protected Action getOKAction() {
return new DisableAction();
}
private class DisableAction extends DialogWrapperAction {
protected DisableAction() {
super(DiagnosticBundle.message("error.dialog.disable.plugin.action.disable"));
putValue(DEFAULT_ACTION, Boolean.TRUE);
}
@Override
protected void doAction(ActionEvent e) {
for (int i = 0; i < myConflictingPlugins.size(); ++i) {
if (myRadioButtons == null || !myRadioButtons.get(i).isSelected()) {
PluginManagerCore.disablePlugin(myConflictingPlugins.get(i).getIdString());
}
}
close(OK_EXIT_CODE);
PluginManagerConfigurable.shutdownOrRestartApp("");
}
}
}

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