Merge remote-tracking branch 'origin/master'

This commit is contained in:
Konstantin Bulenkov
2016-10-19 14:26:02 +02:00
142 changed files with 7318 additions and 4237 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
<component name="libraryTable">
<library name="Eclipse">
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/ecj-4.5.2.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/ecj-4.6.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
+11 -10
View File
@@ -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 <pid> <path> [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)
@@ -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<Class<? extends ProjectTask>, List<ProjectTask>> tasksMap) {
Collection<? extends ProjectTask> buildTasks = tasksMap.get(ModuleBuildTask.class);
if (ContainerUtil.isEmpty(buildTasks)) return;
ModulesBuildSettings modulesBuildSettings = assembleModulesBuildSettings(buildTasks);
if (!ContainerUtil.isEmpty(buildTasks)) {
List<Module> 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<Module> modules;
public ModulesBuildSettings(boolean isIncrementalBuild,
boolean includeDependentModules,
boolean includeRuntimeDependencies,
Collection<Module> 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<? extends ProjectTask> buildTasks) {
Collection<Module> modules = new SmartList<>();
Collection<ModuleBuildTask> incrementalTasks = ContainerUtil.newSmartList();
Collection<ModuleBuildTask> excludeDependentTasks = ContainerUtil.newSmartList();
Collection<ModuleBuildTask> 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<ModuleBuildTask> 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,
@@ -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;
}
@@ -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());
}
@@ -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;
}
}
@@ -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);
}
}
}
@@ -79,13 +79,7 @@ public class ConstructorInsertHandler implements InsertHandler<LookupElementDeco
final PsiExpression enclosing = PsiTreeUtil.getContextOfType(position, PsiExpression.class, true);
final PsiAnonymousClass anonymousClass = PsiTreeUtil.getParentOfType(position, PsiAnonymousClass.class);
final boolean inAnonymous = anonymousClass != null && anonymousClass.getParent() == enclosing;
boolean fillTypeArgs = false;
if (delegate instanceof PsiTypeLookupItem) {
fillTypeArgs = !isRawTypeExpected(context, (PsiTypeLookupItem)delegate) &&
psiClass.getTypeParameters().length > 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<LookupElementDeco
final int offset = context.getTailOffset();
document.insertString(offset, " {}");
editor.getCaretModel().moveToOffset(offset + 2);
OffsetKey insideBraces = context.trackOffset(offset + 2, true);
final PsiFile file = context.getFile();
PsiDocumentManager.getInstance(file.getProject()).commitDocument(document);
reformatEnclosingExpressionListAtOffset(file, offset);
if (fillTypeArgs && JavaCompletionUtil.promptTypeArgs(context, context.getOffset(insideRef))) return;
if (promptTypeOrConstructorArgs(context, delegate, context.getOffset(insideRef))) return;
editor.getCaretModel().moveToOffset(context.getOffset(insideBraces));
context.setLaterRunnable(generateAnonymousBody(editor, file));
}
else {
@@ -147,12 +142,32 @@ public class ConstructorInsertHandler implements InsertHandler<LookupElementDeco
if (mySmart) {
FeatureUsageTracker.getInstance().triggerFeatureUsed(JavaCompletionFeatures.AFTER_NEW);
}
if (fillTypeArgs) {
JavaCompletionUtil.promptTypeArgs(context, context.getOffset(insideRef));
}
promptTypeOrConstructorArgs(context, delegate, context.getOffset(insideRef));
}
}
private static boolean promptTypeOrConstructorArgs(InsertionContext context, LookupElement delegate, int refOffset) {
if (shouldFillTypeArgs(context, delegate) && JavaCompletionUtil.promptTypeArgs(context, refOffset)) {
return true;
}
PsiMethod constructor = JavaConstructorCallElement.extractCalledConstructor(delegate);
return constructor != null && JavaMethodCallElement.startArgumentLiveTemplate(context, constructor);
}
private static boolean shouldFillTypeArgs(InsertionContext context, LookupElement delegate) {
if (!(delegate instanceof PsiTypeLookupItem) ||
isRawTypeExpected(context, (PsiTypeLookupItem)delegate) ||
!((PsiClass)delegate.getObject()).hasTypeParameters()) {
return false;
}
PsiElement position = SmartCompletionDecorator.getPosition(context, delegate);
return position != null &&
((PsiTypeLookupItem)delegate).calcGenerics(position, context).isEmpty() &&
context.getCompletionChar() != '(';
}
private static void reformatEnclosingExpressionListAtOffset(@NotNull PsiFile file, int offset) {
final PsiElement elementAtOffset = PsiUtilCore.getElementAtOffset(file, offset);
PsiExpressionList listToReformat = getEnclosingExpressionList(elementAtOffset.getParent());
@@ -195,7 +210,7 @@ public class ConstructorInsertHandler implements InsertHandler<LookupElementDeco
LookupElement delegate,
final PsiClass psiClass,
final boolean forAnonymous) {
if (context.getCompletionChar() == '[' || JavaConstructorCallElement.isWrapped(delegate)) {
if (context.getCompletionChar() == '[') {
return false;
}
@@ -18,6 +18,7 @@ package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementDecorator;
import com.intellij.codeInsight.lookup.LookupElementPresentation;
import com.intellij.codeInsight.lookup.TypedLookupItem;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
@@ -28,6 +29,7 @@ import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
@@ -36,16 +38,17 @@ import java.util.function.Supplier;
/**
* @author peter
*/
public class JavaConstructorCallElement extends JavaMethodCallElement {
public class JavaConstructorCallElement extends LookupElementDecorator<LookupElement> implements TypedLookupItem {
private static final Key<JavaConstructorCallElement> 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<PsiClassType> 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<PsiMethod> 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;
}
}
@@ -180,10 +180,7 @@ public class JavaMethodCallElement extends LookupItem<PsiMethod> 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<PsiMethod> implements Type
qualifyMethodCall(file, startOffset, document);
}
public static final Key<JavaMethodCallElement> ARGUMENT_TEMPLATE_ACTIVE = Key.create("ARGUMENT_TEMPLATE_ACTIVE");
public static final Key<PsiMethod> 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<PsiMethod> 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<PsiMethod> 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) {
@@ -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) {
@@ -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);
}
}
@@ -0,0 +1,8 @@
abstract class Foo{
public Foo(int x) {
}
{
Foo f = new F<caret>
}
}
@@ -0,0 +1,8 @@
abstract class Foo{
public Foo(int x) {
}
{
Foo f = new Foo(<selection>x</selection><caret>) {}
}
}
@@ -0,0 +1,8 @@
class Foo{
Foo(int arg) {
}
{
Foo f = new F<caret>
}
}
@@ -0,0 +1,8 @@
class Foo{
Foo(int arg) {
}
{
Foo f = new Foo(<selection>arg</selection><caret>)
}
}
@@ -0,0 +1,5 @@
class Foo{
{
Foo f = new F<caret>
}
}
@@ -0,0 +1,5 @@
class Foo{
{
Foo f = new Foo()<caret>
}
}
@@ -0,0 +1,12 @@
class Foo{
Foo(int arg) {
}
Foo(boolean arg) {
}
Foo() {
}
{
Foo f = new F<caret>
}
}
@@ -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<String> s) {
new TreeSet<>(s).contains("abc");
}
}
@@ -0,0 +1,10 @@
// "Replace with 'java.util.TreeSet' constructor" "true"
import java.util.*;
import java.util.stream.*;
class Test {
public static <T, T1 extends T> void test(List<T1> s) {
new TreeSet<T>(s).contains("abc");
}
}
@@ -0,0 +1,18 @@
// "Replace with 'Test.MyType' constructor" "true"
import java.util.*;
import java.util.stream.*;
class Test {
static class MyType extends ArrayList<String> {
public MyType() {}
public MyType(Collection<String> coll) {
super(coll);
}
}
public static void test(List<String> s) {
new MyType(s).contains("abc");
}
}
@@ -0,0 +1,18 @@
// "Replace with 'Test.MyType' constructor" "true"
import java.util.*;
import java.util.stream.*;
class Test {
static class MyType<A,B> extends ArrayList<String> {
public MyType() {}
public MyType(Collection<String> coll) {
super(coll);
}
}
public static void testMy(List<String> s) {
new MyType<String, Number>(s).contains("abc");
}
}
@@ -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<String> s) {
new TreeSet<Object>(s).contains("abc");
}
}
@@ -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<String> s) {
new ArrayList<>(s).contains("abc");
}
}
@@ -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<String> s) {
new ArrayList<Object>(s).contains("abc");
}
}
@@ -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<String> s) {
new HashSet<>(s).contains("abc");
}
}
@@ -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<String> s) {
s.str<caret>eam().collect(Collectors.toCollection(TreeSet<String>::new)).contains("abc");
}
}
@@ -0,0 +1,10 @@
// "Replace with 'java.util.TreeSet' constructor" "true"
import java.util.*;
import java.util.stream.*;
class Test {
public static <T, T1 extends T> void test(List<T1> s) {
s.stream().colle<caret>ct(Collectors.toCollection(TreeSet<T>::new)).contains("abc");
}
}
@@ -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<String> s) {
s.str<caret>eam().collect(Collectors.toCollection(TreeSet<? extends String>::new)).contains("abc");
}
}
@@ -0,0 +1,14 @@
// "Replace with 'Test.MyType' constructor" "false"
import java.util.*;
import java.util.stream.*;
class Test {
static class MyType extends ArrayList<String> {
}
public static void test(List<String> s) {
s.str<caret>eam().collect(Collectors.toCollection(MyType::new)).contains("abc");
}
}
@@ -0,0 +1,18 @@
// "Replace with 'Test.MyType' constructor" "true"
import java.util.*;
import java.util.stream.*;
class Test {
static class MyType extends ArrayList<String> {
public MyType() {}
public MyType(Collection<String> coll) {
super(coll);
}
}
public static void test(List<String> s) {
s.str<caret>eam().collect(Collectors.toCollection(MyType::new)).contains("abc");
}
}
@@ -0,0 +1,18 @@
// "Replace with 'Test.MyType' constructor" "false"
import java.util.*;
import java.util.stream.*;
class Test {
static class MyType extends ArrayList<String> {
public MyType() {}
private MyType(Collection<String> coll) {
super(coll);
}
}
public static void test(List<String> s) {
s.str<caret>eam().collect(Collectors.toCollection(MyType::new)).contains("abc");
}
}
@@ -0,0 +1,18 @@
// "Replace with 'Test.MyType' constructor" "true"
import java.util.*;
import java.util.stream.*;
class Test {
static class MyType<A,B> extends ArrayList<String> {
public MyType() {}
public MyType(Collection<String> coll) {
super(coll);
}
}
public static void testMy(List<String> s) {
s.stream().collect(Collectors.toCollection(MyType<caret><String, Number>::new)).contains("abc");
}
}
@@ -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<String> s) {
s.str<caret>eam().collect(Collectors.toCollection(TreeSet<Object>::new)).contains("abc");
}
}
@@ -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<String> s) {
s.stream().collect(Collectors.toL<caret>ist()).contains("abc");
}
}
@@ -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<String> s) {
s.stream().collect(Collectors.<Object>toL<caret>ist()).contains("abc");
}
}
@@ -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<String> s) {
s.stream().co<caret>llect(Collectors.toSet()).contains("abc");
}
}
@@ -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
}
}
@@ -100,7 +100,7 @@ public class OrderEntryTest extends DaemonAnalyzerTestCase {
private IntentionAction findActionAndCheck(final ActionHint actionHint, Collection<HighlightInfo> infosBefore) {
List<IntentionAction> actions = LightQuickFixTestCase.getAvailableActions(getEditor(), getFile());
return actionHint.findAndCheck(actions, () -> "Infos: " + infosBefore);
return actionHint.findAndCheck(actions, "Infos: " + infosBefore);
}
public void testAddDependency() throws Exception {
@@ -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<IntentionAction> actions, Supplier<String> infoSupplier) {
public IntentionAction findAndCheck(@NotNull Collection<IntentionAction> 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;
}
@@ -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) {
@@ -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 {
@@ -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);
}
}
+28 -31
View File
@@ -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, "<boolean literal>", FALSE, TRUE)) return false;
boolean r;
Marker m = enter_section_(b, l, _NONE_, "<boolean literal>");
Marker m = enter_section_(b, l, _NONE_, BOOLEAN_LITERAL, "<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_, "<literal>");
Marker m = enter_section_(b, l, _COLLAPSE_, LITERAL, "<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_, "<property>");
Marker m = enter_section_(b, l, _NONE_, PROPERTY, "<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, "<string literal>", DOUBLE_QUOTED_STRING, SINGLE_QUOTED_STRING)) return false;
boolean r;
Marker m = enter_section_(b, l, _NONE_, "<string literal>");
Marker m = enter_section_(b, l, _NONE_, STRING_LITERAL, "<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_, "<value>");
Marker m = enter_section_(b, l, _COLLAPSE_, VALUE, "<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;
}
@@ -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);
}
@@ -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);
}
@@ -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);
}
@@ -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);
}
@@ -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);
}
@@ -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);
}
@@ -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);
}
@@ -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);
}
@@ -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);
}
@@ -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);
}
@@ -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);
}
+1 -1
View File
@@ -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
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -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
@@ -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) {
@@ -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;
}
}
@@ -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);
}
@@ -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<VirtualFile> 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<VirtualFile> 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);
}
}
}
@@ -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) {
@@ -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();
}
}
@@ -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']
}
}
@@ -2059,8 +2059,8 @@ class.with.only.private.constructors.problem.descriptor=Class <code>#ref</code>
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=<code>#ref()</code> 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
@@ -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;
@@ -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;
}
@@ -31,7 +31,7 @@ import java.util.Set;
public class ConstantJUnitAssertArgumentInspection extends BaseInspection {
@NonNls
private static final Set<String> ASSERT_METHODS = new HashSet();
private static final Set<String> 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);
}
}
}
@@ -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();
@@ -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;
}
}
}
@@ -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);
@@ -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.*")
@@ -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)) {
@@ -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);
}
@@ -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) {
@@ -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<PsiElement> 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;
}
@@ -1,11 +1,11 @@
<html>
<body>
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 <i>Instance method naming convention</i> inspection
will ignore JUnit 4 test methods automatically.
will ignore JUnit 4+ test methods automatically.
<!-- tooltip end -->
<p>
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 <b>0</b> to not check the length of names. Regular expressions are in standard <b>java.util.regex</b> format.
<p>
</body>
@@ -1,6 +1,6 @@
<html>
<body>
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.
<!-- tooltip end -->
@@ -3,13 +3,13 @@ import org.junit.Test;
public class JUnit4MethodNamingConvention {
@Test
public void <warning descr="JUnit 4 test method name 'a' is too short (1 < 4)">a</warning>() {}
public void <warning descr="JUnit 4+ test method name 'a' is too short (1 < 4)">a</warning>() {}
@Test
public void <warning descr="JUnit 4 test method name 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz' is too long (78 > 64)">abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz</warning>() {}
public void <warning descr="JUnit 4+ test method name 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz' is too long (78 > 64)">abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz</warning>() {}
@Test
public void <warning descr="JUnit 4 test method name 'more$$$' doesn't match regex '[a-z][A-Za-z_\d]*'">more$$$</warning>() {}
public void <warning descr="JUnit 4+ test method name 'more$$$' doesn't match regex '[a-z][A-Za-z_\d]*'">more$$$</warning>() {}
@Test
public void assure_foo_is_never_null() {}
@@ -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<String, String> normalizedFiles2Files)
{
@NotNull final Map<String, String> 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<String, String> normalizedFiles2Files)
{
final @NotNull Map<String, String> 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;
@@ -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<GrAnnotationArgumentListStub>
implements GrAnnotationArgumentList, StubBasedPsiElement<GrAnnotationArgumentListStub> {
public class GrAnnotationArgumentListImpl extends GrStubElementBase<EmptyStub>
implements GrAnnotationArgumentList, StubBasedPsiElement<EmptyStub> {
private static final Logger LOG = Logger.getInstance(GrAnnotationArgumentListImpl.class);
public GrAnnotationArgumentListImpl(@NotNull GrAnnotationArgumentListStub stub) {
public GrAnnotationArgumentListImpl(@NotNull EmptyStub stub) {
super(stub, GroovyElementTypes.ANNOTATION_ARGUMENTS);
}
@@ -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<GrNameValue
GrAnnotation annotation = GroovyPsiElementFactory.getInstance(getProject()).createAnnotationFromText(
"@F(" + text + ")", this
);
((LightVirtualFile)annotation.getContainingFile().getViewProvider().getVirtualFile()).setWritable(false);
PsiAnnotationMemberValue value = annotation.findAttributeValue(null);
myDetachedValue = new SoftReference<>(result = value);
}
@@ -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<GrAnnotationArgumentListStub, GrAnnotationArgumentList> {
public class GrAnnotationArgumentListElementType extends EmptyStubElementType<GrAnnotationArgumentList> {
public GrAnnotationArgumentListElementType() {
super("annotation arguments");
super("annotation arguments", GroovyLanguage.INSTANCE);
}
@Override
@@ -37,23 +34,7 @@ public class GrAnnotationArgumentListElementType extends GrStubElementType<GrAnn
}
@Override
public void serialize(@NotNull GrAnnotationArgumentListStub stub, @NotNull StubOutputStream dataStream) throws IOException {
}
@NotNull
@Override
public GrAnnotationArgumentListStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException {
return new GrAnnotationArgumentListStub(parentStub);
}
@Override
public GrAnnotationArgumentList createPsi(@NotNull GrAnnotationArgumentListStub stub) {
public GrAnnotationArgumentList createPsi(@NotNull EmptyStub stub) {
return new GrAnnotationArgumentListImpl(stub);
}
@NotNull
@Override
public GrAnnotationArgumentListStub createStub(@NotNull GrAnnotationArgumentList psi, StubElement parentStub) {
return new GrAnnotationArgumentListStub(parentStub);
}
}
@@ -40,7 +40,7 @@ import java.io.IOException;
* @author ilyas
*/
public class GrStubFileElementType extends IStubFileElementType<GrFileStub> {
public static final int STUB_VERSION = 31;
public static final int STUB_VERSION = 32;
public GrStubFileElementType(Language language) {
super(language);
@@ -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<GrAnnotationNameValuePair>(parent, ANNOTATION_MEMBER_VALUE_PAIR)
class GrAnnotationArgumentListStub(parent: StubElement<*>?)
: StubBase<GrAnnotationArgumentList>(parent, ANNOTATION_ARGUMENTS)
@@ -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<MavenServer> 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<String> 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<MavenServer> 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<MavenServer> impleme
return MavenUtil.getMavenVersion(mavenHome);
}
@Nullable
public String getCurrentMavenVersion() {
return getMavenVersion(myState.mavenHome);
}
public List<File> collectClassPathAndLibsFolder(boolean forceMaven2) {
final String currentMavenVersion = forceMaven2 ? "2.2.1" : getCurrentMavenVersion();
File mavenHome = forceMaven2 ? BundledMavenPathHolder.myBundledMaven2Home : currentMavenVersion == null ? BundledMavenPathHolder.myBundledMaven3Home : getCurrentMavenHomeFile();
private static List<File> collectClassPathAndLibsFolder(@NotNull String mavenVersion, @NotNull File mavenHome) {
final File pluginFileOrDir = new File(PathUtil.getJarPathForClass(MavenServerManager.class));
final List<File> classpath = new ArrayList<>();
final String root = pluginFileOrDir.getParent();
@@ -396,11 +429,11 @@ public class MavenServerManager extends RemoteObjectWrapper<MavenServer> 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<MavenServer> 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<MavenServer> 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<MavenServer> 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<MavenServer> 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
@@ -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. <a href="#">Configure Maven home</a>
external.maven.home.invalid.substitution.warning=Invalid Maven home directory configured <br>{0} <br>Bundled maven {1} will be used
external.maven.home.invalid.substitution.warning.with.fix=Invalid Maven home directory configured <br>{0} <br>Bundled maven {1} will be used. <a href="#">Configure Maven home</a>.
embedded.executor.caption=Executing Maven - using embedded Maven
embedded.cannot.create=Cannot create Maven Embedder
embedded.build.failed=BUILD FAILED
@@ -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_, "<argument>");
Marker m = enter_section_(b, l, _NONE_, ARGUMENT, "<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, "<option>", LONG_OPTION_NAME_TOKEN, SHORT_OPTION_NAME_TOKEN)) return false;
boolean r;
Marker m = enter_section_(b, l, _NONE_, "<option>");
Marker m = enter_section_(b, l, _NONE_, OPTION, "<option>");
r = option_0(b, l + 1);
if (!r) r = option_1(b, l + 1);
exit_section_(b, l, m, OPTION, r, false, null);
exit_section_(b, l, m, r, false, null);
return r;
}
@@ -1,12 +1,13 @@
// This is a generated file. Not intended for manual editing.
package com.jetbrains.commandInterface.commandLine.psi;
import java.util.List;
import org.jetbrains.annotations.*;
import com.intellij.psi.PsiElement;
import com.jetbrains.commandInterface.commandLine.CommandLinePart;
import com.jetbrains.commandInterface.command.Argument;
import com.jetbrains.commandInterface.command.Help;
import com.jetbrains.commandInterface.command.Option;
import com.jetbrains.commandInterface.commandLine.CommandLinePart;
import org.jetbrains.annotations.Nullable;
public interface CommandLineArgument extends CommandLinePart {
@@ -1,19 +1,18 @@
// This is a generated file. Not intended for manual editing.
package com.jetbrains.commandInterface.commandLine.psi.impl;
import java.util.List;
import org.jetbrains.annotations.*;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.util.PsiTreeUtil;
import static com.jetbrains.commandInterface.commandLine.CommandLineElementTypes.*;
import com.jetbrains.commandInterface.commandLine.CommandLineElement;
import com.jetbrains.commandInterface.commandLine.psi.*;
import com.jetbrains.commandInterface.command.Argument;
import com.jetbrains.commandInterface.command.Help;
import com.jetbrains.commandInterface.command.Option;
import com.jetbrains.commandInterface.commandLine.CommandLineElement;
import com.jetbrains.commandInterface.commandLine.psi.CommandLineArgument;
import com.jetbrains.commandInterface.commandLine.psi.CommandLineVisitor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import static com.jetbrains.commandInterface.commandLine.CommandLineElementTypes.*;
public class CommandLineArgumentImpl extends CommandLineElement implements CommandLineArgument {
@@ -21,8 +20,12 @@ public class CommandLineArgumentImpl extends CommandLineElement implements Comma
super(node);
}
public void accept(@NotNull CommandLineVisitor visitor) {
visitor.visitArgument(this);
}
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof CommandLineVisitor) ((CommandLineVisitor)visitor).visitArgument(this);
if (visitor instanceof CommandLineVisitor) accept((CommandLineVisitor)visitor);
else super.accept(visitor);
}
@@ -17,8 +17,12 @@ public class CommandLineCommandImpl extends CommandLineElement implements Comman
super(node);
}
public void accept(@NotNull CommandLineVisitor visitor) {
visitor.visitCommand(this);
}
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof CommandLineVisitor) ((CommandLineVisitor)visitor).visitCommand(this);
if (visitor instanceof CommandLineVisitor) accept((CommandLineVisitor)visitor);
else super.accept(visitor);
}
@@ -18,8 +18,12 @@ public class CommandLineOptionImpl extends CommandLineElement implements Command
super(node);
}
public void accept(@NotNull CommandLineVisitor visitor) {
visitor.visitOption(this);
}
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof CommandLineVisitor) ((CommandLineVisitor)visitor).visitOption(this);
if (visitor instanceof CommandLineVisitor) accept((CommandLineVisitor)visitor);
else super.accept(visitor);
}
+9 -94
View File
@@ -1,3 +1,6 @@
# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
"""Code coverage measurement for Python.
Ned Batchelder
@@ -5,73 +8,16 @@ http://nedbatchelder.com/code/coverage
"""
from coverage.version import __version__, __url__
from coverage.version import __version__, __url__, version_info
from coverage.control import coverage, process_startup
from coverage.control import Coverage, process_startup
from coverage.data import CoverageData
from coverage.cmdline import main, CoverageScript
from coverage.misc import CoverageException
from coverage.plugin import CoveragePlugin, FileTracer, FileReporter
from coverage.pytracer import PyTracer
# Module-level functions. The original API to this module was based on
# functions defined directly in the module, with a singleton of the coverage()
# class. That design hampered programmability, so the current api uses
# explicitly-created coverage objects. But for backward compatibility, here we
# define the top-level functions to create the singleton when they are first
# called.
# Singleton object for use with module-level functions. The singleton is
# created as needed when one of the module-level functions is called.
_the_coverage = None
def _singleton_method(name):
"""Return a function to the `name` method on a singleton `coverage` object.
The singleton object is created the first time one of these functions is
called.
"""
# Disable pylint msg W0612, because a bunch of variables look unused, but
# they're accessed via locals().
# pylint: disable=W0612
def wrapper(*args, **kwargs):
"""Singleton wrapper around a coverage method."""
global _the_coverage
if not _the_coverage:
_the_coverage = coverage(auto_data=True)
return getattr(_the_coverage, name)(*args, **kwargs)
import inspect
meth = getattr(coverage, name)
args, varargs, kw, defaults = inspect.getargspec(meth)
argspec = inspect.formatargspec(args[1:], varargs, kw, defaults)
docstring = meth.__doc__
wrapper.__doc__ = ("""\
A first-use-singleton wrapper around coverage.%(name)s.
This wrapper is provided for backward compatibility with legacy code.
New code should use coverage.%(name)s directly.
%(name)s%(argspec)s:
%(docstring)s
""" % locals()
)
return wrapper
# Define the module-level functions.
use_cache = _singleton_method('use_cache')
start = _singleton_method('start')
stop = _singleton_method('stop')
erase = _singleton_method('erase')
exclude = _singleton_method('exclude')
analysis = _singleton_method('analysis')
analysis2 = _singleton_method('analysis2')
report = _singleton_method('report')
annotate = _singleton_method('annotate')
# Backward compatibility.
coverage = Coverage
# On Windows, we encode and decode deep enough that something goes wrong and
# the encodings.utf_8 module is loaded and then unloaded, I don't know why.
@@ -87,34 +33,3 @@ try:
del sys.modules['coverage.coverage']
except KeyError:
pass
# COPYRIGHT AND LICENSE
#
# Copyright 2001 Gareth Rees. All rights reserved.
# Copyright 2004-2013 Ned Batchelder. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
@@ -1,4 +1,8 @@
# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
"""Coverage.py's main entry point."""
import sys
from coverage.cmdline import main
sys.exit(main())
+53 -52
View File
@@ -1,10 +1,19 @@
"""Source file annotation for Coverage."""
# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
import os, re
"""Source file annotation for coverage.py."""
from coverage.backward import sorted # pylint: disable=W0622
import io
import os
import re
from coverage.files import flat_rootname
from coverage.misc import isolate_module
from coverage.report import Reporter
os = isolate_module(os)
class AnnotateReporter(Reporter):
"""Generate annotated source files showing line coverage.
@@ -42,61 +51,53 @@ class AnnotateReporter(Reporter):
"""
self.report_files(self.annotate_file, morfs, directory)
def annotate_file(self, cu, analysis):
def annotate_file(self, fr, analysis):
"""Annotate a single file.
`cu` is the CodeUnit for the file to annotate.
`fr` is the FileReporter for the file to annotate.
"""
if not cu.relative:
return
filename = cu.filename
source = cu.source_file()
if self.directory:
dest_file = os.path.join(self.directory, cu.flat_rootname())
dest_file += ".py,cover"
else:
dest_file = filename + ",cover"
dest = open(dest_file, 'w')
statements = sorted(analysis.statements)
missing = sorted(analysis.missing)
excluded = sorted(analysis.excluded)
lineno = 0
i = 0
j = 0
covered = True
while True:
line = source.readline()
if line == '':
break
lineno += 1
while i < len(statements) and statements[i] < lineno:
i += 1
while j < len(missing) and missing[j] < lineno:
j += 1
if i < len(statements) and statements[i] == lineno:
covered = j >= len(missing) or missing[j] > lineno
if self.blank_re.match(line):
dest.write(' ')
elif self.else_re.match(line):
# Special logic for lines containing only 'else:'.
if i >= len(statements) and j >= len(missing):
dest.write('! ')
elif i >= len(statements) or j >= len(missing):
dest.write('> ')
elif statements[i] == missing[j]:
dest.write('! ')
if self.directory:
dest_file = os.path.join(self.directory, flat_rootname(fr.relative_filename()))
if dest_file.endswith("_py"):
dest_file = dest_file[:-3] + ".py"
dest_file += ",cover"
else:
dest_file = fr.filename + ",cover"
with io.open(dest_file, 'w', encoding='utf8') as dest:
i = 0
j = 0
covered = True
source = fr.source()
for lineno, line in enumerate(source.splitlines(True), start=1):
while i < len(statements) and statements[i] < lineno:
i += 1
while j < len(missing) and missing[j] < lineno:
j += 1
if i < len(statements) and statements[i] == lineno:
covered = j >= len(missing) or missing[j] > lineno
if self.blank_re.match(line):
dest.write(u' ')
elif self.else_re.match(line):
# Special logic for lines containing only 'else:'.
if i >= len(statements) and j >= len(missing):
dest.write(u'! ')
elif i >= len(statements) or j >= len(missing):
dest.write(u'> ')
elif statements[i] == missing[j]:
dest.write(u'! ')
else:
dest.write(u'> ')
elif lineno in excluded:
dest.write(u'- ')
elif covered:
dest.write(u'> ')
else:
dest.write('> ')
elif lineno in excluded:
dest.write('- ')
elif covered:
dest.write('> ')
else:
dest.write('! ')
dest.write(line)
source.close()
dest.close()
dest.write(u'! ')
dest.write(line)
@@ -0,0 +1,42 @@
# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
"""Implementations of unittest features from the future."""
# Use unittest2 if it's available, otherwise unittest. This gives us
# back-ported features for 2.6.
try:
import unittest2 as unittest
except ImportError:
import unittest
def unittest_has(method):
"""Does `unittest.TestCase` have `method` defined?"""
return hasattr(unittest.TestCase, method)
class TestCase(unittest.TestCase):
"""Just like unittest.TestCase, but with assert methods added.
Designed to be compatible with 3.1 unittest. Methods are only defined if
`unittest` doesn't have them.
"""
# pylint: disable=missing-docstring
# Many Pythons have this method defined. But PyPy3 has a bug with it
# somehow (https://bitbucket.org/pypy/pypy/issues/2092), so always use our
# own implementation that works everywhere, at least for the ways we're
# calling it.
def assertCountEqual(self, s1, s2):
"""Assert these have the same elements, regardless of order."""
self.assertEqual(sorted(s1), sorted(s2))
if not unittest_has('assertRaisesRegex'):
def assertRaisesRegex(self, *args, **kwargs):
return self.assertRaisesRegexp(*args, **kwargs)
if not unittest_has('assertRegex'):
def assertRegex(self, *args, **kwargs):
return self.assertRegexpMatches(*args, **kwargs)
+102 -114
View File
@@ -1,60 +1,29 @@
# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
"""Add things to old Pythons so I can pretend they are newer."""
# This file does lots of tricky stuff, so disable a bunch of lintisms.
# pylint: disable=F0401,W0611,W0622
# F0401: Unable to import blah
# W0611: Unused import blah
# W0622: Redefining built-in blah
# This file does lots of tricky stuff, so disable a bunch of pylint warnings.
# pylint: disable=redefined-builtin
# pylint: disable=unused-import
# pxlint: disable=no-name-in-module
import os, re, sys
import sys
# Python 2.3 doesn't have `set`
try:
set = set # new in 2.4
except NameError:
from sets import Set as set
from coverage import env
# Python 2.3 doesn't have `sorted`.
try:
sorted = sorted
except NameError:
def sorted(iterable):
"""A 2.3-compatible implementation of `sorted`."""
lst = list(iterable)
lst.sort()
return lst
# Python 2.3 doesn't have `reversed`.
try:
reversed = reversed
except NameError:
def reversed(iterable):
"""A 2.3-compatible implementation of `reversed`."""
lst = list(iterable)
return lst[::-1]
# rpartition is new in 2.5
try:
"".rpartition
except AttributeError:
def rpartition(s, sep):
"""Implement s.rpartition(sep) for old Pythons."""
i = s.rfind(sep)
if i == -1:
return ('', '', s)
else:
return (s[:i], sep, s[i+len(sep):])
else:
def rpartition(s, sep):
"""A common interface for new Pythons."""
return s.rpartition(sep)
# Pythons 2 and 3 differ on where to get StringIO
# Pythons 2 and 3 differ on where to get StringIO.
try:
from cStringIO import StringIO
BytesIO = StringIO
except ImportError:
from io import StringIO, BytesIO
from io import StringIO
# In py3, ConfigParser was renamed to the more-standard configparser
try:
import configparser
except ImportError:
import ConfigParser as configparser
# What's a string called?
try:
@@ -62,6 +31,12 @@ try:
except NameError:
string_class = str
# What's a Unicode string called?
try:
unicode_class = unicode
except NameError:
unicode_class = str
# Where do pickles come from?
try:
import cPickle as pickle
@@ -72,7 +47,16 @@ except ImportError:
try:
range = xrange
except NameError:
range = range
range = range # pylint: disable=redefined-variable-type
# shlex.quote is new, but there's an undocumented implementation in "pipes",
# who knew!?
try:
from shlex import quote as shlex_quote
except ImportError:
# Useful function, available under a different (undocumented) name
# in Python versions earlier than 3.3.
from pipes import quote as shlex_quote
# A function to iterate listlessly over a dict's items.
try:
@@ -86,71 +70,32 @@ else:
"""Produce the items from dict `d`."""
return d.iteritems()
# Exec is a statement in Py2, a function in Py3
if sys.version_info >= (3, 0):
def exec_code_object(code, global_map):
"""A wrapper around exec()."""
exec(code, global_map)
# Getting the `next` function from an iterator is different in 2 and 3.
try:
iter([]).next
except AttributeError:
def iternext(seq):
"""Get the `next` function for iterating over `seq`."""
return iter(seq).__next__
else:
# OK, this is pretty gross. In Py2, exec was a statement, but that will
# be a syntax error if we try to put it in a Py3 file, even if it is never
# executed. So hide it inside an evaluated string literal instead.
eval(
compile(
"def exec_code_object(code, global_map):\n"
" exec code in global_map\n",
"<exec_function>", "exec"
)
)
# Reading Python source and interpreting the coding comment is a big deal.
if sys.version_info >= (3, 0):
# Python 3.2 provides `tokenize.open`, the best way to open source files.
import tokenize
try:
open_source = tokenize.open # pylint: disable=E1101
except AttributeError:
from io import TextIOWrapper
detect_encoding = tokenize.detect_encoding # pylint: disable=E1101
# Copied from the 3.2 stdlib:
def open_source(fname):
"""Open a file in read only mode using the encoding detected by
detect_encoding().
"""
buffer = open(fname, 'rb')
encoding, _ = detect_encoding(buffer.readline)
buffer.seek(0)
text = TextIOWrapper(buffer, encoding, line_buffering=True)
text.mode = 'r'
return text
else:
def open_source(fname):
"""Open a source file the best way."""
return open(fname, "rU")
def iternext(seq):
"""Get the `next` function for iterating over `seq`."""
return iter(seq).next
# Python 3.x is picky about bytes and strings, so provide methods to
# get them right, and make them no-ops in 2.x
if sys.version_info >= (3, 0):
if env.PY3:
def to_bytes(s):
"""Convert string `s` to bytes."""
return s.encode('utf8')
def to_string(b):
"""Convert bytes `b` to a string."""
return b.decode('utf8')
def binary_bytes(byte_values):
"""Produce a byte string with the ints from `byte_values`."""
return bytes(byte_values)
def byte_to_int(byte_value):
"""Turn an element of a bytes object into an int."""
return byte_value
def bytes_to_ints(bytes_value):
"""Turn a bytes object into a sequence of ints."""
# In Py3, iterating bytes gives ints.
# In Python 3, iterating bytes gives ints.
return bytes_value
else:
@@ -158,27 +103,70 @@ else:
"""Convert string `s` to bytes (no-op in 2.x)."""
return s
def to_string(b):
"""Convert bytes `b` to a string (no-op in 2.x)."""
return b
def binary_bytes(byte_values):
"""Produce a byte string with the ints from `byte_values`."""
return "".join([chr(b) for b in byte_values])
def byte_to_int(byte_value):
"""Turn an element of a bytes object into an int."""
return ord(byte_value)
return "".join(chr(b) for b in byte_values)
def bytes_to_ints(bytes_value):
"""Turn a bytes object into a sequence of ints."""
for byte in bytes_value:
yield ord(byte)
# Md5 is available in different places.
try:
import hashlib
md5 = hashlib.md5
# In Python 2.x, the builtins were in __builtin__
BUILTINS = sys.modules['__builtin__']
except KeyError:
# In Python 3.x, they're in builtins
BUILTINS = sys.modules['builtins']
# imp was deprecated in Python 3.3
try:
import importlib
import importlib.util
imp = None
except ImportError:
import md5
md5 = md5.new
importlib = None
# We only want to use importlib if it has everything we need.
try:
importlib_util_find_spec = importlib.util.find_spec
except Exception:
import imp
importlib_util_find_spec = None
# What is the .pyc magic number for this version of Python?
try:
PYC_MAGIC_NUMBER = importlib.util.MAGIC_NUMBER
except AttributeError:
PYC_MAGIC_NUMBER = imp.get_magic()
def import_local_file(modname, modfile=None):
"""Import a local file as a module.
Opens a file in the current directory named `modname`.py, imports it
as `modname`, and returns the module object. `modfile` is the file to
import if it isn't in the current directory.
"""
try:
from importlib.machinery import SourceFileLoader
except ImportError:
SourceFileLoader = None
if modfile is None:
modfile = modname + '.py'
if SourceFileLoader:
mod = SourceFileLoader(modname, modfile).load_module()
else:
for suff in imp.get_suffixes(): # pragma: part covered
if suff[0] == '.py':
break
with open(modfile, 'r') as f:
# pylint: disable=undefined-loop-variable
mod = imp.load_module(modname, f, modfile, suff)
return mod

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