mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
+2
-12
@@ -101,18 +101,8 @@ public class JavaGenericsUtil {
|
||||
final PsiExpression[] args = argumentList.getExpressions();
|
||||
if (args.length == parametersCount) {
|
||||
final PsiExpression lastArg = args[args.length - 1];
|
||||
if (lastArg instanceof PsiReferenceExpression) {
|
||||
final PsiElement lastArgsResolve = ((PsiReferenceExpression)lastArg).resolve();
|
||||
if (lastArgsResolve instanceof PsiParameter) {
|
||||
if (((PsiParameter)lastArgsResolve).getType() instanceof PsiArrayType) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (lastArg instanceof PsiMethodCallExpression) {
|
||||
if (lastArg.getType() instanceof PsiArrayType) {
|
||||
return false;
|
||||
}
|
||||
if (lastArg.getType() instanceof PsiArrayType) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int i = parametersCount - 1; i < args.length; i++) {
|
||||
|
||||
+5
-10
@@ -37,7 +37,10 @@ import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.intellij.util.ObjectUtils.assertNotNull;
|
||||
|
||||
@@ -140,15 +143,7 @@ public class ChangeSignatureProcessor extends ChangeSignatureProcessorBase {
|
||||
if (!processor.setupDefaultValues(myChangeInfo, refUsages, myProject)) return false;
|
||||
}
|
||||
MultiMap<PsiElement, String> conflictDescriptions = new MultiMap<PsiElement, String>();
|
||||
for (ChangeSignatureUsageProcessor usageProcessor : ChangeSignatureUsageProcessor.EP_NAME.getExtensions()) {
|
||||
final MultiMap<PsiElement, String> conflicts = usageProcessor.findConflicts(myChangeInfo, refUsages);
|
||||
for (PsiElement key : conflicts.keySet()) {
|
||||
Collection<String> collection = conflictDescriptions.get(key);
|
||||
if (collection.size() == 0) collection = new HashSet<String>();
|
||||
collection.addAll(conflicts.get(key));
|
||||
conflictDescriptions.put(key, collection);
|
||||
}
|
||||
}
|
||||
collectConflictsFromExtensions(refUsages, conflictDescriptions, myChangeInfo);
|
||||
|
||||
final UsageInfo[] usagesIn = refUsages.get();
|
||||
RenameUtil.addConflictDescriptions(usagesIn, conflictDescriptions);
|
||||
|
||||
+53
-12
@@ -38,6 +38,8 @@ import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.refactoring.MoveDestination;
|
||||
import com.intellij.refactoring.RefactorJBundle;
|
||||
import com.intellij.refactoring.changeSignature.ChangeInfo;
|
||||
import com.intellij.refactoring.changeSignature.ChangeSignatureProcessorBase;
|
||||
import com.intellij.refactoring.introduceparameterobject.usageInfo.*;
|
||||
import com.intellij.refactoring.util.FixableUsageInfo;
|
||||
import com.intellij.refactoring.util.FixableUsagesRefactoringProcessor;
|
||||
@@ -77,6 +79,7 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
private final Set<PsiParameter> paramsNeedingGetters = new HashSet<PsiParameter>();
|
||||
private final PsiClass existingClass;
|
||||
private PsiMethod myExistingClassCompatibleConstructor;
|
||||
private ChangeInfo myChangeInfo;
|
||||
|
||||
public IntroduceParameterObjectProcessor(String className,
|
||||
String packageName,
|
||||
@@ -164,6 +167,7 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
}
|
||||
}
|
||||
}
|
||||
List<UsageInfo> changeSignatureUsages = new ArrayList<>();
|
||||
for (UsageInfo usageInfo : refUsages.get()) {
|
||||
if (usageInfo instanceof FixableUsageInfo) {
|
||||
final String conflictMessage = ((FixableUsageInfo)usageInfo).getConflictMessage();
|
||||
@@ -171,7 +175,13 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
conflicts.putValue(usageInfo.getElement(), conflictMessage);
|
||||
}
|
||||
}
|
||||
else {
|
||||
changeSignatureUsages.add(usageInfo);
|
||||
}
|
||||
}
|
||||
|
||||
ChangeSignatureProcessorBase.collectConflictsFromExtensions(new Ref<>(changeSignatureUsages.toArray(new UsageInfo[changeSignatureUsages.size()])), conflicts, myChangeInfo);
|
||||
|
||||
return showConflicts(conflicts, refUsages.get());
|
||||
}
|
||||
|
||||
@@ -179,7 +189,24 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
if (myUseExistingClass && existingClass != null) {
|
||||
myExistingClassCompatibleConstructor = existingClassIsCompatible(existingClass, parameters);
|
||||
}
|
||||
findUsagesForMethod(method, usages, true);
|
||||
|
||||
final PsiCodeBlock body = method.getBody();
|
||||
final String baseParameterName = StringUtil.decapitalize(className);
|
||||
|
||||
final String fixedParamName =
|
||||
body != null
|
||||
? JavaCodeStyleManager.getInstance(myProject).suggestUniqueVariableName(baseParameterName, body.getLBrace(), true)
|
||||
: JavaCodeStyleManager.getInstance(myProject).propertyNameToVariableName(baseParameterName, VariableKind.PARAMETER);
|
||||
|
||||
myChangeInfo =
|
||||
new MergeMethodArguments(method, className, packageName, fixedParamName, paramsToMerge, typeParams, keepMethodAsDelegate,
|
||||
myCreateInnerClass ? method.getContainingClass() : null).createChangeInfo();
|
||||
|
||||
for (UsageInfo info : ChangeSignatureProcessorBase.findUsages(myChangeInfo)) {
|
||||
usages.add(new ChangeSignatureUsageWrapper(info));
|
||||
}
|
||||
|
||||
findUsagesForMethod(method, usages, fixedParamName);
|
||||
|
||||
if (myUseExistingClass && existingClass != null && !(paramsNeedingGetters.isEmpty() && paramsNeedingSetters.isEmpty())) {
|
||||
usages.add(new AppendAccessorsUsageInfo(existingClass, myGenerateAccessors, paramsNeedingGetters, paramsNeedingSetters, parameters));
|
||||
@@ -187,7 +214,7 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
|
||||
final PsiMethod[] overridingMethods = OverridingMethodsSearch.search(method, true).toArray(PsiMethod.EMPTY_ARRAY);
|
||||
for (PsiMethod siblingMethod : overridingMethods) {
|
||||
findUsagesForMethod(siblingMethod, usages, false);
|
||||
findUsagesForMethod(siblingMethod, usages, fixedParamName);
|
||||
}
|
||||
|
||||
if (myNewVisibility != null) {
|
||||
@@ -195,16 +222,7 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
}
|
||||
}
|
||||
|
||||
private void findUsagesForMethod(PsiMethod overridingMethod, List<FixableUsageInfo> usages, boolean changeSignature) {
|
||||
final PsiCodeBlock body = overridingMethod.getBody();
|
||||
final String baseParameterName = StringUtil.decapitalize(className);
|
||||
final String fixedParamName =
|
||||
body != null
|
||||
? JavaCodeStyleManager.getInstance(myProject).suggestUniqueVariableName(baseParameterName, body.getLBrace(), true)
|
||||
: JavaCodeStyleManager.getInstance(myProject).propertyNameToVariableName(baseParameterName, VariableKind.PARAMETER);
|
||||
|
||||
usages.add(new MergeMethodArguments(overridingMethod, className, packageName, fixedParamName, paramsToMerge, typeParams, keepMethodAsDelegate, myCreateInnerClass ? method.getContainingClass() : null, changeSignature));
|
||||
|
||||
private void findUsagesForMethod(PsiMethod overridingMethod, List<FixableUsageInfo> usages, String fixedParamName) {
|
||||
final ParamUsageVisitor visitor = new ParamUsageVisitor(overridingMethod, paramsToMerge);
|
||||
overridingMethod.accept(visitor);
|
||||
final Set<PsiReferenceExpression> values = visitor.getParameterUsages();
|
||||
@@ -261,6 +279,13 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
}
|
||||
}
|
||||
}
|
||||
List<UsageInfo> changeSignatureUsages = new ArrayList<>();
|
||||
for (UsageInfo info : usageInfos) {
|
||||
if (info instanceof ChangeSignatureUsageWrapper) {
|
||||
changeSignatureUsages.add(((ChangeSignatureUsageWrapper)info).getInfo());
|
||||
}
|
||||
}
|
||||
ChangeSignatureProcessorBase.doChangeSignature(myChangeInfo, changeSignatureUsages.toArray(new UsageInfo[changeSignatureUsages.size()]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -537,4 +562,20 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class ChangeSignatureUsageWrapper extends FixableUsageInfo {
|
||||
private final UsageInfo myInfo;
|
||||
|
||||
public ChangeSignatureUsageWrapper(UsageInfo info) {
|
||||
super(info.getElement());
|
||||
myInfo = info;
|
||||
}
|
||||
|
||||
public UsageInfo getInfo() {
|
||||
return myInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fixUsage() throws IncorrectOperationException {}
|
||||
}
|
||||
}
|
||||
|
||||
+43
-68
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,32 +13,29 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.refactoring.introduceparameterobject.usageInfo;
|
||||
package com.intellij.refactoring.introduceparameterobject;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.impl.source.PsiImmediateClassType;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor;
|
||||
import com.intellij.refactoring.changeSignature.ChangeInfo;
|
||||
import com.intellij.refactoring.changeSignature.JavaChangeInfoImpl;
|
||||
import com.intellij.refactoring.changeSignature.ParameterInfoImpl;
|
||||
import com.intellij.refactoring.util.FixableUsageInfo;
|
||||
import com.intellij.refactoring.util.CanonicalTypes;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.VisibilityUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@SuppressWarnings({"MethodWithTooManyParameters"})
|
||||
public class MergeMethodArguments extends FixableUsageInfo {
|
||||
public class MergeMethodArguments {
|
||||
private final PsiMethod method;
|
||||
private final PsiClass myContainingClass;
|
||||
private final boolean myChangeSignature;
|
||||
private final boolean myKeepMethodAsDelegate;
|
||||
private final List<PsiTypeParameter> typeParams;
|
||||
private final String className;
|
||||
@@ -53,50 +50,45 @@ public class MergeMethodArguments extends FixableUsageInfo {
|
||||
String parameterName,
|
||||
int[] paramsToMerge,
|
||||
List<PsiTypeParameter> typeParams,
|
||||
final boolean keepMethodAsDelegate, final PsiClass containingClass, boolean changeSignature) {
|
||||
super(method);
|
||||
final boolean keepMethodAsDelegate,
|
||||
final PsiClass containingClass) {
|
||||
this.paramsToMerge = paramsToMerge;
|
||||
this.packageName = packageName;
|
||||
this.className = className;
|
||||
this.parameterName = parameterName;
|
||||
this.method = method;
|
||||
myContainingClass = containingClass;
|
||||
myChangeSignature = changeSignature;
|
||||
lastParamIsVararg = method.isVarArgs() && isParameterToMerge(method.getParameterList().getParametersCount() - 1);
|
||||
myKeepMethodAsDelegate = keepMethodAsDelegate;
|
||||
this.typeParams = new ArrayList<PsiTypeParameter>(typeParams);
|
||||
}
|
||||
|
||||
public void fixUsage() throws IncorrectOperationException {
|
||||
public ChangeInfo createChangeInfo() {
|
||||
final Project project = method.getProject();
|
||||
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
|
||||
final PsiMethod deepestSuperMethod = method.findDeepestSuperMethod();
|
||||
final PsiClass psiClass;
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
||||
String packageName;
|
||||
if (myContainingClass != null) {
|
||||
psiClass = myContainingClass.findInnerClassByName(className, false);
|
||||
}
|
||||
else {
|
||||
psiClass = psiFacade.findClass(StringUtil.getQualifiedName(packageName, className), GlobalSearchScope.allScope(project));
|
||||
}
|
||||
assert psiClass != null;
|
||||
PsiSubstitutor subst = PsiSubstitutor.EMPTY;
|
||||
if (deepestSuperMethod != null) {
|
||||
final PsiClass parentClass = deepestSuperMethod.getContainingClass();
|
||||
final PsiSubstitutor parentSubstitutor =
|
||||
TypeConversionUtil.getSuperClassSubstitutor(parentClass, method.getContainingClass(), PsiSubstitutor.EMPTY);
|
||||
for (int i1 = 0; i1 < psiClass.getTypeParameters().length; i1++) {
|
||||
final PsiTypeParameter typeParameter = psiClass.getTypeParameters()[i1];
|
||||
for (PsiTypeParameter parameter : parentClass.getTypeParameters()) {
|
||||
if (Comparing.strEqual(typeParameter.getName(), parameter.getName())) {
|
||||
subst = subst.put(typeParameter, parentSubstitutor.substitute(
|
||||
new PsiImmediateClassType(parameter, PsiSubstitutor.EMPTY)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
packageName = myContainingClass.getQualifiedName();
|
||||
if (packageName == null) {
|
||||
packageName = myContainingClass.getName();
|
||||
}
|
||||
}
|
||||
else {
|
||||
packageName = this.packageName;
|
||||
}
|
||||
|
||||
String text = StringUtil.getQualifiedName(packageName, className);
|
||||
if (!typeParams.isEmpty()) {
|
||||
text += "<" + StringUtil.join(typeParams, new Function<PsiTypeParameter, String>() {
|
||||
@Override
|
||||
public String fun(PsiTypeParameter parameter) {
|
||||
return parameter.getName();
|
||||
}
|
||||
}, ", ") + ">";
|
||||
}
|
||||
final PsiType classType = factory.createTypeFromText(text, method);
|
||||
final List<ParameterInfoImpl> parametersInfo = new ArrayList<ParameterInfoImpl>();
|
||||
final PsiClassType classType = JavaPsiFacade.getElementFactory(project).createType(psiClass, subst);
|
||||
|
||||
final ParameterInfoImpl mergedParamInfo = new ParameterInfoImpl(-1, parameterName, classType, null) {
|
||||
@Override
|
||||
@@ -117,33 +109,16 @@ public class MergeMethodArguments extends FixableUsageInfo {
|
||||
}
|
||||
|
||||
parametersInfo.add(firstIncludedIdx == -1 ? 0 : firstIncludedIdx, mergedParamInfo);
|
||||
final SmartPsiElementPointer<PsiMethod> meth = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(method);
|
||||
|
||||
final Runnable performChangeSignatureRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final PsiMethod psiMethod = meth.getElement();
|
||||
if (psiMethod == null) return;
|
||||
if (myChangeSignature) {
|
||||
final ChangeSignatureProcessor changeSignatureProcessor =
|
||||
new ChangeSignatureProcessor(psiMethod.getProject(), psiMethod,
|
||||
myKeepMethodAsDelegate, null, psiMethod.getName(),
|
||||
psiMethod.getReturnType(),
|
||||
parametersInfo.toArray(new ParameterInfoImpl[parametersInfo.size()]));
|
||||
changeSignatureProcessor.run();
|
||||
}
|
||||
}
|
||||
};
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
performChangeSignatureRunnable.run();
|
||||
} else {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
CommandProcessor.getInstance().runUndoTransparentAction(performChangeSignatureRunnable);
|
||||
}
|
||||
});
|
||||
}
|
||||
PsiType returnType = method.getReturnType();
|
||||
return new JavaChangeInfoImpl(VisibilityUtil.getVisibilityModifier(method.getModifierList()),
|
||||
method,
|
||||
method.getName(),
|
||||
returnType != null ? CanonicalTypes.createTypeWrapper(returnType) : null,
|
||||
parametersInfo.toArray(new ParameterInfoImpl[parametersInfo.size()]),
|
||||
null,
|
||||
myKeepMethodAsDelegate,
|
||||
Collections.emptySet(),
|
||||
Collections.emptySet());
|
||||
}
|
||||
|
||||
private boolean isParameterToMerge(int index) {
|
||||
@@ -307,7 +307,10 @@ public class GenericsUtil {
|
||||
PsiType componentType = arrayType.getComponentType();
|
||||
PsiType type = componentType.accept(this);
|
||||
if (type == componentType) return arrayType;
|
||||
return type.createArrayType();
|
||||
if (type instanceof PsiWildcardType) {
|
||||
type = ((PsiWildcardType)type).getBound();
|
||||
}
|
||||
return type != null ? type.createArrayType() : arrayType;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -764,6 +764,9 @@ public final class PsiUtil extends PsiUtilCore {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies capture conversion to the type in context
|
||||
*/
|
||||
@NotNull
|
||||
public static PsiType captureToplevelWildcards(@NotNull final PsiType type, @NotNull final PsiElement context) {
|
||||
if (type instanceof PsiClassType) {
|
||||
@@ -811,6 +814,38 @@ public final class PsiUtil extends PsiUtilCore {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens top level captured wildcards and remap them according to the context.
|
||||
* The only valid purpose: allow to speculate on non-physical expressions about types, e.g. to detect redundant casts with 'wildcards'
|
||||
*/
|
||||
public static PsiType recaptureWildcards(PsiType type, PsiElement context) {
|
||||
if (type instanceof PsiClassType) {
|
||||
final PsiClassType.ClassResolveResult resolveResult = ((PsiClassType)type).resolveGenerics();
|
||||
final PsiClass aClass = resolveResult.getElement();
|
||||
if (aClass != null) {
|
||||
final PsiSubstitutor substitutor = resolveResult.getSubstitutor();
|
||||
|
||||
PsiSubstitutor resultSubstitution = null;
|
||||
for (PsiTypeParameter parameter : substitutor.getSubstitutionMap().keySet()) {
|
||||
final PsiType substitute = substitutor.substitute(parameter);
|
||||
if (substitute instanceof PsiCapturedWildcardType) {
|
||||
if (resultSubstitution == null) resultSubstitution = substitutor;
|
||||
resultSubstitution = resultSubstitution.put(parameter, ((PsiCapturedWildcardType)substitute).getWildcard());
|
||||
}
|
||||
}
|
||||
|
||||
if (resultSubstitution != null) {
|
||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(context.getProject());
|
||||
return captureToplevelWildcards(factory.createType(aClass, resultSubstitution), context);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type instanceof PsiArrayType) {
|
||||
return recaptureWildcards(((PsiArrayType)type).getComponentType(), context).createArrayType();
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
public static boolean isInsideJavadocComment(PsiElement element) {
|
||||
return PsiTreeUtil.getParentOfType(element, PsiDocComment.class, true) != null;
|
||||
}
|
||||
|
||||
@@ -385,7 +385,7 @@ public class RedundantCastUtil {
|
||||
if (oldMethod.equals(newResult.getElement()) &&
|
||||
(!(newCall instanceof PsiCallExpression) ||
|
||||
oldAnonymousClass != null && newAnonymousClass != null && Comparing.equal(oldAnonymousClass.getBaseClassType(), newAnonymousClass.getBaseClassType()) ||
|
||||
Comparing.equal(((PsiCallExpression)newCall).getType(), ((PsiCallExpression)expression).getType())) &&
|
||||
Comparing.equal(PsiUtil.recaptureWildcards(((PsiCallExpression)newCall).getType(), expression), ((PsiCallExpression)expression).getType())) &&
|
||||
newResult.isValidResult()) {
|
||||
if (!(newArgs[i] instanceof PsiFunctionalExpression) || castType != null && castType.equals(((PsiFunctionalExpression)newArgs[i]).getFunctionalInterfaceType())) {
|
||||
addToResults(cast);
|
||||
|
||||
+8
@@ -29,6 +29,14 @@ class Test {
|
||||
public static void main(String[] args) {
|
||||
<warning descr="Unchecked generics array creation for varargs parameter">asList</warning>(new ArrayList<String>());
|
||||
|
||||
ArrayList<String>[] arrayOfStrings = null;
|
||||
asList(arrayOfStrings);
|
||||
asList((ArrayList<String>[])null);
|
||||
|
||||
//overload should be chosen before target type is known -> inference failure
|
||||
<error descr="Incompatible types. Found: 'java.util.List<java.util.ArrayList<java.lang.String>>', required: 'java.util.List<java.util.ArrayList<java.lang.String>[]>'">List<ArrayList<String>[]> arraysList = asList(arrayOfStrings);</error>
|
||||
System.out.println(arraysList);
|
||||
|
||||
asListSuppressed(new ArrayList<String>());
|
||||
|
||||
//noinspection unchecked
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
|
||||
import java.util.function.IntFunction;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class MyTest {
|
||||
private static void getArguments(final Stream<Class<String>> classStream) {
|
||||
final Class<?>[] classes = classStream.toArray(((<warning descr="Casting '(value) -> new Class<?>[value]' to 'IntFunction<Class<?>[]>' is redundant">IntFunction<Class<?>[]></warning>) (value) -> new Class<?>[value]) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import java.util.function.IntFunction;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class MyTest {
|
||||
private static void getArguments(final Stream<Class<String>> classStream) {
|
||||
IntFunction<Class<?>[]> m = (value) -> new Class<?>[value];
|
||||
final Class<?>[] classes = classStream.toArray(m);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class MyTest {
|
||||
private static void getArguments(final Stream<Class<String>> classStream) {
|
||||
final Class<?>[] classes = classStream.toArray(<selection>(value) -> new Class<?>[value]</selection>);
|
||||
}
|
||||
}
|
||||
+4
@@ -61,6 +61,10 @@ public class LambdaRedundantCastTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testCapturedWildcardInCast() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(BASE_PATH + "/" + getTestName(false) + ".java", true, false);
|
||||
}
|
||||
|
||||
@@ -512,6 +512,10 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase {
|
||||
doTest(new MockIntroduceVariableHandler("m", false, false, false, "I<? extends I<?>>"));
|
||||
}
|
||||
|
||||
public void testDenotableType3() {
|
||||
doTest(new MockIntroduceVariableHandler("m", false, false, false, "java.util.function.IntFunction<java.lang.Class<?>[]>"));
|
||||
}
|
||||
|
||||
public void testReturnNonExportedArray() {
|
||||
doTest(new MockIntroduceVariableHandler("i", false, false, false, "java.io.File[]") {
|
||||
@Override
|
||||
|
||||
@@ -161,11 +161,6 @@ public abstract class TransactionGuard {
|
||||
@NotNull
|
||||
public abstract AccessToken startSynchronousTransaction(@NotNull TransactionKind kind);
|
||||
|
||||
/**
|
||||
* @return whether there's a transaction currently running
|
||||
*/
|
||||
public abstract boolean isInsideTransaction();
|
||||
|
||||
/**
|
||||
* When on UI thread and there's no other transaction running, executes the given runnable. If there is a transaction running,
|
||||
* but the given {@code kind} is allowed via {@link #acceptNestedTransactions(TransactionKind...)}, merges two transactions
|
||||
@@ -190,4 +185,11 @@ public abstract class TransactionGuard {
|
||||
*/
|
||||
@NotNull
|
||||
public abstract AccessToken acceptNestedTransactions(TransactionKind... kinds);
|
||||
|
||||
/**
|
||||
* Asserts that a transaction is currently running, or not. Callable only on Swing thread.
|
||||
* @param transactionRequired whether the assertion should check that the application is inside transaction or not
|
||||
* @param errorMessage the message that will be logged if current transaction status differs from the expected one
|
||||
*/
|
||||
public abstract void assertInsideTransaction(boolean transactionRequired, @NotNull String errorMessage);
|
||||
}
|
||||
|
||||
@@ -18,16 +18,20 @@ package com.intellij.pom;
|
||||
import com.intellij.pom.event.PomModelEvent;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author ik
|
||||
*/
|
||||
public interface PomTransaction {
|
||||
@NotNull
|
||||
PomModelEvent getAccumulatedEvent();
|
||||
|
||||
void run() throws IncorrectOperationException;
|
||||
|
||||
@NotNull
|
||||
PsiElement getChangeScope();
|
||||
|
||||
@NotNull
|
||||
PomModelAspect getTransactionAspect();
|
||||
}
|
||||
|
||||
@@ -21,18 +21,20 @@ import com.intellij.pom.PomTransaction;
|
||||
import com.intellij.pom.event.PomModelEvent;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class PomTransactionBase implements PomTransaction{
|
||||
private final PsiElement myScope;
|
||||
private final PomModelAspect myAspect;
|
||||
private final PomModelEvent myAccumulatedEvent;
|
||||
public PomTransactionBase(PsiElement scope, final PomModelAspect aspect){
|
||||
public PomTransactionBase(@NotNull PsiElement scope, @NotNull final PomModelAspect aspect){
|
||||
myScope = scope;
|
||||
myAspect = aspect;
|
||||
myAccumulatedEvent = new PomModelEvent(PomManager.getModel(scope.getProject()));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PomModelEvent getAccumulatedEvent() {
|
||||
return myAccumulatedEvent;
|
||||
@@ -53,11 +55,13 @@ public abstract class PomTransactionBase implements PomTransaction{
|
||||
@Nullable
|
||||
public abstract PomModelEvent runInner() throws IncorrectOperationException;
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement getChangeScope() {
|
||||
return myScope;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PomModelAspect getTransactionAspect() {
|
||||
return myAspect;
|
||||
|
||||
@@ -36,24 +36,40 @@ public class TransactionGuardImpl extends TransactionGuard {
|
||||
private final Queue<Runnable> myQueue = new LinkedBlockingQueue<Runnable>();
|
||||
private final Set<TransactionKind> myMergeableKinds = ContainerUtil.newHashSet();
|
||||
private String myTransactionStartTrace;
|
||||
private ModalityState myTransactionModality;
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public AccessToken startSynchronousTransaction(@NotNull TransactionKind kind) throws IllegalStateException {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
if (myTransactionStartTrace != null) {
|
||||
if (!myMergeableKinds.contains(kind) && !ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
// please assign exceptions that occur here to Peter
|
||||
LOG.error("Nested transactions are not allowed, see FAQ in TransactionGuard class javadoc. Transaction start trace is in attachment. Kind is " + kind,
|
||||
new Attachment("trace.txt", myTransactionStartTrace));
|
||||
ModalityState modality = ModalityState.current();
|
||||
if (isInsideTransaction()) {
|
||||
if (myTransactionModality == modality) {
|
||||
return AccessToken.EMPTY_ACCESS_TOKEN;
|
||||
}
|
||||
|
||||
if (myMergeableKinds.contains(kind)) {
|
||||
final ModalityState prev = myTransactionModality;
|
||||
myTransactionModality = modality;
|
||||
return new AccessToken() {
|
||||
@Override
|
||||
public void finish() {
|
||||
myTransactionModality = prev;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// please assign exceptions that occur here to Peter
|
||||
LOG.error("Nested transactions are not allowed, see FAQ in TransactionGuard class javadoc. Transaction start trace is in attachment. Kind is " + kind,
|
||||
new Attachment("trace.txt", myTransactionStartTrace));
|
||||
return AccessToken.EMPTY_ACCESS_TOKEN;
|
||||
}
|
||||
myTransactionModality = modality;
|
||||
myTransactionStartTrace = DebugUtil.currentStackTrace();
|
||||
return new AccessToken() {
|
||||
@Override
|
||||
public void finish() {
|
||||
myTransactionStartTrace = null;
|
||||
myTransactionModality = null;
|
||||
if (!myQueue.isEmpty()) {
|
||||
pollQueueLater();
|
||||
}
|
||||
@@ -87,8 +103,7 @@ public class TransactionGuardImpl extends TransactionGuard {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInsideTransaction() {
|
||||
private boolean isInsideTransaction() {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
return myTransactionStartTrace != null;
|
||||
}
|
||||
@@ -144,11 +159,18 @@ public class TransactionGuardImpl extends TransactionGuard {
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assertInsideTransaction(boolean transactionRequired, @NotNull String errorMessage) {
|
||||
if (transactionRequired != isInsideTransaction()) {
|
||||
LOG.error(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void submitTransactionAndWait(@NotNull TransactionKind kind, @NotNull final Runnable transaction) throws ProcessCanceledException {
|
||||
Application app = ApplicationManager.getApplication();
|
||||
if (app.isDispatchThread()) {
|
||||
if (!canRunTransactionNow(kind)) {
|
||||
if (!canRunTransactionNow(kind) && myTransactionModality != ModalityState.current()) {
|
||||
throw new AssertionError("Cannot run submitTransactionAndWait from another transaction, kind " + kind + " is not allowed");
|
||||
}
|
||||
runSyncTransaction(kind, transaction);
|
||||
|
||||
@@ -279,7 +279,7 @@ public abstract class AnAction implements PossiblyDumbAware {
|
||||
|
||||
protected void setShortcutSet(ShortcutSet shortcutSet) {
|
||||
if (myIsGlobal && myShortcutSet != shortcutSet) {
|
||||
LOG.error("Shortcuts of global AnActions should not be changed outside of KeymapManager");
|
||||
LOG.warn("Shortcuts of global AnActions should not be changed outside of KeymapManager", new Throwable());
|
||||
}
|
||||
myShortcutSet = shortcutSet;
|
||||
}
|
||||
|
||||
@@ -94,9 +94,7 @@ public class EndHandler extends EditorActionHandler {
|
||||
// here just as a boolean value holder due to requirement to declare variable used from inner class as final.
|
||||
final AtomicBoolean stopProcessing = new AtomicBoolean(true);
|
||||
|
||||
TransactionGuard guard = TransactionGuard.getInstance();
|
||||
// sometimes this handler is invoked from other actions, then we're already inside a transaction
|
||||
try (AccessToken ignore = guard.isInsideTransaction() ? null : guard.startSynchronousTransaction(TransactionKind.TEXT_EDITING)) {
|
||||
try (AccessToken ignore = TransactionGuard.getInstance().startSynchronousTransaction(TransactionKind.TEXT_EDITING)) {
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments();
|
||||
ApplicationManager.getApplication().runWriteAction(() -> {
|
||||
CodeStyleManager styleManager = CodeStyleManager.getInstance(project);
|
||||
|
||||
@@ -20,8 +20,6 @@ import com.intellij.util.ui.update.MergingUpdateQueue;
|
||||
import com.intellij.util.ui.update.Update;
|
||||
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
import javax.swing.tree.TreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
@@ -34,7 +32,7 @@ public class InspectionTreeUpdater {
|
||||
|
||||
public InspectionTreeUpdater(InspectionResultsView view) {
|
||||
myView = view;
|
||||
myUpdateQueue = new MergingUpdateQueue("InspectionView", 100, true, view);
|
||||
myUpdateQueue = new MergingUpdateQueue("InspectionView", 100, true, view, view);
|
||||
}
|
||||
|
||||
public void updateWithPreviewPanel() {
|
||||
|
||||
+70
-48
@@ -22,6 +22,7 @@ import com.intellij.openapi.command.undo.UndoManager;
|
||||
import com.intellij.openapi.command.undo.UndoableAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.refactoring.BaseRefactoringProcessor;
|
||||
@@ -36,15 +37,13 @@ import com.intellij.refactoring.util.MoveRenameUsageInfo;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.intellij.util.containers.hash.HashMap;
|
||||
import com.intellij.util.containers.hash.HashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Maxim.Medvedev
|
||||
@@ -71,23 +70,41 @@ public abstract class ChangeSignatureProcessorBase extends BaseRefactoringProces
|
||||
@Override
|
||||
@NotNull
|
||||
protected UsageInfo[] findUsages() {
|
||||
List<UsageInfo> infos = new ArrayList<UsageInfo>();
|
||||
return findUsages(myChangeInfo);
|
||||
}
|
||||
|
||||
public static void collectConflictsFromExtensions(@NotNull Ref<UsageInfo[]> refUsages,
|
||||
MultiMap<PsiElement, String> conflictDescriptions,
|
||||
ChangeInfo changeInfo) {
|
||||
for (ChangeSignatureUsageProcessor usageProcessor : ChangeSignatureUsageProcessor.EP_NAME.getExtensions()) {
|
||||
final MultiMap<PsiElement, String> conflicts = usageProcessor.findConflicts(changeInfo, refUsages);
|
||||
for (PsiElement key : conflicts.keySet()) {
|
||||
Collection<String> collection = conflictDescriptions.get(key);
|
||||
if (collection.isEmpty()) collection = new com.intellij.util.containers.HashSet<String>();
|
||||
collection.addAll(conflicts.get(key));
|
||||
conflictDescriptions.put(key, collection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static UsageInfo[] findUsages(ChangeInfo changeInfo) {
|
||||
List<UsageInfo> infos = new ArrayList<UsageInfo>();
|
||||
final ChangeSignatureUsageProcessor[] processors = ChangeSignatureUsageProcessor.EP_NAME.getExtensions();
|
||||
for (ChangeSignatureUsageProcessor processor : processors) {
|
||||
ContainerUtil.addAll(infos, processor.findUsages(myChangeInfo));
|
||||
ContainerUtil.addAll(infos, processor.findUsages(changeInfo));
|
||||
}
|
||||
infos = filterUsages(infos);
|
||||
return infos.toArray(new UsageInfo[infos.size()]);
|
||||
}
|
||||
|
||||
protected List<UsageInfo> filterUsages(List<UsageInfo> infos) {
|
||||
protected static List<UsageInfo> filterUsages(List<UsageInfo> infos) {
|
||||
Map<PsiElement, MoveRenameUsageInfo> moveRenameInfos = new HashMap<PsiElement, MoveRenameUsageInfo>();
|
||||
Set<PsiElement> usedElements = new HashSet<PsiElement>();
|
||||
|
||||
List<UsageInfo> result = new ArrayList<UsageInfo>(infos.size() / 2);
|
||||
for (UsageInfo info : infos) {
|
||||
LOG.assertTrue(info != null, getClass());
|
||||
LOG.assertTrue(info != null);
|
||||
PsiElement element = info.getElement();
|
||||
if (info instanceof MoveRenameUsageInfo) {
|
||||
if (usedElements.contains(element)) continue;
|
||||
@@ -139,14 +156,15 @@ public abstract class ChangeSignatureProcessorBase extends BaseRefactoringProces
|
||||
@Override
|
||||
protected void performRefactoring(@NotNull UsageInfo[] usages) {
|
||||
RefactoringTransaction transaction = getTransaction();
|
||||
final RefactoringElementListener elementListener = transaction == null ? null : transaction.getElementListener(myChangeInfo.getMethod());
|
||||
final String fqn = CopyReferenceAction.elementToFqn(myChangeInfo.getMethod());
|
||||
final ChangeInfo changeInfo = myChangeInfo;
|
||||
final RefactoringElementListener elementListener = transaction == null ? null : transaction.getElementListener(changeInfo.getMethod());
|
||||
final String fqn = CopyReferenceAction.elementToFqn(changeInfo.getMethod());
|
||||
if (fqn != null) {
|
||||
UndoableAction action = new BasicUndoableAction() {
|
||||
@Override
|
||||
public void undo() {
|
||||
if (elementListener instanceof UndoRefactoringElementListener) {
|
||||
((UndoRefactoringElementListener)elementListener).undoElementMovedOrRenamed(myChangeInfo.getMethod(), fqn);
|
||||
((UndoRefactoringElementListener)elementListener).undoElementMovedOrRenamed(changeInfo.getMethod(), fqn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,44 +175,10 @@ public abstract class ChangeSignatureProcessorBase extends BaseRefactoringProces
|
||||
UndoManager.getInstance(myProject).undoableActionPerformed(action);
|
||||
}
|
||||
try {
|
||||
final ChangeSignatureUsageProcessor[] processors = ChangeSignatureUsageProcessor.EP_NAME.getExtensions();
|
||||
|
||||
final ResolveSnapshotProvider resolveSnapshotProvider = myChangeInfo.isParameterNamesChanged() ?
|
||||
VariableInplaceRenamer.INSTANCE.forLanguage(myChangeInfo.getMethod().getLanguage()) : null;
|
||||
final List<ResolveSnapshotProvider.ResolveSnapshot> snapshots = new ArrayList<ResolveSnapshotProvider.ResolveSnapshot>();
|
||||
for (ChangeSignatureUsageProcessor processor : processors) {
|
||||
if (resolveSnapshotProvider != null) {
|
||||
processor.registerConflictResolvers(snapshots, resolveSnapshotProvider, usages, myChangeInfo);
|
||||
}
|
||||
}
|
||||
|
||||
for (UsageInfo usage : usages) {
|
||||
for (ChangeSignatureUsageProcessor processor : processors) {
|
||||
if (processor.processUsage(myChangeInfo, usage, true, usages)) break;
|
||||
}
|
||||
}
|
||||
|
||||
LOG.assertTrue(myChangeInfo.getMethod().isValid());
|
||||
for (ChangeSignatureUsageProcessor processor : processors) {
|
||||
if (processor.processPrimaryMethod(myChangeInfo)) break;
|
||||
}
|
||||
|
||||
for (UsageInfo usage : usages) {
|
||||
for (ChangeSignatureUsageProcessor processor : processors) {
|
||||
if (processor.processUsage(myChangeInfo, usage, false, usages)) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!snapshots.isEmpty()) {
|
||||
for (ParameterInfo parameterInfo : myChangeInfo.getNewParameters()) {
|
||||
for (ResolveSnapshotProvider.ResolveSnapshot snapshot : snapshots) {
|
||||
snapshot.apply(parameterInfo.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
final PsiElement method = myChangeInfo.getMethod();
|
||||
doChangeSignature(changeInfo, usages);
|
||||
final PsiElement method = changeInfo.getMethod();
|
||||
LOG.assertTrue(method.isValid());
|
||||
if (elementListener != null && myChangeInfo.isNameChanged()) {
|
||||
if (elementListener != null && changeInfo.isNameChanged()) {
|
||||
elementListener.elementRenamed(method);
|
||||
}
|
||||
}
|
||||
@@ -203,6 +187,44 @@ public abstract class ChangeSignatureProcessorBase extends BaseRefactoringProces
|
||||
}
|
||||
}
|
||||
|
||||
public static void doChangeSignature(ChangeInfo changeInfo, @NotNull UsageInfo[] usages) {
|
||||
final ChangeSignatureUsageProcessor[] processors = ChangeSignatureUsageProcessor.EP_NAME.getExtensions();
|
||||
|
||||
final ResolveSnapshotProvider resolveSnapshotProvider = changeInfo.isParameterNamesChanged() ?
|
||||
VariableInplaceRenamer.INSTANCE.forLanguage(changeInfo.getMethod().getLanguage()) : null;
|
||||
final List<ResolveSnapshotProvider.ResolveSnapshot> snapshots = new ArrayList<ResolveSnapshotProvider.ResolveSnapshot>();
|
||||
for (ChangeSignatureUsageProcessor processor : processors) {
|
||||
if (resolveSnapshotProvider != null) {
|
||||
processor.registerConflictResolvers(snapshots, resolveSnapshotProvider, usages, changeInfo);
|
||||
}
|
||||
}
|
||||
|
||||
for (UsageInfo usage : usages) {
|
||||
for (ChangeSignatureUsageProcessor processor : processors) {
|
||||
if (processor.processUsage(changeInfo, usage, true, usages)) break;
|
||||
}
|
||||
}
|
||||
|
||||
LOG.assertTrue(changeInfo.getMethod().isValid());
|
||||
for (ChangeSignatureUsageProcessor processor : processors) {
|
||||
if (processor.processPrimaryMethod(changeInfo)) break;
|
||||
}
|
||||
|
||||
for (UsageInfo usage : usages) {
|
||||
for (ChangeSignatureUsageProcessor processor : processors) {
|
||||
if (processor.processUsage(changeInfo, usage, false, usages)) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!snapshots.isEmpty()) {
|
||||
for (ParameterInfo parameterInfo : changeInfo.getNewParameters()) {
|
||||
for (ResolveSnapshotProvider.ResolveSnapshot snapshot : snapshots) {
|
||||
snapshot.apply(parameterInfo.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCommandName() {
|
||||
return RefactoringBundle.message("changing.signature.of.0", DescriptiveNameUtil.getDescriptiveName(myChangeInfo.getMethod()));
|
||||
|
||||
@@ -1644,9 +1644,8 @@ public abstract class DialogWrapper {
|
||||
if (ApplicationManager.getApplication().isWriteAccessAllowed()) {
|
||||
LOG.error("Project-modal dialogs should not be shown under a write action.");
|
||||
}
|
||||
if (TransactionGuard.getInstance().isInsideTransaction()) {
|
||||
LOG.error("Project-modal dialogs should not be shown inside a transaction. See TransactionGuard documentation.");
|
||||
}
|
||||
TransactionGuard.getInstance().assertInsideTransaction(
|
||||
false, "Project-modal dialogs should not be shown inside a transaction. See TransactionGuard documentation.");
|
||||
}
|
||||
|
||||
final AsyncResult<Boolean> result = new AsyncResult<Boolean>();
|
||||
|
||||
@@ -17,8 +17,8 @@ package com.intellij.ui;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.CommonShortcuts;
|
||||
import com.intellij.openapi.actionSystem.EmptyAction;
|
||||
import com.intellij.openapi.actionSystem.IdeActions;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.ui.JBMenuItem;
|
||||
@@ -203,10 +203,7 @@ public class SearchTextField extends JPanel {
|
||||
if (ApplicationManager.getApplication() != null) { //tests
|
||||
final ActionManager actionManager = ActionManager.getInstance();
|
||||
if (actionManager != null) {
|
||||
final AnAction clearTextAction = actionManager.getAction(IdeActions.ACTION_CLEAR_TEXT);
|
||||
if (clearTextAction.getShortcutSet().getShortcuts().length == 0) {
|
||||
clearTextAction.registerCustomShortcutSet(CommonShortcuts.ESCAPE, this);
|
||||
}
|
||||
EmptyAction.registerWithShortcutSet(IdeActions.ACTION_CLEAR_TEXT, CommonShortcuts.ESCAPE, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.ui;
|
||||
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ui.EditableModel;
|
||||
import com.intellij.util.ui.ElementProducer;
|
||||
import com.intellij.util.ui.ListTableModel;
|
||||
@@ -27,6 +28,7 @@ import javax.swing.event.ListSelectionListener;
|
||||
import java.awt.*;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
@@ -149,46 +151,41 @@ class TableToolbarDecorator extends ToolbarDecorator {
|
||||
}
|
||||
};
|
||||
|
||||
myUpAction = new AnActionButtonRunnable() {
|
||||
class MoveRunnable implements AnActionButtonRunnable {
|
||||
final int delta;
|
||||
|
||||
MoveRunnable(int delta) {
|
||||
this.delta = delta;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(AnActionButton button) {
|
||||
final int row = table.getEditingRow();
|
||||
final int col = table.getEditingColumn();
|
||||
public void run(AnActionButton button) {
|
||||
int row = table.getEditingRow();
|
||||
int col = table.getEditingColumn();
|
||||
TableUtil.stopEditing(table);
|
||||
final int[] indexes = table.getSelectedRows();
|
||||
for (int index : indexes) {
|
||||
if (0 < index && index < table.getModel().getRowCount()) {
|
||||
tableModel.exchangeRows(index, index - 1);
|
||||
table.setRowSelectionInterval(index - 1, index - 1);
|
||||
}
|
||||
}
|
||||
int[] idx = table.getSelectedRows();
|
||||
Arrays.sort(idx);
|
||||
if (delta > 0) {
|
||||
idx = ArrayUtil.reverseArray(idx);
|
||||
}
|
||||
|
||||
if (idx.length == 0) return;
|
||||
if (idx[0] + delta < 0) return;
|
||||
if (idx[idx.length - 1] + delta > table.getModel().getRowCount()) return;
|
||||
|
||||
for (int i = 0; i < idx.length; i++) {
|
||||
tableModel.exchangeRows(idx[i], idx[i] + delta);
|
||||
idx[i] += delta;
|
||||
}
|
||||
TableUtil.selectRows(table, idx);
|
||||
table.requestFocus();
|
||||
if (row > 0 && col != -1) {
|
||||
table.editCellAt(row - 1, col);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
myDownAction = new AnActionButtonRunnable() {
|
||||
@Override
|
||||
public void run(AnActionButton button) {
|
||||
final int row = table.getEditingRow();
|
||||
final int col = table.getEditingColumn();
|
||||
|
||||
TableUtil.stopEditing(table);
|
||||
final int[] indexes = table.getSelectedRows();
|
||||
for (int index : indexes) {
|
||||
if (0 <= index && index < table.getModel().getRowCount() - 1) {
|
||||
tableModel.exchangeRows(index, index + 1);
|
||||
table.setRowSelectionInterval(index + 1, index + 1);
|
||||
}
|
||||
}
|
||||
table.requestFocus();
|
||||
if (row < table.getRowCount() - 1 && col != -1) {
|
||||
table.editCellAt(row + 1, col);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
myUpAction = new MoveRunnable(-1);
|
||||
myDownAction = new MoveRunnable(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-3
@@ -1229,9 +1229,9 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
private void startWrite(/*@NotNull*/ Class clazz) {
|
||||
assertIsDispatchThread(getStatus(), "Write access is allowed from event dispatch thread only");
|
||||
HeavyProcessLatch.INSTANCE.stopThreadPrioritizing(); // let non-cancellable read actions complete faster, if present
|
||||
if (!TransactionGuard.getInstance().isInsideTransaction() && Registry.is("ide.require.transaction.for.model.changes", false)) {
|
||||
// please assign exceptions that occur here to Peter
|
||||
LOG.error("Write access is allowed from model transactions only, see TransactionGuard documentation for details");
|
||||
if (Registry.is("ide.require.transaction.for.model.changes", false)) {
|
||||
TransactionGuard.getInstance().assertInsideTransaction(
|
||||
true, "Write access is allowed from model transactions only, see TransactionGuard documentation for details");
|
||||
}
|
||||
boolean writeActionPending = myWriteActionPending;
|
||||
if (gatherWriteActionStatistics && myWriteActionsStack.isEmpty() && !writeActionPending) {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -122,7 +122,7 @@ public class ChangeProjectIconForm {
|
||||
pathToIcon = files[0];
|
||||
}
|
||||
}
|
||||
catch (Exception e1) {
|
||||
catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ import javax.swing.table.TableColumn;
|
||||
import javax.swing.table.TableModel;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.EventObject;
|
||||
import java.util.List;
|
||||
|
||||
import static java.awt.event.KeyEvent.*;
|
||||
@@ -142,6 +143,14 @@ public abstract class JBListTable {
|
||||
myEditor = editor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(EventObject e) {
|
||||
if (e instanceof MouseEvent && UIUtil.isSelectionButtonDown((MouseEvent)e)) {
|
||||
return false;
|
||||
}
|
||||
return super.isCellEditable(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTableCellEditorComponent(final JTable table, Object value, boolean isSelected, final int row, int column) {
|
||||
final JPanel p = new JPanel(new BorderLayout()) {
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<lang.elementManipulator forClass="com.intellij.json.psi.JsonStringLiteral"
|
||||
implementationClass="com.intellij.json.psi.JsonStringLiteralManipulator"/>
|
||||
<projectService serviceImplementation="com.jetbrains.jsonSchema.JsonSchemaMappingsProjectConfiguration"/>
|
||||
<projectConfigurable groupId="language" id="settings.json.schema" displayName="JSON Schema"
|
||||
<projectConfigurable groupId="preferences.externalResources" id="settings.json.schema" displayName="JSON Schema"
|
||||
instance="com.jetbrains.jsonSchema.JsonSchemaMappingsConfigurable" nonDefaultProject="true"/>
|
||||
<projectService serviceInterface="com.jetbrains.jsonSchema.ide.JsonSchemaService"
|
||||
serviceImplementation="com.jetbrains.jsonSchema.impl.JsonSchemaServiceImpl"/>
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
<action id="FullyExpandTreeNode">
|
||||
<keyboard-shortcut first-keystroke="MULTIPLY"/>
|
||||
</action>
|
||||
<!--<action id="TextComponent.ClearAction">
|
||||
<keyboard-shortcut first-keystroke="ESCAPE"/>
|
||||
</action>-->
|
||||
<action id="ExpandTreeNode">
|
||||
<keyboard-shortcut first-keystroke="ADD"/>
|
||||
</action>
|
||||
|
||||
+9
-1
@@ -216,6 +216,10 @@ public class VcsSelectionHistoryDialog extends FrameWrapper implements DataProvi
|
||||
popupActions.add(ActionManager.getInstance().getAction(VcsActions.ACTION_COPY_REVISION_NUMBER));
|
||||
PopupHandler.installPopupHandler(myList, popupActions, ActionPlaces.UPDATE_POPUP, ActionManager.getInstance());
|
||||
|
||||
for (AnAction action : popupActions.getChildren(null)) {
|
||||
action.registerCustomShortcutSet(action.getShortcutSet(), mySplitter);
|
||||
}
|
||||
|
||||
setTitle(title);
|
||||
setComponent(mySplitter);
|
||||
setPreferredFocusedComponent(myList);
|
||||
@@ -241,7 +245,7 @@ public class VcsSelectionHistoryDialog extends FrameWrapper implements DataProvi
|
||||
return myCachedContents.getContentOf(revision);
|
||||
}
|
||||
|
||||
private void loadContentsFor(final VcsFileRevision[] revisions) throws VcsException {
|
||||
private void loadContentsFor(final VcsFileRevision... revisions) throws VcsException {
|
||||
myCachedContents.loadContentsFor(revisions);
|
||||
}
|
||||
|
||||
@@ -426,6 +430,8 @@ public class VcsSelectionHistoryDialog extends FrameWrapper implements DataProvi
|
||||
}
|
||||
|
||||
private void ensureBlocksCreated(int requiredIndex) throws VcsException {
|
||||
loadContentsFor(myRevisions.get(requiredIndex));
|
||||
|
||||
for (int i = 0; i <= requiredIndex; i++) {
|
||||
if (myBlocks.get(i) == null) {
|
||||
myBlocks.set(i, createBlock(i));
|
||||
@@ -460,6 +466,7 @@ public class VcsSelectionHistoryDialog extends FrameWrapper implements DataProvi
|
||||
private class MyDiffAction extends DumbAwareAction {
|
||||
public MyDiffAction() {
|
||||
super(VcsBundle.message("action.name.compare"), VcsBundle.message("action.description.compare"), AllIcons.Actions.Diff);
|
||||
setShortcutSet(CommonShortcuts.getDiff());
|
||||
}
|
||||
|
||||
public void update(final AnActionEvent e) {
|
||||
@@ -489,6 +496,7 @@ public class VcsSelectionHistoryDialog extends FrameWrapper implements DataProvi
|
||||
super(VcsBundle.message("show.diff.with.local.action.text"),
|
||||
VcsBundle.message("show.diff.with.local.action.description"),
|
||||
AllIcons.Actions.DiffWithCurrent);
|
||||
setShortcutSet(ActionManager.getInstance().getAction("Vcs.ShowDiffWithLocal").getShortcutSet());
|
||||
}
|
||||
|
||||
public void update(final AnActionEvent e) {
|
||||
|
||||
-1
@@ -1835,7 +1835,6 @@ overloaded.methods.with.same.number.parameters.option=<html>Ignore overloaded me
|
||||
string.concatenation.in.format.call.display.name=String concatenation as argument to 'format()' call
|
||||
string.concatenation.in.format.call.problem.descriptor=<code>#ref()</code> call has a String concatenation argument #loc
|
||||
string.concatenation.in.format.call.quickfix=Replace concatenation with separate argument
|
||||
string.concatenation.in.format.call.plural.quickfix=Replace concatenation with separate arguments
|
||||
string.concatenation.in.message.format.call.display.name=String concatenation as argument to 'MessageFormat.format()' call
|
||||
string.concatenation.in.message.format.call.problem.descriptor=String concatenation as argument to 'MessageFormat.format()' call #loc
|
||||
shift.out.of.range.quickfix=Replace ''{0}'' with ''{1}''
|
||||
|
||||
+2
-68
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2012 Bas Leijdekkers
|
||||
* Copyright 2010-2016 Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,15 +15,10 @@
|
||||
*/
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.InspectionGadgetsFix;
|
||||
import com.siyeh.ig.PsiReplacementUtil;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
import com.siyeh.ig.psiutils.FormatUtils;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
@@ -44,67 +39,6 @@ public class StringConcatenationInFormatCallInspection extends BaseInspection {
|
||||
return InspectionGadgetsBundle.message("string.concatenation.in.format.call.problem.descriptor");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InspectionGadgetsFix buildFix(Object... infos) {
|
||||
return new StringConcatenationInFormatCallFix(((Boolean)infos[0]).booleanValue());
|
||||
}
|
||||
|
||||
private static class StringConcatenationInFormatCallFix extends InspectionGadgetsFix {
|
||||
|
||||
|
||||
private final boolean myPlural;
|
||||
|
||||
public StringConcatenationInFormatCallFix(boolean plural) {
|
||||
myPlural = plural;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getName() {
|
||||
if (myPlural) {
|
||||
return InspectionGadgetsBundle.message("string.concatenation.in.format.call.plural.quickfix");
|
||||
}
|
||||
else {
|
||||
return InspectionGadgetsBundle.message("string.concatenation.in.format.call.quickfix");
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return InspectionGadgetsBundle.message("string.concatenation.in.format.call.plural.quickfix");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
|
||||
final PsiElement element = descriptor.getPsiElement().getParent().getParent();
|
||||
if (!(element instanceof PsiMethodCallExpression)) {
|
||||
return;
|
||||
}
|
||||
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)element;
|
||||
final PsiExpressionList argumentList = methodCallExpression.getArgumentList();
|
||||
final PsiExpression formatArgument = FormatUtils.getFormatArgument(argumentList);
|
||||
if (!(formatArgument instanceof PsiPolyadicExpression)) {
|
||||
return;
|
||||
}
|
||||
final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)formatArgument;
|
||||
final StringBuilder newExpression = new StringBuilder();
|
||||
final PsiExpression[] operands = polyadicExpression.getOperands();
|
||||
for (PsiExpression operand : operands) {
|
||||
if (operand instanceof PsiReferenceExpression) {
|
||||
argumentList.add(operand);
|
||||
continue;
|
||||
}
|
||||
final PsiJavaToken token = polyadicExpression.getTokenBeforeOperand(operand);
|
||||
if (token != null) {
|
||||
newExpression.append(token.getText());
|
||||
}
|
||||
newExpression.append(operand.getText());
|
||||
}
|
||||
PsiReplacementUtil.replaceExpression(polyadicExpression, newExpression.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseInspectionVisitor buildVisitor() {
|
||||
return new StringConcatenationInFormatCallVisitor();
|
||||
@@ -141,7 +75,7 @@ public class StringConcatenationInFormatCallInspection extends BaseInspection {
|
||||
if (count == 0) {
|
||||
return;
|
||||
}
|
||||
registerMethodCallError(expression, Boolean.valueOf(count > 1));
|
||||
registerMethodCallError(expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -72,6 +72,9 @@ public class UtilityClassCanBeEnumInspection extends BaseInspection {
|
||||
@Override
|
||||
protected void doFix(Project project, ProblemDescriptor descriptor) {
|
||||
final PsiElement element = descriptor.getPsiElement();
|
||||
if (!PsiUtil.isLanguageLevel5OrHigher(element)) {
|
||||
return;
|
||||
}
|
||||
final PsiElement parent = element.getParent();
|
||||
if (!(parent instanceof PsiClass)) {
|
||||
return;
|
||||
|
||||
+6
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 Bas Leijdekkers
|
||||
* Copyright 2011-2016 Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -74,7 +74,11 @@ public class AddThisQualifierFix extends InspectionGadgetsFix {
|
||||
return;
|
||||
}
|
||||
}
|
||||
newExpression = containingClass.getQualifiedName() + ".this." + expression.getText();
|
||||
final String qualifiedName = containingClass.getQualifiedName();
|
||||
if (qualifiedName == null) {
|
||||
return;
|
||||
}
|
||||
newExpression = qualifiedName + ".this." + expression.getText();
|
||||
}
|
||||
PsiReplacementUtil.replaceExpressionAndShorten(expression, newExpression);
|
||||
}
|
||||
|
||||
+24
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2015 Dave Griffith, Bas Leijdekkers
|
||||
* Copyright 2003-2016 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -156,27 +156,35 @@ public class ImplicitNumericConversionInspection extends BaseInspection {
|
||||
if (expressionType == null) {
|
||||
return null;
|
||||
}
|
||||
final String text = expression.getText();
|
||||
if (expressionType.equals(PsiType.INT) && expectedType.equals(PsiType.LONG)) {
|
||||
return expression.getText() + 'L';
|
||||
return text + 'L';
|
||||
}
|
||||
if (expressionType.equals(PsiType.INT) && expectedType.equals(PsiType.FLOAT)) {
|
||||
return expression.getText() + ".0F";
|
||||
if (!isDecimalLiteral(text)) {
|
||||
return null;
|
||||
}
|
||||
return text + ".0F";
|
||||
}
|
||||
if (expressionType.equals(PsiType.INT) && expectedType.equals(PsiType.DOUBLE)) {
|
||||
return expression.getText() + ".0";
|
||||
if (!isDecimalLiteral(text)) {
|
||||
return null;
|
||||
}
|
||||
return text + ".0";
|
||||
}
|
||||
if (expressionType.equals(PsiType.LONG) && expectedType.equals(PsiType.FLOAT)) {
|
||||
final String text = expression.getText();
|
||||
final int length = text.length();
|
||||
return text.substring(0, length - 1) + ".0F";
|
||||
if (!isDecimalLiteral(text)) {
|
||||
return null;
|
||||
}
|
||||
return text.substring(0, text.length() - 1) + ".0F";
|
||||
}
|
||||
if (expressionType.equals(PsiType.LONG) && expectedType.equals(PsiType.DOUBLE)) {
|
||||
final String text = expression.getText();
|
||||
final int length = text.length();
|
||||
return text.substring(0, length - 1) + ".0";
|
||||
if (!isDecimalLiteral(text)) {
|
||||
return null;
|
||||
}
|
||||
return text.substring(0, text.length() - 1) + ".0";
|
||||
}
|
||||
if (expressionType.equals(PsiType.DOUBLE) && expectedType.equals(PsiType.FLOAT)) {
|
||||
final String text = expression.getText();
|
||||
final int length = text.length();
|
||||
if (text.charAt(length - 1) == 'd' || text.charAt(length - 1) == 'D') {
|
||||
return text.substring(0, length - 1) + 'F';
|
||||
@@ -186,13 +194,17 @@ public class ImplicitNumericConversionInspection extends BaseInspection {
|
||||
}
|
||||
}
|
||||
if (expressionType.equals(PsiType.FLOAT) && expectedType.equals(PsiType.DOUBLE)) {
|
||||
final String text = expression.getText();
|
||||
final int length = text.length();
|
||||
return text.substring(0, length - 1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isDecimalLiteral(String text) {
|
||||
// should not be binary, octal or hexadecimal: 0b101, 077, 0xFF
|
||||
return text.length() > 0 && text.charAt(0) != '0';
|
||||
}
|
||||
|
||||
private static boolean isNegatedLiteral(PsiExpression expression) {
|
||||
if (!(expression instanceof PsiPrefixExpression)) {
|
||||
return false;
|
||||
|
||||
+7
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2013 Bas Leijdekkers
|
||||
* Copyright 2006-2016 Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@ package com.siyeh.ig.style;
|
||||
import com.intellij.codeInspection.CleanupLocalInspectionTool;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
@@ -71,10 +72,13 @@ public class UnqualifiedFieldAccessInspection extends BaseInspection implements
|
||||
return;
|
||||
}
|
||||
final PsiClass fieldClass = field.getContainingClass();
|
||||
if (fieldClass instanceof PsiAnonymousClass) {
|
||||
if (fieldClass == null) {
|
||||
return;
|
||||
}
|
||||
if (PsiUtil.isLocalOrAnonymousClass(fieldClass)) {
|
||||
final PsiClass expressionClass = PsiTreeUtil.getParentOfType(expression, PsiClass.class);
|
||||
if (expressionClass != null && !expressionClass.equals(fieldClass)) {
|
||||
// qualified this expression not possible for anonymous class
|
||||
// qualified this expression not possible for anonymous or local class
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
+11
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2012 Bas Leijdekkers
|
||||
* Copyright 2006-2016 Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,8 @@ package com.siyeh.ig.style;
|
||||
|
||||
import com.intellij.codeInspection.CleanupLocalInspectionTool;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
@@ -70,9 +72,16 @@ public class UnqualifiedMethodAccessInspection extends BaseInspection implements
|
||||
return;
|
||||
}
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass instanceof PsiAnonymousClass) {
|
||||
if (containingClass == null) {
|
||||
return;
|
||||
}
|
||||
if (PsiUtil.isLocalOrAnonymousClass(containingClass)) {
|
||||
final PsiClass expressionClass = PsiTreeUtil.getParentOfType(expression, PsiClass.class);
|
||||
if (expressionClass == null || !expressionClass.equals(containingClass)) {
|
||||
// qualified this expression not possible for anonymous or local class
|
||||
return;
|
||||
}
|
||||
}
|
||||
registerError(expression);
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
class HexadecimalLiteral {
|
||||
|
||||
void a() {
|
||||
double value = (double) 0xFF;
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
class HexadecimalLiteral {
|
||||
|
||||
void a() {
|
||||
double value = <caret>0xFF;
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package com.siyeh.igtest.bugs.string_concatenation_in_format_call;
|
||||
|
||||
|
||||
|
||||
public class StringConcatenationInFormatCall {
|
||||
|
||||
void foo(int i) {
|
||||
String.<warning descr="'format()' call has a String concatenation argument">format</warning>("a" + "b" + i);
|
||||
String.<warning descr="'format()' call has a String concatenation argument">format</warning>("c: " + i);
|
||||
}
|
||||
}
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
package com.siyeh.igtest.bugs.string_concatenation_in_format_call;
|
||||
|
||||
|
||||
|
||||
public class StringContenationInFormatCall {
|
||||
|
||||
void foo(int i) {
|
||||
String.format("a" + "b" + i);
|
||||
String.format("c: " + i);
|
||||
}
|
||||
}
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>StringContenationInFormatCall.java</file>
|
||||
<line>8</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">String concatenation as argument to 'format()' call</problem_class>
|
||||
<description><code>format()</code> call has a String concatenation argument #loc</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>StringContenationInFormatCall.java</file>
|
||||
<line>9</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">String concatenation as argument to 'format()' call</problem_class>
|
||||
<description><code>format()</code> call has a String concatenation argument #loc</description>
|
||||
</problem>
|
||||
</problems>
|
||||
+13
-3
@@ -5,8 +5,8 @@ public class UnqualifiedFieldAccess {
|
||||
private String field;
|
||||
|
||||
public void x () {
|
||||
field = "foofoo";
|
||||
final String s = String.valueOf(field.hashCode());
|
||||
<warning descr="Instance field access 'field' is not qualified with 'this'">field</warning> = "foofoo";
|
||||
final String s = String.valueOf(<warning descr="Instance field access 'field' is not qualified with 'this'">field</warning>.hashCode());
|
||||
System.out.println(s);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,16 @@ public class UnqualifiedFieldAccess {
|
||||
};
|
||||
}
|
||||
};
|
||||
class A {
|
||||
int i;
|
||||
void a() {
|
||||
new Object() {
|
||||
void b() {
|
||||
System.out.println(i);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void simpleAnonymous() {
|
||||
@@ -28,7 +38,7 @@ public class UnqualifiedFieldAccess {
|
||||
String s;
|
||||
|
||||
void foo() {
|
||||
System.out.println(s);
|
||||
System.out.println(<warning descr="Instance field access 's' is not qualified with 'this'">s</warning>);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>UnqualifiedFieldAccess.java</file>
|
||||
<line>8</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Instance field access not qualified with 'this'</problem_class>
|
||||
<description>Instance field access <code>field</code> is not qualified with 'this' #loc</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>UnqualifiedFieldAccess.java</file>
|
||||
<line>9</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Instance field access not qualified with 'this'</problem_class>
|
||||
<description>Instance field access <code>field</code> is not qualified with 'this' #loc</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>UnqualifiedFieldAccess.java</file>
|
||||
<line>31</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Instance field access not qualified with 'this'</problem_class>
|
||||
<description>Instance field access <code>s</code> is not qualified with 'this' #loc</description>
|
||||
</problem>
|
||||
</problems>
|
||||
+12
-1
@@ -9,11 +9,21 @@ public class UnqualifiedMethodAccess extends JPanel {
|
||||
|
||||
void foo() {}
|
||||
void bar() {
|
||||
foo();
|
||||
<warning descr="Instance method call 'foo' is not qualified with 'this'">foo</warning>();
|
||||
}
|
||||
|
||||
void foo(String s) {
|
||||
this.foo();
|
||||
class A {
|
||||
void a() {
|
||||
<warning descr="Instance method call 'a' is not qualified with 'this'">a</warning>();
|
||||
new Object() {
|
||||
void b() {
|
||||
a();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void anonymous() {
|
||||
@@ -22,6 +32,7 @@ public class UnqualifiedMethodAccess extends JPanel {
|
||||
new Object() {
|
||||
void foo() {
|
||||
bar();
|
||||
<warning descr="Instance method call 'foo' is not qualified with 'this'">foo</warning>();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>UnqualifiedMethodAccess.java</file>
|
||||
<line>12</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Instance method call not qualified with 'this'</problem_class>
|
||||
<description>Instance method call <code>foo</code> is not qualified with 'this' #loc</description>
|
||||
</problem>
|
||||
</problems>
|
||||
+27
-4
@@ -1,10 +1,33 @@
|
||||
/*
|
||||
* 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.siyeh.ig.bugs;
|
||||
|
||||
import com.siyeh.ig.IGInspectionTestCase;
|
||||
import com.intellij.codeInspection.InspectionProfileEntry;
|
||||
import com.siyeh.ig.LightInspectionTestCase;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class StringConcatenationInFormatCallInspectionTest extends IGInspectionTestCase {
|
||||
public class StringConcatenationInFormatCallInspectionTest extends LightInspectionTestCase {
|
||||
|
||||
public void test() throws Exception {
|
||||
doTest("com/siyeh/igtest/bugs/string_concatenation_in_format_call", new StringConcatenationInFormatCallInspection());
|
||||
public void testStringConcatenationInFormatCall() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected InspectionProfileEntry getInspection() {
|
||||
return new StringConcatenationInFormatCallInspection();
|
||||
}
|
||||
}
|
||||
+3
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,9 +24,8 @@ import com.siyeh.ig.numeric.ImplicitNumericConversionInspection;
|
||||
*/
|
||||
public class ImplicitNumericConversionFixTest extends IGQuickFixesTestCase {
|
||||
|
||||
public void testOperatorAssignment() {
|
||||
doTest();
|
||||
}
|
||||
public void testOperatorAssignment() { doTest(); }
|
||||
public void testHexadecimalLiteral() { doTest(); }
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
|
||||
+27
-4
@@ -1,10 +1,33 @@
|
||||
/*
|
||||
* 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.siyeh.ig.style;
|
||||
|
||||
import com.siyeh.ig.IGInspectionTestCase;
|
||||
import com.intellij.codeInspection.InspectionProfileEntry;
|
||||
import com.siyeh.ig.LightInspectionTestCase;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class UnqualifiedFieldAccessInspectionTest extends IGInspectionTestCase {
|
||||
public class UnqualifiedFieldAccessInspectionTest extends LightInspectionTestCase {
|
||||
|
||||
public void test() throws Exception {
|
||||
doTest("com/siyeh/igtest/style/unqualified_field_access", new UnqualifiedFieldAccessInspection());
|
||||
public void testUnqualifiedFieldAccess() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected InspectionProfileEntry getInspection() {
|
||||
return new UnqualifiedFieldAccessInspection();
|
||||
}
|
||||
}
|
||||
+27
-5
@@ -1,11 +1,33 @@
|
||||
/*
|
||||
* 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.siyeh.ig.style;
|
||||
|
||||
import com.siyeh.ig.IGInspectionTestCase;
|
||||
import com.intellij.codeInspection.InspectionProfileEntry;
|
||||
import com.siyeh.ig.LightInspectionTestCase;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class UnqualifiedMethodAccessInspectionTest
|
||||
extends IGInspectionTestCase {
|
||||
public class UnqualifiedMethodAccessInspectionTest extends LightInspectionTestCase {
|
||||
|
||||
public void test() throws Exception {
|
||||
doTest("com/siyeh/igtest/style/unqualified_method_access", new UnqualifiedMethodAccessInspection());
|
||||
public void testUnqualifiedMethodAccess() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected InspectionProfileEntry getInspection() {
|
||||
return new UnqualifiedMethodAccessInspection();
|
||||
}
|
||||
}
|
||||
+1
-11
@@ -22,7 +22,6 @@ import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.refactoring.changeSignature.ChangeSignatureProcessorBase;
|
||||
import com.intellij.refactoring.changeSignature.ChangeSignatureUsageProcessor;
|
||||
import com.intellij.refactoring.changeSignature.ChangeSignatureViewDescriptor;
|
||||
import com.intellij.refactoring.rename.RenameUtil;
|
||||
import com.intellij.refactoring.ui.ConflictsDialog;
|
||||
@@ -33,7 +32,6 @@ import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -68,15 +66,7 @@ public class GrChangeSignatureProcessor extends ChangeSignatureProcessorBase {
|
||||
@Override
|
||||
protected boolean preprocessUsages(@NotNull Ref<UsageInfo[]> refUsages) {
|
||||
MultiMap<PsiElement, String> conflictDescriptions = new MultiMap<PsiElement, String>();
|
||||
for (ChangeSignatureUsageProcessor usageProcessor : ChangeSignatureUsageProcessor.EP_NAME.getExtensions()) {
|
||||
final MultiMap<PsiElement, String> conflicts = usageProcessor.findConflicts(myChangeInfo, refUsages);
|
||||
for (PsiElement key : conflicts.keySet()) {
|
||||
Collection<String> collection = conflictDescriptions.get(key);
|
||||
if (collection.isEmpty()) collection = new HashSet<String>();
|
||||
collection.addAll(conflicts.get(key));
|
||||
conflictDescriptions.put(key, collection);
|
||||
}
|
||||
}
|
||||
collectConflictsFromExtensions(refUsages, conflictDescriptions, myChangeInfo);
|
||||
|
||||
final UsageInfo[] usagesIn = refUsages.get();
|
||||
RenameUtil.addConflictDescriptions(usagesIn, conflictDescriptions);
|
||||
|
||||
+3
@@ -34,6 +34,7 @@ public class AddConstructorMatchingSuperTest extends GrIntentionTestCase {
|
||||
|
||||
void testGroovyToGroovy() {
|
||||
doTextTest('''\
|
||||
@interface Anno {}
|
||||
class Base {
|
||||
Base(int p, @Anno int x) throws Exception {}
|
||||
}
|
||||
@@ -41,6 +42,7 @@ class Base {
|
||||
class Derived exten<caret>ds Base {
|
||||
}
|
||||
''', '''\
|
||||
@interface Anno {}
|
||||
class Base {
|
||||
Base(int p, @Anno int x) throws Exception {}
|
||||
}
|
||||
@@ -55,6 +57,7 @@ class Derived extends Base {
|
||||
|
||||
void testJavaToGroovy() {
|
||||
myFixture.addClass('''\
|
||||
@interface Anno {}
|
||||
class Base {
|
||||
Base(int p, @Anno int x) throws Exception {}
|
||||
}
|
||||
|
||||
@@ -566,12 +566,10 @@ _UseNewThreadStartup = _NewThreadStartupWithTrace
|
||||
|
||||
def _get_threading_modules_to_patch():
|
||||
threading_modules_to_patch = []
|
||||
try:
|
||||
import thread as _thread
|
||||
threading_modules_to_patch.append(_thread)
|
||||
except:
|
||||
import _thread # @UnresolvedImport @Reimport
|
||||
threading_modules_to_patch.append(_thread)
|
||||
|
||||
from _pydev_imps._pydev_saved_modules import thread as _thread
|
||||
threading_modules_to_patch.append(_thread)
|
||||
|
||||
return threading_modules_to_patch
|
||||
|
||||
threading_modules_to_patch = _get_threading_modules_to_patch()
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
import sys
|
||||
IS_PY2 = True
|
||||
if sys.version_info[0] >= 3:
|
||||
IS_PY2 = False
|
||||
IS_PY2 = sys.version_info < (3,)
|
||||
|
||||
import threading
|
||||
|
||||
if IS_PY2:
|
||||
import thread
|
||||
else:
|
||||
import _thread as thread
|
||||
|
||||
import time
|
||||
|
||||
import socket
|
||||
@@ -17,21 +10,14 @@ import socket
|
||||
import select
|
||||
|
||||
if IS_PY2:
|
||||
import thread
|
||||
import Queue as _queue
|
||||
else:
|
||||
import queue as _queue
|
||||
|
||||
if IS_PY2:
|
||||
import xmlrpclib
|
||||
else:
|
||||
import xmlrpc.client as xmlrpclib
|
||||
|
||||
if IS_PY2:
|
||||
import SimpleXMLRPCServer as _pydev_SimpleXMLRPCServer
|
||||
else:
|
||||
import xmlrpc.server as _pydev_SimpleXMLRPCServer
|
||||
|
||||
if IS_PY2:
|
||||
import BaseHTTPServer
|
||||
else:
|
||||
import _thread as thread
|
||||
import queue as _queue
|
||||
import xmlrpc.client as xmlrpclib
|
||||
import xmlrpc.server as _pydev_SimpleXMLRPCServer
|
||||
import http.server as BaseHTTPServer
|
||||
@@ -61,6 +61,7 @@ each command has a format:
|
||||
from _pydev_bundle.pydev_imports import _queue
|
||||
from _pydev_imps._pydev_saved_modules import time
|
||||
from _pydev_imps._pydev_saved_modules import thread
|
||||
from _pydev_imps._pydev_saved_modules import threading
|
||||
from _pydev_imps._pydev_saved_modules import socket
|
||||
from socket import socket, AF_INET, SOCK_STREAM, SHUT_RD, SHUT_WR
|
||||
from _pydevd_bundle.pydevd_constants import * #@UnusedWildImport
|
||||
|
||||
@@ -91,6 +91,10 @@ except AttributeError:
|
||||
|
||||
try:
|
||||
SUPPORT_GEVENT = os.getenv('GEVENT_SUPPORT', 'False') == 'True'
|
||||
try:
|
||||
import gevent
|
||||
except:
|
||||
SUPPORT_GEVENT = False
|
||||
except:
|
||||
# Jython 2.1 doesn't accept that construct
|
||||
SUPPORT_GEVENT = False
|
||||
@@ -102,6 +106,11 @@ USE_LIB_COPY = SUPPORT_GEVENT and \
|
||||
|
||||
|
||||
def protect_libraries_from_patching():
|
||||
"""
|
||||
In this function we delete some modules from `sys.modules` dictionary and import them again inside
|
||||
`_pydev_saved_modules` in order to save their original copies there. After that we can use these
|
||||
saved modules within the debugger to protect them from patching by external libraries (e.g. gevent).
|
||||
"""
|
||||
patched = ['threading', 'thread', '_thread', 'time', 'socket', 'Queue', 'queue', 'select',
|
||||
'xmlrpclib', 'SimpleXMLRPCServer', 'BaseHTTPServer', 'SocketServer',
|
||||
'xmlrpc.client', 'xmlrpc.server', 'http.server', 'socketserver']
|
||||
|
||||
@@ -117,13 +117,18 @@ public class PySignature {
|
||||
|
||||
public String getTypeQualifiedName() {
|
||||
if (myTypes.size() == 1) {
|
||||
return myTypes.get(0);
|
||||
return noneTypeToNone(myTypes.get(0));
|
||||
}
|
||||
else {
|
||||
return StringUtil.join(myTypes, " or ");
|
||||
return "Union[" + StringUtil.join(myTypes, NamedParameter::noneTypeToNone, ", ") + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String noneTypeToNone(@Nullable String type) {
|
||||
return "NoneType".equals(type) ? "None" : type;
|
||||
}
|
||||
|
||||
public void addType(String type) {
|
||||
if (!myTypes.contains(type)) {
|
||||
myTypes.add(type);
|
||||
|
||||
+1
-1
@@ -203,7 +203,7 @@ public class PyAnnotateTypesIntention implements IntentionAction {
|
||||
PyParameter[] params = function.getParameterList().getParameters();
|
||||
|
||||
for (int i = params.length - 1; i >= 0; i--) {
|
||||
if (params[i] instanceof PyNamedParameter) {
|
||||
if (params[i] instanceof PyNamedParameter && !params[i].isSelf()) {
|
||||
params[i] = annotateParameter(project, editor, (PyNamedParameter)params[i], false);
|
||||
}
|
||||
}
|
||||
|
||||
+15
-10
@@ -137,8 +137,7 @@ public class SpecifyTypeInPy3AnnotationsIntention extends TypeIntention {
|
||||
|
||||
static String returnType(@NotNull PyFunction function) {
|
||||
String returnType = PyNames.OBJECT;
|
||||
final PySignature signature = PySignatureCacheManager.getInstance(function.getProject()).findSignature(
|
||||
function);
|
||||
final PySignature signature = PySignatureCacheManager.getInstance(function.getProject()).findSignature(function);
|
||||
if (signature != null) {
|
||||
returnType = ObjectUtils.chooseNotNull(signature.getReturnTypeQualifiedName(), returnType);
|
||||
}
|
||||
@@ -148,22 +147,28 @@ public class SpecifyTypeInPy3AnnotationsIntention extends TypeIntention {
|
||||
public static PyExpression annotateReturnType(Project project, PyFunction function, boolean createTemplate) {
|
||||
String returnType = returnType(function);
|
||||
|
||||
final String annotationText = " -> " + returnType;
|
||||
|
||||
final PsiElement prevElem = PyPsiUtils.getPrevNonCommentSibling(function.getStatementList(), true);
|
||||
assert prevElem != null;
|
||||
final String annotationText = "-> " + returnType;
|
||||
|
||||
final PsiDocumentManager manager = PsiDocumentManager.getInstance(project);
|
||||
Document documentWithCallable = manager.getDocument(function.getContainingFile());
|
||||
if (documentWithCallable != null) {
|
||||
try {
|
||||
final TextRange range = prevElem.getTextRange();
|
||||
manager.doPostponedOperationsAndUnblockDocument(documentWithCallable);
|
||||
if (prevElem.getNode().getElementType() == PyTokenTypes.COLON) {
|
||||
documentWithCallable.insertString(range.getStartOffset(), annotationText);
|
||||
final PyAnnotation oldAnnotation = function.getAnnotation();
|
||||
if (oldAnnotation != null) {
|
||||
final TextRange oldRange = oldAnnotation.getTextRange();
|
||||
documentWithCallable.replaceString(oldRange.getStartOffset(), oldRange.getEndOffset(), annotationText);
|
||||
}
|
||||
else {
|
||||
documentWithCallable.insertString(range.getEndOffset(), annotationText + ":");
|
||||
final PsiElement prevElem = PyPsiUtils.getPrevNonCommentSibling(function.getStatementList(), true);
|
||||
assert prevElem != null;
|
||||
final TextRange range = prevElem.getTextRange();
|
||||
if (prevElem.getNode().getElementType() == PyTokenTypes.COLON) {
|
||||
documentWithCallable.insertString(range.getStartOffset(), " " + annotationText);
|
||||
}
|
||||
else {
|
||||
documentWithCallable.insertString(range.getEndOffset(), " " + annotationText + ":");
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
|
||||
Reference in New Issue
Block a user