diff --git a/.idea/libraries/Eclipse.xml b/.idea/libraries/Eclipse.xml index 270d58e2ae95..f680844b8415 100644 --- a/.idea/libraries/Eclipse.xml +++ b/.idea/libraries/Eclipse.xml @@ -1,7 +1,7 @@ - + diff --git a/bin/linux/restart.py b/bin/linux/restart.py index 93bf229db65e..5d49a22c3820 100755 --- a/bin/linux/restart.py +++ b/bin/linux/restart.py @@ -3,21 +3,22 @@ # Waits for the parent process to terminate, then executes specified commands. import os +import signal import sys import time -if len(sys.argv) < 2: - raise Exception('At least one argument expected') +if len(sys.argv) < 3: + raise Exception('usage: restart.py [optional command]') -pid = os.getppid() +signal.signal(signal.SIGHUP, signal.SIG_IGN) + +pid = int(sys.argv[1]) while os.getppid() == pid: time.sleep(0.5) -if len(sys.argv) > 2: - os.spawnv(os.P_WAIT, sys.argv[2], sys.argv[2:]) +if len(sys.argv) > 3: + to_launch = sys.argv[3:] + os.spawnv(os.P_WAIT, to_launch[0], to_launch) -to_launch = sys.argv[1] -if sys.platform == 'darwin': - os.execv('/usr/bin/open', ['/usr/bin/open', to_launch]) -else: - os.execv(to_launch, [to_launch]) +to_launch = ['/usr/bin/open', sys.argv[2]] if sys.platform == 'darwin' else [sys.argv[2]] +os.execv(to_launch[0], to_launch) diff --git a/java/compiler/impl/src/com/intellij/task/impl/InternalProjectTaskRunner.java b/java/compiler/impl/src/com/intellij/task/impl/InternalProjectTaskRunner.java index 5aa4c074f6d2..d922e54f3883 100644 --- a/java/compiler/impl/src/com/intellij/task/impl/InternalProjectTaskRunner.java +++ b/java/compiler/impl/src/com/intellij/task/impl/InternalProjectTaskRunner.java @@ -25,6 +25,7 @@ import com.intellij.openapi.compiler.CompilerManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.packaging.artifacts.Artifact; import com.intellij.packaging.impl.compiler.ArtifactCompileScope; @@ -89,54 +90,79 @@ public class InternalProjectTaskRunner extends ProjectTaskRunner { @Nullable CompileStatusNotification compileNotification, @NotNull Map, List> tasksMap) { Collection buildTasks = tasksMap.get(ModuleBuildTask.class); + if (ContainerUtil.isEmpty(buildTasks)) return; + ModulesBuildSettings modulesBuildSettings = assembleModulesBuildSettings(buildTasks); - - if (!ContainerUtil.isEmpty(buildTasks)) { - List modules = new SmartList<>(); - - Boolean isIncrementalBuild = null; - Boolean includeDependentModules = null; - Boolean includeRuntimeDependencies = null; - - for (ProjectTask buildProjectTask : buildTasks) { - ModuleBuildTask moduleBuildTask = (ModuleBuildTask)buildProjectTask; - assertModuleBuildSettings(moduleBuildTask, isIncrementalBuild, includeDependentModules, includeRuntimeDependencies); - modules.add(moduleBuildTask.getModule()); - if (!moduleBuildTask.isIncrementalBuild()) { - isIncrementalBuild = false; - } - if (moduleBuildTask.isIncludeDependentModules()) { - includeDependentModules = true; - } - if (moduleBuildTask.isIncludeRuntimeDependencies()) { - includeRuntimeDependencies = true; - } - } - CompilerManager compilerManager = CompilerManager.getInstance(project); - CompileScope scope = createScope( - compilerManager, context, modules, includeDependentModules != null, includeRuntimeDependencies != null); - if (isIncrementalBuild == null) { - compilerManager.make(scope, compileNotification); - } - else { - compilerManager.compile(scope, compileNotification); - } + CompilerManager compilerManager = CompilerManager.getInstance(project); + CompileScope scope = createScope(compilerManager, context, + modulesBuildSettings.modules, + modulesBuildSettings.includeDependentModules, + modulesBuildSettings.includeRuntimeDependencies); + if (modulesBuildSettings.isIncrementalBuild) { + compilerManager.make(scope, compileNotification); + } + else { + compilerManager.compile(scope, compileNotification); } } - private static void assertModuleBuildSettings(ModuleBuildTask moduleBuildTask, - Boolean isIncrementalBuild, - Boolean includeDependentModules, - Boolean includeRuntimeDependencies) { - if (isIncrementalBuild != null && moduleBuildTask.isIncrementalBuild()) { - LOG.warn("Incremental build setting for the module '" + moduleBuildTask.getModule().getName() + "' will be ignored"); + private static class ModulesBuildSettings { + final boolean isIncrementalBuild; + final boolean includeDependentModules; + final boolean includeRuntimeDependencies; + final Collection modules; + + public ModulesBuildSettings(boolean isIncrementalBuild, + boolean includeDependentModules, + boolean includeRuntimeDependencies, + Collection modules) { + this.isIncrementalBuild = isIncrementalBuild; + this.includeDependentModules = includeDependentModules; + this.includeRuntimeDependencies = includeRuntimeDependencies; + this.modules = modules; } - if (includeDependentModules != null && !moduleBuildTask.isIncludeDependentModules()) { - LOG.warn("'Module '" + moduleBuildTask.getModule().getName() + "' will be built along with dependent modules"); + } + + private static ModulesBuildSettings assembleModulesBuildSettings(Collection buildTasks) { + Collection modules = new SmartList<>(); + Collection incrementalTasks = ContainerUtil.newSmartList(); + Collection excludeDependentTasks = ContainerUtil.newSmartList(); + Collection excludeRuntimeTasks = ContainerUtil.newSmartList(); + + for (ProjectTask buildProjectTask : buildTasks) { + ModuleBuildTask moduleBuildTask = (ModuleBuildTask)buildProjectTask; + modules.add(moduleBuildTask.getModule()); + + if (moduleBuildTask.isIncrementalBuild()) { + incrementalTasks.add(moduleBuildTask); + } + if (!moduleBuildTask.isIncludeDependentModules()) { + excludeDependentTasks.add(moduleBuildTask); + } + if (!moduleBuildTask.isIncludeRuntimeDependencies()) { + excludeRuntimeTasks.add(moduleBuildTask); + } } - if (includeRuntimeDependencies != null && !moduleBuildTask.isIncludeRuntimeDependencies()) { - LOG.warn("'Module '" + moduleBuildTask.getModule().getName() + "' will be built along with runtime dependencies"); + + boolean isIncrementalBuild = incrementalTasks.size() == buildTasks.size(); + boolean includeDependentModules = excludeDependentTasks.size() != buildTasks.size(); + boolean includeRuntimeDependencies = excludeRuntimeTasks.size() != buildTasks.size(); + + if (!isIncrementalBuild && !incrementalTasks.isEmpty()) { + assertModuleBuildSettingsConsistent(incrementalTasks, "will be built ignoring incremental build setting"); } + if (includeDependentModules && !excludeDependentTasks.isEmpty()) { + assertModuleBuildSettingsConsistent(excludeDependentTasks, "will be built along with dependent modules"); + } + if (includeRuntimeDependencies && !excludeRuntimeTasks.isEmpty()) { + assertModuleBuildSettingsConsistent(excludeRuntimeTasks, "will be built along with runtime dependencies"); + } + return new ModulesBuildSettings(isIncrementalBuild, includeDependentModules, includeRuntimeDependencies, modules); + } + + private static void assertModuleBuildSettingsConsistent(Collection moduleBuildTasks, String warnMsg) { + String moduleNames = StringUtil.join(moduleBuildTasks, task -> task.getModule().getName(), ", "); + LOG.warn("Module" + (moduleBuildTasks.size() > 1 ? "s": "") + " : '" + moduleNames + "' " + warnMsg); } private static CompileScope createScope(CompilerManager compilerManager, diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java index bd47b8918fd9..ea908fe312d2 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java @@ -882,21 +882,24 @@ public abstract class DebuggerUtilsEx extends DebuggerUtils { PsiElement body = lambda.getBody(); if (body == null || !intersects(lineRange, body)) return null; if (body instanceof PsiCodeBlock) { - for (PsiStatement statement : ((PsiCodeBlock)body).getStatements()) { - // return first statement starting on the line - if (lineRange.contains(statement.getTextOffset())) { - return statement; - } - // otherwise check all children - else if (intersects(lineRange, statement)) { - for (PsiElement element : SyntaxTraverser.psiTraverser(statement)) { - if (lineRange.contains(element.getTextOffset())) { - return element; + PsiStatement[] statements = ((PsiCodeBlock)body).getStatements(); + if (statements.length > 0) { + for (PsiStatement statement : statements) { + // return first statement starting on the line + if (lineRange.contains(statement.getTextOffset())) { + return statement; + } + // otherwise check all children + else if (intersects(lineRange, statement)) { + for (PsiElement element : SyntaxTraverser.psiTraverser(statement)) { + if (lineRange.contains(element.getTextOffset())) { + return element; + } } } } + return null; } - return null; } return body; } diff --git a/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java b/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java index 990fea7bd281..d63f2bc7bd4f 100644 --- a/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java +++ b/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java @@ -120,6 +120,7 @@ public class JUnitUtil { if (psiMethod.getParameterList().getParametersCount() > 0) return false; if (psiMethod.hasModifierProperty(PsiModifier.STATIC) && SUITE_METHOD_NAME.equals(psiMethod.getName())) return false; if (!psiMethod.getName().startsWith("test")) return false; + if (psiMethod.hasModifierProperty(PsiModifier.STATIC)) return false; PsiClass testCaseClass = getTestCaseClassOrNull(location); return testCaseClass != null && psiMethod.getContainingClass().isInheritor(testCaseClass, true) && PsiType.VOID.equals(psiMethod.getReturnType()); } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java index 48dbf15eda4b..d45440dbe99a 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java @@ -298,9 +298,7 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp return null; } PsiType type = typeElement.getType(); - if (type instanceof PsiPrimitiveType) return null; - type = type.getDeepComponentType(); - if (type instanceof PsiClassType && (((PsiClassType)type).resolve() instanceof PsiTypeParameter)) return null; + if (type instanceof PsiPrimitiveType || PsiUtil.resolveClassInType(type) instanceof PsiTypeParameter) return null; return expression; } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/SimplifyStreamApiCallChainsInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/SimplifyStreamApiCallChainsInspection.java index e29355b85b9c..30c38eae0a3e 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/SimplifyStreamApiCallChainsInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/SimplifyStreamApiCallChainsInspection.java @@ -20,7 +20,9 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; +import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.impl.PsiDiamondTypeUtil; import com.intellij.psi.util.*; import com.siyeh.ig.psiutils.BoolUtils; import org.jetbrains.annotations.Contract; @@ -30,6 +32,7 @@ import org.jetbrains.annotations.Nullable; import java.text.MessageFormat; import java.util.Arrays; +import java.util.stream.Stream; /** * @author Pavel.Dolgov @@ -57,6 +60,9 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns private static final String ALL_MATCH_METHOD = "allMatch"; private static final String COUNTING_COLLECTOR = "counting"; + private static final String TO_LIST_COLLECTOR = "toList"; + private static final String TO_SET_COLLECTOR = "toSet"; + private static final String TO_COLLECTION_COLLECTOR = "toCollection"; private static final String MIN_BY_COLLECTOR = "minBy"; private static final String MAX_BY_COLLECTOR = "maxBy"; private static final String MAPPING_COLLECTOR = "mapping"; @@ -150,6 +156,13 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns } } + @Contract("null -> false") + private boolean isCollectionStream(PsiMethodCallExpression qualifierCall) { + if (qualifierCall == null) return false; + PsiMethod qualifier = qualifierCall.resolveMethod(); + return isCallOf(qualifier, CommonClassNames.JAVA_UTIL_COLLECTION, STREAM_METHOD, 0); + } + private void handleStreamForEach(PsiMethodCallExpression methodCall, PsiMethod method) { final String name; if (isCallOf(method, CommonClassNames.JAVA_UTIL_STREAM_STREAM, FOR_EACH_METHOD, 1)) { @@ -162,9 +175,7 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns return; } final PsiMethodCallExpression qualifierCall = getQualifierMethodCall(methodCall); - if (qualifierCall == null) return; - final PsiMethod qualifier = qualifierCall.resolveMethod(); - if (isCallOf(qualifier, CommonClassNames.JAVA_UTIL_COLLECTION, STREAM_METHOD, 0)) { + if (isCollectionStream(qualifierCall)) { final ReplaceStreamMethodFix fix = new ReplaceStreamMethodFix(name, FOR_EACH_METHOD, true); holder .registerProblem(methodCall, getCallChainRange(methodCall, qualifierCall), fix.getMessage(), new SimplifyCallChainFix(fix)); @@ -176,7 +187,7 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns if(parameter instanceof PsiMethodCallExpression) { PsiMethodCallExpression collectorCall = (PsiMethodCallExpression)parameter; PsiMethod collectorMethod = collectorCall.resolveMethod(); - ReplaceCollectorFix fix = null; + ReplaceCollectorFix fix; 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)) { @@ -197,9 +208,26 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns fix = new ReplaceCollectorFix(SUMMING_LONG_COLLECTOR, "mapToLong({0}).sum()", false); } else if(isCallOf(collectorMethod, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, SUMMING_DOUBLE_COLLECTOR, 1)) { fix = new ReplaceCollectorFix(SUMMING_DOUBLE_COLLECTOR, "mapToDouble({0}).sum()", false); + } else { + PsiType type = methodCall.getType(); + if(type instanceof PsiClassType && !(((PsiClassType)type).resolve() instanceof PsiTypeParameter)) { + String replacement = collectorToCollection(collectorCall); + if (replacement != null) { + PsiMethodCallExpression qualifier = getQualifierMethodCall(methodCall); + if (isCollectionStream(qualifier)) { + PsiElement startElement = qualifier.getMethodExpression().getReferenceNameElement(); + if (startElement != null) { + holder.registerProblem(methodCall, new TextRange(startElement.getTextOffset() - methodCall.getTextOffset(), + methodCall.getTextLength()), + "Can be replaced with '" + replacement + "' constructor", + new SimplifyCallChainFix(new SimplifyCollectionCreationFix(replacement))); + } + } + } + } + return; } - if (fix != null && - collectorCall.getArgumentList().getExpressions().length == collectorMethod.getParameterList().getParametersCount()) { + if (collectorCall.getArgumentList().getExpressions().length == collectorMethod.getParameterList().getParametersCount()) { TextRange range = methodCall.getTextRange(); PsiElement nameElement = methodCall.getMethodExpression().getReferenceNameElement(); if(nameElement != null) { @@ -247,6 +275,51 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns }; } + private static boolean isCollectionConstructor(PsiMethod ctor) { + if(!ctor.getModifierList().hasExplicitModifier(PsiModifier.PUBLIC)) return false; + PsiParameterList list = ctor.getParameterList(); + if(list.getParametersCount() != 1) return false; + PsiParameter parameter = list.getParameters()[0]; + PsiTypeElement typeElement = parameter.getTypeElement(); + if(typeElement == null) return false; + PsiType type = typeElement.getType(); + if(!(type instanceof PsiClassType)) return false; + PsiClass aClass = ((PsiClassType)type).resolve(); + if(aClass == null) return false; + return CommonClassNames.JAVA_UTIL_COLLECTION.equals(aClass.getQualifiedName()); + } + + @Nullable + private static String collectorToCollection(PsiMethodCallExpression call) { + PsiMethod method = call.resolveMethod(); + if(isCallOf(method, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, TO_LIST_COLLECTOR, 0)) { + return CommonClassNames.JAVA_UTIL_ARRAY_LIST; + } + if(isCallOf(method, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, TO_SET_COLLECTOR, 0)) { + return CommonClassNames.JAVA_UTIL_HASH_SET; + } + if(isCallOf(method, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, TO_COLLECTION_COLLECTOR, 1)) { + PsiExpression[] expressions = call.getArgumentList().getExpressions(); + if(expressions.length == 1 && expressions[0] instanceof PsiMethodReferenceExpression) { + PsiMethodReferenceExpression methodRef = (PsiMethodReferenceExpression)expressions[0]; + if(methodRef.isConstructor()) { + PsiElement element = methodRef.resolve(); + if(element instanceof PsiMethod) { + PsiMethod ctor = (PsiMethod)element; + if(ctor.getParameterList().getParametersCount() == 0) { + PsiClass aClass = ctor.getContainingClass(); + if (aClass != null && + Stream.of(aClass.getConstructors()).anyMatch(SimplifyStreamApiCallChainsInspection::isCollectionConstructor)) { + return aClass.getQualifiedName(); + } + } + } + } + } + } + return null; + } + static boolean isParentNegated(PsiMethodCallExpression methodCall) { PsiElement parent = PsiUtil.skipParenthesizedExprUp(methodCall.getParent()); return parent instanceof PsiExpression && BoolUtils.isNegation((PsiExpression)parent); @@ -689,4 +762,51 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns } } } + + private static class SimplifyCollectionCreationFix implements CallChainFix { + private String myReplacement; + + public SimplifyCollectionCreationFix(String replacement) { + myReplacement = replacement; + } + + @Override + public String getName() { + return "Replace with '"+myReplacement+"' constructor"; + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + PsiElement element = descriptor.getStartElement(); + if(!(element instanceof PsiMethodCallExpression)) return; + PsiMethodCallExpression collectCall = (PsiMethodCallExpression)element; + PsiType type = collectCall.getType(); + if(!(type instanceof PsiClassType)) return; + PsiClass resolvedType = ((PsiClassType)type).resolve(); + if(resolvedType == null || resolvedType instanceof PsiTypeParameter) return; + PsiMethodCallExpression streamCall = getQualifierMethodCall(collectCall); + if(streamCall == null) return; + PsiExpression collectionExpression = streamCall.getMethodExpression().getQualifierExpression(); + if(collectionExpression == null) return; + String typeText = type.getCanonicalText(); + if(CommonClassNames.JAVA_UTIL_LIST.equals(resolvedType.getQualifiedName()) || + CommonClassNames.JAVA_UTIL_SET.equals(resolvedType.getQualifiedName())) { + PsiType[] parameters = ((PsiClassType)type).getParameters(); + if(parameters.length != 1) return; + typeText = myReplacement + "<" + parameters[0].getCanonicalText() + ">"; + } + if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return; + PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); + PsiExpression result = factory + .createExpressionFromText("new " + typeText + "(" + collectionExpression.getText() + ")", element); + PsiNewExpression newExpression = (PsiNewExpression)element.replace(result); + PsiJavaCodeReferenceElement classReference = newExpression.getClassOrAnonymousClassReference(); + LOG.assertTrue(classReference != null); + JavaCodeStyleManager.getInstance(project).shortenClassReferences(classReference); + if (PsiDiamondTypeUtil.canCollapseToDiamond(newExpression, newExpression, null)) { + PsiDiamondTypeUtil.replaceExplicitWithDiamond(classReference.getParameterList()); + } + CodeStyleManager.getInstance(project).reformat(newExpression); + } + } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java b/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java index d31afee0a899..a57029729610 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java @@ -79,13 +79,7 @@ public class ConstructorInsertHandler implements InsertHandler 0 && - ((PsiTypeLookupItem)delegate).calcGenerics(position, context).isEmpty() && - context.getCompletionChar() != '('; - if (context.getDocument().getTextLength() > context.getTailOffset() && context.getDocument().getCharsSequence().charAt(context.getTailOffset()) == '<') { PsiJavaCodeReferenceElement ref = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getTailOffset(), PsiJavaCodeReferenceElement.class, false); @@ -124,14 +118,15 @@ public class ConstructorInsertHandler implements InsertHandler implements TypedLookupItem { private static final Key WRAPPING_CONSTRUCTOR_CALL = Key.create("WRAPPING_CONSTRUCTOR_CALL"); - @NotNull private final LookupElement myClassItem; + @NotNull private final PsiMethod myConstructor; @NotNull private final PsiClassType myType; + @NotNull private final PsiSubstitutor mySubstitutor; - private JavaConstructorCallElement(@NotNull LookupElement classItem, @NotNull PsiMethod constructor, @NotNull Supplier type) { - super(constructor); - myClassItem = classItem; - myType = type.get(); - setQualifierSubstitutor(myType.resolveGenerics().getSubstitutor()); + private JavaConstructorCallElement(@NotNull LookupElement classItem, @NotNull PsiMethod constructor, @NotNull PsiClassType type) { + super(classItem); + myConstructor = constructor; + myType = type; + mySubstitutor = myType.resolveGenerics().getSubstitutor(); markClassItemWrapped(classItem); } @@ -59,28 +62,38 @@ public class JavaConstructorCallElement extends JavaMethodCallElement { } } + @NotNull + @Override + public PsiMethod getObject() { + return myConstructor; + } + + @Override + public boolean equals(Object o) { + return this == o || super.equals(o) && myConstructor.equals(((JavaConstructorCallElement)o).myConstructor); + } + + @Override + public int hashCode() { + return 31 * super.hashCode() + myConstructor.hashCode(); + } + @NotNull @Override public PsiType getType() { return myType; } - @Override - public void handleInsert(InsertionContext context) { - myClassItem.handleInsert(context); - super.handleInsert(context); - } - @Override public void renderElement(LookupElementPresentation presentation) { - myClassItem.renderElement(presentation); + super.renderElement(presentation); 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(MemberLookupHelper.getMethodParameterString(myConstructor, mySubstitutor), false); presentation.appendTailText(tailText.substring(genericsEnd), true); } @@ -94,7 +107,7 @@ public class JavaConstructorCallElement extends JavaMethodCallElement { if (Registry.is("java.completion.show.constructors") && isConstructorCallPlace(position)) { List constructors = ContainerUtil.filter(psiClass.getConstructors(), c -> shouldSuggestConstructor(psiClass, position, c)); if (!constructors.isEmpty()) { - return ContainerUtil.map(constructors, c -> new JavaConstructorCallElement(classItem, c, type)); + return ContainerUtil.map(constructors, c -> new JavaConstructorCallElement(classItem, c, type.get())); } } return Collections.singletonList(classItem); @@ -117,8 +130,10 @@ public class JavaConstructorCallElement extends JavaMethodCallElement { }); } - static boolean isWrapped(LookupElement element) { - return element.getUserData(WRAPPING_CONSTRUCTOR_CALL) != null; + @Nullable + static PsiMethod extractCalledConstructor(@NotNull LookupElement element) { + JavaConstructorCallElement callItem = element.getUserData(WRAPPING_CONSTRUCTOR_CALL); + return callItem != null ? callItem.getObject() : null; } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java index 065527c55642..21a494ed31f8 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java @@ -180,10 +180,7 @@ public class JavaMethodCallElement extends LookupItem implements Type } } - context.commitDocument(); - if (hasParams && context.getCompletionChar() != Lookup.COMPLETE_STATEMENT_SELECT_CHAR && Registry.is("java.completion.argument.live.template")) { - startArgumentLiveTemplate(context, method); - } + startArgumentLiveTemplate(context, method); } private void importOrQualify(Document document, PsiFile file, PsiMethod method, int startOffset) { @@ -198,7 +195,7 @@ public class JavaMethodCallElement extends LookupItem implements Type qualifyMethodCall(file, startOffset, document); } - public static final Key ARGUMENT_TEMPLATE_ACTIVE = Key.create("ARGUMENT_TEMPLATE_ACTIVE"); + public static final Key ARGUMENT_TEMPLATE_ACTIVE = Key.create("ARGUMENT_TEMPLATE_ACTIVE"); @NotNull private static Template createArgTemplate(PsiMethod method, int caretOffset, @@ -226,19 +223,25 @@ public class JavaMethodCallElement extends LookupItem implements Type return template; } - private void startArgumentLiveTemplate(InsertionContext context, PsiMethod method) { - Editor editor = context.getEditor(); + public static boolean startArgumentLiveTemplate(InsertionContext context, PsiMethod method) { + if (method.getParameterList().getParametersCount() == 0 || + context.getCompletionChar() == Lookup.COMPLETE_STATEMENT_SELECT_CHAR || + !Registry.is("java.completion.argument.live.template")) { + return false; + } - PsiCallExpression call = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiCallExpression.class, false); + Editor editor = context.getEditor(); + context.commitDocument(); + PsiCall call = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiCall.class, false); PsiExpressionList argList = call == null ? null : call.getArgumentList(); if (argList == null || argList.getExpressions().length > 0) { - return; + return false; } TextRange argRange = argList.getTextRange(); int caretOffset = editor.getCaretModel().getOffset(); if (!argRange.contains(caretOffset)) { - return; + return false; } Template template = createArgTemplate(method, caretOffset, argList, argRange); @@ -247,16 +250,17 @@ public class JavaMethodCallElement extends LookupItem implements Type TemplateManager.getInstance(method.getProject()).startTemplate(editor, template); TemplateState templateState = TemplateManagerImpl.getTemplateState(editor); - if (templateState == null) return; + if (templateState == null) return false; setupNonFilledArgumentRemoving(editor, templateState); - editor.putUserData(ARGUMENT_TEMPLATE_ACTIVE, this); + editor.putUserData(ARGUMENT_TEMPLATE_ACTIVE, method); Disposer.register(templateState, () -> { - if (editor.getUserData(ARGUMENT_TEMPLATE_ACTIVE) == this) { + if (editor.getUserData(ARGUMENT_TEMPLATE_ACTIVE) == method) { editor.putUserData(ARGUMENT_TEMPLATE_ACTIVE, null); } }); + return true; } private static void setupNonFilledArgumentRemoving(final Editor editor, final TemplateState templateState) { diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/InlineStreamMapAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/InlineStreamMapAction.java index 7dbb7f3a3fce..cf3dcba1c3a5 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/InlineStreamMapAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/InlineStreamMapAction.java @@ -31,8 +31,8 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.util.LambdaRefactoringUtil; import com.intellij.util.IncorrectOperationException; import com.siyeh.ig.psiutils.ParenthesesUtils; -import com.siyeh.ig.style.MethodRefCanBeReplacedWithLambdaInspection; import one.util.streamex.StreamEx; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -87,8 +87,7 @@ public class InlineStreamMapAction extends PsiElementBaseIntentionAction { return lambdaExpression.getParameterList().getParametersCount() == 1 && (!requireExpressionLambda || LambdaUtil.extractSingleExpressionFromBody(lambdaExpression.getBody()) != null); } else if(expression instanceof PsiMethodReferenceExpression) { - PsiMethodReferenceExpression methodReference = (PsiMethodReferenceExpression)expression; - return !MethodRefCanBeReplacedWithLambdaInspection.isWithSideEffects(methodReference); + return LambdaRefactoringUtil.canConvertToLambda((PsiMethodReferenceExpression)expression); } return false; } @@ -161,12 +160,29 @@ public class InlineStreamMapAction extends PsiElementBaseIntentionAction { } } if(nextName.equals("flatMap") && prevClassName.equals(CommonClassNames.JAVA_UTIL_STREAM_STREAM)) { - String mapMethod = translateMap(prevName); - return "flatM"+mapMethod.substring(1); + return mapToFlatMap(prevName); } return null; } + @Contract(pure = true) + @Nullable + private static String mapToFlatMap(String mapMethod) { + switch (mapMethod) { + case "map": + return "flatMap"; + case "mapToInt": + return "flatMapToInt"; + case "mapToLong": + return "flatMapToLong"; + case "mapToDouble": + return "flatMapToDouble"; + } + // Something unsupported passed: ignore + return null; + } + + @Contract(pure = true) @NotNull private static String translateMap(String nextMethod) { switch (nextMethod) { diff --git a/java/java-impl/src/com/intellij/refactoring/util/LambdaRefactoringUtil.java b/java/java-impl/src/com/intellij/refactoring/util/LambdaRefactoringUtil.java index 6763e30c1864..e5d467213976 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/LambdaRefactoringUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/util/LambdaRefactoringUtil.java @@ -77,7 +77,6 @@ public class LambdaRefactoringUtil { final PsiParameter[] psiParameters = resolve instanceof PsiMethod ? ((PsiMethod)resolve).getParameterList().getParameters() : null; final StringBuilder buf = new StringBuilder("("); - LOG.assertTrue(functionalInterfaceType != null); buf.append(GenericsUtil.getVariableTypeByExpressionType(functionalInterfaceType).getCanonicalText()).append(")("); final PsiParameterList parameterList = interfaceMethod.getParameterList(); final PsiParameter[] parameters = parameterList.getParameters(); @@ -103,6 +102,7 @@ public class LambdaRefactoringUtil { else { initialName = parameter.getName(); } + LOG.assertTrue(initialName != null); baseName = codeStyleManager.variableNameToPropertyName(initialName, VariableKind.PARAMETER); } @@ -265,4 +265,16 @@ public class LambdaRefactoringUtil { } } } + + /** + * Checks whether method reference can be converted to lambda without significant semantics change + * (i.e. method reference qualifier has no side effects) + * + * @param methodReferenceExpression method reference to check + * @return true if method reference can be converted to lambda + */ + public static boolean canConvertToLambda(PsiMethodReferenceExpression methodReferenceExpression) { + final PsiExpression qualifierExpression = methodReferenceExpression.getQualifierExpression(); + return qualifierExpression != null && !SideEffectChecker.mayHaveSideEffects(qualifierExpression); + } } diff --git a/java/java-tests/testData/codeInsight/completion/signature/AnonymousNonDefaultConstructor.java b/java/java-tests/testData/codeInsight/completion/signature/AnonymousNonDefaultConstructor.java new file mode 100644 index 000000000000..3a09e0ada409 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/signature/AnonymousNonDefaultConstructor.java @@ -0,0 +1,8 @@ +abstract class Foo{ + public Foo(int x) { + } + + { + Foo f = new F + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/signature/AnonymousNonDefaultConstructor_after.java b/java/java-tests/testData/codeInsight/completion/signature/AnonymousNonDefaultConstructor_after.java new file mode 100644 index 000000000000..49dde1b89a5a --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/signature/AnonymousNonDefaultConstructor_after.java @@ -0,0 +1,8 @@ +abstract class Foo{ + public Foo(int x) { + } + + { + Foo f = new Foo(x) {} + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/signature/NonDefaultConstructor.java b/java/java-tests/testData/codeInsight/completion/signature/NonDefaultConstructor.java new file mode 100644 index 000000000000..1d0e66afb20c --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/signature/NonDefaultConstructor.java @@ -0,0 +1,8 @@ +class Foo{ + Foo(int arg) { + } + + { + Foo f = new F + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/signature/NonDefaultConstructor_after.java b/java/java-tests/testData/codeInsight/completion/signature/NonDefaultConstructor_after.java new file mode 100644 index 000000000000..d45f63ded1db --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/signature/NonDefaultConstructor_after.java @@ -0,0 +1,8 @@ +class Foo{ + Foo(int arg) { + } + + { + Foo f = new Foo(arg) + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/signature/OnlyDefaultConstructor.java b/java/java-tests/testData/codeInsight/completion/signature/OnlyDefaultConstructor.java new file mode 100644 index 000000000000..adb41ada931b --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/signature/OnlyDefaultConstructor.java @@ -0,0 +1,5 @@ +class Foo{ + { + Foo f = new F + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/signature/OnlyDefaultConstructor_after.java b/java/java-tests/testData/codeInsight/completion/signature/OnlyDefaultConstructor_after.java new file mode 100644 index 000000000000..e21f30961fc4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/signature/OnlyDefaultConstructor_after.java @@ -0,0 +1,5 @@ +class Foo{ + { + Foo f = new Foo() + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/signature/SeveralConstructors.java b/java/java-tests/testData/codeInsight/completion/signature/SeveralConstructors.java new file mode 100644 index 000000000000..fecb2c4573af --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/signature/SeveralConstructors.java @@ -0,0 +1,12 @@ +class Foo{ + Foo(int arg) { + } + Foo(boolean arg) { + } + Foo() { + } + + { + Foo f = new F + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToCollection.java b/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToCollection.java new file mode 100644 index 000000000000..dccf7083d015 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToCollection.java @@ -0,0 +1,10 @@ +// "Replace with 'java.util.TreeSet' constructor" "true" + +import java.util.*; +import java.util.stream.*; + +class Test { + public static void test(List s) { + new TreeSet<>(s).contains("abc"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToCollectionGeneric.java b/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToCollectionGeneric.java new file mode 100644 index 000000000000..4a40cf0dc51e --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToCollectionGeneric.java @@ -0,0 +1,10 @@ +// "Replace with 'java.util.TreeSet' constructor" "true" + +import java.util.*; +import java.util.stream.*; + +class Test { + public static void test(List s) { + new TreeSet(s).contains("abc"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToCollectionMyTypeAddAll.java b/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToCollectionMyTypeAddAll.java new file mode 100644 index 000000000000..4fb25baaf003 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToCollectionMyTypeAddAll.java @@ -0,0 +1,18 @@ +// "Replace with 'Test.MyType' constructor" "true" + +import java.util.*; +import java.util.stream.*; + +class Test { + static class MyType extends ArrayList { + public MyType() {} + + public MyType(Collection coll) { + super(coll); + } + } + + public static void test(List s) { + new MyType(s).contains("abc"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToCollectionMyTypeGeneric.java b/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToCollectionMyTypeGeneric.java new file mode 100644 index 000000000000..8b73ffd5cef4 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToCollectionMyTypeGeneric.java @@ -0,0 +1,18 @@ +// "Replace with 'Test.MyType' constructor" "true" + +import java.util.*; +import java.util.stream.*; + +class Test { + static class MyType extends ArrayList { + public MyType() {} + + public MyType(Collection coll) { + super(coll); + } + } + + public static void testMy(List s) { + new MyType(s).contains("abc"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToCollectionOtherType.java b/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToCollectionOtherType.java new file mode 100644 index 000000000000..6b1baeccdcaa --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToCollectionOtherType.java @@ -0,0 +1,10 @@ +// "Replace with 'java.util.TreeSet' constructor" "true" + +import java.util.*; +import java.util.stream.*; + +class Test { + public static void test(List s) { + new TreeSet(s).contains("abc"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToList.java b/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToList.java new file mode 100644 index 000000000000..81ea9abe9a18 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToList.java @@ -0,0 +1,11 @@ +// "Replace with 'java.util.ArrayList' constructor" "true" + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.*; + +class Test { + public static void test(List s) { + new ArrayList<>(s).contains("abc"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToListOtherType.java b/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToListOtherType.java new file mode 100644 index 000000000000..8ee47516fa34 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToListOtherType.java @@ -0,0 +1,11 @@ +// "Replace with 'java.util.ArrayList' constructor" "true" + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.*; + +class Test { + public static void test(List s) { + new ArrayList(s).contains("abc"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToSet.java b/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToSet.java new file mode 100644 index 000000000000..e340cfe9684e --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterStreamToSet.java @@ -0,0 +1,11 @@ +// "Replace with 'java.util.HashSet' constructor" "true" + +import java.util.HashSet; +import java.util.List; +import java.util.stream.*; + +class Test { + public static void test(List s) { + new HashSet<>(s).contains("abc"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollection.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollection.java new file mode 100644 index 000000000000..31eb7befc2f6 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollection.java @@ -0,0 +1,10 @@ +// "Replace with 'java.util.TreeSet' constructor" "true" + +import java.util.*; +import java.util.stream.*; + +class Test { + public static void test(List s) { + s.stream().collect(Collectors.toCollection(TreeSet::new)).contains("abc"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollectionGeneric.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollectionGeneric.java new file mode 100644 index 000000000000..5ea3bff968e3 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollectionGeneric.java @@ -0,0 +1,10 @@ +// "Replace with 'java.util.TreeSet' constructor" "true" + +import java.util.*; +import java.util.stream.*; + +class Test { + public static void test(List s) { + s.stream().collect(Collectors.toCollection(TreeSet::new)).contains("abc"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollectionInvalid.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollectionInvalid.java new file mode 100644 index 000000000000..3523cbd17f59 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollectionInvalid.java @@ -0,0 +1,10 @@ +// "Replace with 'java.util.TreeSet' constructor" "false" + +import java.util.*; +import java.util.stream.*; + +class Test { + public static void test(List s) { + s.stream().collect(Collectors.toCollection(TreeSet::new)).contains("abc"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollectionMyType.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollectionMyType.java new file mode 100644 index 000000000000..70e4bdfba45b --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollectionMyType.java @@ -0,0 +1,14 @@ +// "Replace with 'Test.MyType' constructor" "false" + +import java.util.*; +import java.util.stream.*; + +class Test { + static class MyType extends ArrayList { + + } + + public static void test(List s) { + s.stream().collect(Collectors.toCollection(MyType::new)).contains("abc"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollectionMyTypeAddAll.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollectionMyTypeAddAll.java new file mode 100644 index 000000000000..770e70aa5ed4 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollectionMyTypeAddAll.java @@ -0,0 +1,18 @@ +// "Replace with 'Test.MyType' constructor" "true" + +import java.util.*; +import java.util.stream.*; + +class Test { + static class MyType extends ArrayList { + public MyType() {} + + public MyType(Collection coll) { + super(coll); + } + } + + public static void test(List s) { + s.stream().collect(Collectors.toCollection(MyType::new)).contains("abc"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollectionMyTypeAddAllPrivate.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollectionMyTypeAddAllPrivate.java new file mode 100644 index 000000000000..30ff25be3cee --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollectionMyTypeAddAllPrivate.java @@ -0,0 +1,18 @@ +// "Replace with 'Test.MyType' constructor" "false" + +import java.util.*; +import java.util.stream.*; + +class Test { + static class MyType extends ArrayList { + public MyType() {} + + private MyType(Collection coll) { + super(coll); + } + } + + public static void test(List s) { + s.stream().collect(Collectors.toCollection(MyType::new)).contains("abc"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollectionMyTypeGeneric.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollectionMyTypeGeneric.java new file mode 100644 index 000000000000..8b207a2fe13b --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollectionMyTypeGeneric.java @@ -0,0 +1,18 @@ +// "Replace with 'Test.MyType' constructor" "true" + +import java.util.*; +import java.util.stream.*; + +class Test { + static class MyType extends ArrayList { + public MyType() {} + + public MyType(Collection coll) { + super(coll); + } + } + + public static void testMy(List s) { + s.stream().collect(Collectors.toCollection(MyType::new)).contains("abc"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollectionOtherType.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollectionOtherType.java new file mode 100644 index 000000000000..492cc61b4dd5 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToCollectionOtherType.java @@ -0,0 +1,10 @@ +// "Replace with 'java.util.TreeSet' constructor" "true" + +import java.util.*; +import java.util.stream.*; + +class Test { + public static void test(List s) { + s.stream().collect(Collectors.toCollection(TreeSet::new)).contains("abc"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToList.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToList.java new file mode 100644 index 000000000000..dcf6c386e8e6 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToList.java @@ -0,0 +1,10 @@ +// "Replace with 'java.util.ArrayList' constructor" "true" + +import java.util.List; +import java.util.stream.*; + +class Test { + public static void test(List s) { + s.stream().collect(Collectors.toList()).contains("abc"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToListOtherType.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToListOtherType.java new file mode 100644 index 000000000000..10edac2d1b3e --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToListOtherType.java @@ -0,0 +1,10 @@ +// "Replace with 'java.util.ArrayList' constructor" "true" + +import java.util.List; +import java.util.stream.*; + +class Test { + public static void test(List s) { + s.stream().collect(Collectors.toList()).contains("abc"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToSet.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToSet.java new file mode 100644 index 000000000000..574e4e371636 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeStreamToSet.java @@ -0,0 +1,10 @@ +// "Replace with 'java.util.HashSet' constructor" "true" + +import java.util.List; +import java.util.stream.*; + +class Test { + public static void test(List s) { + s.stream().collect(Collectors.toSet()).contains("abc"); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SignatureCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SignatureCompletionTest.groovy new file mode 100644 index 000000000000..c2a504fbf36e --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SignatureCompletionTest.groovy @@ -0,0 +1,69 @@ +/* + * 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.codeInsight.completion + +import com.intellij.JavaTestUtil +import com.intellij.codeInsight.template.impl.TemplateManagerImpl +import com.intellij.openapi.util.registry.Registry +/** + * @author peter + */ +class SignatureCompletionTest extends LightFixtureCompletionTestCase { + + @Override + protected String getBasePath() { + return JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInsight/completion/signature/" + } + + @Override + protected void setUp() throws Exception { + super.setUp() + Registry.get("java.completion.argument.live.template").value = true + Registry.get("java.completion.show.constructors").value = true + TemplateManagerImpl.setTemplateTesting(getProject(), getTestRootDisposable()) + } + + @Override + protected void tearDown() throws Exception { + Registry.get("java.completion.argument.live.template").value = false + Registry.get("java.completion.show.constructors").value = false + super.tearDown() + } + + private checkResult() { + checkResultByFile(getTestName(false) + "_after.java") + } + + private void doFirstItemTest() { + configureByTestName() + myFixture.type('\n') + checkResult() + } + + void testOnlyDefaultConstructor() { doFirstItemTest() } + + void testNonDefaultConstructor() { doFirstItemTest() } + + void testAnonymousNonDefaultConstructor() { doFirstItemTest() } + + void testSeveralConstructors() { + myFixture.configureByFile(getTestName(false) + ".java") + myFixture.complete(CompletionType.SMART) + def items = myFixture.lookup.items + assert items.size() == 3 + } + +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/OrderEntryTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/OrderEntryTest.java index d6cf7e6a9ad0..5768afa9a718 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/OrderEntryTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/OrderEntryTest.java @@ -100,7 +100,7 @@ public class OrderEntryTest extends DaemonAnalyzerTestCase { private IntentionAction findActionAndCheck(final ActionHint actionHint, Collection infosBefore) { List actions = LightQuickFixTestCase.getAvailableActions(getEditor(), getFile()); - return actionHint.findAndCheck(actions, () -> "Infos: " + infosBefore); + return actionHint.findAndCheck(actions, "Infos: " + infosBefore); } public void testAddDependency() throws Exception { diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/ActionHint.java b/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/ActionHint.java index 425a6558ba4e..b0bc698ad4c6 100644 --- a/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/ActionHint.java +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/ActionHint.java @@ -25,7 +25,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; -import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -72,19 +71,19 @@ public class ActionHint { * if this ActionHint asserts that no action should be present. * * @param actions actions collection to search inside - * @param infoSupplier a supplier which provides additional info which will be appended to exception message if check fails + * @param errorMessage an additional error message which will be appended to exception message if check fails * @return the action or null * @throws AssertionError if no action is found, but it should present, or if action is found, but it should not present. */ @Nullable - public IntentionAction findAndCheck(Collection actions, Supplier infoSupplier) { + public IntentionAction findAndCheck(@NotNull Collection actions, @NotNull String errorMessage) { IntentionAction result = actions.stream().filter(t -> t.getText().equals(myExpectedText)).findFirst().orElse(null); if(result == null && myShouldPresent) { fail("Action with text '" + myExpectedText + "' not found\nAvailable actions: " + actions.stream().map(IntentionAction::getText).collect(Collectors.joining(", ", "[", "]\n")) + - infoSupplier.get()); + errorMessage); } else if(result != null && !myShouldPresent) { - fail("Action with text '" + myExpectedText + "' is present, but should not\n" + infoSupplier.get()); + fail("Action with text '" + myExpectedText + "' is present, but should not\n" + errorMessage); } return result; } diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java index 19ec879a4f35..7abf74ec5e7b 100644 --- a/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java @@ -103,7 +103,7 @@ public abstract class LightQuickFixTestCase extends LightDaemonAnalyzerTestCase String testName, QuickFixTestCase quickFix) throws Exception { IntentionAction action = actionHint.findAndCheck(quickFix.getAvailableActions(), - () -> "Test: "+testFullPath+"\nInfos: "+quickFix.doHighlighting()); + "Test: "+testFullPath+"\nInfos: "+quickFix.doHighlighting()); if (action != null) { String text = action.getText(); quickFix.invoke(action); @@ -157,7 +157,7 @@ public abstract class LightQuickFixTestCase extends LightDaemonAnalyzerTestCase } protected IntentionAction findActionAndCheck(@NotNull ActionHint hint, String testFullPath) { - return hint.findAndCheck(getAvailableActions(), () -> "Test: "+testFullPath); + return hint.findAndCheck(getAvailableActions(), "Test: "+testFullPath); } protected IntentionAction findActionWithText(@NotNull String text) { diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/java/EclipseCompilerTool.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/java/EclipseCompilerTool.java index a76b5d8fcf02..22630d16bfd6 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/java/EclipseCompilerTool.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/java/EclipseCompilerTool.java @@ -26,7 +26,7 @@ import org.jetbrains.jps.incremental.CompileContext; import org.jetbrains.jps.incremental.Utils; import org.jetbrains.jps.model.java.compiler.JavaCompilers; -import javax.tools.*; +import javax.tools.JavaCompiler; import java.io.File; import java.io.FilenameFilter; import java.util.Collections; @@ -34,6 +34,9 @@ import java.util.List; import java.util.ServiceLoader; /** + * The latest version of ecj batch compiler can be found here: + * http://download.eclipse.org/eclipse/downloads/ + * * @author nik */ public class EclipseCompilerTool extends JavaCompilingTool { diff --git a/json/gen/com/intellij/json/JsonElementTypes.java b/json/gen/com/intellij/json/JsonElementTypes.java index cbff0ab596f9..176ea7d64a3d 100644 --- a/json/gen/com/intellij/json/JsonElementTypes.java +++ b/json/gen/com/intellij/json/JsonElementTypes.java @@ -44,9 +44,6 @@ public interface JsonElementTypes { else if (type == BOOLEAN_LITERAL) { return new JsonBooleanLiteralImpl(node); } - else if (type == LITERAL) { - return new JsonLiteralImpl(node); - } else if (type == NULL_LITERAL) { return new JsonNullLiteralImpl(node); } @@ -65,9 +62,6 @@ public interface JsonElementTypes { else if (type == STRING_LITERAL) { return new JsonStringLiteralImpl(node); } - else if (type == VALUE) { - return new JsonValueImpl(node); - } throw new AssertionError("Unknown element type: " + type); } } diff --git a/json/gen/com/intellij/json/JsonParser.java b/json/gen/com/intellij/json/JsonParser.java index 5046debe9f7b..e3dd969ea831 100644 --- a/json/gen/com/intellij/json/JsonParser.java +++ b/json/gen/com/intellij/json/JsonParser.java @@ -64,9 +64,6 @@ public class JsonParser implements PsiParser, LightPsiParser { } public static final TokenSet[] EXTENDS_SETS_ = new TokenSet[] { - create_token_set_(ARRAY, OBJECT), - create_token_set_(BOOLEAN_LITERAL, LITERAL, NULL_LITERAL, NUMBER_LITERAL, - STRING_LITERAL), create_token_set_(ARRAY, BOOLEAN_LITERAL, LITERAL, NULL_LITERAL, NUMBER_LITERAL, OBJECT, REFERENCE_EXPRESSION, STRING_LITERAL, VALUE), @@ -78,12 +75,12 @@ public class JsonParser implements PsiParser, LightPsiParser { if (!recursion_guard_(b, l, "array")) return false; if (!nextTokenIs(b, L_BRACKET)) return false; boolean r, p; - Marker m = enter_section_(b, l, _NONE_, null); + Marker m = enter_section_(b, l, _NONE_, ARRAY, null); r = consumeToken(b, L_BRACKET); p = r; // pin = 1 r = r && report_error_(b, array_1(b, l + 1)); r = p && consumeToken(b, R_BRACKET) && r; - exit_section_(b, l, m, ARRAY, r, p, null); + exit_section_(b, l, m, r, p, null); return r || p; } @@ -104,11 +101,11 @@ public class JsonParser implements PsiParser, LightPsiParser { static boolean array_element(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "array_element")) return false; boolean r, p; - Marker m = enter_section_(b, l, _NONE_, null); + Marker m = enter_section_(b, l, _NONE_); r = value(b, l + 1); p = r; // pin = 1 r = r && array_element_1(b, l + 1); - exit_section_(b, l, m, null, r, p, not_bracket_or_next_value_parser_); + exit_section_(b, l, m, r, p, not_bracket_or_next_value_parser_); return r || p; } @@ -127,9 +124,9 @@ public class JsonParser implements PsiParser, LightPsiParser { private static boolean array_element_1_1(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "array_element_1_1")) return false; boolean r; - Marker m = enter_section_(b, l, _AND_, null); + Marker m = enter_section_(b, l, _AND_); r = consumeToken(b, R_BRACKET); - exit_section_(b, l, m, null, r, false, null); + exit_section_(b, l, m, r, false, null); return r; } @@ -139,10 +136,10 @@ public class JsonParser implements PsiParser, LightPsiParser { if (!recursion_guard_(b, l, "boolean_literal")) return false; if (!nextTokenIs(b, "", FALSE, TRUE)) return false; boolean r; - Marker m = enter_section_(b, l, _NONE_, ""); + Marker m = enter_section_(b, l, _NONE_, BOOLEAN_LITERAL, ""); r = consumeToken(b, TRUE); if (!r) r = consumeToken(b, FALSE); - exit_section_(b, l, m, BOOLEAN_LITERAL, r, false, null); + exit_section_(b, l, m, r, false, null); return r; } @@ -168,12 +165,12 @@ public class JsonParser implements PsiParser, LightPsiParser { public static boolean literal(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "literal")) return false; boolean r; - Marker m = enter_section_(b, l, _COLLAPSE_, ""); + Marker m = enter_section_(b, l, _COLLAPSE_, LITERAL, ""); r = string_literal(b, l + 1); if (!r) r = number_literal(b, l + 1); if (!r) r = boolean_literal(b, l + 1); if (!r) r = null_literal(b, l + 1); - exit_section_(b, l, m, LITERAL, r, false, null); + exit_section_(b, l, m, r, false, null); return r; } @@ -182,9 +179,9 @@ public class JsonParser implements PsiParser, LightPsiParser { static boolean not_brace_or_next_value(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "not_brace_or_next_value")) return false; boolean r; - Marker m = enter_section_(b, l, _NOT_, null); + Marker m = enter_section_(b, l, _NOT_); r = !not_brace_or_next_value_0(b, l + 1); - exit_section_(b, l, m, null, r, false, null); + exit_section_(b, l, m, r, false, null); return r; } @@ -204,9 +201,9 @@ public class JsonParser implements PsiParser, LightPsiParser { static boolean not_bracket_or_next_value(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "not_bracket_or_next_value")) return false; boolean r; - Marker m = enter_section_(b, l, _NOT_, null); + Marker m = enter_section_(b, l, _NOT_); r = !not_bracket_or_next_value_0(b, l + 1); - exit_section_(b, l, m, null, r, false, null); + exit_section_(b, l, m, r, false, null); return r; } @@ -251,12 +248,12 @@ public class JsonParser implements PsiParser, LightPsiParser { if (!recursion_guard_(b, l, "object")) return false; if (!nextTokenIs(b, L_CURLY)) return false; boolean r, p; - Marker m = enter_section_(b, l, _NONE_, null); + Marker m = enter_section_(b, l, _NONE_, OBJECT, null); r = consumeToken(b, L_CURLY); p = r; // pin = 1 r = r && report_error_(b, object_1(b, l + 1)); r = p && consumeToken(b, R_CURLY) && r; - exit_section_(b, l, m, OBJECT, r, p, null); + exit_section_(b, l, m, r, p, null); return r || p; } @@ -277,11 +274,11 @@ public class JsonParser implements PsiParser, LightPsiParser { static boolean object_element(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "object_element")) return false; boolean r, p; - Marker m = enter_section_(b, l, _NONE_, null); + Marker m = enter_section_(b, l, _NONE_); r = property(b, l + 1); p = r; // pin = 1 r = r && object_element_1(b, l + 1); - exit_section_(b, l, m, null, r, p, not_brace_or_next_value_parser_); + exit_section_(b, l, m, r, p, not_brace_or_next_value_parser_); return r || p; } @@ -300,9 +297,9 @@ public class JsonParser implements PsiParser, LightPsiParser { private static boolean object_element_1_1(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "object_element_1_1")) return false; boolean r; - Marker m = enter_section_(b, l, _AND_, null); + Marker m = enter_section_(b, l, _AND_); r = consumeToken(b, R_CURLY); - exit_section_(b, l, m, null, r, false, null); + exit_section_(b, l, m, r, false, null); return r; } @@ -311,11 +308,11 @@ public class JsonParser implements PsiParser, LightPsiParser { public static boolean property(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "property")) return false; boolean r, p; - Marker m = enter_section_(b, l, _NONE_, ""); + Marker m = enter_section_(b, l, _NONE_, PROPERTY, ""); r = property_name(b, l + 1); p = r; // pin = 1 r = r && property_1(b, l + 1); - exit_section_(b, l, m, PROPERTY, r, p, null); + exit_section_(b, l, m, r, p, null); return r || p; } @@ -323,11 +320,11 @@ public class JsonParser implements PsiParser, LightPsiParser { private static boolean property_1(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "property_1")) return false; boolean r, p; - Marker m = enter_section_(b, l, _NONE_, null); + Marker m = enter_section_(b, l, _NONE_); r = consumeToken(b, COLON); p = r; // pin = 1 r = r && value(b, l + 1); - exit_section_(b, l, m, null, r, p, null); + exit_section_(b, l, m, r, p, null); return r || p; } @@ -361,10 +358,10 @@ public class JsonParser implements PsiParser, LightPsiParser { if (!recursion_guard_(b, l, "string_literal")) return false; if (!nextTokenIs(b, "", DOUBLE_QUOTED_STRING, SINGLE_QUOTED_STRING)) return false; boolean r; - Marker m = enter_section_(b, l, _NONE_, ""); + Marker m = enter_section_(b, l, _NONE_, STRING_LITERAL, ""); r = consumeToken(b, SINGLE_QUOTED_STRING); if (!r) r = consumeToken(b, DOUBLE_QUOTED_STRING); - exit_section_(b, l, m, STRING_LITERAL, r, false, null); + exit_section_(b, l, m, r, false, null); return r; } @@ -373,12 +370,12 @@ public class JsonParser implements PsiParser, LightPsiParser { public static boolean value(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "value")) return false; boolean r; - Marker m = enter_section_(b, l, _COLLAPSE_, ""); + Marker m = enter_section_(b, l, _COLLAPSE_, VALUE, ""); r = object(b, l + 1); if (!r) r = array(b, l + 1); if (!r) r = literal(b, l + 1); if (!r) r = reference_expression(b, l + 1); - exit_section_(b, l, m, VALUE, r, false, null); + exit_section_(b, l, m, r, false, null); return r; } diff --git a/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java b/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java index 018aeb334e02..d6e698ef7abf 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java @@ -17,8 +17,12 @@ public class JsonArrayImpl extends JsonContainerImpl implements JsonArray { super(node); } + public void accept(@NotNull JsonElementVisitor visitor) { + visitor.visitArray(this); + } + public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonElementVisitor) ((JsonElementVisitor)visitor).visitArray(this); + if (visitor instanceof JsonElementVisitor) accept((JsonElementVisitor)visitor); else super.accept(visitor); } diff --git a/json/gen/com/intellij/json/psi/impl/JsonBooleanLiteralImpl.java b/json/gen/com/intellij/json/psi/impl/JsonBooleanLiteralImpl.java index b7a6e607ff1e..f8958b047083 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonBooleanLiteralImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonBooleanLiteralImpl.java @@ -16,8 +16,12 @@ public class JsonBooleanLiteralImpl extends JsonLiteralImpl implements JsonBoole super(node); } + public void accept(@NotNull JsonElementVisitor visitor) { + visitor.visitBooleanLiteral(this); + } + public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonElementVisitor) ((JsonElementVisitor)visitor).visitBooleanLiteral(this); + if (visitor instanceof JsonElementVisitor) accept((JsonElementVisitor)visitor); else super.accept(visitor); } diff --git a/json/gen/com/intellij/json/psi/impl/JsonContainerImpl.java b/json/gen/com/intellij/json/psi/impl/JsonContainerImpl.java index 765b2c06a107..56365d502858 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonContainerImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonContainerImpl.java @@ -16,8 +16,12 @@ public class JsonContainerImpl extends JsonValueImpl implements JsonContainer { super(node); } + public void accept(@NotNull JsonElementVisitor visitor) { + visitor.visitContainer(this); + } + public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonElementVisitor) ((JsonElementVisitor)visitor).visitContainer(this); + if (visitor instanceof JsonElementVisitor) accept((JsonElementVisitor)visitor); else super.accept(visitor); } diff --git a/json/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java b/json/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java index da4d688e4873..840158283bd5 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java @@ -10,14 +10,18 @@ import com.intellij.psi.util.PsiTreeUtil; import static com.intellij.json.JsonElementTypes.*; import com.intellij.json.psi.*; -public class JsonLiteralImpl extends JsonLiteralMixin implements JsonLiteral { +public abstract class JsonLiteralImpl extends JsonLiteralMixin implements JsonLiteral { public JsonLiteralImpl(ASTNode node) { super(node); } + public void accept(@NotNull JsonElementVisitor visitor) { + visitor.visitLiteral(this); + } + public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonElementVisitor) ((JsonElementVisitor)visitor).visitLiteral(this); + if (visitor instanceof JsonElementVisitor) accept((JsonElementVisitor)visitor); else super.accept(visitor); } diff --git a/json/gen/com/intellij/json/psi/impl/JsonNullLiteralImpl.java b/json/gen/com/intellij/json/psi/impl/JsonNullLiteralImpl.java index c74a4616e5b8..55274253e2bd 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonNullLiteralImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonNullLiteralImpl.java @@ -16,8 +16,12 @@ public class JsonNullLiteralImpl extends JsonLiteralImpl implements JsonNullLite super(node); } + public void accept(@NotNull JsonElementVisitor visitor) { + visitor.visitNullLiteral(this); + } + public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonElementVisitor) ((JsonElementVisitor)visitor).visitNullLiteral(this); + if (visitor instanceof JsonElementVisitor) accept((JsonElementVisitor)visitor); else super.accept(visitor); } diff --git a/json/gen/com/intellij/json/psi/impl/JsonNumberLiteralImpl.java b/json/gen/com/intellij/json/psi/impl/JsonNumberLiteralImpl.java index f61e828ed29b..7ff647107787 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonNumberLiteralImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonNumberLiteralImpl.java @@ -16,8 +16,12 @@ public class JsonNumberLiteralImpl extends JsonLiteralImpl implements JsonNumber super(node); } + public void accept(@NotNull JsonElementVisitor visitor) { + visitor.visitNumberLiteral(this); + } + public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonElementVisitor) ((JsonElementVisitor)visitor).visitNumberLiteral(this); + if (visitor instanceof JsonElementVisitor) accept((JsonElementVisitor)visitor); else super.accept(visitor); } diff --git a/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java b/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java index a0a80e880247..a5410cc10d3c 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java @@ -17,8 +17,12 @@ public class JsonObjectImpl extends JsonObjectMixin implements JsonObject { super(node); } + public void accept(@NotNull JsonElementVisitor visitor) { + visitor.visitObject(this); + } + public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonElementVisitor) ((JsonElementVisitor)visitor).visitObject(this); + if (visitor instanceof JsonElementVisitor) accept((JsonElementVisitor)visitor); else super.accept(visitor); } diff --git a/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java b/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java index 90422bb3a91e..5ec5a1094605 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java @@ -17,8 +17,12 @@ public class JsonPropertyImpl extends JsonPropertyMixin implements JsonProperty super(node); } + public void accept(@NotNull JsonElementVisitor visitor) { + visitor.visitProperty(this); + } + public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonElementVisitor) ((JsonElementVisitor)visitor).visitProperty(this); + if (visitor instanceof JsonElementVisitor) accept((JsonElementVisitor)visitor); else super.accept(visitor); } diff --git a/json/gen/com/intellij/json/psi/impl/JsonReferenceExpressionImpl.java b/json/gen/com/intellij/json/psi/impl/JsonReferenceExpressionImpl.java index c4d2ec080b8a..1a538f3bb3f0 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonReferenceExpressionImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonReferenceExpressionImpl.java @@ -16,8 +16,12 @@ public class JsonReferenceExpressionImpl extends JsonValueImpl implements JsonRe super(node); } + public void accept(@NotNull JsonElementVisitor visitor) { + visitor.visitReferenceExpression(this); + } + public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonElementVisitor) ((JsonElementVisitor)visitor).visitReferenceExpression(this); + if (visitor instanceof JsonElementVisitor) accept((JsonElementVisitor)visitor); else super.accept(visitor); } diff --git a/json/gen/com/intellij/json/psi/impl/JsonStringLiteralImpl.java b/json/gen/com/intellij/json/psi/impl/JsonStringLiteralImpl.java index c899097a4a76..33bb4ae9ae0f 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonStringLiteralImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonStringLiteralImpl.java @@ -18,8 +18,12 @@ public class JsonStringLiteralImpl extends JsonStringLiteralMixin implements Jso super(node); } + public void accept(@NotNull JsonElementVisitor visitor) { + visitor.visitStringLiteral(this); + } + public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonElementVisitor) ((JsonElementVisitor)visitor).visitStringLiteral(this); + if (visitor instanceof JsonElementVisitor) accept((JsonElementVisitor)visitor); else super.accept(visitor); } diff --git a/json/gen/com/intellij/json/psi/impl/JsonValueImpl.java b/json/gen/com/intellij/json/psi/impl/JsonValueImpl.java index c8fe9a4682fe..545f94751d71 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonValueImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonValueImpl.java @@ -10,14 +10,18 @@ import com.intellij.psi.util.PsiTreeUtil; import static com.intellij.json.JsonElementTypes.*; import com.intellij.json.psi.*; -public class JsonValueImpl extends JsonElementImpl implements JsonValue { +public abstract class JsonValueImpl extends JsonElementImpl implements JsonValue { public JsonValueImpl(ASTNode node) { super(node); } + public void accept(@NotNull JsonElementVisitor visitor) { + visitor.visitValue(this); + } + public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonElementVisitor) ((JsonElementVisitor)visitor).visitValue(this); + if (visitor instanceof JsonElementVisitor) accept((JsonElementVisitor)visitor); else super.accept(visitor); } diff --git a/json/json.bnf b/json/json.bnf index 2e103f41eee8..556052e3a3d0 100644 --- a/json/json.bnf +++ b/json/json.bnf @@ -128,7 +128,7 @@ literal ::= string_literal | number_literal | boolean_literal | null_literal { mixin="com.intellij.json.psi.impl.JsonLiteralMixin" } -fake container ::= object | literal +fake container ::= reference_expression ::= INDENTIFIER diff --git a/lib/ecj-4.5.2.jar b/lib/ecj-4.5.2.jar deleted file mode 100644 index 7457eda29057..000000000000 Binary files a/lib/ecj-4.5.2.jar and /dev/null differ diff --git a/lib/ecj-4.6.1.jar b/lib/ecj-4.6.1.jar new file mode 100644 index 000000000000..1c7e9cad3046 Binary files /dev/null and b/lib/ecj-4.6.1.jar differ diff --git a/lib/required_for_dist.txt b/lib/required_for_dist.txt index 9ca949275b3c..38879ce13c8b 100644 --- a/lib/required_for_dist.txt +++ b/lib/required_for_dist.txt @@ -13,7 +13,7 @@ httpcore-4.4.5.jar httpclient-4.5.2.jar fluent-hc-4.5.2.jar httpmime-4.5.2.jar -ecj-4.5.2.jar +ecj-4.6.1.jar groovy-all-2.4.6.jar gson-2.5.jar guava-19.0.jar diff --git a/platform/core-impl/src/com/intellij/openapi/application/TransactionGuardImpl.java b/platform/core-impl/src/com/intellij/openapi/application/TransactionGuardImpl.java index 9c4e4a3cdcf9..bfb79838045a 100644 --- a/platform/core-impl/src/com/intellij/openapi/application/TransactionGuardImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/application/TransactionGuardImpl.java @@ -260,13 +260,20 @@ public class TransactionGuardImpl extends TransactionGuard { @Override public void submitTransactionLater(@NotNull final Disposable parentDisposable, @NotNull final Runnable transaction) { final TransactionIdImpl id = getContextTransaction(); - Runnable runnable = new Runnable() { + final ModalityState startModality = ModalityState.defaultModalityState(); + invokeLater(new Runnable() { @Override public void run() { - submitTransaction(parentDisposable, id, transaction); + boolean allowWriting = ModalityState.current() == startModality; + AccessToken token = startActivity(allowWriting); + try { + submitTransaction(parentDisposable, id, transaction); + } + finally { + token.finish(); + } } - }; - invokeLater(runnable); + }); } private static void invokeLater(Runnable runnable) { diff --git a/platform/diff-impl/src/com/intellij/diff/contents/DiffPsiFileSupport.java b/platform/diff-impl/src/com/intellij/diff/contents/DiffPsiFileSupport.java index 28f83801977e..fc56425127b8 100644 --- a/platform/diff-impl/src/com/intellij/diff/contents/DiffPsiFileSupport.java +++ b/platform/diff-impl/src/com/intellij/diff/contents/DiffPsiFileSupport.java @@ -58,11 +58,11 @@ public class DiffPsiFileSupport { } - private static boolean isDiffFile(@Nullable PsiFile file) { + public static boolean isDiffFile(@Nullable PsiFile file) { return file != null && isDiffFile(file.getVirtualFile()); } - private static boolean isDiffFile(@Nullable VirtualFile file) { + public static boolean isDiffFile(@Nullable VirtualFile file) { return file != null && file.getUserData(KEY) == Boolean.TRUE; } } diff --git a/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java b/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java index cffa472ff73b..cfb1832cf095 100644 --- a/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java +++ b/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java @@ -180,12 +180,7 @@ public class GeneralCommandLine implements UserDataHolder { return myParentEnvironmentType != ParentEnvironmentType.NONE; } - /** @deprecated use {@link #withParentEnvironmentType(ParentEnvironmentType)} (to be removed in IDEA 2017.*) */ - public GeneralCommandLine withPassParentEnvironment(boolean passParentEnvironment) { - return withParentEnvironmentType(passParentEnvironment ? ParentEnvironmentType.CONSOLE : ParentEnvironmentType.NONE); - } - - /** @deprecated use {@link #withParentEnvironmentType(ParentEnvironmentType)} (to be removed in IDEA 2017.*) */ + /** @deprecated use {@link #withParentEnvironmentType(ParentEnvironmentType)} (to be removed in IDEA 2018.*) */ public void setPassParentEnvironment(boolean passParentEnvironment) { withParentEnvironmentType(passParentEnvironment ? ParentEnvironmentType.CONSOLE : ParentEnvironmentType.NONE); } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java index 9fb0645567d5..24965ef91f0c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java @@ -136,7 +136,7 @@ public class FileChooserDialogImpl extends DialogWrapper implements FileChooserD restoreSelection(null); // select last opened file } else { - selectInTree(toSelect, true); + selectInTree(toSelect, true, true); } show(); @@ -454,10 +454,10 @@ public class FileChooserDialogImpl extends DialogWrapper implements FileChooserD public void dropFiles(final List files) { if (!myChooserDescriptor.isChooseMultiple() && files.size() > 0) { - selectInTree(new VirtualFile[]{files.get(0)}, true); + selectInTree(new VirtualFile[]{files.get(0)}, true, true); } else { - selectInTree(VfsUtilCore.toVirtualFileArray(files), true); + selectInTree(VfsUtilCore.toVirtualFileArray(files), true, true); } } }); @@ -675,7 +675,7 @@ public class FileChooserDialogImpl extends DialogWrapper implements FileChooserD private void selectInTree(final VirtualFile vFile, String fromText) { if (vFile != null && vFile.isValid()) { if (fromText == null || fromText.equalsIgnoreCase(myPathTextField.getTextFieldText())) { - selectInTree(new VirtualFile[]{vFile}, false); + selectInTree(new VirtualFile[]{vFile}, false, fromText == null); } } else { @@ -683,7 +683,7 @@ public class FileChooserDialogImpl extends DialogWrapper implements FileChooserD } } - private void selectInTree(final VirtualFile[] array, final boolean requestFocus) { + private void selectInTree(VirtualFile[] array, boolean requestFocus, boolean updatePathNeeded) { myTreeIsUpdating = true; final List fileList = Arrays.asList(array); if (!Arrays.asList(myFileSystemTree.getSelectedFiles()).containsAll(fileList)) { @@ -691,20 +691,22 @@ public class FileChooserDialogImpl extends DialogWrapper implements FileChooserD if (!myFileSystemTree.areHiddensShown() && !Arrays.asList(myFileSystemTree.getSelectedFiles()).containsAll(fileList)) { // try to select files in hidden folders myFileSystemTree.showHiddens(true); - selectInTree(array, requestFocus); + selectInTree(array, requestFocus, updatePathNeeded); return; } if (array.length == 1 && !Arrays.asList(myFileSystemTree.getSelectedFiles()).containsAll(fileList)) { // try to select a parent of a missed file VirtualFile parent = array[0].getParent(); if (parent != null && parent.isValid()) { - selectInTree(new VirtualFile[]{parent}, requestFocus); + selectInTree(new VirtualFile[]{parent}, requestFocus, updatePathNeeded); return; } } reportFileNotFound(); - updatePathFromTree(fileList, true); + if (updatePathNeeded) { + updatePathFromTree(fileList, true); + } if (requestFocus) { //noinspection SSBasedInspection SwingUtilities.invokeLater(() -> myFileSystemTree.getTree().requestFocus()); @@ -713,7 +715,9 @@ public class FileChooserDialogImpl extends DialogWrapper implements FileChooserD } else { reportFileNotFound(); - updatePathFromTree(fileList, true); + if (updatePathNeeded) { + updatePathFromTree(fileList, true); + } } } diff --git a/platform/platform-impl/src/com/intellij/ui/EditorComboBox.java b/platform/platform-impl/src/com/intellij/ui/EditorComboBox.java index 3c21c3a15504..ed2e48dcf121 100644 --- a/platform/platform-impl/src/com/intellij/ui/EditorComboBox.java +++ b/platform/platform-impl/src/com/intellij/ui/EditorComboBox.java @@ -36,7 +36,6 @@ import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import javax.swing.*; -import javax.swing.border.EmptyBorder; import java.awt.*; import java.awt.event.*; import java.util.ArrayList; @@ -272,12 +271,6 @@ public class EditorComboBox extends JComboBox implements DocumentListener { setEditor(); super.addNotify(); - if (UIUtil.isUnderDarcula() || UIUtil.isUnderIntelliJLaF()) { - final JScrollPane scrollPane = UIUtil.findComponentOfType(myEditorField, JScrollPane.class); - if (scrollPane != null) { - scrollPane.setBorder(new EmptyBorder(1,0,1,0)); - } - } myEditorField.getFocusTarget().addFocusListener(new FocusAdapter() { @Override public void focusGained(FocusEvent e) { diff --git a/platform/platform-impl/src/com/intellij/util/Restarter.java b/platform/platform-impl/src/com/intellij/util/Restarter.java index ad3fac4234ea..4eb4a60bcbde 100644 --- a/platform/platform-impl/src/com/intellij/util/Restarter.java +++ b/platform/platform-impl/src/com/intellij/util/Restarter.java @@ -21,6 +21,7 @@ import com.intellij.openapi.application.PathManager; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.util.text.StringUtil; +import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.WString; @@ -40,13 +41,19 @@ public class Restarter { public static boolean isSupported() { if (SystemInfo.isWindows) { - return JnaLoader.isLoaded() && new File(PathManager.getBinPath(), "restarter.exe").exists(); + return JnaLoader.isLoaded() && + new File(PathManager.getBinPath(), "restarter.exe").exists(); } + if (SystemInfo.isMac) { - return PathManager.getHomePath().contains(".app") && new File(PathManager.getBinPath(), "restarter").canExecute(); + return PathManager.getHomePath().contains(".app") && + new File(PathManager.getBinPath(), "restarter").canExecute(); } + if (SystemInfo.isUnix) { - return CreateDesktopEntryAction.getLauncherScript() != null && new File(PathManager.getBinPath(), "restart.py").canExecute(); + return JnaLoader.isLoaded() && + CreateDesktopEntryAction.getLauncherScript() != null && + new File(PathManager.getBinPath(), "restart.py").canExecute(); } return false; @@ -135,7 +142,12 @@ public class Restarter { private static void restartOnUnix(String... beforeRestart) throws IOException { String launcherScript = CreateDesktopEntryAction.getLauncherScript(); if (launcherScript == null) throw new IOException("Launcher script not found in " + PathManager.getBinPath()); + + LibC lib = (LibC)Native.loadLibrary("c", LibC.class); + int pid = lib.getpid(); + doScheduleRestart(new File(PathManager.getBinPath(), "restart.py"), commands -> { + commands.add(String.valueOf(pid)); commands.add(launcherScript); Collections.addAll(commands, beforeRestart); }); @@ -182,4 +194,9 @@ public class Restarter { private interface Shell32 extends StdCallLibrary { Pointer CommandLineToArgvW(WString command_line, IntByReference argc); } + + @SuppressWarnings("SpellCheckingInspection") + private interface LibC extends Library { + int getpid(); + } } \ No newline at end of file diff --git a/platform/platform-tests/testSrc/com/intellij/application/TransactionTest.groovy b/platform/platform-tests/testSrc/com/intellij/application/TransactionTest.groovy index 3c9cedb99107..18093567b21e 100644 --- a/platform/platform-tests/testSrc/com/intellij/application/TransactionTest.groovy +++ b/platform/platform-tests/testSrc/com/intellij/application/TransactionTest.groovy @@ -377,4 +377,14 @@ class TransactionTest extends LightPlatformTestCase { assert log == ['1', '2'] } + void "test submitTransactionLater vs app invokeLater ordering in the same modality state"() { + TransactionGuard.submitTransaction testRootDisposable, { + log << '1' + guard.submitTransactionLater testRootDisposable, { log << '2' } + app.invokeLater { log << '3' } + } + UIUtil.dispatchAllInvocationEvents() + assert log == ['1', '2', '3'] + } + } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties index ff0227571fed..6522283735f2 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties @@ -2059,8 +2059,8 @@ class.with.only.private.constructors.problem.descriptor=Class #ref property.value.set.to.itself.display.name=Property value set to itself equals.with.itself.display.name='equals()' called on itself equals.with.itself.problem.descriptor=#ref() called on itself -junit4.method.naming.convention.display.name=JUnit 4 test method naming convention -junit4.method.naming.convention.element.description=JUnit 4 test method +junit4.method.naming.convention.display.name=JUnit 4+ test method naming convention +junit4.method.naming.convention.element.description=JUnit 4+ test method junit3.method.naming.convention.display.name=JUnit 3 test method naming convention junit3.method.naming.convention.element.description=JUnit 3 test method introduce.holder.class.quickfix=Introduce holder class diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertEqualsHint.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertEqualsHint.java index 3479e2f04e56..1753ca0dd1b1 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertEqualsHint.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertEqualsHint.java @@ -50,13 +50,8 @@ public class AssertEqualsHint { return null; } final PsiClass containingClass = method.getContainingClass(); - final boolean messageOnLastPosition = InheritanceUtil.isInheritor(containingClass, JUnitCommonClassNames.ORG_JUNIT_JUPITER_API_ASSERTIONS) || - InheritanceUtil.isInheritor(containingClass, "org.testng.Assert"); - if (!InheritanceUtil.isInheritor(containingClass, JUnitCommonClassNames.JUNIT_FRAMEWORK_ASSERT) && - !InheritanceUtil.isInheritor(containingClass, JUnitCommonClassNames.ORG_JUNIT_ASSERT) && - !InheritanceUtil.isInheritor(containingClass, JUnitCommonClassNames.JUNIT_FRAMEWORK_TEST_CASE) && - !InheritanceUtil.isInheritor(containingClass, "org.testng.AssertJUnit") && - !messageOnLastPosition) { + final boolean messageOnLastPosition = isMessageOnLastPosition(containingClass); + if (!isMessageOnFirstPosition(containingClass) && !messageOnLastPosition) { return null; } final PsiParameterList parameterList = method.getParameterList(); @@ -83,6 +78,18 @@ public class AssertEqualsHint { return new AssertEqualsHint(argumentIndex, method); } + public static boolean isMessageOnFirstPosition(PsiClass containingClass) { + return InheritanceUtil.isInheritor(containingClass, JUnitCommonClassNames.JUNIT_FRAMEWORK_ASSERT) || + InheritanceUtil.isInheritor(containingClass, JUnitCommonClassNames.ORG_JUNIT_ASSERT) || + InheritanceUtil.isInheritor(containingClass, JUnitCommonClassNames.JUNIT_FRAMEWORK_TEST_CASE) || + InheritanceUtil.isInheritor(containingClass, "org.testng.AssertJUnit"); + } + + public static boolean isMessageOnLastPosition(PsiClass containingClass) { + return InheritanceUtil.isInheritor(containingClass, JUnitCommonClassNames.ORG_JUNIT_JUPITER_API_ASSERTIONS) || + InheritanceUtil.isInheritor(containingClass, "org.testng.Assert"); + } + public static String areExpectedActualTypesCompatible(PsiMethodCallExpression expression) { final AssertEqualsHint assertEqualsHint = create(expression); if (assertEqualsHint == null) return null; diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertsWithoutMessagesInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertsWithoutMessagesInspection.java index 87d5ed2a37fb..9c98e1dc0f34 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertsWithoutMessagesInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertsWithoutMessagesInspection.java @@ -82,8 +82,9 @@ public class AssertsWithoutMessagesInspection extends BaseInspection { return; } final PsiClass containingClass = method.getContainingClass(); - if (!InheritanceUtil.isInheritor(containingClass, JUnitCommonClassNames.JUNIT_FRAMEWORK_ASSERT) && - !InheritanceUtil.isInheritor(containingClass, JUnitCommonClassNames.ORG_JUNIT_ASSERT)) { + final boolean messageOnFirstPosition = AssertEqualsHint.isMessageOnFirstPosition(containingClass); + final boolean messageOnLastPosition = AssertEqualsHint.isMessageOnLastPosition(containingClass); + if (!messageOnFirstPosition && !messageOnLastPosition) { return; } final PsiParameterList parameterList = method.getParameterList(); @@ -98,7 +99,7 @@ public class AssertsWithoutMessagesInspection extends BaseInspection { } final PsiType stringType = TypeUtils.getStringType(expression); final PsiParameter[] parameters = parameterList.getParameters(); - final PsiType parameterType1 = parameters[0].getType(); + final PsiType parameterType1 = parameters[messageOnFirstPosition ? 0 : parameters.length - 1].getType(); if (!parameterType1.equals(stringType)) { registerMethodCallError(expression); return; @@ -106,7 +107,7 @@ public class AssertsWithoutMessagesInspection extends BaseInspection { if (parameters.length != 2) { return; } - final PsiType parameterType2 = parameters[1].getType(); + final PsiType parameterType2 = parameters[messageOnFirstPosition ? parameterCount - 1 : 0].getType(); if (!parameterType2.equals(stringType)) { return; } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/ConstantJUnitAssertArgumentInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/ConstantJUnitAssertArgumentInspection.java index e02bfb7bc0fd..2f92530545dc 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/ConstantJUnitAssertArgumentInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/ConstantJUnitAssertArgumentInspection.java @@ -31,7 +31,7 @@ import java.util.Set; public class ConstantJUnitAssertArgumentInspection extends BaseInspection { @NonNls - private static final Set ASSERT_METHODS = new HashSet(); + private static final Set ASSERT_METHODS = new HashSet<>(); static { ASSERT_METHODS.add("assertTrue"); @@ -60,28 +60,24 @@ public class ConstantJUnitAssertArgumentInspection extends BaseInspection { return new ConstantJUnitAssertArgumentVisitor(); } - private static class ConstantJUnitAssertArgumentVisitor - extends BaseInspectionVisitor { + private static class ConstantJUnitAssertArgumentVisitor extends BaseInspectionVisitor { @Override - public void visitMethodCallExpression( - PsiMethodCallExpression expression) { - final PsiReferenceExpression methodExpression = - expression.getMethodExpression(); - @NonNls final String methodName = - methodExpression.getReferenceName(); + public void visitMethodCallExpression(PsiMethodCallExpression expression) { + final PsiReferenceExpression methodExpression = expression.getMethodExpression(); + @NonNls final String methodName = methodExpression.getReferenceName(); if (!ASSERT_METHODS.contains(methodName)) { return; } + final PsiMethod method = expression.resolveMethod(); if (method == null) { return; } final PsiClass containingClass = method.getContainingClass(); - if (!InheritanceUtil.isInheritor(containingClass, - JUnitCommonClassNames.JUNIT_FRAMEWORK_ASSERT) && - !InheritanceUtil.isInheritor(containingClass, - JUnitCommonClassNames.ORG_JUNIT_ASSERT)) { + final boolean messageOnFirstPosition = AssertEqualsHint.isMessageOnFirstPosition(containingClass); + final boolean messageOnLastPosition = AssertEqualsHint.isMessageOnLastPosition(containingClass); + if (!messageOnFirstPosition && !messageOnLastPosition) { return; } final PsiExpressionList argumentList = expression.getArgumentList(); @@ -89,11 +85,11 @@ public class ConstantJUnitAssertArgumentInspection extends BaseInspection { if (arguments.length == 0) { return; } - final PsiExpression lastArgument = arguments[arguments.length - 1]; - if (!PsiUtil.isConstantExpression(lastArgument)) { + final PsiExpression argument = arguments[messageOnFirstPosition ? arguments.length - 1 : 0]; + if (!PsiUtil.isConstantExpression(argument)) { return; } - registerError(lastArgument); + registerError(argument); } } } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/JUnit4MethodNamingConventionInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/JUnit4MethodNamingConventionInspectionBase.java index 07d5ecfb455d..459d63cbcf01 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/JUnit4MethodNamingConventionInspectionBase.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/JUnit4MethodNamingConventionInspectionBase.java @@ -15,8 +15,11 @@ */ package com.siyeh.ig.junit; +import com.intellij.codeInsight.TestFrameworks; +import com.intellij.psi.PsiClass; import com.intellij.psi.PsiIdentifier; import com.intellij.psi.PsiMethod; +import com.intellij.testIntegration.TestFramework; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.naming.ConventionInspection; @@ -68,7 +71,7 @@ public class JUnit4MethodNamingConventionInspectionBase extends ConventionInspec @Override public void visitMethod(PsiMethod method) { super.visitMethod(method); - if (!TestUtils.isJUnit4TestMethod(method) || !TestUtils.isRunnable(method)) { + if (!TestUtils.isAnnotatedTestMethod(method)) { return; } final PsiIdentifier nameIdentifier = method.getNameIdentifier(); diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/JUnitTestClassNamingConventionInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/JUnitTestClassNamingConventionInspectionBase.java index d44126fd027c..d64e43fd7a60 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/JUnitTestClassNamingConventionInspectionBase.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/JUnitTestClassNamingConventionInspectionBase.java @@ -15,8 +15,10 @@ */ package com.siyeh.ig.junit; +import com.intellij.codeInsight.TestFrameworks; import com.intellij.psi.*; import com.intellij.psi.util.InheritanceUtil; +import com.intellij.testIntegration.TestFramework; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.naming.ConventionInspection; @@ -82,12 +84,12 @@ public class JUnitTestClassNamingConventionInspectionBase extends ConventionInsp if (aClass.hasModifierProperty(PsiModifier.ABSTRACT)) { return; } - if (!InheritanceUtil.isInheritor(aClass, - JUnitCommonClassNames.JUNIT_FRAMEWORK_TEST_CASE)) { - if (!hasJUnit4TestMethods(aClass)) { - return; - } + + final TestFramework framework = TestFrameworks.detectFramework(aClass); + if (framework == null || !framework.getName().startsWith("JUnit") || !framework.isTestClass(aClass)) { + return; } + final String name = aClass.getName(); if (name == null) { return; @@ -107,19 +109,5 @@ public class JUnitTestClassNamingConventionInspectionBase extends ConventionInsp registerClassError(aClass, name); } } - - private boolean hasJUnit4TestMethods(@NotNull PsiClass aClass) { - //use this if this method turns out to have bad performance: - //if (!TestUtils.isTest(aClass)) { - // return false; - //} - final PsiMethod[] methods = aClass.getMethods(); - for (PsiMethod method : methods) { - if (TestUtils.isJUnit4TestMethod(method)) { - return true; - } - } - return false; - } } } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestMethodInProductCodeInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestMethodInProductCodeInspection.java index ace8cd165d8f..f885a677f53f 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestMethodInProductCodeInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestMethodInProductCodeInspection.java @@ -57,7 +57,7 @@ public class TestMethodInProductCodeInspection extends BaseInspection { public void visitMethod(PsiMethod method) { final PsiClass containingClass = method.getContainingClass(); if (TestUtils.isInTestSourceContent(containingClass) || - !TestUtils.isJUnit4TestMethod(method)) { + !TestUtils.isAnnotatedTestMethod(method)) { return; } registerMethodError(method); diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestMethodWithoutAssertionInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestMethodWithoutAssertionInspectionBase.java index f794e08a9c08..5f2b42d2d533 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestMethodWithoutAssertionInspectionBase.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestMethodWithoutAssertionInspectionBase.java @@ -37,6 +37,7 @@ public class TestMethodWithoutAssertionInspectionBase extends BaseInspection { methodMatcher = new MethodMatcher(true, "assertionMethods") .add(JUnitCommonClassNames.ORG_JUNIT_ASSERT, "assert.*|fail.*") .add(JUnitCommonClassNames.JUNIT_FRAMEWORK_ASSERT, "assert.*|fail.*") + .add(JUnitCommonClassNames.ORG_JUNIT_JUPITER_API_ASSERTIONS, "assert.*|fail.*") .add("org.mockito.Mockito", "verify.*") .add("org.mockito.InOrder", "verify") .add("org.junit.rules.ExpectedException", "expect.*") diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/naming/InstanceMethodNamingConventionInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/naming/InstanceMethodNamingConventionInspectionBase.java index 85fe6d20e8ca..82cd4f109dd8 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/naming/InstanceMethodNamingConventionInspectionBase.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/naming/InstanceMethodNamingConventionInspectionBase.java @@ -93,7 +93,7 @@ public class InstanceMethodNamingConventionInspectionBase extends ConventionInsp return; } if (TestUtils.isRunnable(method)) { - if (TestUtils.isJUnit4TestMethod(method) && isInspectionEnabled("JUnit4MethodNamingConvention", method)) { + if (TestUtils.isAnnotatedTestMethod(method) && isInspectionEnabled("JUnit4MethodNamingConvention", method)) { return; } if (TestUtils.isJUnit3TestMethod(method) && isInspectionEnabled("JUnit3MethodNamingConvention", method)) { diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/TestUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/TestUtils.java index eadaa038c86e..68c85078e271 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/TestUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/TestUtils.java @@ -24,6 +24,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.testIntegration.TestFramework; import com.siyeh.ig.junit.JUnitCommonClassNames; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -62,7 +63,11 @@ public class TestUtils { } public static boolean isJUnitTestMethod(@Nullable PsiMethod method) { - return isRunnable(method) && (isJUnit3TestMethod(method) || isJUnit4TestMethod(method)); + if (method == null) return false; + final PsiClass containingClass = method.getContainingClass(); + if (containingClass == null) return false; + final TestFramework framework = TestFrameworks.detectFramework(containingClass); + return framework != null && framework.getName().startsWith("JUnit") && framework.isTestMethod(method); } public static boolean isRunnable(PsiMethod method) { @@ -99,6 +104,21 @@ public class TestUtils { return method != null && AnnotationUtil.isAnnotated(method, "org.junit.Test", true); } + public static boolean isAnnotatedTestMethod(@Nullable PsiMethod method) { + if (method == null) return false; + final PsiClass containingClass = method.getContainingClass(); + if (containingClass == null) return false; + final TestFramework testFramework = TestFrameworks.detectFramework(containingClass); + if (testFramework == null) return false; + if (testFramework.isTestMethod(method)) { + final String testFrameworkName = testFramework.getName(); + return testFrameworkName.equals("JUnit4") || testFrameworkName.equals("JUnit5"); + } + return false; + } + + + public static boolean isJUnitTestClass(@Nullable PsiClass targetClass) { return targetClass != null && InheritanceUtil.isInheritor(targetClass, JUnitCommonClassNames.JUNIT_FRAMEWORK_TEST_CASE); } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/JUnitTestClassNamingConventionInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/JUnitTestClassNamingConventionInspection.java index 59d5d2a62d9b..b6922df84944 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/JUnitTestClassNamingConventionInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/JUnitTestClassNamingConventionInspection.java @@ -18,8 +18,7 @@ package com.siyeh.ig.junit; import com.siyeh.ig.InspectionGadgetsFix; import com.siyeh.ig.fixes.RenameFix; -public class JUnitTestClassNamingConventionInspection - extends JUnitTestClassNamingConventionInspectionBase { +public class JUnitTestClassNamingConventionInspection extends JUnitTestClassNamingConventionInspectionBase { @Override protected InspectionGadgetsFix buildFix(Object... infos) { diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/MethodRefCanBeReplacedWithLambdaInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/MethodRefCanBeReplacedWithLambdaInspection.java index 4d755dcf77d1..9cfe67755b83 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/MethodRefCanBeReplacedWithLambdaInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/MethodRefCanBeReplacedWithLambdaInspection.java @@ -34,14 +34,10 @@ import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.InspectionGadgetsFix; -import com.siyeh.ig.psiutils.SideEffectChecker; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.List; - public class MethodRefCanBeReplacedWithLambdaInspection extends BaseInspection { @Nls @@ -74,16 +70,6 @@ public class MethodRefCanBeReplacedWithLambdaInspection extends BaseInspection { return null; } - public static boolean isWithSideEffects(PsiMethodReferenceExpression methodReferenceExpression) { - final PsiExpression qualifierExpression = methodReferenceExpression.getQualifierExpression(); - if (qualifierExpression != null) { - final List sideEffects = new ArrayList<>(); - SideEffectChecker.checkSideEffects(qualifierExpression, sideEffects); - return !sideEffects.isEmpty(); - } - return false; - } - private static class MethodRefToLambdaVisitor extends BaseInspectionVisitor { @Override public void visitMethodReferenceExpression(PsiMethodReferenceExpression methodReferenceExpression) { @@ -92,12 +78,13 @@ public class MethodRefCanBeReplacedWithLambdaInspection extends BaseInspection { if (interfaceType != null && LambdaUtil.getFunctionalInterfaceMethod(interfaceType) != null && methodReferenceExpression.resolve() != null) { - registerError(methodReferenceExpression, getFixFactory(isWithSideEffects(methodReferenceExpression), isOnTheFly())); + registerError(methodReferenceExpression, + getFixFactory(LambdaRefactoringUtil.canConvertToLambda(methodReferenceExpression), isOnTheFly())); } } - private static FixFactory getFixFactory(boolean withSideEffects, boolean onTheFly) { - if (!withSideEffects) return MethodRefToLambdaFix::new; + private static FixFactory getFixFactory(boolean canConvert, boolean onTheFly) { + if (canConvert) return MethodRefToLambdaFix::new; if (onTheFly || ApplicationManager.getApplication().isUnitTestMode()) return SideEffectsMethodRefToLambdaFix::new; return null; } diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/JUnit4MethodNamingConvention.html b/plugins/InspectionGadgets/src/inspectionDescriptions/JUnit4MethodNamingConvention.html index b2f7c7986a58..213d1d6a20f7 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/JUnit4MethodNamingConvention.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/JUnit4MethodNamingConvention.html @@ -1,11 +1,11 @@ -Reports JUnit 4 test methods whose names are either too short, too long, or do not follow the specified regular expression pattern. +Reports JUnit 4+ test methods whose names are either too short, too long, or do not follow the specified regular expression pattern. When this inspection is enabled, the Instance method naming convention inspection -will ignore JUnit 4 test methods automatically. +will ignore JUnit 4+ test methods automatically.

-Use the fields below to specify minimum length, maximum length and regular expression expected for JUnit 4 test method names. +Use the fields below to specify minimum length, maximum length and regular expression expected for JUnit 4+ test method names. Specify 0 to not check the length of names. Regular expressions are in standard java.util.regex format.

diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/TestMethodInProductCode.html b/plugins/InspectionGadgets/src/inspectionDescriptions/TestMethodInProductCode.html index deb66cd95ef4..767453325178 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/TestMethodInProductCode.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/TestMethodInProductCode.html @@ -1,6 +1,6 @@ -Reports JUnit 4.0 @Test methods in product source trees. +Reports JUnit 4+ @Test methods in product source trees. This most likely indicates programmer error, and can result in test code being shipped into production. diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/junit4_method_naming_convention/JUnit4MethodNamingConvention.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/junit4_method_naming_convention/JUnit4MethodNamingConvention.java index 69379a9abb87..4f23a659ba16 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/junit4_method_naming_convention/JUnit4MethodNamingConvention.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/junit4_method_naming_convention/JUnit4MethodNamingConvention.java @@ -3,13 +3,13 @@ import org.junit.Test; public class JUnit4MethodNamingConvention { @Test - public void a() {} + public void a() {} @Test - public void abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz() {} + public void abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz() {} @Test - public void more$$$() {} + public void more$$$() {} @Test public void assure_foo_is_never_null() {} diff --git a/plugins/coverage-common/src/com/intellij/coverage/SimpleCoverageAnnotator.java b/plugins/coverage-common/src/com/intellij/coverage/SimpleCoverageAnnotator.java index eb41bcfe34a9..98c4d88becba 100644 --- a/plugins/coverage-common/src/com/intellij/coverage/SimpleCoverageAnnotator.java +++ b/plugins/coverage-common/src/com/intellij/coverage/SimpleCoverageAnnotator.java @@ -140,8 +140,7 @@ public abstract class SimpleCoverageAnnotator extends BaseCoverageAnnotator { protected FileCoverageInfo collectBaseFileCoverage(@NotNull final VirtualFile file, @NotNull final Annotator annotator, @NotNull final ProjectData projectData, - @NotNull final Map normalizedFiles2Files) - { + @NotNull final Map normalizedFiles2Files) { final String filePath = normalizeFilePath(file.getPath()); // process file @@ -166,8 +165,7 @@ public abstract class SimpleCoverageAnnotator extends BaseCoverageAnnotator { private static @Nullable ClassData getClassData( final @NotNull String filePath, final @NotNull ProjectData data, - final @NotNull Map normalizedFiles2Files) - { + final @NotNull Map normalizedFiles2Files) { final String originalFileName = normalizedFiles2Files.get(filePath); if (originalFileName == null) { return null; @@ -272,8 +270,7 @@ public abstract class SimpleCoverageAnnotator extends BaseCoverageAnnotator { @NotNull final CoverageSuitesBundle suite, final @NotNull CoverageDataManager dataManager, @NotNull final ProjectData data, final Project project, - final Annotator annotator) - { + final Annotator annotator) { if (!contentRoot.isValid()) { return; } @@ -395,7 +392,7 @@ public abstract class SimpleCoverageAnnotator extends BaseCoverageAnnotator { } @Nullable - private static FileCoverageInfo fileInfoForCoveredFile(@NotNull final ClassData classData) { + private FileCoverageInfo fileInfoForCoveredFile(@NotNull final ClassData classData) { final Object[] lines = classData.getLines(); // class data lines = [0, 1, ... count] but first element with index = #0 is fake and isn't @@ -408,27 +405,31 @@ public abstract class SimpleCoverageAnnotator extends BaseCoverageAnnotator { final FileCoverageInfo info = new FileCoverageInfo(); - int srcLinesCount = 0; - int coveredLinesCount = 0; + info.coveredLineCount = 0; + info.totalLineCount = 0; // let's count covered lines for (int i = 1; i <= count; i++) { final LineData lineData = classData.getLineData(i); - if (lineData == null) { - // Ignore not src code - continue; - } - final int status = lineData.getStatus(); - // covered - if src code & covered (or inferred covered) - if (status != LineCoverage.NONE) { - coveredLinesCount++; - } - srcLinesCount++; + + processLineData(info, lineData); } - info.totalLineCount = srcLinesCount; - info.coveredLineCount = coveredLinesCount; return info; } + protected void processLineData(@NotNull FileCoverageInfo info, @Nullable LineData lineData) { + if (lineData == null) { + // Ignore not src code + return; + } + final int status = lineData.getStatus(); + // covered - if src code & covered (or inferred covered) + + if (status != LineCoverage.NONE) { + info.coveredLineCount++; + } + info.totalLineCount++; + } + @Nullable protected FileCoverageInfo fillInfoForUncoveredFile(@NotNull File file) { return null; diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationArgumentListImpl.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationArgumentListImpl.java index 49408103f50f..a3de593134f6 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationArgumentListImpl.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationArgumentListImpl.java @@ -21,6 +21,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.PsiAnnotation; import com.intellij.psi.PsiNameValuePair; import com.intellij.psi.StubBasedPsiElement; +import com.intellij.psi.stubs.EmptyStub; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; @@ -30,14 +31,13 @@ import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationArgumentList; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationNameValuePair; import org.jetbrains.plugins.groovy.lang.psi.impl.GrStubElementBase; -import org.jetbrains.plugins.groovy.lang.psi.stubs.GrAnnotationArgumentListStub; -public class GrAnnotationArgumentListImpl extends GrStubElementBase - implements GrAnnotationArgumentList, StubBasedPsiElement { +public class GrAnnotationArgumentListImpl extends GrStubElementBase + implements GrAnnotationArgumentList, StubBasedPsiElement { private static final Logger LOG = Logger.getInstance(GrAnnotationArgumentListImpl.class); - public GrAnnotationArgumentListImpl(@NotNull GrAnnotationArgumentListStub stub) { + public GrAnnotationArgumentListImpl(@NotNull EmptyStub stub) { super(stub, GroovyElementTypes.ANNOTATION_ARGUMENTS); } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationNameValuePairImpl.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationNameValuePairImpl.java index a549bbf1cf95..ad347d0a5432 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationNameValuePairImpl.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationNameValuePairImpl.java @@ -21,6 +21,7 @@ import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; import com.intellij.reference.SoftReference; +import com.intellij.testFramework.LightVirtualFile; import com.intellij.util.ArrayUtilRt; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ContainerUtilRt; @@ -112,6 +113,7 @@ public class GrAnnotationNameValuePairImpl extends GrStubElementBase(result = value); } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrAnnotationArgumentListElementType.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrAnnotationArgumentListElementType.java index 866bdb0f812d..f5231c5fec57 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrAnnotationArgumentListElementType.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrAnnotationArgumentListElementType.java @@ -15,20 +15,17 @@ */ package org.jetbrains.plugins.groovy.lang.psi.stubs.elements; -import com.intellij.psi.stubs.StubElement; -import com.intellij.psi.stubs.StubInputStream; -import com.intellij.psi.stubs.StubOutputStream; +import com.intellij.psi.stubs.EmptyStub; +import com.intellij.psi.stubs.EmptyStubElementType; import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.GroovyLanguage; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationArgumentList; import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.annotation.GrAnnotationArgumentListImpl; -import org.jetbrains.plugins.groovy.lang.psi.stubs.GrAnnotationArgumentListStub; -import java.io.IOException; - -public class GrAnnotationArgumentListElementType extends GrStubElementType { +public class GrAnnotationArgumentListElementType extends EmptyStubElementType { public GrAnnotationArgumentListElementType() { - super("annotation arguments"); + super("annotation arguments", GroovyLanguage.INSTANCE); } @Override @@ -37,23 +34,7 @@ public class GrAnnotationArgumentListElementType extends GrStubElementType { - public static final int STUB_VERSION = 31; + public static final int STUB_VERSION = 32; public GrStubFileElementType(Language language) { super(language); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/stubs/stubs.kt b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/stubs/stubs.kt index 2508e5c57e4b..4b97dcc8b35d 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/stubs/stubs.kt +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/stubs/stubs.kt @@ -17,13 +17,8 @@ package org.jetbrains.plugins.groovy.lang.psi.stubs import com.intellij.psi.stubs.StubBase import com.intellij.psi.stubs.StubElement -import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.ANNOTATION_ARGUMENTS import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.ANNOTATION_MEMBER_VALUE_PAIR -import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationArgumentList import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationNameValuePair class GrNameValuePairStub(parent: StubElement<*>?, val name: String?, val value: String?) : StubBase(parent, ANNOTATION_MEMBER_VALUE_PAIR) - -class GrAnnotationArgumentListStub(parent: StubElement<*>?) -: StubBase(parent, ANNOTATION_ARGUMENTS) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java index 365fbb2a9daf..bf0742c74dba 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java @@ -25,6 +25,7 @@ import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.rmi.RemoteProcessSupport; import com.intellij.execution.runners.ProgramRunner; import com.intellij.notification.Notification; +import com.intellij.notification.NotificationListener; import com.intellij.notification.NotificationType; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.AnAction; @@ -33,7 +34,9 @@ import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; +import com.intellij.openapi.options.ShowSettingsUtil; import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.projectRoots.*; import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl; import com.intellij.openapi.roots.ProjectRootManager; @@ -51,6 +54,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; import org.jetbrains.idea.maven.execution.MavenExecutionOptions; import org.jetbrains.idea.maven.execution.MavenRunnerSettings; +import org.jetbrains.idea.maven.execution.RunnerBundle; import org.jetbrains.idea.maven.model.MavenExplicitProfiles; import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.model.MavenModel; @@ -59,10 +63,12 @@ import org.jetbrains.idea.maven.project.MavenGeneralSettings; import org.jetbrains.idea.maven.project.MavenProjectsManager; import org.jetbrains.idea.maven.utils.MavenLog; import org.jetbrains.idea.maven.utils.MavenProgressIndicator; +import org.jetbrains.idea.maven.utils.MavenSettings; import org.jetbrains.idea.maven.utils.MavenUtil; import org.slf4j.Logger; import org.slf4j.impl.Log4jLoggerFactory; +import javax.swing.event.HyperlinkEvent; import java.io.File; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; @@ -283,14 +289,43 @@ public class MavenServerManager extends RemoteObjectWrapper impleme } } - final String currentMavenVersion = forceMaven2 ? "2.2.1" : getCurrentMavenVersion(); - params.getVMParametersList().addProperty(MavenServerEmbedder.MAVEN_EMBEDDER_VERSION, currentMavenVersion); + final File mavenHome; + final String mavenVersion; + final File currentMavenHomeFile = forceMaven2 ? BundledMavenPathHolder.myBundledMaven2Home : getCurrentMavenHomeFile(); + if (currentMavenHomeFile == null) { + mavenHome = BundledMavenPathHolder.myBundledMaven3Home; + mavenVersion = getMavenVersion(mavenHome); + + Project[] openProjects = ProjectManager.getInstance().getOpenProjects(); + final Project project = openProjects.length == 1 ? openProjects[0] : null; + if (project != null) { + new Notification(MavenUtil.MAVEN_NOTIFICATION_GROUP, "", RunnerBundle.message( + "external.maven.home.invalid.substitution.warning.with.fix", myState.mavenHome, mavenVersion), NotificationType.WARNING, + new NotificationListener() { + @Override + public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) { + ShowSettingsUtil.getInstance().showSettingsDialog(project, MavenSettings.DISPLAY_NAME); + } + }).notify(null); + } + else { + new Notification(MavenUtil.MAVEN_NOTIFICATION_GROUP, "", RunnerBundle.message( + "external.maven.home.invalid.substitution.warning", myState.mavenHome, mavenVersion), NotificationType.WARNING).notify(null); + } + } + else { + mavenHome = currentMavenHomeFile; + mavenVersion = getMavenVersion(mavenHome); + } + assert mavenVersion != null; + + params.getVMParametersList().addProperty(MavenServerEmbedder.MAVEN_EMBEDDER_VERSION, mavenVersion); String sdkConfigLocation = "Settings | Build, Execution, Deployment | Build Tools | Maven | Importing | JDK for Importer"; - verifyMavenSdkRequirements(jdk, currentMavenVersion, sdkConfigLocation); + verifyMavenSdkRequirements(jdk, mavenVersion, sdkConfigLocation); final List classPath = new ArrayList<>(); classPath.add(PathUtil.getJarPathForClass(org.apache.log4j.Logger.class)); - if (currentMavenVersion == null || StringUtil.compareVersionNumbers(currentMavenVersion, "3.1") < 0) { + if (StringUtil.compareVersionNumbers(mavenVersion, "3.1") < 0) { classPath.add(PathUtil.getJarPathForClass(Logger.class)); classPath.add(PathUtil.getJarPathForClass(Log4jLoggerFactory.class)); } @@ -299,7 +334,7 @@ public class MavenServerManager extends RemoteObjectWrapper impleme ContainerUtil.addIfNotNull(classPath, PathUtil.getJarPathForClass(Query.class)); params.getClassPath().add(PathManager.getResourceRoot(getClass(), "/messages/CommonBundle.properties")); params.getClassPath().addAll(classPath); - params.getClassPath().addAllFiles(collectClassPathAndLibsFolder(forceMaven2)); + params.getClassPath().addAllFiles(collectClassPathAndLibsFolder(mavenVersion, mavenHome)); String embedderXmx = System.getProperty("idea.maven.embedder.xmx"); if (embedderXmx != null) { @@ -381,14 +416,12 @@ public class MavenServerManager extends RemoteObjectWrapper impleme return MavenUtil.getMavenVersion(mavenHome); } + @Nullable public String getCurrentMavenVersion() { return getMavenVersion(myState.mavenHome); } - public List collectClassPathAndLibsFolder(boolean forceMaven2) { - final String currentMavenVersion = forceMaven2 ? "2.2.1" : getCurrentMavenVersion(); - File mavenHome = forceMaven2 ? BundledMavenPathHolder.myBundledMaven2Home : currentMavenVersion == null ? BundledMavenPathHolder.myBundledMaven3Home : getCurrentMavenHomeFile(); - + private static List collectClassPathAndLibsFolder(@NotNull String mavenVersion, @NotNull File mavenHome) { final File pluginFileOrDir = new File(PathUtil.getJarPathForClass(MavenServerManager.class)); final List classpath = new ArrayList<>(); final String root = pluginFileOrDir.getParent(); @@ -396,11 +429,11 @@ public class MavenServerManager extends RemoteObjectWrapper impleme if (pluginFileOrDir.isDirectory()) { classpath.add(new File(root, "maven-server-api")); File parentFile = getMavenPluginParentFile(); - if (forceMaven2 || (currentMavenVersion != null && StringUtil.compareVersionNumbers(currentMavenVersion, "3") < 0)) { + if (StringUtil.compareVersionNumbers(mavenVersion, "3") < 0) { classpath.add(new File(root, "maven2-server-impl")); addDir(classpath, new File(parentFile, "maven2-server-impl/lib")); // use bundled maven 2.2.1 for all 2.0.x version (since we use org.apache.maven.project.interpolation.StringSearchModelInterpolator introduced in 2.1.0) - if (StringUtil.compareVersionNumbers(currentMavenVersion, "2.1.0") < 0) { + if (StringUtil.compareVersionNumbers(mavenVersion, "2.1.0") < 0) { mavenHome = BundledMavenPathHolder.myBundledMaven2Home; } } @@ -408,7 +441,7 @@ public class MavenServerManager extends RemoteObjectWrapper impleme classpath.add(new File(root, "maven3-server-common")); addDir(classpath, new File(parentFile, "maven3-server-common/lib")); - if (currentMavenVersion == null || StringUtil.compareVersionNumbers(currentMavenVersion, "3.1") < 0) { + if (StringUtil.compareVersionNumbers(mavenVersion, "3.1") < 0) { classpath.add(new File(root, "maven30-server-impl")); } else { @@ -419,7 +452,7 @@ public class MavenServerManager extends RemoteObjectWrapper impleme else { classpath.add(new File(root, "maven-server-api.jar")); - if (forceMaven2 || (currentMavenVersion != null && StringUtil.compareVersionNumbers(currentMavenVersion, "3") < 0)) { + if (StringUtil.compareVersionNumbers(mavenVersion, "3") < 0) { classpath.add(new File(root, "maven2-server-impl.jar")); addDir(classpath, new File(root, "maven2-server-lib")); } @@ -427,7 +460,7 @@ public class MavenServerManager extends RemoteObjectWrapper impleme classpath.add(new File(root, "maven3-server-common.jar")); addDir(classpath, new File(root, "maven3-server-lib")); - if (currentMavenVersion == null || StringUtil.compareVersionNumbers(currentMavenVersion, "3.1") < 0) { + if (StringUtil.compareVersionNumbers(mavenVersion, "3.1") < 0) { classpath.add(new File(root, "maven30-server-impl.jar")); } else { @@ -602,7 +635,7 @@ public class MavenServerManager extends RemoteObjectWrapper impleme public boolean isUseMaven2() { final String version = getCurrentMavenVersion(); - return StringUtil.compareVersionNumbers(version, "3") < 0 && StringUtil.compareVersionNumbers(version, "2") >= 0; + return version != null && StringUtil.compareVersionNumbers(version, "3") < 0 && StringUtil.compareVersionNumbers(version, "2") >= 0; } @TestOnly diff --git a/plugins/maven/src/main/resources/RunnerBundle.properties b/plugins/maven/src/main/resources/RunnerBundle.properties index 4ebc0700a113..8e9ec5416fa8 100644 --- a/plugins/maven/src/main/resources/RunnerBundle.properties +++ b/plugins/maven/src/main/resources/RunnerBundle.properties @@ -16,6 +16,9 @@ external.maven.home.does.not.exist.with.fix=Specified Maven home directory ({0}) external.maven.home.invalid={0} is not a valid Maven home directory external.maven.home.invalid.with.fix={0} is not a valid Maven home directory. Configure Maven home +external.maven.home.invalid.substitution.warning=Invalid Maven home directory configured
{0}
Bundled maven {1} will be used +external.maven.home.invalid.substitution.warning.with.fix=Invalid Maven home directory configured
{0}
Bundled maven {1} will be used. Configure Maven home. + embedded.executor.caption=Executing Maven - using embedded Maven embedded.cannot.create=Cannot create Maven Embedder embedded.build.failed=BUILD FAILED diff --git a/python/gen/com/jetbrains/commandInterface/commandLine/CommandLineParser.java b/python/gen/com/jetbrains/commandInterface/commandLine/CommandLineParser.java index f652c7ae1fb7..84fa8f433273 100644 --- a/python/gen/com/jetbrains/commandInterface/commandLine/CommandLineParser.java +++ b/python/gen/com/jetbrains/commandInterface/commandLine/CommandLineParser.java @@ -1,15 +1,15 @@ // This is a generated file. Not intended for manual editing. package com.jetbrains.commandInterface.commandLine; -import com.intellij.lang.ASTNode; -import com.intellij.lang.LightPsiParser; import com.intellij.lang.PsiBuilder; import com.intellij.lang.PsiBuilder.Marker; -import com.intellij.lang.PsiParser; -import com.intellij.psi.tree.IElementType; - import static com.jetbrains.commandInterface.commandLine.CommandLineElementTypes.*; import static com.jetbrains.commandInterface.commandLine.CommandLineParserUtil.*; +import com.intellij.psi.tree.IElementType; +import com.intellij.lang.ASTNode; +import com.intellij.psi.tree.TokenSet; +import com.intellij.lang.PsiParser; +import com.intellij.lang.LightPsiParser; @SuppressWarnings({"SimplifiableIfStatement", "UnusedAssignment"}) public class CommandLineParser implements PsiParser, LightPsiParser { @@ -47,11 +47,11 @@ public class CommandLineParser implements PsiParser, LightPsiParser { public static boolean argument(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "argument")) return false; boolean r; - Marker m = enter_section_(b, l, _NONE_, ""); + Marker m = enter_section_(b, l, _NONE_, ARGUMENT, ""); r = consumeToken(b, LITERAL_STARTS_FROM_LETTER); if (!r) r = consumeToken(b, LITERAL_STARTS_FROM_DIGIT); if (!r) r = consumeToken(b, LITERAL_STARTS_FROM_SYMBOL); - exit_section_(b, l, m, ARGUMENT, r, false, null); + exit_section_(b, l, m, r, false, null); return r; } @@ -79,10 +79,10 @@ public class CommandLineParser implements PsiParser, LightPsiParser { if (!recursion_guard_(b, l, "option")) return false; if (!nextTokenIs(b, "

\n

0) { + no_rows.hide(); + } + table.show(); + + } + else { + // Filter table items by value. + var hidden = 0; + var shown = 0; + + // Hide / show elements. + $.each(table_row_names, function () { + var element = $(this).parents("tr"); + + if ($(this).text().indexOf(filter_value) === -1) { + // hide + element.addClass("hidden"); + hidden++; + } + else { + // show + element.removeClass("hidden"); + shown++; + } + }); + + // Show placeholder if no rows will be displayed. + if (no_rows.length > 0) { + if (shown === 0) { + // Show placeholder, hide table. + no_rows.show(); + table.hide(); + } + else { + // Hide placeholder, show table. + no_rows.hide(); + table.show(); + } + } + + // Manage dynamic header: + if (hidden > 0) { + // Calculate new dynamic sum values based on visible rows. + for (var column = 2; column < 20; column++) { + // Calculate summed value. + var cells = table_rows.find('td:nth-child(' + column + ')'); + if (!cells.length) { + // No more columns...! + break; + } + + var sum = 0, numer = 0, denom = 0; + $.each(cells.filter(':visible'), function () { + var ratio = $(this).data("ratio"); + if (ratio) { + var splitted = ratio.split(" "); + numer += parseInt(splitted[0], 10); + denom += parseInt(splitted[1], 10); + } + else { + sum += parseInt(this.innerHTML, 10); + } + }); + + // Get footer cell element. + var footer_cell = table_dynamic_footer.find('td:nth-child(' + column + ')'); + + // Set value into dynamic footer cell element. + if (cells[0].innerHTML.indexOf('%') > -1) { + // Percentage columns use the numerator and denominator, + // and adapt to the number of decimal places. + var match = /\.([0-9]+)/.exec(cells[0].innerHTML); + var places = 0; + if (match) { + places = match[1].length; + } + var pct = numer * 100 / denom; + footer_cell.text(pct.toFixed(places) + '%'); + } + else { + footer_cell.text(sum); + } + } + + // Hide standard footer, show dynamic footer. + table_footer.addClass("hidden"); + table_dynamic_footer.removeClass("hidden"); + } + else { + // Show standard footer, hide dynamic footer. + table_footer.removeClass("hidden"); + table_dynamic_footer.addClass("hidden"); + } + } + })); + + // Trigger change event on setup, to force filter on page refresh + // (filter value may still be present). + $("#filter").trigger("change"); +}; + // Loaded on index.html coverage.index_ready = function ($) { // Look for a cookie containing previous sort settings: @@ -95,6 +227,7 @@ coverage.index_ready = function ($) { coverage.assign_shortkeys(); coverage.wire_up_help_panel(); + coverage.wire_up_filter(); // Watch for page unload events so we can save the final sort settings: $(window).unload(function () { @@ -129,6 +262,11 @@ coverage.pyfile_ready = function ($) { coverage.assign_shortkeys(); coverage.wire_up_help_panel(); + + coverage.init_scroll_markers(); + + // Rebuild scroll markers after window high changing + $(window).resize(coverage.resize_scroll_markers); }; coverage.toggle_lines = function (btn, cls) { @@ -187,12 +325,13 @@ coverage.to_next_chunk = function () { // Find the start of the next colored chunk. var probe = c.sel_end; + var color, probe_line; while (true) { - var probe_line = c.line_elt(probe); + probe_line = c.line_elt(probe); if (probe_line.length === 0) { return; } - var color = probe_line.css("background-color"); + color = probe_line.css("background-color"); if (!c.is_transparent(color)) { break; } @@ -374,3 +513,72 @@ coverage.scroll_window = function (to_pos) { coverage.finish_scrolling = function () { $("html,body").stop(true, true); }; + +coverage.init_scroll_markers = function () { + var c = coverage; + // Init some variables + c.lines_len = $('td.text p').length; + c.body_h = $('body').height(); + c.header_h = $('div#header').height(); + c.missed_lines = $('td.text p.mis, td.text p.par'); + + // Build html + c.resize_scroll_markers(); +}; + +coverage.resize_scroll_markers = function () { + var c = coverage, + min_line_height = 3, + max_line_height = 10, + visible_window_h = $(window).height(); + + $('#scroll_marker').remove(); + // Don't build markers if the window has no scroll bar. + if (c.body_h <= visible_window_h) { + return; + } + + $("body").append("

 
"); + var scroll_marker = $('#scroll_marker'), + marker_scale = scroll_marker.height() / c.body_h, + line_height = scroll_marker.height() / c.lines_len; + + // Line height must be between the extremes. + if (line_height > min_line_height) { + if (line_height > max_line_height) { + line_height = max_line_height; + } + } + else { + line_height = min_line_height; + } + + var previous_line = -99, + last_mark, + last_top; + + c.missed_lines.each(function () { + var line_top = Math.round($(this).offset().top * marker_scale), + id_name = $(this).attr('id'), + line_number = parseInt(id_name.substring(1, id_name.length)); + + if (line_number === previous_line + 1) { + // If this solid missed block just make previous mark higher. + last_mark.css({ + 'height': line_top + line_height - last_top + }); + } + else { + // Add colored line in scroll_marker block. + scroll_marker.append('
'); + last_mark = $('#m' + line_number); + last_mark.css({ + 'height': line_height, + 'top': line_top + }); + last_top = line_top; + } + + previous_line = line_number; + }); +}; diff --git a/python/helpers/coveragepy/coverage/htmlfiles/index.html b/python/helpers/coveragepy/coverage/htmlfiles/index.html index c831823dd239..ee2deab0b627 100644 --- a/python/helpers/coveragepy/coverage/htmlfiles/index.html +++ b/python/helpers/coveragepy/coverage/htmlfiles/index.html @@ -1,101 +1,115 @@ - +{# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 #} +{# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt #} + + - + {{ title|escape }} - + {% if extra_css %} - + {% endif %} - - - - - + + + + + - + -