diff --git a/iron-python/src/main/java/consulo/ironPython/psi/impl/PyDotNetClassType.java b/iron-python/src/main/java/consulo/ironPython/psi/impl/PyDotNetClassType.java index 230162ed..228ef7d1 100644 --- a/iron-python/src/main/java/consulo/ironPython/psi/impl/PyDotNetClassType.java +++ b/iron-python/src/main/java/consulo/ironPython/psi/impl/PyDotNetClassType.java @@ -13,13 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package consulo.ironPython.psi.impl; +import com.jetbrains.python.impl.psi.impl.ResolveResultList; import com.jetbrains.python.psi.AccessDirection; import com.jetbrains.python.psi.PyCallSiteExpression; import com.jetbrains.python.psi.PyExpression; -import com.jetbrains.python.impl.psi.impl.ResolveResultList; import com.jetbrains.python.psi.resolve.PyResolveContext; import com.jetbrains.python.psi.resolve.RatedResolveResult; import com.jetbrains.python.psi.types.PyCallableParameter; @@ -27,7 +26,6 @@ import com.jetbrains.python.psi.types.PyType; import com.jetbrains.python.psi.types.TypeEvalContext; import consulo.annotation.access.RequiredReadAction; -import consulo.application.util.function.Processor; import consulo.dotnet.psi.DotNetNamedElement; import consulo.dotnet.psi.DotNetTypeDeclaration; import consulo.dotnet.psi.resolve.DotNetTypeRef; @@ -37,9 +35,10 @@ import consulo.language.psi.PsiNamedElement; import consulo.language.util.ProcessingContext; import consulo.util.collection.ArrayUtil; - import org.jspecify.annotations.Nullable; + import java.util.*; +import java.util.function.Predicate; /** * @author yole @@ -57,6 +56,7 @@ public PyDotNetClassType(DotNetTypeDeclaration aClass, boolean definition) @Override @Nullable + @RequiredReadAction public List resolveMember(String name, PyExpression location, AccessDirection direction, PyResolveContext resolveContext) { @@ -65,6 +65,7 @@ public List resolveMember(String name, PyExpressio @Nullable @Override + @RequiredReadAction public List resolveMember(String name, @Nullable PyExpression location, AccessDirection direction, PyResolveContext resolveContext, boolean inherited) { @@ -82,15 +83,17 @@ public List resolveMember(String name, @Nullable P } @Override - public void visitMembers(Processor processor, boolean inherited, TypeEvalContext context) + @RequiredReadAction + public void visitMembers(Predicate processor, boolean inherited, TypeEvalContext context) { for(DotNetNamedElement dotNetNamedElement : myClass.getMembers()) { - processor.process(dotNetNamedElement); + processor.test(dotNetNamedElement); } } @Override + @RequiredReadAction public Set getMemberNames(boolean inherited, TypeEvalContext context) { Set names = new HashSet<>(); @@ -102,9 +105,10 @@ public Set getMemberNames(boolean inherited, TypeEvalContext context) } @Override + @RequiredReadAction public Object[] getCompletionVariants(String completionPrefix, PsiElement location, ProcessingContext context) { - List variants = new ArrayList(); + List variants = new ArrayList<>(); for(PsiElement child : myClass.getMembers()) { if(child instanceof PsiNamedElement) @@ -116,6 +120,7 @@ public Object[] getCompletionVariants(String completionPrefix, PsiElement locati } @Override + @RequiredReadAction public String getName() { if(myClass != null) @@ -184,6 +189,7 @@ public PyClassLikeType toInstance() @Nullable @Override + @RequiredReadAction public String getClassQName() { return myClass.getPresentableQName(); @@ -193,7 +199,7 @@ public String getClassQName() @RequiredReadAction public List getSuperClassTypes(TypeEvalContext context) { - List result = new ArrayList(); + List result = new ArrayList<>(); for(DotNetTypeRef typeRef : myClass.getExtendTypeRefs()) { PsiElement resolve = typeRef.resolve().getElement(); @@ -206,6 +212,7 @@ public List getSuperClassTypes(TypeEvalContext context) } @Override + @RequiredReadAction public boolean isValid() { return myClass.isValid(); diff --git a/iron-python/src/main/java/consulo/ironPython/sdk/flavors/IronPythonSdkFlavor.java b/iron-python/src/main/java/consulo/ironPython/sdk/flavors/IronPythonSdkFlavor.java index 8cf6334e..7c874781 100644 --- a/iron-python/src/main/java/consulo/ironPython/sdk/flavors/IronPythonSdkFlavor.java +++ b/iron-python/src/main/java/consulo/ironPython/sdk/flavors/IronPythonSdkFlavor.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package consulo.ironPython.sdk.flavors; import com.jetbrains.python.impl.PythonIcons; @@ -36,7 +35,7 @@ public class IronPythonSdkFlavor extends PythonSdkFlavor @Override public Collection suggestHomePaths() { - Set result = new TreeSet(); + Set result = new TreeSet<>(); String root = System.getenv("ProgramFiles(x86)"); if(root == null) { @@ -72,7 +71,8 @@ public boolean isValidSdkPath(File file) return name.equals("ipy.exe") || name.equals("ipy64.exe"); } - public String getVersionStringFromOutput(String version) + @Override + public String getVersionStringFromOutput(String version) { return getName() + " " + version; } diff --git a/jython/src/main/java/com/jetbrains/python/jython/psi/impl/PyJavaClassType.java b/jython/src/main/java/com/jetbrains/python/jython/psi/impl/PyJavaClassType.java index dfc69eb1..6e8e020c 100644 --- a/jython/src/main/java/com/jetbrains/python/jython/psi/impl/PyJavaClassType.java +++ b/jython/src/main/java/com/jetbrains/python/jython/psi/impl/PyJavaClassType.java @@ -19,23 +19,24 @@ import com.intellij.java.language.psi.PsiField; import com.intellij.java.language.psi.PsiMethod; import com.jetbrains.python.impl.psi.impl.ResolveResultList; +import com.jetbrains.python.impl.psi.resolve.CompletionVariantsProcessor; import com.jetbrains.python.psi.AccessDirection; import com.jetbrains.python.psi.PyCallSiteExpression; import com.jetbrains.python.psi.PyExpression; -import com.jetbrains.python.impl.psi.resolve.CompletionVariantsProcessor; import com.jetbrains.python.psi.resolve.PyResolveContext; import com.jetbrains.python.psi.resolve.RatedResolveResult; import com.jetbrains.python.psi.types.PyCallableParameter; import com.jetbrains.python.psi.types.PyClassLikeType; import com.jetbrains.python.psi.types.PyType; import com.jetbrains.python.psi.types.TypeEvalContext; -import consulo.application.util.function.Processor; +import consulo.annotation.access.RequiredReadAction; import consulo.language.psi.PsiElement; import consulo.language.psi.resolve.ResolveState; import consulo.language.util.ProcessingContext; - import org.jspecify.annotations.Nullable; + import java.util.*; +import java.util.function.Predicate; /** * @author yole @@ -50,6 +51,7 @@ public PyJavaClassType(PsiClass aClass, boolean definition) { } @Nullable + @Override public List resolveMember(String name, @Nullable PyExpression location, AccessDirection direction, @@ -79,19 +81,17 @@ public List resolveMember(String name, return null; } + @Override public Object[] getCompletionVariants(String completionPrefix, PsiElement location, ProcessingContext context) { CompletionVariantsProcessor processor = new CompletionVariantsProcessor(location); myClass.processDeclarations(processor, ResolveState.initial(), null, location); return processor.getResult(); } + @Override + @RequiredReadAction public String getName() { - if (myClass != null) { - return myClass.getName(); - } - else { - return null; - } + return myClass != null ? myClass.getName() : null; } @Override @@ -155,13 +155,13 @@ public List getSuperClassTypes(TypeEvalContext context) { } @Override - public void visitMembers(Processor processor, boolean inherited, TypeEvalContext context) { + public void visitMembers(Predicate processor, boolean inherited, TypeEvalContext context) { for (PsiMethod method : myClass.getAllMethods()) { - processor.process(method); + processor.test(method); } for (PsiField field : myClass.getAllFields()) { - processor.process(field); + processor.test(field); } if (!inherited) { @@ -176,6 +176,7 @@ public void visitMembers(Processor processor, boolean inherited, Typ } @Override + @RequiredReadAction public Set getMemberNames(boolean inherited, TypeEvalContext context) { Set result = new LinkedHashSet<>(); @@ -223,6 +224,7 @@ public List getAncestorTypes(TypeEvalContext context) { } @Override + @RequiredReadAction public boolean isValid() { return myClass.isValid(); } @@ -238,24 +240,13 @@ public PsiClass getPsiClass() { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) { return true; } - if (!(o instanceof PyJavaClassType)) { - return false; - } - - PyJavaClassType type = (PyJavaClassType)o; - - if (myDefinition != type.myDefinition) { - return false; - } - if (myClass != null ? !myClass.equals(type.myClass) : type.myClass != null) { - return false; - } - - return true; + return o instanceof PyJavaClassType type + && myDefinition == type.myDefinition + && Objects.equals(myClass, type.myClass); } @Override diff --git a/jython/src/main/java/com/jetbrains/python/jython/sdk/flavors/JythonSdkFlavor.java b/jython/src/main/java/com/jetbrains/python/jython/sdk/flavors/JythonSdkFlavor.java index bae5a552..e0f7c20a 100644 --- a/jython/src/main/java/com/jetbrains/python/jython/sdk/flavors/JythonSdkFlavor.java +++ b/jython/src/main/java/com/jetbrains/python/jython/sdk/flavors/JythonSdkFlavor.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.jetbrains.python.jython.sdk.flavors; import com.jetbrains.python.impl.sdk.flavors.PythonSdkFlavor; @@ -45,13 +44,13 @@ public class JythonSdkFlavor extends PythonSdkFlavor private static final String JYTHONPATH = "JYTHONPATH"; private static final String PYTHON_PATH_PREFIX = "-Dpython.path="; - public static String getPythonPathCmdLineArgument(Collection path) { return PYTHON_PATH_PREFIX + StringUtil.join(appendSystemEnvPaths(path, JYTHONPATH), File.pathSeparator); } - public boolean isValidSdkPath(File file) + @Override + public boolean isValidSdkPath(File file) { return FileUtil.getNameWithoutExtension(file).toLowerCase().startsWith("jython"); } @@ -101,7 +100,7 @@ public ProcessHandler createProcessHandler(GeneralCommandLine commandLine, boole @Override public Collection collectDebugPythonPath() { - List list = new ArrayList(2); + List list = new ArrayList<>(2); //that fixes Jython problem changing sys.argv on execfile, see PY-8164 list.add(PythonHelpersLocator.getHelperPath("pycharm")); list.add(PythonHelpersLocator.getHelperPath("pydev")); diff --git a/python-debugger/src/main/java/com/jetbrains/python/console/pydev/FastStringBuffer.java b/python-debugger/src/main/java/com/jetbrains/python/console/pydev/FastStringBuffer.java index dc4f0211..34c8c500 100644 --- a/python-debugger/src/main/java/com/jetbrains/python/console/pydev/FastStringBuffer.java +++ b/python-debugger/src/main/java/com/jetbrains/python/console/pydev/FastStringBuffer.java @@ -352,9 +352,7 @@ public char lastChar() { return this.value[this.count-1]; } - public final static class BackwardCharIterator implements Iterable{ - private int i; private FastStringBuffer fastStringBuffer; @@ -363,17 +361,20 @@ public BackwardCharIterator(FastStringBuffer fastStringBuffer) { i = fastStringBuffer.length(); } + @Override public Iterator iterator() { - return new Iterator(){ - + return new Iterator<>(){ + @Override public boolean hasNext() { return i > 0; } + @Override public Character next() { return fastStringBuffer.value[--i]; } + @Override public void remove() { throw new RuntimeException("Not implemented"); } @@ -460,5 +461,4 @@ public void setCharAt(int i, char c) { public void setLength(int i) { this.count = i; } - } \ No newline at end of file diff --git a/python-debugger/src/main/java/com/jetbrains/python/debugger/pydev/LoadSourceCommand.java b/python-debugger/src/main/java/com/jetbrains/python/debugger/pydev/LoadSourceCommand.java index 5eee7e46..a6ed2315 100644 --- a/python-debugger/src/main/java/com/jetbrains/python/debugger/pydev/LoadSourceCommand.java +++ b/python-debugger/src/main/java/com/jetbrains/python/debugger/pydev/LoadSourceCommand.java @@ -16,6 +16,7 @@ protected LoadSourceCommand(RemoteDebugger debugger, String path) { myPath = path; } + @Override public boolean isResponseExpected() { return true; } diff --git a/python-debugger/src/main/java/com/jetbrains/python/debugger/pydev/MultiProcessDebugger.java b/python-debugger/src/main/java/com/jetbrains/python/debugger/pydev/MultiProcessDebugger.java index 90f61fae..eb27ae07 100644 --- a/python-debugger/src/main/java/com/jetbrains/python/debugger/pydev/MultiProcessDebugger.java +++ b/python-debugger/src/main/java/com/jetbrains/python/debugger/pydev/MultiProcessDebugger.java @@ -1,19 +1,18 @@ package com.jetbrains.python.debugger.pydev; -import com.google.common.base.Function; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.jetbrains.python.console.pydev.PydevCompletionVariant; import com.jetbrains.python.debugger.*; -import consulo.application.ApplicationManager; +import consulo.application.Application; import consulo.execution.debug.breakpoint.SuspendPolicy; import consulo.execution.debug.frame.XValueChildrenList; import consulo.logging.Logger; import consulo.process.ExecutionException; - import org.jspecify.annotations.Nullable; + import java.io.IOException; import java.io.PrintWriter; import java.net.ServerSocket; @@ -65,36 +64,29 @@ public boolean isConnected() @Override public void waitForConnect() throws Exception { - try - { - //noinspection SocketOpenedButNotSafelyClosed - Socket socket = myServerSocket.accept(); - - ApplicationManager.getApplication().executeOnPooledThread(() -> { - try - { - //do we need any synchronization here with myMainDebugger.waitForConnect() ??? TODO - sendDebuggerPort(socket, myDebugServerSocket, myDebugProcess); - } - catch(Exception e) - { - throw new RuntimeException(e); - } - }); + //noinspection SocketOpenedButNotSafelyClosed + Socket socket = myServerSocket.accept(); - myMainDebugger.waitForConnect(); + Application.get().executeOnPooledThread(() -> { + try + { + //do we need any synchronization here with myMainDebugger.waitForConnect() ??? TODO + sendDebuggerPort(socket, myDebugServerSocket, myDebugProcess); + } + catch(Exception e) + { + throw new RuntimeException(e); + } + }); + myMainDebugger.waitForConnect(); - disposeAcceptor(); - myDebugProcessAcceptor = new DebuggerProcessAcceptor(this, myServerSocket); - ApplicationManager.getApplication().executeOnPooledThread(myDebugProcessAcceptor); - } - finally - { + disposeAcceptor(); - } - } + myDebugProcessAcceptor = new DebuggerProcessAcceptor(this, myServerSocket); + Application.get().executeOnPooledThread(myDebugProcessAcceptor); + } private static void sendDebuggerPort(Socket socket, ServerSocket serverSocket, IPyDebugProcess processHandler) throws IOException { @@ -207,7 +199,8 @@ public XValueChildrenList loadVariable(String threadId, String frameId, PyDebugV return debugger(threadId).loadVariable(threadId, frameId, var); } - public ArrayChunk loadArrayItems(String threadId, String frameId, PyDebugValue var, int rowOffset, int colOffset, int rows, int cols, String format) throws PyDebuggerException + @Override + public ArrayChunk loadArrayItems(String threadId, String frameId, PyDebugValue var, int rowOffset, int colOffset, int rows, int cols, String format) throws PyDebuggerException { return debugger(threadId).loadArrayItems(threadId, frameId, var, rowOffset, colOffset, rows, cols, format); } @@ -294,17 +287,12 @@ public Collection getThreads() if(myOtherDebuggers.size() > 0) { //here we add process id to thread name in case there are more then one process - return Collections.unmodifiableCollection(Collections2.transform(threads, new Function() - { - @Override - public PyThreadInfo apply(PyThreadInfo t) - { - String threadName = ThreadRegistry.threadName(t.getName(), t.getId()); - PyThreadInfo newThread = new PyThreadInfo(t.getId(), threadName, t.getFrames(), t.getStopReason(), t.getMessage()); - newThread.updateState(t.getState(), t.getFrames()); - return newThread; - } - })); + return Collections.unmodifiableCollection(Collections2.transform(threads, t -> { + String threadName = ThreadRegistry.threadName(t.getName(), t.getId()); + PyThreadInfo newThread = new PyThreadInfo(t.getId(), threadName, t.getFrames(), t.getStopReason(), t.getMessage()); + newThread.updateState(t.getState(), t.getFrames()); + return newThread; + })); } else { @@ -604,7 +592,8 @@ private void addDebugger(RemoteDebugger debugger) } } - public void addCloseListener(RemoteDebuggerCloseListener listener) + @Override + public void addCloseListener(RemoteDebuggerCloseListener listener) { myMainDebugger.addCloseListener(listener); } diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/PyBraceMatcher.java b/python-impl/src/main/java/com/jetbrains/python/impl/PyBraceMatcher.java index 7a6dfdd1..f3570025 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/PyBraceMatcher.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/PyBraceMatcher.java @@ -38,10 +38,12 @@ public PyBraceMatcher() { new BracePair(PyTokenTypes.LBRACKET, PyTokenTypes.RBRACKET, false), new BracePair(PyTokenTypes.LBRACE, PyTokenTypes.RBRACE, false)}; } + @Override public BracePair[] getPairs() { return PAIRS; } + @Override public boolean isPairedBracesAllowedBeforeType(IElementType lbraceType, @Nullable IElementType contextType) { return PyTokenTypes.WHITESPACE_OR_LINEBREAK.contains(contextType) || diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/PyCustomType.java b/python-impl/src/main/java/com/jetbrains/python/impl/PyCustomType.java index 76f5e652..3259efc5 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/PyCustomType.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/PyCustomType.java @@ -15,55 +15,45 @@ */ package com.jetbrains.python.impl; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - -import org.jspecify.annotations.Nullable; import com.google.common.base.Preconditions; -import com.google.common.base.Predicate; import com.google.common.collect.Collections2; -import consulo.language.editor.completion.lookup.LookupElement; -import consulo.util.lang.StringUtil; -import consulo.language.psi.PsiElement; -import consulo.language.util.ProcessingContext; -import consulo.application.util.function.Processor; +import com.jetbrains.python.impl.psi.PyUtil; import com.jetbrains.python.psi.AccessDirection; import com.jetbrains.python.psi.PyCallSiteExpression; import com.jetbrains.python.psi.PyElement; import com.jetbrains.python.psi.PyExpression; -import com.jetbrains.python.impl.psi.PyUtil; import com.jetbrains.python.psi.resolve.PyResolveContext; import com.jetbrains.python.psi.resolve.RatedResolveResult; -import com.jetbrains.python.psi.types.PyCallableParameter; -import com.jetbrains.python.psi.types.PyClassLikeType; -import com.jetbrains.python.psi.types.PyClassType; -import com.jetbrains.python.psi.types.PyType; -import com.jetbrains.python.psi.types.TypeEvalContext; +import com.jetbrains.python.psi.types.*; +import consulo.annotation.access.RequiredReadAction; +import consulo.language.editor.completion.lookup.LookupElement; +import consulo.language.psi.PsiElement; +import consulo.language.util.ProcessingContext; +import consulo.python.impl.localize.PyLocalize; +import consulo.util.collection.ContainerUtil; +import consulo.util.lang.StringUtil; +import org.jspecify.annotations.Nullable; + +import java.util.*; +import java.util.function.Predicate; /** * Custom (aka dynamic) type that delegates calls to some classes you pass to it. * We say this this class mimics such classes. * To be used for cases like "type()". - * It optionally filters methods using {@link Processor} + * It optionally filters methods using {@link Predicate} * * @author Ilya.Kazakevich */ public class PyCustomType implements PyClassLikeType { - private final List myTypesToMimic = new ArrayList<>(); @Nullable - private final Processor myFilter; + private final Predicate myFilter; private final boolean myInstanceType; - /** * @param filter filter to filter methods from classes (may be null to do no filtering) * @param instanceType if true, then this class implements instance (it reports it is not definition and returns "this @@ -71,7 +61,7 @@ public class PyCustomType implements PyClassLikeType * (like ctor) * @param typesToMimic types to "mimic": delegate calls to (must be one at least!) */ - public PyCustomType(@Nullable Processor filter, boolean instanceType, PyClassLikeType... typesToMimic) + public PyCustomType(@Nullable Predicate filter, boolean instanceType, PyClassLikeType... typesToMimic) { Preconditions.checkArgument(typesToMimic.length > 0, "Provide at least one class"); myFilter = filter; @@ -130,7 +120,7 @@ public final List resolveMember(String name, if(results != null) { - globalResult.addAll(Collections2.filter(results, new ResolveFilter())); + globalResult.addAll(ContainerUtil.filter(results, new ResolveFilter())); } } return globalResult; @@ -225,14 +215,14 @@ public final Object[] getCompletionVariants(String completionPrefix, PsiElement for(PyClassLikeType parentType : myTypesToMimic) { - lookupElements.addAll(Collections2.filter(Arrays.asList(parentType.getCompletionVariants(completionPrefix, location, context)), new CompletionFilter())); + lookupElements.addAll(ContainerUtil.filter(Arrays.asList(parentType.getCompletionVariants(completionPrefix, location, context)), new CompletionFilter())); } return lookupElements.toArray(new Object[lookupElements.size()]); } - @Nullable @Override + @RequiredReadAction public final String getName() { Collection classNames = new ArrayList<>(myTypesToMimic.size()); @@ -249,8 +239,7 @@ public final String getName() } } - - return PyBundle.message("custom.type.mimic.name", StringUtil.join(classNames, ",")); + return PyLocalize.customTypeMimicName(StringUtil.join(classNames, ",")).get(); } @Override @@ -275,7 +264,7 @@ public final void assertValid(String message) private class ResolveFilter implements Predicate { @Override - public final boolean apply(@Nullable RatedResolveResult input) + public final boolean test(@Nullable RatedResolveResult input) { if(input == null) { @@ -290,24 +279,24 @@ public final boolean apply(@Nullable RatedResolveResult input) { return false; } - return myFilter.process(pyElement); + return myFilter.test(pyElement); } } @Override - public final void visitMembers(Processor processor, boolean inherited, TypeEvalContext context) + public final void visitMembers(Predicate processor, boolean inherited, TypeEvalContext context) { for(PyClassLikeType type : myTypesToMimic) { // Only visit methods that are allowed by filter (if any) type.visitMembers(t -> { - if(!(t instanceof PyElement)) + if(!(t instanceof PyElement element)) { return true; } - if(myFilter == null || myFilter.process((PyElement) t)) + if(myFilter == null || myFilter.test(element)) { - return processor.process(t); + return processor.test(t); } return true; }, inherited, context); @@ -315,6 +304,7 @@ public final void visitMembers(Processor processor, boolean inherite } @Override + @RequiredReadAction public Set getMemberNames(boolean inherited, TypeEvalContext context) { Set result = new LinkedHashSet<>(); @@ -333,7 +323,7 @@ public Set getMemberNames(boolean inherited, TypeEvalContext context) private class CompletionFilter implements Predicate { @Override - public final boolean apply(@Nullable Object input) + public final boolean test(@Nullable Object input) { if(input == null) { @@ -352,7 +342,7 @@ public final boolean apply(@Nullable Object input) { return false; } - return myFilter.process(pyElement); + return myFilter.test(pyElement); } } } diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/buildout/config/BuildoutCfgParser.java b/python-impl/src/main/java/com/jetbrains/python/impl/buildout/config/BuildoutCfgParser.java index e5bbf9e0..17dedfd0 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/buildout/config/BuildoutCfgParser.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/buildout/config/BuildoutCfgParser.java @@ -15,7 +15,6 @@ */ package com.jetbrains.python.impl.buildout.config; - import consulo.language.ast.ASTNode; import consulo.language.version.LanguageVersion; import consulo.language.parser.PsiBuilder; @@ -26,6 +25,7 @@ * @author traff */ public class BuildoutCfgParser implements PsiParser, BuildoutCfgElementTypes, BuildoutCfgTokenTypes { + @Override public ASTNode parse(IElementType root, PsiBuilder builder, LanguageVersion languageVersion) { PsiBuilder.Marker rootMarker = builder.mark(); Parsing parsing = new Parsing(builder); @@ -141,7 +141,6 @@ private PsiBuilder.Marker mark() { return myBuilder.mark(); } - public void doneAdvance(PsiBuilder.Marker marker, IElementType element) { myBuilder.advanceLexer(); marker.done(element); diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/PyBreakContinueGotoProvider.java b/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/PyBreakContinueGotoProvider.java index c7a947c5..ce2f3291 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/PyBreakContinueGotoProvider.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/PyBreakContinueGotoProvider.java @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.jetbrains.python.impl.codeInsight; import com.jetbrains.python.PyTokenTypes; import com.jetbrains.python.PythonLanguage; import com.jetbrains.python.impl.psi.PyUtil; import com.jetbrains.python.psi.*; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; import consulo.codeEditor.Editor; import consulo.language.ast.ASTNode; @@ -32,12 +32,14 @@ /** * Provides reaction on ctrl+click for {@code break} and {@code continue} statements. - * User: dcheryasov - * Date: Nov 5, 2009 4:58:54 AM + * @author dcheryasov + * @since 2009-11-05 */ @ExtensionImpl public class PyBreakContinueGotoProvider extends GotoDeclarationHandlerBase { + @Override + @RequiredReadAction public PsiElement getGotoDeclarationTarget(PsiElement source, Editor editor) { if (source.getLanguage() instanceof PythonLanguage) { PyLoopStatement loop = PsiTreeUtil.getParentOfType(source, PyLoopStatement.class, false, PyFunction.class, PyClass.class); diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/editorActions/smartEnter/fixers/PyClassFixer.java b/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/editorActions/smartEnter/fixers/PyClassFixer.java index 1cb36e8e..901dba41 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/editorActions/smartEnter/fixers/PyClassFixer.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/editorActions/smartEnter/fixers/PyClassFixer.java @@ -17,6 +17,7 @@ import static com.jetbrains.python.impl.psi.PyUtil.sure; +import consulo.annotation.access.RequiredWriteAction; import consulo.codeEditor.Editor; import consulo.language.psi.PsiElement; import consulo.language.psi.util.PsiTreeUtil; @@ -28,37 +29,31 @@ import consulo.language.util.IncorrectOperationException; /** - * Created by IntelliJ IDEA. - * Author: Alexey.Ivanov - * Date: 16.04.2010 - * Time: 18:41:08 + * @author Alexey.Ivanov + * @since 2010-04-16 */ -public class PyClassFixer extends PyFixer -{ - public PyClassFixer() - { - super(PyClass.class); - } +public class PyClassFixer extends PyFixer { + public PyClassFixer() { + super(PyClass.class); + } - public void doApply(Editor editor, PySmartEnterProcessor processor, PyClass pyClass) throws IncorrectOperationException - { - PsiElement colon = PyPsiUtils.getFirstChildOfType(pyClass, PyTokenTypes.COLON); - if(colon == null) - { - PyArgumentList argList = PsiTreeUtil.getChildOfType(pyClass, PyArgumentList.class); - int colonOffset = sure(argList).getTextRange().getEndOffset(); - String textToInsert = ":"; - if(pyClass.getNameNode() == null) - { - int newCaretOffset = argList.getTextOffset(); - if(argList.getTextLength() == 0) - { - newCaretOffset += 1; - textToInsert = " :"; - } - processor.registerUnresolvedError(newCaretOffset); - } - editor.getDocument().insertString(colonOffset, textToInsert); - } - } + @Override + @RequiredWriteAction + public void doApply(Editor editor, PySmartEnterProcessor processor, PyClass pyClass) throws IncorrectOperationException { + PsiElement colon = PyPsiUtils.getFirstChildOfType(pyClass, PyTokenTypes.COLON); + if (colon == null) { + PyArgumentList argList = PsiTreeUtil.getChildOfType(pyClass, PyArgumentList.class); + int colonOffset = sure(argList).getTextRange().getEndOffset(); + String textToInsert = ":"; + if (pyClass.getNameNode() == null) { + int newCaretOffset = argList.getTextOffset(); + if (argList.getTextLength() == 0) { + newCaretOffset += 1; + textToInsert = " :"; + } + processor.registerUnresolvedError(newCaretOffset); + } + editor.getDocument().insertString(colonOffset, textToInsert); + } + } } diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/imports/OptimizeImportsQuickFix.java b/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/imports/OptimizeImportsQuickFix.java index 3ff606cc..db3e8099 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/imports/OptimizeImportsQuickFix.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/imports/OptimizeImportsQuickFix.java @@ -28,6 +28,7 @@ import consulo.language.psi.PsiFile; import com.jetbrains.python.psi.PyFile; import consulo.language.util.IncorrectOperationException; +import consulo.ui.annotation.RequiredUIAccess; /** * @author yole @@ -49,6 +50,7 @@ public boolean isAvailable(Project project, Editor editor, PsiFile file) { } @Override + @RequiredUIAccess public void invoke(Project project, Editor editor, PsiFile file) throws IncorrectOperationException { optimizeImports(project, file); } @@ -58,6 +60,8 @@ public boolean startInWriteAction() { return false; } + @Override + @RequiredUIAccess public void applyFix(Project project, ProblemDescriptor descriptor) { PsiElement element = descriptor.getPsiElement(); if (element == null) { // stale PSI @@ -67,6 +71,7 @@ public void applyFix(Project project, ProblemDescriptor descriptor) { optimizeImports(project, file); } + @RequiredUIAccess private void optimizeImports(final Project project, final PsiFile file) { ImportOptimizer optimizer = new PyImportOptimizer(); final Runnable runnable = optimizer.processFile(file); diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/intentions/ImportFromToImportIntention.java b/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/intentions/ImportFromToImportIntention.java index 6c63dac3..1df039da 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/intentions/ImportFromToImportIntention.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/intentions/ImportFromToImportIntention.java @@ -21,6 +21,8 @@ import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.PyPsiUtils; import com.jetbrains.python.psi.types.TypeEvalContext; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.codeEditor.Editor; import consulo.document.Document; import consulo.language.ast.ASTNode; @@ -146,6 +148,8 @@ private static String getDots(int level) { return dots; } + @Override + @RequiredReadAction public boolean isAvailable(Project project, Editor editor, PsiFile file) { if (!(file instanceof PyFile)) { return false; @@ -187,20 +191,22 @@ public boolean isAvailable(Project project, Editor editor, PsiFile file) { /** * Adds myModuleName as a qualifier to target. * - * @param target_node what to qualify + * @param targetNode what to qualify * @param project * @param qualifier */ - private static void qualifyTarget(ASTNode target_node, Project project, String qualifier) { + @RequiredWriteAction + private static void qualifyTarget(ASTNode targetNode, Project project, String qualifier) { PyElementGenerator generator = PyElementGenerator.getInstance(project); - target_node.addChild(generator.createDot(), target_node.getFirstChildNode()); - target_node.addChild(sure(generator.createFromText(LanguageLevel.getDefault(), PyReferenceExpression.class, qualifier, new int[]{ + targetNode.addChild(generator.createDot(), targetNode.getFirstChildNode()); + targetNode.addChild(sure(generator.createFromText(LanguageLevel.getDefault(), PyReferenceExpression.class, qualifier, new int[]{ 0, 0 - }).getNode()), target_node.getFirstChildNode()); + }).getNode()), targetNode.getFirstChildNode()); } @Override + @RequiredWriteAction public void doInvoke(Project project, Editor editor, PsiFile file) throws IncorrectOperationException { InfoHolder info = InfoHolder.collect(getElementFromEditor(editor, file)); try { @@ -219,45 +225,43 @@ public void doInvoke(Project project, Editor editor, PsiFile file) throws Incorr qualifier = info.myModuleName; } // find all unqualified references that lead to one of our import elements - final PyImportElement[] ielts = info.myFromImportStatement.getImportElements(); - final PyStarImportElement star_ielt = info.myFromImportStatement.getStarImportElement(); - final Map references = new HashMap<>(); - final List star_references = new ArrayList<>(); - PsiTreeUtil.processElements(file, new PsiElementProcessor() { - public boolean execute(PsiElement element) { - PyPsiUtils.assertValid(element); - if (element instanceof PyReferenceExpression && PsiTreeUtil.getParentOfType(element, PyImportElement.class) == null) { - PyReferenceExpression ref = (PyReferenceExpression) element; - if (!ref.isQualified()) { - ResolveResult[] resolved = ref.getReference().multiResolve(false); - for (ResolveResult rr : resolved) { - if (rr.isValidResult()) { - if (rr.getElement() == star_ielt) { - star_references.add(ref.getReference()); - } - for (PyImportElement ielt : ielts) { - if (rr.getElement() == ielt) { - references.put(ref.getReference(), ielt); - } + PyImportElement[] iElts = info.myFromImportStatement.getImportElements(); + PyStarImportElement starIElt = info.myFromImportStatement.getStarImportElement(); + Map references = new HashMap<>(); + List star_references = new ArrayList<>(); + PsiTreeUtil.processElements(file, element -> { + PyPsiUtils.assertValid(element); + if (element instanceof PyReferenceExpression && PsiTreeUtil.getParentOfType(element, PyImportElement.class) == null) { + PyReferenceExpression ref = (PyReferenceExpression) element; + if (!ref.isQualified()) { + ResolveResult[] resolved = ref.getReference().multiResolve(false); + for (ResolveResult rr : resolved) { + if (rr.isValidResult()) { + if (rr.getElement() == starIElt) { + star_references.add(ref.getReference()); + } + for (PyImportElement iElt : iElts) { + if (rr.getElement() == iElt) { + references.put(ref.getReference(), iElt); } } } } } - return true; } + return true; }); // check that at every replacement site our topmost qualifier name is visible - PyQualifiedExpression top_qualifier; + PyQualifiedExpression topQualifier; PyExpression feeler = info.myModuleReference; do { sure(feeler instanceof PyQualifiedExpression); // if for some crazy reason module name refers to numbers, etc, no point to continue. - top_qualifier = (PyQualifiedExpression) feeler; - feeler = top_qualifier.getQualifier(); + topQualifier = (PyQualifiedExpression) feeler; + feeler = topQualifier.getQualifier(); } while (feeler != null); - String top_name = top_qualifier.getName(); + String top_name = topQualifier.getName(); Collection possible_targets = references.keySet(); if (star_references.size() > 0) { possible_targets = new ArrayList<>(references.keySet().size() + star_references.size()); @@ -277,31 +281,31 @@ public boolean execute(PsiElement element) { // add qualifiers PyElementGenerator generator = PyElementGenerator.getInstance(project); for (Map.Entry entry : references.entrySet()) { - PsiElement referring_elt = entry.getKey().getElement(); - assert referring_elt.isValid(); // else we won't add it - ASTNode target_node = referring_elt.getNode(); - assert target_node != null; // else it won't be valid - PyImportElement ielt = entry.getValue(); - if (ielt.getAsNameElement() != null) { + PsiElement referringElt = entry.getKey().getElement(); + assert referringElt.isValid(); // else we won't add it + ASTNode targetNode = referringElt.getNode(); + assert targetNode != null; // else it won't be valid + PyImportElement iElt = entry.getValue(); + if (iElt.getAsNameElement() != null) { // we have an alias, replace it with real name - PyReferenceExpression refex = ielt.getImportReferenceExpression(); - assert refex != null; // else we won't resolve to this ielt - String real_name = refex.getReferencedName(); - ASTNode new_qualifier = generator.createExpressionFromText(real_name).getNode(); - assert new_qualifier != null; + PyReferenceExpression refEx = iElt.getImportReferenceExpression(); + assert refEx != null; // else we won't resolve to this iElt + String realName = refEx.getReferencedName(); + ASTNode newQualifier = generator.createExpressionFromText(realName).getNode(); + assert newQualifier != null; //ASTNode first_under_target = target_node.getFirstChildNode(); //if (first_under_target != null) new_qualifier.addChildren(first_under_target, null, null); // save the children if any - target_node.getTreeParent().replaceChild(target_node, new_qualifier); - target_node = new_qualifier; + targetNode.getTreeParent().replaceChild(targetNode, newQualifier); + targetNode = newQualifier; } - qualifyTarget(target_node, project, qualifier); + qualifyTarget(targetNode, project, qualifier); } for (PsiReference reference : star_references) { - PsiElement referring_elt = reference.getElement(); - assert referring_elt.isValid(); // else we won't add it - ASTNode target_node = referring_elt.getNode(); - assert target_node != null; // else it won't be valid - qualifyTarget(target_node, project, qualifier); + PsiElement referringElt = reference.getElement(); + assert referringElt.isValid(); // else we won't add it + ASTNode targetNode = referringElt.getNode(); + assert targetNode != null; // else it won't be valid + qualifyTarget(targetNode, project, qualifier); } // transform the import statement PyStatement new_import; @@ -322,8 +326,7 @@ public boolean execute(PsiElement element) { //myFromImportStatement.replace(new_import); } catch (IncorrectOperationException ignored) { - PyUtil.showBalloon(project, PyLocalize.qfixActionFailed().get(), NotificationType.WARNING); + PyUtil.showBalloon(project, PyLocalize.qfixActionFailed(), NotificationType.WARNING); } } } - diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/intentions/ImportToImportFromIntention.java b/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/intentions/ImportToImportFromIntention.java index 372f3d99..3981550c 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/intentions/ImportToImportFromIntention.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/intentions/ImportToImportFromIntention.java @@ -15,16 +15,16 @@ */ package com.jetbrains.python.impl.codeInsight.intentions; -import com.jetbrains.python.impl.PyBundle; import com.jetbrains.python.impl.psi.PyUtil; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.PyPsiUtils; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.codeEditor.Editor; import consulo.language.editor.FileModificationService; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; import consulo.language.psi.PsiReference; -import consulo.language.psi.resolve.PsiElementProcessor; import consulo.language.psi.util.PsiTreeUtil; import consulo.language.util.IncorrectOperationException; import consulo.localize.LocalizeValue; @@ -32,7 +32,6 @@ import consulo.python.impl.localize.PyLocalize; import consulo.ui.NotificationType; import consulo.util.lang.StringUtil; - import org.jspecify.annotations.Nullable; import java.util.ArrayList; @@ -52,7 +51,6 @@ * @since 2009-09-22 */ public class ImportToImportFromIntention extends PyBaseIntentionAction { - private static class IntentionState { private String myModuleName = null; private String myQualifierName = null; @@ -63,6 +61,7 @@ private static class IntentionState { // is anything that resolves to our imported module is just an exact reference to that module private int myRelativeLevel; // true if "from ... import" + @RequiredReadAction public IntentionState(Editor editor, PsiFile file) { boolean available = false; myImportElement = findImportElement(editor, file); @@ -72,8 +71,7 @@ public IntentionState(Editor editor, PsiFile file) { myRelativeLevel = 0; available = true; } - else if (parent instanceof PyFromImportStatement) { - PyFromImportStatement fromImport = (PyFromImportStatement) parent; + else if (parent instanceof PyFromImportStatement fromImport) { int relativeLevel = fromImport.getRelativeLevel(); PyPsiUtils.assertValid(fromImport); if (fromImport.isValid() && relativeLevel > 0 && fromImport.getImportSource() == null) { @@ -91,6 +89,7 @@ public boolean isAvailable() { return myReferences != null && myReferences.size() > 0; } + @RequiredReadAction private void collectReferencesAndOtherData(PsiFile file) { //PyImportElement myImportElement = findImportElement(editor, file); assert myImportElement != null : "isAvailable() must have returned true, but myImportElement is null"; @@ -103,35 +102,31 @@ private void collectReferencesAndOtherData(PsiFile file) { myReferee = importReference.getReference().resolve(); myHasModuleReference = false; if (myReferee != null && myModuleName != null && myQualifierName != null) { - final Collection references = new ArrayList<>(); - PsiTreeUtil.processElements(file, new PsiElementProcessor() { - public boolean execute(PsiElement element) { - if (element instanceof PyReferenceExpression && PsiTreeUtil.getParentOfType( - element, - PyImportElement.class - ) == null) { - PyReferenceExpression ref = (PyReferenceExpression) element; - if (myQualifierName.equals(PyPsiUtils.toPath(ref))) { // filter out other names that might resolve to our target - PsiElement parentElt = ref.getParent(); - if (parentElt instanceof PyQualifiedExpression) { // really qualified by us, not just referencing? - PsiElement resolved = ref.getReference().resolve(); - if (resolved == myReferee) { - references.add(ref.getReference()); - } - } - else { - myHasModuleReference = true; + Collection references = new ArrayList<>(); + PsiTreeUtil.processElements(file, element -> { + if (element instanceof PyReferenceExpression ref + && PsiTreeUtil.getParentOfType(element, PyImportElement.class) == null) { + if (myQualifierName.equals(PyPsiUtils.toPath(ref))) { // filter out other names that might resolve to our target + PsiElement parentElt = ref.getParent(); + if (parentElt instanceof PyQualifiedExpression) { // really qualified by us, not just referencing? + PsiElement resolved = ref.getReference().resolve(); + if (resolved == myReferee) { + references.add(ref.getReference()); } } + else { + myHasModuleReference = true; + } } - return true; } + return true; }); myReferences = references; } } } + @RequiredWriteAction public void invoke() { assert myImportElement != null : "isAvailable() must have returned true, but myImportElement is null"; sure(myImportElement.getImportReferenceExpression()); @@ -160,19 +155,17 @@ public void invoke() { // create a separate import stmt for the module PsiElement importer = myImportElement.getParent(); - PyStatement importStatement; - PyImportElement[] importElements; - if (importer instanceof PyImportStatement) { - importStatement = (PyImportStatement) importer; - importElements = ((PyImportStatement) importStatement).getImportElements(); + PyImportStatementBase importStatement; + if (importer instanceof PyImportStatement importStmt) { + importStatement = importStmt; } - else if (importer instanceof PyFromImportStatement) { - importStatement = (PyFromImportStatement) importer; - importElements = ((PyFromImportStatement) importStatement).getImportElements(); + else if (importer instanceof PyFromImportStatement fromImportStmt) { + importStatement = fromImportStmt; } else { throw new IncorrectOperationException("Not an import at all"); } + PyImportElement[] importElements = importStatement.getImportElements(); PyFromImportStatement newImportStatement = generator.createFromImportStatement(languageLevel, getDots() + myModuleName, StringUtil.join(usedNames, ", "), null); PsiElement parent = importStatement.getParent(); @@ -201,7 +194,7 @@ else if (importer instanceof PyFromImportStatement) { } } catch (IncorrectOperationException ignored) { - PyUtil.showBalloon(project, PyBundle.message("QFIX.action.failed"), NotificationType.WARNING); + PyUtil.showBalloon(project, PyLocalize.qfixActionFailed(), NotificationType.WARNING); } } @@ -226,6 +219,7 @@ private String getDots() { } @Nullable + @RequiredReadAction private static PyImportElement findImportElement(Editor editor, PsiFile file) { PsiElement elementAtCaret = file.findElementAt(editor.getCaretModel().getOffset()); PyImportElement importElement = PsiTreeUtil.getParentOfType(elementAtCaret, PyImportElement.class); @@ -238,6 +232,8 @@ private static PyImportElement findImportElement(Editor editor, PsiFile file) { } } + @Override + @RequiredReadAction public boolean isAvailable(Project project, Editor editor, PsiFile file) { if (!(file instanceof PyFile)) { return false; @@ -252,6 +248,7 @@ public boolean isAvailable(Project project, Editor editor, PsiFile file) { } @Override + @RequiredWriteAction public void doInvoke(Project project, Editor editor, PsiFile file) throws IncorrectOperationException { IntentionState state = new IntentionState(editor, file); state.invoke(); diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/intentions/ImportToggleAliasIntention.java b/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/intentions/ImportToggleAliasIntention.java index d9c4dfde..9f7c9fc5 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/intentions/ImportToggleAliasIntention.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/intentions/ImportToggleAliasIntention.java @@ -17,11 +17,11 @@ import com.jetbrains.python.PyNames; import com.jetbrains.python.codeInsight.controlflow.ScopeOwner; -import com.jetbrains.python.impl.PyBundle; import com.jetbrains.python.impl.psi.PyUtil; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.PyPsiUtils; import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.application.Application; import consulo.application.ApplicationManager; import consulo.codeEditor.Editor; @@ -39,8 +39,10 @@ import consulo.project.Project; import consulo.python.impl.localize.PyLocalize; import consulo.ui.NotificationType; +import consulo.ui.annotation.RequiredUIAccess; import consulo.ui.ex.InputValidator; import consulo.ui.ex.awt.Messages; +import consulo.ui.ex.awt.UIUtil; import consulo.util.lang.Pair; import java.util.ArrayList; @@ -65,6 +67,7 @@ private static class IntentionState { private PyImportStatement myImportStatement; private String myAlias; + @RequiredReadAction private static IntentionState fromContext(Editor editor, PsiFile file) { IntentionState state = new IntentionState(); state.myImportElement = @@ -85,6 +88,7 @@ private static IntentionState fromContext(Editor editor, PsiFile file) { return state; } + @RequiredReadAction public boolean isAvailable() { if (myFromImportStatement != null) { PyPsiUtils.assertValid(myFromImportStatement); @@ -99,25 +103,24 @@ public boolean isAvailable() { } } PyReferenceExpression referenceExpression = myImportElement.getImportReferenceExpression(); - if (referenceExpression == null || referenceExpression.getReference().resolve() == null) { - return false; - } - return true; + return referenceExpression != null && referenceExpression.getReference().resolve() != null; } @RequiredReadAction public LocalizeValue getText() { LocalizeValue addName = LocalizeValue.localizeTODO("Add alias"); if (myImportElement != null) { - PyReferenceExpression refex = myImportElement.getImportReferenceExpression(); - if (refex != null) { - addName = PyLocalize.intnAddAliasForImport$0(refex.getText()); + PyReferenceExpression refEx = myImportElement.getImportReferenceExpression(); + if (refEx != null) { + addName = PyLocalize.intnAddAliasForImport$0(refEx.getText()); } } return myAlias == null ? addName : PyLocalize.intnRemoveAliasForImport$0(myAlias); } } + @Override + @RequiredReadAction public boolean isAvailable(Project project, Editor editor, PsiFile file) { if (!(file instanceof PyFile)) { return false; @@ -129,20 +132,21 @@ public boolean isAvailable(Project project, Editor editor, PsiFile file) { } @Override + @RequiredWriteAction public void doInvoke(final Project project, Editor editor, PsiFile file) throws IncorrectOperationException { // sanity check: isAvailable must have set it. IntentionState state = IntentionState.fromContext(editor, file); // - String target_name; // we set in in the source - final String remove_name; // we replace it in the source + String targetName; // we set in in the source + final String removeName; // we replace it in the source PyReferenceExpression reference = sure(state.myImportElement.getImportReferenceExpression()); // search for references to us with the right name try { - String imported_name = PyPsiUtils.toPath(reference); + String importedName = PyPsiUtils.toPath(reference); if (state.myAlias != null) { // have to remove alias, rename everything to original - target_name = imported_name; - remove_name = state.myAlias; + targetName = importedName; + removeName = state.myAlias; } else { // ask for and add alias @@ -150,38 +154,40 @@ public void doInvoke(final Project project, Editor editor, PsiFile file) throws if (application != null && !application.isUnitTestMode()) { String alias = Messages.showInputDialog( project, - PyBundle.message("INTN.alias.for.$0.dialog.title", imported_name), + PyLocalize.intnAliasFor$0DialogTitle(importedName).get(), "Add Alias", - Messages.getQuestionIcon(), + UIUtil.getQuestionIcon(), "", - new - InputValidator() { - @Override - public boolean checkInput(String inputString) { - return PyNames.isIdentifier(inputString); - } + new InputValidator() { + @Override + @RequiredUIAccess + public boolean checkInput(String inputString) { + return PyNames.isIdentifier(inputString); + } - @Override - public boolean canClose(String inputString) { - return PyNames.isIdentifier(inputString); - } + @Override + @RequiredUIAccess + public boolean canClose(String inputString) { + return PyNames.isIdentifier(inputString); } + } ); if (alias == null) { return; } - target_name = alias; + targetName = alias; } else { // test mode - target_name = "alias"; + targetName = "alias"; } - remove_name = imported_name; + removeName = importedName; } final PsiElement referee = reference.getReference().resolve(); - if (referee != null && imported_name != null) { + if (referee != null && importedName != null) { final Collection references = new ArrayList<>(); ScopeOwner scope = PsiTreeUtil.getParentOfType(state.myImportElement, ScopeOwner.class); PsiTreeUtil.processElements(scope, new PsiElementProcessor() { + @Override public boolean execute(PsiElement element) { getReferences(element); if (element instanceof PyStringLiteralExpression) { @@ -193,11 +199,9 @@ public boolean execute(PsiElement element) { PsiElement first = pair.getFirst(); if (first instanceof ScopeOwner) { ScopeOwner scopeOwner = (ScopeOwner) first; - PsiTreeUtil.processElements(scopeOwner, new PsiElementProcessor() { - public boolean execute(PsiElement element) { - getReferences(element); - return true; - } + PsiTreeUtil.processElements(scopeOwner, element1 -> { + getReferences(element1); + return true; }); } } @@ -207,12 +211,9 @@ public boolean execute(PsiElement element) { } private void getReferences(PsiElement element) { - if (element instanceof PyReferenceExpression && PsiTreeUtil.getParentOfType( - element, - PyImportElement.class - ) == null) { - PyReferenceExpression ref = (PyReferenceExpression) element; - if (remove_name.equals(PyPsiUtils.toPath(ref))) { // filter out other names that might resolve to our target + if (element instanceof PyReferenceExpression ref + && PsiTreeUtil.getParentOfType(element, PyImportElement.class) == null) { + if (removeName.equals(PyPsiUtils.toPath(ref))) { // filter out other names that might resolve to our target PsiElement resolved = ref.getReference().resolve(); if (resolved == referee) { references.add(ref.getReference()); @@ -224,8 +225,8 @@ private void getReferences(PsiElement element) { // no references here is OK by us. if (showConflicts( project, - findDefinitions(target_name, references, Collections.emptySet()), - target_name, + findDefinitions(targetName, references, Collections.emptySet()), + targetName, null )) { return; // got conflicts @@ -244,35 +245,32 @@ private void getReferences(PsiElement element) { } else { // add alias - ASTNode my_ielt_node = sure(state.myImportElement.getNode()); + ASTNode myIEltNode = sure(state.myImportElement.getNode()); PyImportElement fountain = - generator.createFromText(languageLevel, PyImportElement.class, "import foo as " + target_name, new int[]{ - 0, - 2 - }); + generator.createFromText(languageLevel, PyImportElement.class, "import foo as " + targetName, new int[]{0, 2}); ASTNode graft_node = sure(fountain.getNode()); // at import elt graft_node = sure(graft_node.getFirstChildNode()); // at ref graft_node = sure(graft_node.getTreeNext()); // space - my_ielt_node.addChild((ASTNode) graft_node.clone()); + myIEltNode.addChild((ASTNode) graft_node.clone()); graft_node = sure(graft_node.getTreeNext()); // 'as' - my_ielt_node.addChild((ASTNode) graft_node.clone()); + myIEltNode.addChild((ASTNode) graft_node.clone()); graft_node = sure(graft_node.getTreeNext()); // space - my_ielt_node.addChild((ASTNode) graft_node.clone()); + myIEltNode.addChild((ASTNode) graft_node.clone()); graft_node = sure(graft_node.getTreeNext()); // alias - my_ielt_node.addChild((ASTNode) graft_node.clone()); + myIEltNode.addChild((ASTNode) graft_node.clone()); } // alter references for (PsiReference ref : references) { ASTNode ref_name_node = sure(sure(ref.getElement()).getNode()); ASTNode parent = sure(ref_name_node.getTreeParent()); - ASTNode new_name_node = generator.createExpressionFromText(languageLevel, target_name).getNode(); - assert new_name_node != null; - parent.replaceChild(ref_name_node, new_name_node); + ASTNode newNameNode = generator.createExpressionFromText(languageLevel, targetName).getNode(); + assert newNameNode != null; + parent.replaceChild(ref_name_node, newNameNode); } } } catch (IncorrectOperationException ignored) { - PyUtil.showBalloon(project, PyBundle.message("QFIX.action.failed"), NotificationType.WARNING); + PyUtil.showBalloon(project, PyLocalize.qfixActionFailed(), NotificationType.WARNING); } } } diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/intentions/NameUsage.java b/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/intentions/NameUsage.java index 76e832cb..2582038b 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/intentions/NameUsage.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/intentions/NameUsage.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.jetbrains.python.impl.codeInsight.intentions; +import consulo.annotation.access.RequiredReadAction; import consulo.colorScheme.TextAttributes; import consulo.document.Document; import consulo.fileEditor.FileEditorLocation; @@ -34,11 +34,10 @@ /** * Simplistic usage object for demonstration of name clashes, etc. - * User: dcheryasov - * Date: Oct 11, 2009 6:24:05 AM + * @author dcheryasov + * @since 2009-10-11 */ class NameUsage implements PsiElementUsage { - private final PsiElement myElement; private final PsiElement myCulprit; @@ -65,17 +64,23 @@ public NameUsage(PsiElement element, PsiElement culprit, String name, boolean pr myIsPrefix = prefix; } + @Override public FileEditorLocation getLocation() { return null; } + @Override public UsagePresentation getPresentation() { return new UsagePresentation() { @Nullable + @Override + @RequiredReadAction public Image getIcon() { return myElement.isValid() ? IconDescriptorUpdaters.getIcon(myElement, 0) : null; } + @Override + @RequiredReadAction public TextChunk[] getText() { if (myElement.isValid()) { TextChunk[] chunks = new TextChunk[3]; @@ -95,45 +100,61 @@ public TextChunk[] getText() { else return new TextChunk[]{new TextChunk(SLANTED, "?")}; } + @Override + @RequiredReadAction public String getPlainText() { return myElement.getText(); } + @Override + @RequiredReadAction public String getTooltipText() { return myElement.getText(); } }; } + @Override public boolean isValid() { return true; } + @Override public boolean isReadOnly() { return false; } + @Override public void selectInEditor() { } + @Override public void highlightInEditor() { } + @Override + @RequiredReadAction public void navigate(boolean requestFocus) { Navigatable descr = EditSourceUtil.getDescriptor(myElement); if (descr != null) descr.navigate(requestFocus); } + @Override + @RequiredReadAction public boolean canNavigate() { return EditSourceUtil.canNavigate(myElement); } + @Override + @RequiredReadAction public boolean canNavigateToSource() { return false; } + @Override public PsiElement getElement() { return myCulprit; } + @Override public boolean isNonCodeUsage() { return false; } diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/stdlib/PyNamedTupleType.java b/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/stdlib/PyNamedTupleType.java index 882fdc73..9b5b2fd9 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/stdlib/PyNamedTupleType.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/codeInsight/stdlib/PyNamedTupleType.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Set; +import consulo.annotation.access.RequiredReadAction; import org.jspecify.annotations.Nullable; import consulo.language.editor.completion.lookup.LookupElementBuilder; import consulo.language.psi.PsiElement; @@ -95,6 +96,7 @@ public Object[] getCompletionVariants(String completionPrefix, PsiElement locati } @Override + @RequiredReadAction public String getName() { return myName; @@ -130,6 +132,7 @@ public String toString() } @Override + @RequiredReadAction public Set getMemberNames(boolean inherited, TypeEvalContext context) { Set result = super.getMemberNames(inherited, context); diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/debugger/array/JBTableWithRowHeaders.java b/python-impl/src/main/java/com/jetbrains/python/impl/debugger/array/JBTableWithRowHeaders.java index 22cf1f4f..365f125b 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/debugger/array/JBTableWithRowHeaders.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/debugger/array/JBTableWithRowHeaders.java @@ -65,16 +65,15 @@ public JBScrollPane getScrollPane() return myScrollPane; } - public boolean getScrollableTracksViewportWidth() + @Override + public boolean getScrollableTracksViewportWidth() { return getPreferredSize().width < getParent().getWidth(); } - @Override public void setModel(TableModel model) { - super.setModel(model); if(model instanceof AsyncArrayTableModel) { @@ -110,7 +109,6 @@ protected void paintComponent(Graphics g) super.paintComponent(g); } - @Override public void setModel(TableModel model) { @@ -135,15 +133,14 @@ public int getRowHeight(int row) return super.getRowHeight(row); } - @Override public boolean isCellEditable(int row, int column) { return false; } - - public void propertyChange(PropertyChangeEvent e) + @Override + public void propertyChange(PropertyChangeEvent e) { if("selectionModel".equals(e.getPropertyName())) { @@ -169,7 +166,8 @@ public RowNumberRenderer() setHorizontalAlignment(SwingConstants.CENTER); } - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { if(table != null) { @@ -198,7 +196,6 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole public static class CustomTableHeader extends JTableHeader { - public CustomTableHeader(JTable table) { super(); @@ -230,7 +227,6 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole public static class DefaultTableHeaderCellRenderer extends DefaultTableCellRenderer { - public DefaultTableHeaderCellRenderer() { setHorizontalAlignment(CENTER); diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/facet/FacetLibraryConfigurator.java b/python-impl/src/main/java/com/jetbrains/python/impl/facet/FacetLibraryConfigurator.java index 3e1437d4..e479dc3b 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/facet/FacetLibraryConfigurator.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/facet/FacetLibraryConfigurator.java @@ -13,10 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.jetbrains.python.impl.facet; -import consulo.application.ApplicationManager; +import consulo.application.Application; import consulo.content.base.BinariesOrderRootType; import consulo.content.library.Library; import consulo.content.library.LibraryTable; @@ -29,12 +28,13 @@ import consulo.module.content.util.OrderEntryUtil; import consulo.project.Project; import consulo.project.content.library.ProjectLibraryTable; +import consulo.ui.annotation.RequiredUIAccess; import consulo.virtualFileSystem.LocalFileSystem; import consulo.virtualFileSystem.VirtualFile; import consulo.virtualFileSystem.archive.ArchiveFileType; import consulo.virtualFileSystem.archive.ArchiveVfsUtil; - import org.jspecify.annotations.Nullable; + import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -47,36 +47,37 @@ public class FacetLibraryConfigurator { private FacetLibraryConfigurator() { } - public static void attachLibrary(final Module module, - @Nullable final ModifiableRootModel existingModel, - final String libraryName, - final List paths) { - ApplicationManager.getApplication().runWriteAction(new Runnable() { - public void run() { - // add all paths to library - ModifiableRootModel model = - existingModel != null ? existingModel : ModuleRootManager.getInstance(module).getModifiableModel(); - LibraryOrderEntry orderEntry = OrderEntryUtil.findLibraryOrderEntry(model, libraryName); - if (orderEntry != null) { - // update existing - Library lib = orderEntry.getLibrary(); - if (lib != null) { - fillLibrary(module.getProject(), lib, paths); - if (existingModel == null) { - model.commit(); - } - return; + @RequiredUIAccess + public static void attachLibrary( + Module module, + @Nullable ModifiableRootModel existingModel, + String libraryName, + List paths + ) { + Application.get().runWriteAction(() -> { + // add all paths to library + ModifiableRootModel model = + existingModel != null ? existingModel : ModuleRootManager.getInstance(module).getModifiableModel(); + LibraryOrderEntry orderEntry = OrderEntryUtil.findLibraryOrderEntry(model, libraryName); + if (orderEntry != null) { + // update existing + Library lib = orderEntry.getLibrary(); + if (lib != null) { + fillLibrary(module.getProject(), lib, paths); + if (existingModel == null) { + model.commit(); } + return; } - // create new - LibraryTable.ModifiableModel projectLibrariesModel = ProjectLibraryTable.getInstance(model.getProject()).getModifiableModel(); - Library lib = projectLibrariesModel.createLibrary(libraryName); - fillLibrary(module.getProject(), lib, paths); - projectLibrariesModel.commit(); - model.addLibraryEntry(lib); - if (existingModel == null) { - model.commit(); - } + } + // create new + LibraryTable.ModifiableModel projectLibrariesModel = ProjectLibraryTable.getInstance(model.getProject()).getModifiableModel(); + Library lib = projectLibrariesModel.createLibrary(libraryName); + fillLibrary(module.getProject(), lib, paths); + projectLibrariesModel.commit(); + model.addLibraryEntry(lib); + if (existingModel == null) { + model.commit(); } }); } @@ -86,7 +87,7 @@ private static void fillLibrary(Project project, Library lib, List paths for (String root : lib.getUrls(BinariesOrderRootType.ID)) { modifiableModel.removeRoot(root, BinariesOrderRootType.ID); } - Set roots = new HashSet(); + Set roots = new HashSet<>(); ProjectRootManager rootManager = ProjectRootManager.getInstance(project); Collections.addAll(roots, rootManager.getContentRoots()); Collections.addAll(roots, rootManager.getContentSourceRoots()); @@ -111,19 +112,18 @@ private static void fillLibrary(Project project, Library lib, List paths modifiableModel.commit(); } - public static void detachLibrary(final Module module, final String libraryName) { - ApplicationManager.getApplication().runWriteAction(new Runnable() { - public void run() { - // remove the library - ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel(); - OrderEntry entry = OrderEntryUtil.findLibraryOrderEntry(model, libraryName); - if (entry == null) { - model.dispose(); - } - else { - model.removeOrderEntry(entry); - model.commit(); - } + @RequiredUIAccess + public static void detachLibrary(Module module, String libraryName) { + Application.get().runWriteAction(() -> { + // remove the library + ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel(); + OrderEntry entry = OrderEntryUtil.findLibraryOrderEntry(model, libraryName); + if (entry == null) { + model.dispose(); + } + else { + model.removeOrderEntry(entry); + model.commit(); } }); } diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/findUsages/PyClassGroupingRuleProvider.java b/python-impl/src/main/java/com/jetbrains/python/impl/findUsages/PyClassGroupingRuleProvider.java index f7cecb97..fc36e500 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/findUsages/PyClassGroupingRuleProvider.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/findUsages/PyClassGroupingRuleProvider.java @@ -13,10 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.jetbrains.python.impl.findUsages; - +import consulo.annotation.access.RequiredReadAction; import consulo.project.Project; import consulo.language.psi.PsiElement; import consulo.language.psi.util.PsiTreeUtil; @@ -33,17 +32,20 @@ */ public class PyClassGroupingRuleProvider implements FileStructureGroupRuleProvider { + @Override public UsageGroupingRule getUsageGroupingRule(Project project) { return new PyClassGroupingRule(); } private static class PyClassGroupingRule implements UsageGroupingRule { + @Override + @RequiredReadAction public UsageGroup groupUsage(Usage usage) { - if (!(usage instanceof PsiElementUsage)) return null; - PsiElement psiElement = ((PsiElementUsage)usage).getElement(); + if (!(usage instanceof PsiElementUsage elementUsage)) return null; + PsiElement psiElement = elementUsage.getElement(); PyClass pyClass = PsiTreeUtil.getParentOfType(psiElement, PyClass.class); if (pyClass != null) { - return new PsiNamedElementUsageGroupBase(pyClass); + return new PsiNamedElementUsageGroupBase<>(pyClass); } return null; } diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/inspections/quickfix/ListCreationQuickFix.java b/python-impl/src/main/java/com/jetbrains/python/impl/inspections/quickfix/ListCreationQuickFix.java index e001f924..4a1e0b0d 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/inspections/quickfix/ListCreationQuickFix.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/inspections/quickfix/ListCreationQuickFix.java @@ -16,6 +16,7 @@ package com.jetbrains.python.impl.inspections.quickfix; import com.jetbrains.python.psi.*; +import consulo.annotation.access.RequiredWriteAction; import consulo.language.editor.inspection.LocalQuickFix; import consulo.language.editor.inspection.ProblemDescriptor; import consulo.localize.LocalizeValue; @@ -30,7 +31,7 @@ */ public class ListCreationQuickFix implements LocalQuickFix { private final PyAssignmentStatement myStatement; - private final List myStatements = new ArrayList(); + private final List myStatements = new ArrayList<>(); public ListCreationQuickFix(PyAssignmentStatement statement) { myStatement = statement; @@ -45,6 +46,8 @@ public LocalizeValue getName() { return PyLocalize.qfixListCreation(); } + @Override + @RequiredWriteAction public void applyFix(Project project, ProblemDescriptor descriptor) { PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project); StringBuilder stringBuilder = new StringBuilder(); @@ -62,6 +65,7 @@ public void applyFix(Project project, ProblemDescriptor descriptor) { statement.delete(); } assignedValue.replace( - elementGenerator.createExpressionFromText("[" + stringBuilder.substring(0, stringBuilder.length() - 2) + "]")); + elementGenerator.createExpressionFromText("[" + stringBuilder.substring(0, stringBuilder.length() - 2) + "]") + ); } } diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/inspections/quickfix/MoveFromFutureImportQuickFix.java b/python-impl/src/main/java/com/jetbrains/python/impl/inspections/quickfix/MoveFromFutureImportQuickFix.java index 8be70376..ca7c7ecf 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/inspections/quickfix/MoveFromFutureImportQuickFix.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/inspections/quickfix/MoveFromFutureImportQuickFix.java @@ -16,10 +16,10 @@ package com.jetbrains.python.impl.inspections.quickfix; import com.jetbrains.python.psi.PyFile; +import consulo.annotation.access.RequiredWriteAction; import consulo.language.editor.inspection.LocalQuickFix; import consulo.language.editor.inspection.ProblemDescriptor; import consulo.language.psi.PsiElement; -import consulo.language.psi.PsiFile; import consulo.localize.LocalizeValue; import consulo.project.Project; import consulo.python.impl.localize.PyLocalize; @@ -34,11 +34,11 @@ public LocalizeValue getName() { return PyLocalize.qfixMoveFromFutureImport(); } + @Override + @RequiredWriteAction public void applyFix(Project project, ProblemDescriptor descriptor) { PsiElement problemElement = descriptor.getPsiElement(); - PsiFile psiFile = problemElement.getContainingFile(); - if (psiFile instanceof PyFile) { - PyFile file = (PyFile) psiFile; + if (problemElement.getContainingFile() instanceof PyFile file) { file.addBefore(problemElement, file.getStatements().get(0)); problemElement.delete(); } diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/inspections/quickfix/PyAddExceptionSuperClassQuickFix.java b/python-impl/src/main/java/com/jetbrains/python/impl/inspections/quickfix/PyAddExceptionSuperClassQuickFix.java index 69f7daa9..f74b7a03 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/inspections/quickfix/PyAddExceptionSuperClassQuickFix.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/inspections/quickfix/PyAddExceptionSuperClassQuickFix.java @@ -16,11 +16,10 @@ package com.jetbrains.python.impl.inspections.quickfix; import com.jetbrains.python.psi.*; +import consulo.annotation.access.RequiredWriteAction; import consulo.language.ast.ASTNode; import consulo.language.editor.inspection.LocalQuickFix; import consulo.language.editor.inspection.ProblemDescriptor; -import consulo.language.psi.PsiElement; -import consulo.language.psi.PsiPolyVariantReference; import consulo.localize.LocalizeValue; import consulo.project.Project; import consulo.python.impl.localize.PyLocalize; @@ -31,30 +30,26 @@ public LocalizeValue getName() { return PyLocalize.qfixNameAddExceptionBase(); } + @Override + @RequiredWriteAction public void applyFix(Project project, ProblemDescriptor descriptor) { - PsiElement element = descriptor.getPsiElement(); - if (element instanceof PyCallExpression) { - PyExpression callee = ((PyCallExpression) element).getCallee(); - if (callee instanceof PyReferenceExpression) { - PsiPolyVariantReference reference = ((PyReferenceExpression) callee).getReference(); - PsiElement psiElement = reference.resolve(); - if (psiElement instanceof PyClass) { - PyElementGenerator generator = PyElementGenerator.getInstance(project); - PyArgumentList list = ((PyClass) psiElement).getSuperClassExpressionList(); - if (list != null) { - PyExpression exception = generator.createExpressionFromText(LanguageLevel.forElement(element), "Exception"); - list.addArgument(exception); - } - else { - PyArgumentList expressionList = - generator.createFromText(LanguageLevel.forElement(element), PyClass.class, "class A(Exception): pass") - .getSuperClassExpressionList(); - assert expressionList != null; - ASTNode nameNode = ((PyClass) psiElement).getNameNode(); - assert nameNode != null; - psiElement.addAfter(expressionList, nameNode.getPsi()); - } - } + if (descriptor.getPsiElement() instanceof PyCallExpression call + && call.getCallee() instanceof PyReferenceExpression callee + && callee.getReference().resolve() instanceof PyClass pyClass) { + PyElementGenerator generator = PyElementGenerator.getInstance(project); + PyArgumentList list = pyClass.getSuperClassExpressionList(); + if (list != null) { + PyExpression exception = generator.createExpressionFromText(LanguageLevel.forElement(call), "Exception"); + list.addArgument(exception); + } + else { + PyArgumentList expressionList = + generator.createFromText(LanguageLevel.forElement(call), PyClass.class, "class A(Exception): pass") + .getSuperClassExpressionList(); + assert expressionList != null; + ASTNode nameNode = pyClass.getNameNode(); + assert nameNode != null; + pyClass.addAfter(expressionList, nameNode.getPsi()); } } } diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/inspections/quickfix/PyAddPropertyForFieldQuickFix.java b/python-impl/src/main/java/com/jetbrains/python/impl/inspections/quickfix/PyAddPropertyForFieldQuickFix.java index c41ba67a..e211e10b 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/inspections/quickfix/PyAddPropertyForFieldQuickFix.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/inspections/quickfix/PyAddPropertyForFieldQuickFix.java @@ -17,6 +17,7 @@ import com.jetbrains.python.impl.psi.PyUtil; import com.jetbrains.python.psi.*; +import consulo.annotation.access.RequiredWriteAction; import consulo.language.editor.inspection.LocalQuickFix; import consulo.language.editor.inspection.ProblemDescriptor; import consulo.language.psi.PsiElement; @@ -39,6 +40,8 @@ public LocalizeValue getName() { return myName; } + @Override + @RequiredWriteAction public void applyFix(Project project, ProblemDescriptor descriptor) { PsiElement element = descriptor.getPsiElement(); if (element instanceof PyReferenceExpression) { @@ -47,8 +50,7 @@ public void applyFix(Project project, ProblemDescriptor descriptor) { return; } PsiElement resolved = reference.resolve(); - if (resolved instanceof PyTargetExpression) { - PyTargetExpression target = (PyTargetExpression) resolved; + if (resolved instanceof PyTargetExpression target) { PyClass containingClass = target.getContainingClass(); if (containingClass != null) { String name = target.getName(); diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/inspections/quickfix/PyChangeSignatureQuickFix.java b/python-impl/src/main/java/com/jetbrains/python/impl/inspections/quickfix/PyChangeSignatureQuickFix.java index 86f4dbea..bf295457 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/inspections/quickfix/PyChangeSignatureQuickFix.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/inspections/quickfix/PyChangeSignatureQuickFix.java @@ -29,6 +29,7 @@ import consulo.localize.LocalizeValue; import consulo.project.Project; import consulo.python.impl.localize.PyLocalize; +import consulo.ui.annotation.RequiredUIAccess; import java.util.List; @@ -44,6 +45,8 @@ public LocalizeValue getName() { return PyLocalize.qfixNameChangeSignature(); } + @Override + @RequiredUIAccess public void applyFix(Project project, ProblemDescriptor descriptor) { final PyFunction function = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PyFunction.class); if (function == null) { @@ -78,7 +81,7 @@ public List getParameters() { dialog.show(); } - //@Override + @Override public boolean startInWriteAction() { return false; } diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/LightNamedElement.java b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/LightNamedElement.java index b6e7432b..d972a25c 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/LightNamedElement.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/LightNamedElement.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.jetbrains.python.impl.psi.impl; import consulo.language.Language; @@ -36,22 +35,27 @@ public LightNamedElement(PsiManager manager, Language language, String name) { myName = name; } + @Override public String getText() { return myName; } + @Override public void accept(PsiElementVisitor visitor) { visitor.visitElement(this); } + @Override public PsiElement copy() { return null; } + @Override public String getName() { return myName; } + @Override public PsiElement setName(String name) throws IncorrectOperationException { throw new UnsupportedOperationException("LightNamedElement#setName() is not supported"); diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/ParamHelper.java b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/ParamHelper.java index ce9a7592..718371e4 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/ParamHelper.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/ParamHelper.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.jetbrains.python.impl.psi.impl; import com.jetbrains.python.psi.*; @@ -89,20 +88,25 @@ public interface ParamWalker { } public static abstract class ParamVisitor implements ParamWalker { + @Override public void enterTupleParameter(PyTupleParameter param, boolean first, boolean last) { } + @Override public void leaveTupleParameter(PyTupleParameter param, boolean first, boolean last) { } + @Override public void visitNamedParameter(PyNamedParameter param, boolean first, boolean last) { } + @Override public void visitSingleStarParameter(PySingleStarParameter param, boolean first, boolean last) { } } public static List collectNamedParameters(PyParameterList plist) { - final List result = new ArrayList(10); // a random 'enough' + final List result = new ArrayList<>(10); // a random 'enough' walkDownParamArray( plist.getParameters(), new ParamVisitor() { + @Override public void visitNamedParameter(PyNamedParameter param, boolean first, boolean last) { result.add(param); } @@ -110,5 +114,4 @@ public void visitNamedParameter(PyNamedParameter param, boolean first, boolean l ); return result; } - } diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyArgumentListImpl.java b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyArgumentListImpl.java index 019346aa..cfe66564 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyArgumentListImpl.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyArgumentListImpl.java @@ -24,6 +24,8 @@ import com.jetbrains.python.impl.PythonDialectsTokenSetProvider; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.PyPsiUtils; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.language.ast.ASTNode; import consulo.language.ast.IElementType; import consulo.language.ast.TokenSet; @@ -71,12 +73,15 @@ public Collection getArgumentExpressions() return result; } - public PyExpression[] getArguments() + @Override + public PyExpression[] getArguments() { return childrenToPsi(PythonDialectsTokenSetProvider.INSTANCE.getExpressionTokens(), PyExpression.EMPTY_ARRAY); } - @Nullable + @Nullable + @Override + @RequiredReadAction public PyKeywordArgument getKeywordArgument(String name) { ASTNode node = getNode().getFirstChildNode(); @@ -97,6 +102,7 @@ public PyKeywordArgument getKeywordArgument(String name) } @Override + @RequiredWriteAction public void addArgument(PyExpression arg) { PyElementGenerator generator = new PyElementGeneratorImpl(getProject()); @@ -112,42 +118,30 @@ public void addArgument(PyExpression arg) } - if(arg instanceof PyKeywordArgument) - { - if(parameters.isEmpty()) - { + if (arg instanceof PyKeywordArgument) { + if (parameters.isEmpty()) { generator.insertItemIntoListRemoveRedundantCommas(this, keywordArguments.getLast(), arg); } - else - { - if(keywordArguments.isEmpty()) - { - generator.insertItemIntoListRemoveRedundantCommas(this, parameters.getLast(), arg); - } - else - { - generator.insertItemIntoListRemoveRedundantCommas(this, keywordArguments.getLast(), arg); - } - } - } - else - { - if(parameters.isEmpty()) - { - generator.insertItemIntoListRemoveRedundantCommas(this, null, arg); - } - else - { - generator.insertItemIntoListRemoveRedundantCommas(this, parameters.getLast(), arg); - } + else if (keywordArguments.isEmpty()) { + generator.insertItemIntoListRemoveRedundantCommas(this, parameters.getLast(), arg); + } + else { + generator.insertItemIntoListRemoveRedundantCommas(this, keywordArguments.getLast(), arg); + } } + else if (parameters.isEmpty()) { + generator.insertItemIntoListRemoveRedundantCommas(this, null, arg); + } + else { + generator.insertItemIntoListRemoveRedundantCommas(this, parameters.getLast(), arg); + } } - /** * @return parameters (as opposite to keyword arguments) */ - private Deque getParameters() + @RequiredReadAction + private Deque getParameters() { PyExpression[] childrenOfType = PsiTreeUtil.getChildrenOfType(this, PyExpression.class); if(childrenOfType == null) @@ -160,12 +154,15 @@ private Deque getParameters() /** * @return keyword arguments (as opposite to parameters) */ - private Deque getKeyWordArguments() + @RequiredReadAction + private Deque getKeyWordArguments() { return Queues.newArrayDeque(PsiTreeUtil.findChildrenOfType(this, PyKeywordArgument.class)); } - public void addArgumentFirst(PyExpression arg) + @Override + @RequiredWriteAction + public void addArgumentFirst(PyExpression arg) { ASTNode node = getNode(); ASTNode[] pars = node.getChildren(TokenSet.create(PyTokenTypes.LPAR)); @@ -230,6 +227,7 @@ private static boolean elementPrecedesElementsOfType(ASTNode before, TokenSet ex return false; } + @RequiredWriteAction private void addArgumentLastWithoutComma(PyExpression arg) { ASTNode par = getClosingParen(); @@ -252,6 +250,8 @@ private void addArgumentLastWithoutComma(PyExpression arg) } @Nullable + @Override + @RequiredReadAction public ASTNode getClosingParen() { ASTNode node = getNode(); @@ -259,7 +259,8 @@ public ASTNode getClosingParen() return children.length == 0 ? null : children[children.length - 1]; } - private void addArgumentNode(PyExpression arg, ASTNode beforeThis, boolean commaFirst) + @RequiredWriteAction + private void addArgumentNode(PyExpression arg, ASTNode beforeThis, boolean commaFirst) { ASTNode comma = PyElementGenerator.getInstance(getProject()).createComma(); ASTNode node = getNode(); @@ -278,7 +279,9 @@ private void addArgumentNode(PyExpression arg, ASTNode beforeThis, boolean comma } } - public void addArgumentAfter(PyExpression argument, @Nullable PyExpression afterThis) + @Override + @RequiredWriteAction + public void addArgumentAfter(PyExpression argument, @Nullable PyExpression afterThis) { if(afterThis == null) { @@ -338,12 +341,15 @@ else if(next.getElementType() == PyTokenTypes.RPAR) } @Nullable + @Override + @RequiredReadAction public PyCallExpression getCallExpression() { return PsiTreeUtil.getParentOfType(this, PyCallExpression.class); } @Override + @RequiredWriteAction public void deleteChildInternal(ASTNode node) { if(ArrayUtil.contains(node.getPsi(), getArguments())) @@ -364,6 +370,7 @@ protected boolean applyNotNull(PyExpression input) @Nullable @Override + @RequiredReadAction public PyExpression getValueExpressionForParam(FunctionParameter parameter) { String parameterName = parameter.getName(); diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyAssertStatementImpl.java b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyAssertStatementImpl.java index 0122c88e..2b0beced 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyAssertStatementImpl.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyAssertStatementImpl.java @@ -16,6 +16,7 @@ package com.jetbrains.python.impl.psi.impl; +import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.ASTNode; import com.jetbrains.python.impl.PythonDialectsTokenSetProvider; import com.jetbrains.python.psi.PyAssertStatement; @@ -30,11 +31,13 @@ public PyAssertStatementImpl(ASTNode astNode) { super(astNode); } + @Override protected void acceptPyVisitor(PyElementVisitor pyVisitor) { pyVisitor.visitPyAssertStatement(this); } @Override + @RequiredReadAction public PyExpression[] getArguments() { return childrenToPsi(PythonDialectsTokenSetProvider.INSTANCE.getExpressionTokens(), PyExpression.EMPTY_ARRAY); } diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyAssignmentStatementImpl.java b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyAssignmentStatementImpl.java index ee28746f..cf8560c8 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyAssignmentStatementImpl.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyAssignmentStatementImpl.java @@ -19,6 +19,7 @@ import java.util.Arrays; import java.util.List; +import consulo.annotation.access.RequiredReadAction; import org.jspecify.annotations.Nullable; import com.google.common.collect.Lists; import com.jetbrains.python.impl.psi.PyUtil; @@ -53,7 +54,9 @@ protected void acceptPyVisitor(PyElementVisitor pyVisitor) pyVisitor.visitPyAssignmentStatement(this); } - public PyExpression[] getTargets() + @Override + @RequiredReadAction + public PyExpression[] getTargets() { if(myTargets == null) { @@ -63,12 +66,14 @@ public PyExpression[] getTargets() } @Override + @RequiredReadAction public PyExpression[] getRawTargets() { return calcTargets(true); } - private PyExpression[] calcTargets(boolean raw) + @RequiredReadAction + private PyExpression[] calcTargets(boolean raw) { ASTNode[] eqSigns = getNode().getChildren(TokenSet.create(PyTokenTypes.EQ)); if(eqSigns.length == 0) @@ -111,6 +116,7 @@ private PyExpression[] calcTargets(boolean raw) @Nullable @Override + @RequiredReadAction public PyAnnotation getAnnotation() { return findChildByClass(PyAnnotation.class); @@ -148,6 +154,8 @@ else if(psi instanceof PyStarExpression) * @return rightmost expression in statement, which is supposedly the assigned value, or null. */ @Nullable + @Override + @RequiredReadAction public PyExpression getAssignedValue() { PsiElement child = getLastChild(); @@ -162,7 +170,9 @@ public PyExpression getAssignedValue() return (PyExpression) child; } - public List> getTargetsToValuesMapping() + @Override + @RequiredReadAction + public List> getTargetsToValuesMapping() { List> ret = new SmartList<>(); if(!PsiTreeUtil.hasErrorElements(this)) @@ -186,6 +196,8 @@ public List> getTargetsToValuesMapping() } @Nullable + @Override + @RequiredReadAction public PyExpression getLeftHandSideExpression() { PsiElement child = getFirstChild(); @@ -201,6 +213,7 @@ public PyExpression getLeftHandSideExpression() } @Override + @RequiredReadAction public boolean isAssignmentTo(String name) { PyExpression lhs = getLeftHandSideExpression(); @@ -275,7 +288,8 @@ else if(lhs_tuple != null && rhs_tuple != null) } } - public List getNamedElements() + @Override + public List getNamedElements() { List expressions = PyUtil.flattenedParensAndStars(getTargets()); List result = new ArrayList<>(); @@ -295,6 +309,7 @@ public List getNamedElements() } @Nullable + @RequiredReadAction public PsiNamedElement getNamedElement(String the_name) { // performance: check simple case first diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyAugAssignmentStatementImpl.java b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyAugAssignmentStatementImpl.java index 45cdbafb..dc593723 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyAugAssignmentStatementImpl.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyAugAssignmentStatementImpl.java @@ -21,6 +21,7 @@ import com.jetbrains.python.psi.PyElementVisitor; import com.jetbrains.python.psi.PyExpression; import com.jetbrains.python.psi.impl.PyPsiUtils; +import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.ASTNode; import consulo.language.psi.PsiElement; @@ -42,7 +43,9 @@ protected void acceptPyVisitor(PyElementVisitor pyVisitor) pyVisitor.visitPyAugAssignmentStatement(this); } - public PyExpression getTarget() + @Override + @RequiredReadAction + public PyExpression getTarget() { PyExpression target = childToPsi(PythonDialectsTokenSetProvider.INSTANCE.getExpressionTokens(), 0); if(target == null) @@ -52,13 +55,16 @@ public PyExpression getTarget() return target; } - @Nullable + @Nullable + @Override + @RequiredReadAction public PyExpression getValue() { return childToPsi(PythonDialectsTokenSetProvider.INSTANCE.getExpressionTokens(), 1); } @Nullable + @Override public PsiElement getOperation() { return PyPsiUtils.getChildByFilter(this, PyTokenTypes.AUG_ASSIGN_OPERATIONS, 0); diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyBaseElementImpl.java b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyBaseElementImpl.java index b63b3202..27b00912 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyBaseElementImpl.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyBaseElementImpl.java @@ -24,6 +24,7 @@ import com.jetbrains.python.psi.impl.PyPsiUtils; import com.jetbrains.python.psi.resolve.PyResolveContext; import com.jetbrains.python.psi.types.TypeEvalContext; +import consulo.annotation.access.RequiredReadAction; import consulo.document.util.TextRange; import consulo.language.ast.ASTNode; import consulo.language.ast.IElementType; @@ -55,6 +56,7 @@ public PyBaseElementImpl(ASTNode node) } @Override + @RequiredReadAction public PythonLanguage getLanguage() { return (PythonLanguage) PythonFileType.INSTANCE.getLanguage(); @@ -73,6 +75,7 @@ public String toString() return className; } + @Override public void accept(PsiElementVisitor visitor) { PyUtil.verboseOnly(() -> PyPsiUtils.assertValid(this)); @@ -91,13 +94,15 @@ protected void acceptPyVisitor(PyElementVisitor pyVisitor) pyVisitor.visitPyElement(this); } - protected T[] childrenToPsi(TokenSet filterSet, T[] array) + @RequiredReadAction + protected T[] childrenToPsi(TokenSet filterSet, T[] array) { ASTNode[] nodes = getNode().getChildren(filterSet); return PyPsiUtils.nodesToPsi(nodes, array); } @Nullable + @RequiredReadAction protected T childToPsi(TokenSet filterSet, int index) { ASTNode[] nodes = getNode().getChildren(filterSet); @@ -110,6 +115,7 @@ protected T childToPsi(TokenSet filterSet, int index) } @Nullable + @RequiredReadAction protected T childToPsi(IElementType elType) { ASTNode node = getNode().findChildByType(elType); @@ -123,6 +129,7 @@ protected T childToPsi(IElementType elType) } @Nullable + @RequiredReadAction protected T childToPsi(TokenSet elTypes) { ASTNode node = getNode().findChildByType(elTypes); @@ -130,7 +137,8 @@ protected T childToPsi(TokenSet elTypes) return node != null ? (T) node.getPsi() : null; } - protected T childToPsiNotNull(TokenSet filterSet, int index) + @RequiredReadAction + protected T childToPsiNotNull(TokenSet filterSet, int index) { PyElement child = childToPsi(filterSet, index); if(child == null) @@ -141,7 +149,8 @@ protected T childToPsiNotNull(TokenSet filterSet, int inde return (T) child; } - protected T childToPsiNotNull(IElementType elType) + @RequiredReadAction + protected T childToPsiNotNull(IElementType elType) { PyElement child = childToPsi(elType); if(child == null) @@ -161,6 +170,7 @@ protected T childToPsiNotNull(IElementType elType) * @return the reference or null. */ @Override + @RequiredReadAction public PsiReference findReferenceAt(int offset) { // copy/paste from SharedPsiElementImplUtil @@ -197,6 +207,7 @@ public PsiReference findReferenceAt(int offset) return new PsiMultiReference(referencesList.toArray(new PsiReference[referencesList.size()]), referencesList.get(referencesList.size() - 1).getElement()); } + @RequiredReadAction private static void addReferences(int offset, PsiElement element, Collection outReferences, PyResolveContext resolveContext) { PsiReference[] references; diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyBinaryExpressionImpl.java b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyBinaryExpressionImpl.java index 0b8aa1c4..fdb7169b 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyBinaryExpressionImpl.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyBinaryExpressionImpl.java @@ -27,6 +27,8 @@ import com.jetbrains.python.psi.resolve.PyResolveContext; import com.jetbrains.python.psi.types.PyType; import com.jetbrains.python.psi.types.TypeEvalContext; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.language.ast.ASTNode; import consulo.language.ast.IElementType; import consulo.language.psi.PsiElement; @@ -55,21 +57,29 @@ protected void acceptPyVisitor(PyElementVisitor pyVisitor) { } @Nullable + @Override + @RequiredReadAction public PyExpression getLeftExpression() { return PsiTreeUtil.getChildOfType(this, PyExpression.class); } + @Override + @RequiredReadAction public PyExpression getRightExpression() { return PsiTreeUtil.getNextSiblingOfType(getLeftExpression(), PyExpression.class); } @Nullable + @Override + @RequiredReadAction public PyElementType getOperator() { PsiElement psiOperator = getPsiOperator(); return psiOperator != null ? (PyElementType)psiOperator.getNode().getElementType() : null; } @Nullable + @Override + @RequiredReadAction public PsiElement getPsiOperator() { ASTNode node = getNode(); ASTNode child = node.findChildByType(PyElementTypes.BINARY_OPS); @@ -79,6 +89,8 @@ public PsiElement getPsiOperator() { return null; } + @Override + @RequiredReadAction public boolean isOperator(String chars) { ASTNode child = getNode().getFirstChildNode(); StringBuilder buf = new StringBuilder(); @@ -93,6 +105,8 @@ public boolean isOperator(String chars) { } @Nullable + @Override + @RequiredReadAction public PyExpression getOppositeExpression(PyExpression expression) throws IllegalArgumentException { PyExpression right = getRightExpression(); PyExpression left = getLeftExpression(); @@ -106,6 +120,7 @@ public PyExpression getOppositeExpression(PyExpression expression) throws Illega } @Override + @RequiredWriteAction public void deleteChildInternal(ASTNode child) { PyExpression left = getLeftExpression(); PyExpression right = getRightExpression(); @@ -130,6 +145,8 @@ public PsiPolyVariantReference getReference(PyResolveContext context) { return new PyOperatorReference(this, context); } + @Override + @RequiredReadAction public PyType getType(TypeEvalContext context, TypeEvalContext.Key key) { if (isOperator("and") || isOperator("or")) { PyExpression left = getLeftExpression(); @@ -183,6 +200,7 @@ public PyType getType(TypeEvalContext context, TypeEvalContext.Key key) { } @Override + @RequiredReadAction public PyExpression getQualifier() { return getLeftExpression(); } @@ -194,17 +212,20 @@ public QualifiedName asQualifiedName() { } @Override + @RequiredReadAction public boolean isQualified() { return getQualifier() != null; } @Override + @RequiredReadAction public String getReferencedName() { PyElementType t = getOperator(); return t != null ? t.getSpecialMethodName() : null; } @Override + @RequiredReadAction public ASTNode getNameElement() { PsiElement op = getPsiOperator(); return op != null ? op.getNode() : null; diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyBoolLiteralExpressionImpl.java b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyBoolLiteralExpressionImpl.java index ea85c0ce..f55f0631 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyBoolLiteralExpressionImpl.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyBoolLiteralExpressionImpl.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.jetbrains.python.impl.psi.impl; +import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.ASTNode; import com.jetbrains.python.psi.PyBoolLiteralExpression; import com.jetbrains.python.psi.PyElementVisitor; @@ -30,11 +30,13 @@ public PyBoolLiteralExpressionImpl(ASTNode astNode) { super(astNode); } + @Override public PyType getType(TypeEvalContext context, TypeEvalContext.Key key) { return PyBuiltinCache.getInstance(this).getBoolType(); } @Override + @RequiredReadAction public boolean getValue() { return "True".equals(getText()); } diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyBreakStatementImpl.java b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyBreakStatementImpl.java index 11fd2f84..c19a9cb0 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyBreakStatementImpl.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyBreakStatementImpl.java @@ -13,10 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.jetbrains.python.impl.psi.impl; - import consulo.language.ast.ASTNode; import consulo.language.psi.PsiElement; import consulo.language.psi.util.PsiTreeUtil; @@ -28,30 +26,27 @@ * @author yole */ public class PyBreakStatementImpl extends PyElementImpl implements PyBreakStatement { - public PyBreakStatementImpl(ASTNode astNode) { - super(astNode); - } + public PyBreakStatementImpl(ASTNode astNode) { + super(astNode); + } - @Override - protected void acceptPyVisitor(PyElementVisitor pyVisitor) { - pyVisitor.visitPyBreakStatement(this); - } + @Override + protected void acceptPyVisitor(PyElementVisitor pyVisitor) { + pyVisitor.visitPyBreakStatement(this); + } - @Nullable - public PyLoopStatement getLoopStatement() { - return getLoopStatement(this); - } + @Nullable + @Override + public PyLoopStatement getLoopStatement() { + return getLoopStatement(this); + } - @Nullable - private static PyLoopStatement getLoopStatement(PsiElement element) { - PyLoopStatement loop = PsiTreeUtil.getParentOfType(element, PyLoopStatement.class); - if (loop instanceof PyStatementWithElse) { - PyStatementWithElse stmt = (PyStatementWithElse)loop; - PyElsePart elsePart = stmt.getElsePart(); - if (PsiTreeUtil.isAncestor(elsePart, element, true)) { - return getLoopStatement(loop); - } + @Nullable + private static PyLoopStatement getLoopStatement(PsiElement element) { + PyLoopStatement loop = PsiTreeUtil.getParentOfType(element, PyLoopStatement.class); + if (loop instanceof PyStatementWithElse stmt && PsiTreeUtil.isAncestor(stmt.getElsePart(), element, true)) { + return getLoopStatement(loop); + } + return loop; } - return loop; - } } diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyCallExpressionImpl.java b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyCallExpressionImpl.java index eab99c13..f15aa8a1 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyCallExpressionImpl.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyCallExpressionImpl.java @@ -15,22 +15,18 @@ */ package com.jetbrains.python.impl.psi.impl; -import org.jspecify.annotations.Nullable; -import consulo.language.ast.ASTNode; -import consulo.language.psi.PsiElement; -import consulo.language.psi.util.PsiTreeUtil; import com.jetbrains.python.FunctionParameter; -import com.jetbrains.python.nameResolver.FQNamesProvider; -import com.jetbrains.python.psi.PyArgumentList; -import com.jetbrains.python.psi.PyCallExpression; -import com.jetbrains.python.psi.PyCallable; -import com.jetbrains.python.psi.PyElementVisitor; -import com.jetbrains.python.psi.PyExpression; -import com.jetbrains.python.psi.PyParenthesizedExpression; import com.jetbrains.python.impl.psi.PyUtil; +import com.jetbrains.python.nameResolver.FQNamesProvider; +import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.resolve.PyResolveContext; import com.jetbrains.python.psi.types.PyType; import com.jetbrains.python.psi.types.TypeEvalContext; +import consulo.annotation.access.RequiredReadAction; +import consulo.language.ast.ASTNode; +import consulo.language.psi.PsiElement; +import consulo.language.psi.util.PsiTreeUtil; +import org.jspecify.annotations.Nullable; /** * @author yole @@ -50,36 +46,44 @@ protected void acceptPyVisitor(PyElementVisitor pyVisitor) } @Nullable + @Override + @RequiredReadAction public PyExpression getCallee() { // peel off any parens, because we may have smth like (lambda x: x+1)(2) PsiElement seeker = getFirstChild(); - while(seeker instanceof PyParenthesizedExpression) + while(seeker instanceof PyParenthesizedExpression parenthesizedExpr) { - seeker = ((PyParenthesizedExpression) seeker).getContainedExpression(); + seeker = parenthesizedExpr.getContainedExpression(); } - return seeker instanceof PyExpression ? (PyExpression) seeker : null; + return seeker instanceof PyExpression expression ? expression : null; } - public PyArgumentList getArgumentList() + @Override + @RequiredReadAction + public PyArgumentList getArgumentList() { return PsiTreeUtil.getChildOfType(this, PyArgumentList.class); } - public PyExpression[] getArguments() + @Override + @RequiredReadAction + public PyExpression[] getArguments() { PyArgumentList argList = getArgumentList(); return argList != null ? argList.getArguments() : PyExpression.EMPTY_ARRAY; } @Override + @RequiredReadAction public T getArgument(int index, Class argClass) { PyExpression[] args = getArguments(); return args.length > index && argClass.isInstance(args[index]) ? argClass.cast(args[index]) : null; } - @Override + @Override + @RequiredReadAction public T getArgument(int index, String keyword, Class argClass) { PyExpression argument = getKeywordArgument(keyword); @@ -103,12 +107,14 @@ public PyExpression getKeywordArgument(String keyword) return PyCallExpressionHelper.getKeywordArgument(this, keyword); } - public void addArgument(PyExpression expression) + @Override + public void addArgument(PyExpression expression) { PyCallExpressionHelper.addArgument(this, expression); } - public PyMarkedCallee resolveCallee(PyResolveContext resolveContext) + @Override + public PyMarkedCallee resolveCallee(PyResolveContext resolveContext) { return PyCallExpressionHelper.resolveCallee(this, resolveContext); } @@ -119,7 +125,8 @@ public PyCallable resolveCalleeFunction(PyResolveContext resolveContext) return PyCallExpressionHelper.resolveCalleeFunction(this, resolveContext); } - public PyMarkedCallee resolveCallee(PyResolveContext resolveContext, int offset) + @Override + public PyMarkedCallee resolveCallee(PyResolveContext resolveContext, int offset) { return PyCallExpressionHelper.resolveCallee(this, resolveContext, offset); } @@ -149,12 +156,14 @@ public boolean isCallee(FQNamesProvider... name) } @Override + @RequiredReadAction public String toString() { return "PyCallExpression: " + PyUtil.getReadableRepr(getCallee(), true); //or: getCalledFunctionReference().getReferencedName(); } - public PyType getType(TypeEvalContext context, TypeEvalContext.Key key) + @Override + public PyType getType(TypeEvalContext context, TypeEvalContext.Key key) { return PyCallExpressionHelper.getCallType(this, context); } diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyClassImpl.java b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyClassImpl.java index 4f7d0970..670ca40a 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyClassImpl.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyClassImpl.java @@ -40,9 +40,10 @@ import com.jetbrains.python.psi.stubs.PyTargetExpressionStub; import com.jetbrains.python.psi.types.*; import com.jetbrains.python.toolbox.Maybe; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.application.Application; import consulo.application.util.*; -import consulo.application.util.function.Processor; import consulo.content.scope.SearchScope; import consulo.language.ast.ASTNode; import consulo.language.ast.TokenSet; @@ -61,11 +62,12 @@ import consulo.util.collection.ContainerUtil; import consulo.util.collection.SmartList; import consulo.util.lang.Comparing; -import consulo.util.lang.ref.Ref; - +import consulo.util.lang.ref.SimpleReference; import org.jspecify.annotations.Nullable; + import java.util.*; import java.util.function.Function; +import java.util.function.Predicate; import static consulo.util.lang.StringUtil.join; import static consulo.util.lang.StringUtil.notNullize; @@ -99,6 +101,7 @@ public MROException(String s) { private class CachedAncestorsProvider implements Function> { @Nullable @Override + @RequiredReadAction public List apply(TypeEvalContext context) { List ancestorTypes; if (isNewStyleClass(context)) { @@ -136,8 +139,8 @@ public PyType getType(TypeEvalContext context, TypeEvalContext.Key key) { } private class NewStyleCachedValueProvider implements ParameterizedCachedValueProvider { - @Override + @RequiredReadAction public CachedValueProvider.@Nullable Result compute(TypeEvalContext param) { return new CachedValueProvider.Result<>(calculateNewStyleClass(param), PsiModificationTracker.MODIFICATION_COUNT); } @@ -170,6 +173,8 @@ private TypeEvalContextBasedCache> getAncestorsCache() { } } + @Override + @RequiredWriteAction public PsiElement setName(String name) throws IncorrectOperationException { ASTNode nameElement = PyUtil.createNewName(this, name); ASTNode node = getNameNode(); @@ -181,6 +186,7 @@ public PsiElement setName(String name) throws IncorrectOperationException { @Nullable @Override + @RequiredReadAction public String getName() { PyClassStub stub = getStub(); if (stub != null) { @@ -192,11 +198,15 @@ public String getName() { } } + @Override + @RequiredReadAction public PsiElement getNameIdentifier() { ASTNode nameNode = getNameNode(); return nameNode != null ? nameNode.getPsi() : null; } + @Override + @RequiredReadAction public ASTNode getNameNode() { return getNode().findChildByType(PyTokenTypes.IDENTIFIER); } @@ -207,6 +217,7 @@ protected void acceptPyVisitor(PyElementVisitor pyVisitor) { } @Override + @RequiredReadAction public PyStatementList getStatementList() { PyStatementList statementList = childToPsi(PyElementTypes.STATEMENT_LIST); assert statementList != null : "Statement list missing for class " + getText(); @@ -214,6 +225,7 @@ public PyStatementList getStatementList() { } @Override + @RequiredReadAction public PyArgumentList getSuperClassExpressionList() { PyArgumentList argList = PsiTreeUtil.getChildOfType(this, PyArgumentList.class); if (argList != null && argList.getFirstChild() != null) { @@ -223,6 +235,7 @@ public PyArgumentList getSuperClassExpressionList() { } @Override + @RequiredReadAction public PyExpression[] getSuperClassExpressions() { PyArgumentList argList = getSuperClassExpressionList(); if (argList != null) { @@ -263,6 +276,7 @@ public final List getAncestorClasses(@Nullable TypeEvalContext context) return results; } + @Override public boolean isSubclass(PyClass parent, @Nullable TypeEvalContext context) { if (this == parent) { return true; @@ -291,16 +305,20 @@ public boolean isSubclass(String superClassQName, @Nullable TypeEvalContext cont return false; } + @Override + @RequiredReadAction public PyDecoratorList getDecoratorList() { return getStubOrPsiChild(PyElementTypes.DECORATOR_LIST); } @Nullable + @Override public String getQualifiedName() { return QualifiedNameFinder.getQualifiedName(this); } @Override + @RequiredReadAction public List getSlots(TypeEvalContext context) { Set result = new LinkedHashSet<>(); boolean found = false; @@ -321,6 +339,7 @@ public List getSlots(TypeEvalContext context) { @Nullable @Override + @RequiredReadAction public List getOwnSlots() { PyClassStub stub = getStub(); if (stub != null) { @@ -329,6 +348,8 @@ public List getOwnSlots() { return PyFileImpl.getStringListFromTargetExpression(PyNames.SLOTS, getClassAttributes()); } + @Override + @RequiredReadAction public PyClass[] getSuperClasses(@Nullable TypeEvalContext context) { if (context == null) { context = TypeEvalContext.codeInsightFallback(getProject()); @@ -351,6 +372,7 @@ public ItemPresentation getPresentation() { return new PyElementPresentation(this) { @Nullable @Override + @RequiredReadAction public String getPresentableText() { PyPsiUtils.assertValid(PyClassImpl.this); StringBuilder result = new StringBuilder(notNullize(getName(), PyNames.UNNAMED_ELEMENT)); @@ -423,19 +445,18 @@ private static List mroMerge(List> sequen } // we either return inside the loop or die by assertion } - private static List mroLinearize(PyClassLikeType type, boolean addThisType, TypeEvalContext context, - Map>> cache) throws MROException { - Ref> computed = cache.get(type); + Map>> cache) throws MROException { + SimpleReference> computed = cache.get(type); if (computed != null) { if (computed.isNull()) { throw new MROException("Circular class inheritance"); } return computed.get(); } - cache.put(type, Ref.create()); + cache.put(type, SimpleReference.create()); List result = null; try { List bases = removeNotNullDuplicates(type.getSuperClassTypes(context)); @@ -459,7 +480,7 @@ private static List mroLinearize(PyClassLikeType type, result = Collections.unmodifiableList(result); } finally { - cache.put(type, Ref.create(result)); + cache.put(type, SimpleReference.create(result)); } return result; } @@ -480,21 +501,25 @@ private static List removeNotNullDuplicates(List list) { } @Override + @RequiredReadAction public PyFunction[] getMethods() { return getClassChildren(PythonDialectsTokenSetProvider.INSTANCE.getFunctionDeclarationTokens(), PyFunction.ARRAY_FACTORY); } @Override + @RequiredReadAction public Map getProperties() { initProperties(); return new HashMap<>(myPropertyCache); } @Override + @RequiredReadAction public PyClass[] getNestedClasses() { return getClassChildren(TokenSet.create(PyElementTypes.CLASS_DECLARATION), PyClass.ARRAY_FACTORY); } + @RequiredReadAction protected T[] getClassChildren(TokenSet elementTypes, ArrayFactory factory) { // TODO: gather all top-level functions, maybe within control statements PyClassStub classStub = getStub(); @@ -512,7 +537,7 @@ protected T[] getClassChildren(TokenSet elementTypes, Arr return result.toArray(factory.create(result.size())); } - private static class NameFinder implements Processor { + private static class NameFinder implements Predicate { private T myResult; private final String[] myNames; @@ -525,7 +550,8 @@ public T getResult() { return myResult; } - public boolean process(T target) { + @Override + public boolean test(T target) { String targetName = target.getName(); for (String name : myNames) { if (name.equals(targetName)) { @@ -538,6 +564,7 @@ public boolean process(T target) { } @Override + @RequiredReadAction public PyFunction findMethodByName(@Nullable String name, boolean inherited, @Nullable TypeEvalContext context) { if (name == null) { return null; @@ -549,6 +576,7 @@ public PyFunction findMethodByName(@Nullable String name, boolean inherited, @Nu @Nullable @Override + @RequiredReadAction public PyClass findNestedClass(String name, boolean inherited) { if (name == null) { return null; @@ -559,6 +587,8 @@ public PyClass findNestedClass(String name, boolean inherited) { } @Nullable + @Override + @RequiredReadAction public PyFunction findInitOrNew(boolean inherited, @Nullable TypeEvalContext context) { NameFinder proc; if (isNewStyleClass(context)) { @@ -581,7 +611,8 @@ public PyFunction findInitOrNew(boolean inherited, @Nullable TypeEvalContext con * @return the first property that both filters accepted. */ @Nullable - private Property processPropertiesInClass(@Nullable String name, @Nullable Processor property_filter, boolean advanced) { + @RequiredReadAction + private Property processPropertiesInClass(@Nullable String name, @Nullable Predicate property_filter, boolean advanced) { // NOTE: fast enough to be rerun every time Property prop = processDecoratedProperties(name, property_filter, advanced); if (prop != null) { @@ -599,7 +630,7 @@ private Property processPropertiesInClass(@Nullable String name, @Nullable Proce if (name == null || name.equals(target.getName())) { prop = PropertyImpl.fromTarget(target); if (prop != null) { - if (property_filter == null || property_filter.process(prop)) { + if (property_filter == null || property_filter.test(prop)) { return prop; } } @@ -610,7 +641,8 @@ private Property processPropertiesInClass(@Nullable String name, @Nullable Proce } @Nullable - private Property processDecoratedProperties(@Nullable String name, @Nullable Processor filter, boolean useAdvancedSyntax) { + @RequiredReadAction + private Property processDecoratedProperties(@Nullable String name, @Nullable Predicate filter, boolean useAdvancedSyntax) { // look at @property decorators Map> grouped = new HashMap<>(); // group suitable same-named methods, each group defines a property @@ -665,7 +697,7 @@ else if (useAdvancedSyntax && qname.matches(decoratorName, PyNames.DELETER)) { } if (getter != NONE || setter != NONE || deleter != NONE) { PropertyImpl prop = new PropertyImpl(decoratorName, getter, setter, deleter, doc, null); - if (filter == null || filter.process(prop)) { + if (filter == null || filter.test(prop)) { return prop; } } @@ -673,6 +705,7 @@ else if (useAdvancedSyntax && qname.matches(decoratorName, PyNames.DELETER)) { return null; } + @RequiredReadAction private Maybe fromPacked(Maybe maybeName) { if (maybeName.isDefined()) { String value = maybeName.value(); @@ -688,7 +721,8 @@ private Maybe fromPacked(Maybe maybeName) { } @Nullable - private Property processStubProperties(@Nullable String name, @Nullable Processor propertyProcessor) { + @RequiredReadAction + private Property processStubProperties(@Nullable String name, @Nullable Predicate propertyProcessor) { PyClassStub stub = getStub(); if (stub != null) { for (StubElement subStub : stub.getChildrenStubs()) { @@ -702,7 +736,7 @@ private Property processStubProperties(@Nullable String name, @Nullable Processo String doc = prop.getDoc(); if (getter != NONE || setter != NONE || deleter != NONE) { PropertyImpl property = new PropertyImpl(targetStub.getName(), getter, setter, deleter, doc, targetStub.getPsi()); - if (propertyProcessor == null || propertyProcessor.process(property)) { + if (propertyProcessor == null || propertyProcessor.test(property)) { return property; } } @@ -715,6 +749,7 @@ private Property processStubProperties(@Nullable String name, @Nullable Processo @Nullable @Override + @RequiredReadAction public Property findProperty(String name, boolean inherited, @Nullable TypeEvalContext context) { Property property = findLocalProperty(name); if (property != null) { @@ -735,6 +770,7 @@ public Property findProperty(String name, boolean inherited, @Nullable TypeEvalC } @Override + @RequiredReadAction public Property findPropertyByCallable(PyCallable callable) { initProperties(); for (Property property : myPropertyCache.values()) { @@ -747,17 +783,20 @@ public Property findPropertyByCallable(PyCallable callable) { return null; } + @RequiredReadAction private Property findLocalProperty(String name) { initProperties(); return myPropertyCache.get(name); } + @RequiredReadAction private synchronized void initProperties() { if (myPropertyCache == null) { myPropertyCache = initializePropertyCache(); } } + @RequiredReadAction private Map initializePropertyCache() { Map result = new HashMap<>(); processProperties(null, property -> { @@ -769,12 +808,14 @@ private Map initializePropertyCache() { @Nullable @Override - public Property scanProperties(@Nullable Processor filter, boolean inherited) { + @RequiredReadAction + public Property scanProperties(@Nullable Predicate filter, boolean inherited) { return processProperties(null, filter, inherited); } @Nullable - private Property processProperties(@Nullable String name, @Nullable Processor filter, boolean inherited) { + @RequiredReadAction + private Property processProperties(@Nullable String name, @Nullable Predicate filter, boolean inherited) { PyPsiUtils.assertValid(this); LanguageLevel level = LanguageLevel.getDefault(); // EA-32381: A tree-based instance may not have a parent element somehow, so getContainingFile() may be not appropriate @@ -833,29 +874,28 @@ public Maybe getDeleter() { return filterNonStubExpression(myDeleter); } + @Override public String getName() { return myName; } + @Override public PyTargetExpression getDefinitionSite() { return mySite; } @Override public Maybe getByDirection(AccessDirection direction) { - switch (direction) { - case READ: - return getGetter(); - case WRITE: - return getSetter(); - case DELETE: - return getDeleter(); - } - throw new IllegalArgumentException("Unknown direction " + PyUtil.nvl(direction)); + return switch (direction) { + case READ -> getGetter(); + case WRITE -> getSetter(); + case DELETE -> getDeleter(); + }; } @Nullable @Override + @RequiredReadAction public PyType getType(TypeEvalContext context) { if (mySite instanceof PyTargetExpressionImpl) { PyType targetDocStringType = ((PyTargetExpressionImpl)mySite).getTypeFromDocString(); @@ -875,6 +915,7 @@ public PyType getType(TypeEvalContext context) { } @Override + @RequiredReadAction protected Maybe translate(@Nullable PyExpression expr) { if (expr == null) { return NONE; @@ -905,6 +946,7 @@ private static Maybe filterNonStubExpression(Maybe maybe return maybeCallable; } + @Override public String toString() { return "property(" + myGetter + ", " + mySetter + ", " + myDeleter + ", " + myDoc + ")"; } @@ -918,11 +960,14 @@ public static PropertyImpl fromTarget(PyTargetExpression target) { } } - public boolean visitMethods(Processor processor, boolean inherited, @Nullable TypeEvalContext context) { + @Override + @RequiredReadAction + public boolean visitMethods(Predicate processor, boolean inherited, @Nullable TypeEvalContext context) { return visitMethods(processor, inherited, false, context); } - private boolean visitMethods(Processor processor, boolean inherited, boolean skipClassObj, TypeEvalContext context) { + @RequiredReadAction + private boolean visitMethods(Predicate processor, boolean inherited, boolean skipClassObj, TypeEvalContext context) { PyFunction[] methods = getMethods(); if (!ContainerUtil.process(methods, processor)) { return false; @@ -940,7 +985,8 @@ private boolean visitMethods(Processor processor, boolean inherited, return true; } - public boolean visitNestedClasses(Processor processor, boolean inherited) { + @RequiredReadAction + public boolean visitNestedClasses(Predicate processor, boolean inherited) { PyClass[] nestedClasses = getNestedClasses(); if (!ContainerUtil.process(nestedClasses, processor)) { return false; @@ -955,7 +1001,9 @@ public boolean visitNestedClasses(Processor processor, boolean inherite return true; } - public boolean visitClassAttributes(Processor processor, boolean inherited, @Nullable TypeEvalContext context) { + @Override + @RequiredReadAction + public boolean visitClassAttributes(Predicate processor, boolean inherited, @Nullable TypeEvalContext context) { List methods = getClassAttributes(); if (!ContainerUtil.process(methods, processor)) { return false; @@ -972,12 +1020,15 @@ public boolean visitClassAttributes(Processor processor, boo } @Override + @RequiredReadAction public final List getClassAttributesInherited(TypeEvalContext context) { MyAttributesCollector attributesCollector = new MyAttributesCollector(); visitClassAttributes(attributesCollector, true, context); return attributesCollector.getAttributes(); } + @Override + @RequiredReadAction public List getClassAttributes() { PyClassStub stub = getStub(); if (stub != null) { @@ -986,12 +1037,11 @@ public List getClassAttributes() { } List result = new ArrayList<>(); for (PsiElement psiElement : getStatementList().getChildren()) { - if (psiElement instanceof PyAssignmentStatement) { - PyAssignmentStatement assignmentStatement = (PyAssignmentStatement)psiElement; + if (psiElement instanceof PyAssignmentStatement assignmentStatement) { PyExpression[] targets = assignmentStatement.getTargets(); for (PyExpression target : targets) { - if (target instanceof PyTargetExpression) { - result.add((PyTargetExpression)target); + if (target instanceof PyTargetExpression targetExpr) { + result.add(targetExpr); } } } @@ -1000,12 +1050,15 @@ public List getClassAttributes() { } @Override + @RequiredReadAction public PyTargetExpression findClassAttribute(String name, boolean inherited, TypeEvalContext context) { NameFinder processor = new NameFinder<>(name); visitClassAttributes(processor, inherited, context); return processor.getResult(); } + @Override + @RequiredReadAction public List getInstanceAttributes() { if (myInstanceAttributes == null) { myInstanceAttributes = collectInstanceAttributes(); @@ -1015,6 +1068,7 @@ public List getInstanceAttributes() { @Nullable @Override + @RequiredReadAction public PyTargetExpression findInstanceAttribute(String name, boolean inherited) { List instanceAttributes = getInstanceAttributes(); for (PyTargetExpression instanceAttribute : instanceAttributes) { @@ -1033,6 +1087,7 @@ public PyTargetExpression findInstanceAttribute(String name, boolean inherited) return null; } + @RequiredReadAction private List collectInstanceAttributes() { Map result = new HashMap<>(); @@ -1053,6 +1108,7 @@ private List collectInstanceAttributes() { return new ArrayList<>(expressions); } + @RequiredReadAction private void collectAttributesInNew(Map result) { PyFunction newMethod = findMethodByName(PyNames.NEW, false, null); if (newMethod != null) { @@ -1062,10 +1118,12 @@ private void collectAttributesInNew(Map result) { } } + @RequiredReadAction public static void collectInstanceAttributes(PyFunction method, Map result) { collectInstanceAttributes(method, result, null); } + @RequiredReadAction public static void collectInstanceAttributes(PyFunction method, Map result, Set existing) { @@ -1093,6 +1151,7 @@ private static List getTargetExpressions(PyFunction function public void visitPyClass(PyClass node) { } + @Override public void visitPyAssignmentStatement(PyAssignmentStatement node) { for (PyExpression expression : node.getTargets()) { if (expression instanceof PyTargetExpression) { @@ -1105,6 +1164,7 @@ public void visitPyAssignmentStatement(PyAssignmentStatement node) { } } + @Override public boolean isNewStyleClass(@Nullable TypeEvalContext context) { return new NotNullLazyValue>() { @Override @@ -1114,9 +1174,9 @@ protected ParameterizedCachedValue compute() { }.getValue().getValue(context); } + @RequiredReadAction private boolean calculateNewStyleClass(@Nullable TypeEvalContext context) { - PsiFile containingFile = getContainingFile(); - if (containingFile instanceof PyFile && ((PyFile)containingFile).getLanguageLevel().isPy3K()) { + if (getContainingFile() instanceof PyFile containingFile && containingFile.getLanguageLevel().isPy3K()) { return true; } PyClass objClass = PyBuiltinCache.getInstance(this).getClass(PyNames.OBJECT); @@ -1143,20 +1203,14 @@ private boolean calculateNewStyleClass(@Nullable TypeEvalContext context) { } private static boolean hasNewStyleMetaClass(PyClass pyClass) { - PsiFile containingFile = pyClass.getContainingFile(); - if (containingFile instanceof PyFile) { - PsiElement element = ((PyFile)containingFile).getElementNamed(PyNames.DUNDER_METACLASS); - if (element instanceof PyTargetExpression) { - QualifiedName qName = ((PyTargetExpression)element).getAssignedQName(); - if (qName != null && qName.matches("type")) { - return true; - } + if (pyClass.getContainingFile() instanceof PyFile containingFile + && containingFile.getElementNamed(PyNames.DUNDER_METACLASS) instanceof PyTargetExpression target) { + QualifiedName qName = target.getAssignedQName(); + if (qName != null && qName.matches("type")) { + return true; } } - if (pyClass.findClassAttribute(PyNames.DUNDER_METACLASS, false, null) != null) { - return true; - } - return false; + return pyClass.findClassAttribute(PyNames.DUNDER_METACLASS, false, null) != null; } @Override @@ -1177,6 +1231,7 @@ public boolean processClassLevelDeclarations(PsiScopeProcessor processor) { } @Override + @RequiredReadAction public boolean processInstanceLevelDeclarations(PsiScopeProcessor processor, @Nullable PsiElement location) { Map declarationsInMethod = new HashMap<>(); PyFunction instanceMethod = PsiTreeUtil.getParentOfType(location, PyFunction.class); @@ -1200,11 +1255,15 @@ public boolean processInstanceLevelDeclarations(PsiScopeProcessor processor, @Nu return true; } + @Override + @RequiredReadAction public int getTextOffset() { ASTNode name = getNameNode(); return name != null ? name.getStartOffset() : super.getTextOffset(); } + @Override + @RequiredReadAction public PyStringLiteralExpression getDocStringExpression() { return DocStringUtil.findDocStringExpression(getStatementList()); } @@ -1224,10 +1283,13 @@ public StructuredDocString getStructuredDocString() { return DocStringUtil.getStructuredDocString(this); } + @Override + @RequiredReadAction public String toString() { return "PyClass: " + getName(); } + @Override public void subtreeChanged() { super.subtreeChanged(); ControlFlowCache.clear(this); @@ -1247,6 +1309,7 @@ public SearchScope getUseScope() { } @Override + @RequiredReadAction public List getSuperClassTypes(TypeEvalContext context) { if (PyNames.FAKE_OLD_BASE.equals(getName())) { return Collections.emptyList(); @@ -1277,6 +1340,7 @@ public List getSuperClassTypes(TypeEvalContext context) { return result; } + @RequiredReadAction private void fillSuperClassesSwitchingToAst(TypeEvalContext context, List result) { for (PyExpression expression : getSuperClassExpressions()) { context.getType(expression); @@ -1326,6 +1390,7 @@ public List getAncestorTypes(TypeEvalContext context) { @Nullable @Override + @RequiredReadAction public PyType getMetaClassType(TypeEvalContext context) { PyPsiUtils.assertValid(this); if (context.maySwitchToAST(this)) { @@ -1349,21 +1414,17 @@ public PyType getMetaClassType(TypeEvalContext context) { } } LanguageLevel level = LanguageLevel.forElement(this); - if (level.isOlderThan(LanguageLevel.PYTHON30)) { - PsiFile file = getContainingFile(); - if (file instanceof PyFile) { - PyFile pyFile = (PyFile)file; - PsiElement element = pyFile.getElementNamed(PyNames.DUNDER_METACLASS); - if (element instanceof PyTypedElement) { - return context.getType((PyTypedElement)element); - } - } + if (level.isOlderThan(LanguageLevel.PYTHON30) + && getContainingFile() instanceof PyFile pyFile + && pyFile.getElementNamed(PyNames.DUNDER_METACLASS) instanceof PyTypedElement typed) { + return context.getType(typed); } return null; } @Nullable @Override + @RequiredReadAction public PyExpression getMetaClassExpression() { LanguageLevel level = LanguageLevel.forElement(this); if (level.isAtLeast(LanguageLevel.PYTHON30)) { @@ -1386,6 +1447,7 @@ public PyExpression getMetaClassExpression() { return null; } + @RequiredReadAction private List getMROAncestorTypes(TypeEvalContext context) throws MROException { PyPsiUtils.assertValid(this); PyType thisType = context.getType(this); @@ -1416,9 +1478,8 @@ private boolean isOverriddenMRO(List ancestorTypes, TypeEvalCon PyClass typeClass = PyBuiltinCache.getInstance(this).getClass("type"); for (PyClass cls : classes) { - PyType metaClassType = cls.getMetaClassType(context); - if (metaClassType instanceof PyClassType) { - PyClass metaClass = ((PyClassType)metaClassType).getPyClass(); + if (cls.getMetaClassType(context) instanceof PyClassType metaClassType) { + PyClass metaClass = metaClassType.getPyClass(); if (cls == metaClass) { return false; } @@ -1540,11 +1601,11 @@ public PyClassLikeType getType(TypeEvalContext context) { return PyUtil.as(context.getType(this), PyClassLikeType.class); } - private static final class MyAttributesCollector implements Processor { + private static final class MyAttributesCollector implements Predicate { private final List myAttributes = new ArrayList<>(); @Override - public boolean process(PyTargetExpression expression) { + public boolean test(PyTargetExpression expression) { myAttributes.add(expression); return true; } diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyElementGeneratorImpl.java b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyElementGeneratorImpl.java index fa7d5aa3..7cd43883 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyElementGeneratorImpl.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/PyElementGeneratorImpl.java @@ -234,9 +234,11 @@ public PsiElement insertItemIntoListRemoveRedundantCommas(PyElement list, // TODO: Adds comma to empty list: adding "foo" to () will create (foo,). That is why "insertItemIntoListRemoveRedundantCommas" was created. // We probably need to fix this method and delete insertItemIntoListRemoveRedundantCommas @Override - public PsiElement insertItemIntoList(PyElement list, - @Nullable PyExpression afterThis, - PyExpression toInsert) throws IncorrectOperationException { + public PsiElement insertItemIntoList( + PyElement list, + @Nullable PyExpression afterThis, + PyExpression toInsert + ) throws IncorrectOperationException { ASTNode add = toInsert.getNode().copyElement(); if (afterThis == null) { ASTNode exprNode = list.getNode(); diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/stubs/PyAnnotationElementType.java b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/stubs/PyAnnotationElementType.java index 3cc9533a..607dd3fa 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/stubs/PyAnnotationElementType.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/stubs/PyAnnotationElementType.java @@ -41,24 +41,27 @@ public PyAnnotationElementType(String debugName) { super(debugName); } + @Override public PyAnnotation createPsi(PyAnnotationStub stub) { return new PyAnnotationImpl(stub); } + @Override public PyAnnotationStub createStub(PyAnnotation psi, StubElement parentStub) { return new PyAnnotationStubImpl(parentStub, PyElementTypes.ANNOTATION); } + @Override public PsiElement createElement(ASTNode node) { return new PyAnnotationImpl(node); } - public void serialize(PyAnnotationStub stub, StubOutputStream dataStream) - throws IOException { + @Override + public void serialize(PyAnnotationStub stub, StubOutputStream dataStream) throws IOException { } - public PyAnnotationStub deserialize(StubInputStream dataStream, StubElement parentStub) - throws IOException { + @Override + public PyAnnotationStub deserialize(StubInputStream dataStream, StubElement parentStub) throws IOException { return new PyAnnotationStubImpl(parentStub, PyElementTypes.ANNOTATION); } } \ No newline at end of file diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/stubs/PyClassElementType.java b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/stubs/PyClassElementType.java index 2b0d4d49..fdfb0301 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/stubs/PyClassElementType.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/psi/impl/stubs/PyClassElementType.java @@ -26,6 +26,7 @@ import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.PyPsiUtils; import com.jetbrains.python.psi.stubs.PyClassStub; +import consulo.annotation.access.RequiredReadAction; import consulo.index.io.StringRef; import consulo.language.ast.ASTNode; import consulo.language.psi.PsiElement; @@ -52,20 +53,31 @@ public PyClassElementType(String debugName) super(debugName); } - public PsiElement createElement(ASTNode node) + @Override + public PsiElement createElement(ASTNode node) { return new PyClassImpl(node); } - public PyClass createPsi(PyClassStub stub) + @Override + public PyClass createPsi(PyClassStub stub) { return new PyClassImpl(stub); } - public PyClassStub createStub(PyClass psi, StubElement parentStub) + @Override + @RequiredReadAction + public PyClassStub createStub(PyClass psi, StubElement parentStub) { - return new PyClassStubImpl(psi.getName(), parentStub, getSuperClassQNames(psi), PyPsiUtils.toQualifiedName(psi.getMetaClassExpression()), psi.getOwnSlots(), PyPsiUtils.strValue(psi - .getDocStringExpression()), getStubElementType()); + return new PyClassStubImpl( + psi.getName(), + parentStub, + getSuperClassQNames(psi), + PyPsiUtils.toQualifiedName(psi.getMetaClassExpression()), + psi.getOwnSlots(), + PyPsiUtils.strValue(psi.getDocStringExpression()), + getStubElementType() + ); } public static Map getSuperClassQNames(PyClass pyClass) @@ -103,7 +115,8 @@ private static QualifiedName resolveOriginalSuperClassQName(PyExpression superCl return PyPsiUtils.toQualifiedName(superClassExpression); } - public void serialize(PyClassStub pyClassStub, StubOutputStream dataStream) throws IOException + @Override + public void serialize(PyClassStub pyClassStub, StubOutputStream dataStream) throws IOException { dataStream.writeName(pyClassStub.getName()); @@ -123,7 +136,8 @@ public void serialize(PyClassStub pyClassStub, StubOutputStream dataStream) thro dataStream.writeUTFFast(docString != null ? docString : ""); } - public PyClassStub deserialize(StubInputStream dataStream, StubElement parentStub) throws IOException + @Override + public PyClassStub deserialize(StubInputStream dataStream, StubElement parentStub) throws IOException { String name = StringRef.toString(dataStream.readName()); @@ -144,7 +158,8 @@ public PyClassStub deserialize(StubInputStream dataStream, StubElement parentStu return new PyClassStubImpl(name, parentStub, superClasses, metaClass, slots, docString, getStubElementType()); } - public void indexStub(PyClassStub stub, IndexSink sink) + @Override + public void indexStub(PyClassStub stub, IndexSink sink) { String name = stub.getName(); if(name != null) diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/psi/resolve/CompletionVariantsProcessor.java b/python-impl/src/main/java/com/jetbrains/python/impl/psi/resolve/CompletionVariantsProcessor.java index a0505594..c53f5aff 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/psi/resolve/CompletionVariantsProcessor.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/psi/resolve/CompletionVariantsProcessor.java @@ -20,13 +20,13 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Predicate; import org.jspecify.annotations.Nullable; import consulo.language.editor.completion.lookup.LookupElement; import consulo.language.editor.completion.lookup.LookupElementBuilder; import consulo.project.Project; -import consulo.util.lang.function.Condition; import consulo.util.lang.StringUtil; import consulo.language.psi.PsiElement; import consulo.language.psi.util.PsiTreeUtil; @@ -62,7 +62,7 @@ public CompletionVariantsProcessor(PsiElement context) super(context); } - public CompletionVariantsProcessor(PsiElement context, @Nullable Condition nodeFilter, @Nullable Condition nameFilter) + public CompletionVariantsProcessor(PsiElement context, @Nullable Predicate nodeFilter, @Nullable Predicate nameFilter) { super(context, nodeFilter, nameFilter); } diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/psi/resolve/VariantsProcessor.java b/python-impl/src/main/java/com/jetbrains/python/impl/psi/resolve/VariantsProcessor.java index 47e61ab4..433dad6c 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/psi/resolve/VariantsProcessor.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/psi/resolve/VariantsProcessor.java @@ -15,31 +15,28 @@ */ package com.jetbrains.python.impl.psi.resolve; -import java.util.ArrayList; -import java.util.List; - -import org.jspecify.annotations.Nullable; -import consulo.util.lang.function.Condition; -import consulo.util.dataholder.Key; -import consulo.util.io.FileUtil; +import com.jetbrains.python.impl.psi.PyUtil; +import com.jetbrains.python.psi.*; +import consulo.annotation.access.RequiredReadAction; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiInvalidElementAccessException; import consulo.language.psi.PsiNamedElement; -import consulo.language.psi.resolve.ResolveState; import consulo.language.psi.resolve.PsiScopeProcessor; +import consulo.language.psi.resolve.ResolveState; import consulo.language.psi.util.QualifiedName; -import com.jetbrains.python.psi.PyElement; -import com.jetbrains.python.psi.PyFile; -import com.jetbrains.python.psi.PyImportElement; -import com.jetbrains.python.psi.PyImportedNameDefiner; -import com.jetbrains.python.psi.PyReferenceExpression; -import com.jetbrains.python.impl.psi.PyUtil; +import consulo.util.dataholder.Key; +import consulo.util.io.FileUtil; +import org.jspecify.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; public abstract class VariantsProcessor implements PsiScopeProcessor { protected final PsiElement myContext; - protected Condition myNodeFilter; - protected Condition myNameFilter; + protected Predicate myNodeFilter; + protected Predicate myNameFilter; protected boolean myPlainNamesOnly = false; // if true, add insert handlers to known things like functions private List myAllowedNames; @@ -51,7 +48,7 @@ public VariantsProcessor(PsiElement context) myContext = context; } - public VariantsProcessor(PsiElement context, @Nullable Condition nodeFilter, @Nullable Condition nameFilter) + public VariantsProcessor(PsiElement context, @Nullable Predicate nodeFilter, @Nullable Predicate nameFilter) { myContext = context; myNodeFilter = nodeFilter; @@ -68,27 +65,25 @@ public void setPlainNamesOnly(boolean plainNamesOnly) myPlainNamesOnly = plainNamesOnly; } - - @Override + @Override + @RequiredReadAction public boolean execute(PsiElement element, ResolveState substitutor) { - if(myNodeFilter != null && !myNodeFilter.value(element)) + if(myNodeFilter != null && !myNodeFilter.test(element)) { return true; // skip whatever the filter rejects } // TODO: refactor to look saner; much code duplication - if(element instanceof PsiNamedElement) + if(element instanceof PsiNamedElement psiNamedElement) { - PsiNamedElement psiNamedElement = (PsiNamedElement) element; String name = PyUtil.getElementNameWithoutExtension(psiNamedElement); if(name != null && nameIsAcceptable(name)) { addElement(name, psiNamedElement); } } - else if(element instanceof PyReferenceExpression) + else if(element instanceof PyReferenceExpression expr) { - PyReferenceExpression expr = (PyReferenceExpression) element; String referencedName = expr.getReferencedName(); if(nameIsAcceptable(referencedName)) { @@ -98,9 +93,8 @@ else if(element instanceof PyReferenceExpression) else if(element instanceof PyImportedNameDefiner) { boolean handledAsImported = false; - if(element instanceof PyImportElement) + if(element instanceof PyImportElement importElement) { - PyImportElement importElement = (PyImportElement) element; handledAsImported = handleImportElement(importElement); } if(!handledAsImported) @@ -166,16 +160,12 @@ private boolean nameIsAcceptable(String name) { return false; } - if(myNameFilter != null && !myNameFilter.value(name)) + if(myNameFilter != null && !myNameFilter.test(name)) { return false; } - if(myAllowedNames != null && !myAllowedNames.contains(name)) - { - return false; - } - return true; - } + return myAllowedNames == null || myAllowedNames.contains(name); + } @Override @Nullable diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/psi/stubs/PropertyStubStorage.java b/python-impl/src/main/java/com/jetbrains/python/impl/psi/stubs/PropertyStubStorage.java index c14dd2d6..49738d52 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/psi/stubs/PropertyStubStorage.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/psi/stubs/PropertyStubStorage.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.jetbrains.python.impl.psi.stubs; import consulo.language.psi.stub.StubInputStream; @@ -32,8 +31,8 @@ /** * Packs property description for storage in a stub. - * User: dcheryasov - * Date: Jun 3, 2010 6:46:01 AM + * @author dcheryasov + * @since 2010-06-03 */ public class PropertyStubStorage extends PropertyBunch implements CustomTargetExpressionStub { @@ -41,7 +40,7 @@ public class PropertyStubStorage extends PropertyBunch implements Custom protected Maybe translate(@Nullable PyExpression ref) { if (ref != null) { String name = ref.getName(); - return name != null ? new Maybe(name) : unknown; + return name != null ? new Maybe<>(name) : unknown; } return none; } @@ -58,6 +57,7 @@ public Class getTypeClass() { return PropertyStubType.class; } + @Override public void serialize(StubOutputStream stream) throws IOException { writeOne(myGetter, stream); writeOne(mySetter, stream); @@ -81,8 +81,8 @@ public static PropertyStubStorage deserialize(StubInputStream stream) throws IOE return me; } - private static final Maybe unknown = new Maybe(); - private static final Maybe none = new Maybe(null); + private static final Maybe unknown = new Maybe<>(); + private static final Maybe none = new Maybe<>(null); @Nullable private static Maybe readOne(StubInputStream stream) throws IOException { @@ -91,7 +91,7 @@ private static Maybe readOne(StubInputStream stream) throws IOException else { String s = ref.getString(); if (IMPOSSIBLE_NAME.equals(s)) return unknown; - else return new Maybe(s); + else return new Maybe<>(s); } } @@ -101,5 +101,4 @@ public static PropertyStubStorage fromCall(@Nullable PyExpression expr) { boolean success = fillFromCall(expr, prop); return success? prop : null; } - } diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/psi/types/PyClassTypeImpl.java b/python-impl/src/main/java/com/jetbrains/python/impl/psi/types/PyClassTypeImpl.java index 46eedb4b..0e3b0550 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/psi/types/PyClassTypeImpl.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/psi/types/PyClassTypeImpl.java @@ -32,7 +32,7 @@ import com.jetbrains.python.psi.resolve.RatedResolveResult; import com.jetbrains.python.psi.types.*; import com.jetbrains.python.toolbox.Maybe; -import consulo.application.util.function.Processor; +import consulo.annotation.access.RequiredReadAction; import consulo.component.extension.Extensions; import consulo.language.editor.completion.CompletionUtilCore; import consulo.language.editor.completion.lookup.LookupElement; @@ -47,11 +47,11 @@ import consulo.util.dataholder.Key; import consulo.util.dataholder.UserDataHolderBase; import consulo.util.lang.Pair; -import consulo.util.lang.function.Condition; import consulo.util.lang.ref.Ref; - import org.jspecify.annotations.Nullable; + import java.util.*; +import java.util.function.Predicate; /** * @author yole @@ -62,7 +62,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType protected final PyClass myClass; protected final boolean myIsDefinition; - private static ThreadLocal>> ourResolveMemberStack = new ThreadLocal>>() + private static ThreadLocal>> ourResolveMemberStack = new ThreadLocal<>() { @Override protected Set> initialValue() @@ -655,14 +655,14 @@ public Object[] getCompletionVariants(String prefix, PsiElement location, Proces } @Override - public void visitMembers(Processor processor, boolean inherited, TypeEvalContext context) + public void visitMembers(Predicate processor, boolean inherited, TypeEvalContext context) { myClass.visitMethods(new MyProcessorWrapper<>(processor), false, context); myClass.visitClassAttributes(new MyProcessorWrapper<>(processor), false, context); for(PyTargetExpression expression : myClass.getInstanceAttributes()) { - processor.process(expression); + processor.test(expression); } if(!inherited) @@ -681,6 +681,7 @@ public void visitMembers(Processor processor, boolean inherited, Typ } @Override + @RequiredReadAction public Set getMemberNames(boolean inherited, TypeEvalContext context) { Set result = new LinkedHashSet<>(); @@ -913,19 +914,19 @@ public static PyClassTypeImpl createTypeByQName(PsiElement anchor, String classQ return new PyClassTypeImpl(pyClass, isDefinition); } - private static final class MyProcessorWrapper implements Processor + private static final class MyProcessorWrapper implements Predicate { - private final Processor myProcessor; + private final Predicate myProcessor; - private MyProcessorWrapper(Processor processor) + private MyProcessorWrapper(Predicate processor) { myProcessor = processor; } @Override - public boolean process(T t) + public boolean test(T t) { - myProcessor.process(t); + myProcessor.test(t); return true; } } @@ -933,7 +934,7 @@ public boolean process(T t) /** * Accepts only targets that are not the given object. */ - public static class FilterNotInstance implements Condition + public static class FilterNotInstance implements Predicate { Object instance; @@ -942,7 +943,7 @@ public FilterNotInstance(Object instance) this.instance = instance; } - public boolean value(PsiElement target) + public boolean test(PsiElement target) { return (instance != target); } diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/refactoring/changeSignature/PyChangeSignatureDialog.java b/python-impl/src/main/java/com/jetbrains/python/impl/refactoring/changeSignature/PyChangeSignatureDialog.java index 54c2eb4a..6c209982 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/refactoring/changeSignature/PyChangeSignatureDialog.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/refactoring/changeSignature/PyChangeSignatureDialog.java @@ -13,17 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.jetbrains.python.impl.refactoring.changeSignature; import com.jetbrains.python.PyNames; import com.jetbrains.python.PythonFileType; import com.jetbrains.python.PythonLanguage; -import com.jetbrains.python.impl.PyBundle; import com.jetbrains.python.impl.refactoring.introduce.IntroduceValidator; import com.jetbrains.python.psi.LanguageLevel; import com.jetbrains.python.psi.PyFunction; import com.jetbrains.python.psi.PyParameterList; +import consulo.annotation.access.RequiredReadAction; import consulo.document.Document; import consulo.document.event.DocumentAdapter; import consulo.document.event.DocumentEvent; @@ -41,6 +40,8 @@ import consulo.language.psi.PsiDocumentManager; import consulo.language.psi.util.PsiTreeUtil; import consulo.project.Project; +import consulo.python.impl.localize.PyLocalize; +import consulo.ui.annotation.RequiredUIAccess; import consulo.ui.ex.awt.JBLabel; import consulo.ui.ex.awt.UIUtil; import consulo.ui.ex.awt.ValidationInfo; @@ -54,8 +55,6 @@ import javax.swing.*; import java.awt.*; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -63,7 +62,7 @@ import java.util.function.Consumer; /** - * User : ktisha + * @author ktisha */ public class PyChangeSignatureDialog extends ChangeSignatureDialogBase { @@ -78,6 +77,7 @@ protected LanguageFileType getFileType() { } @Override + @RequiredReadAction protected PyParameterTableModel createParametersInfoModel(PyMethodDescriptor method) { PyParameterList parameterList = PsiTreeUtil.getChildOfType(method.getMethod(), PyParameterList.class); return new PyParameterTableModel(parameterList, myDefaultValueContext, myProject); @@ -104,26 +104,27 @@ protected CallerChooserBase createCallerChooser(String title, Tree t public boolean isNameValid(String name, Project project) { NamesValidator validator = NamesValidator.forLanguage(PythonLanguage.getInstance()); - return (name != null) && - (validator.isIdentifier(name, project)) && - !(validator.isKeyword(name, project)); + return name != null + && validator.isIdentifier(name, project) + && !validator.isKeyword(name, project); } @Nullable @Override + @RequiredReadAction protected String validateAndCommitData() { String functionName = myNameField.getText().trim(); if (!functionName.equals(myMethod.getName())) { boolean defined = IntroduceValidator.isDefinedInScope(functionName, myMethod.getMethod()); if (defined) { - return PyBundle.message("refactoring.change.signature.dialog.validation.name.defined"); + return PyLocalize.refactoringChangeSignatureDialogValidationNameDefined().get(); } if (!isNameValid(functionName, myProject)) { - return PyBundle.message("refactoring.change.signature.dialog.validation.function.name"); + return PyLocalize.refactoringChangeSignatureDialogValidationFunctionName().get(); } } List parameters = myParametersTableModel.getItems(); - Set parameterNames = new HashSet(); + Set parameterNames = new HashSet<>(); boolean hadPositionalContainer = false; boolean hadKeywordContainer = false; boolean hadDefaultValue = false; @@ -138,43 +139,43 @@ protected String validateAndCommitData() { PyParameterInfo parameter = info.parameter; String name = parameter.getName(); if (parameterNames.contains(name)) { - return PyBundle.message("ANN.duplicate.param.name"); + return PyLocalize.annDuplicateParamName().get(); } parameterNames.add(name); if (name.equals("*")) { hadSingleStar = true; if (index == parametersLength - 1) { - return PyBundle.message("ANN.named.arguments.after.star"); + return PyLocalize.annNamedArgumentsAfterStar().get(); } } else if (name.startsWith("*") && !name.startsWith("**")) { if (hadKeywordContainer) { - return PyBundle.message("ANN.starred.param.after.kwparam"); + return PyLocalize.annStarredParamAfterKwparam().get(); } if (hadSingleStar) { - return PyBundle.message("refactoring.change.signature.dialog.validation.multiple.star"); + return PyLocalize.refactoringChangeSignatureDialogValidationMultipleStar().get(); } hadPositionalContainer = true; } else if (name.startsWith("**")) { hadKeywordContainer = true; if (hadSingleStar && !hadParamsAfterSingleStar) { - return PyBundle.message("ANN.named.arguments.after.star"); + return PyLocalize.annNamedArgumentsAfterStar().get(); } } else { if (!isNameValid(name, myProject)) { - return PyBundle.message("refactoring.change.signature.dialog.validation.parameter.name"); + return PyLocalize.refactoringChangeSignatureDialogValidationParameterName().get(); } if (hadSingleStar) { hadParamsAfterSingleStar = true; } if (hadPositionalContainer && !languageLevel.isPy3K()) { - return PyBundle.message("ANN.regular.param.after.vararg"); + return PyLocalize.annRegularParamAfterVararg().get(); } else if (hadKeywordContainer) { - return PyBundle.message("ANN.regular.param.after.keyword"); + return PyLocalize.annRegularParamAfterKeyword().get(); } String defaultValue = info.getDefaultValue(); if (defaultValue != null && !StringUtil.isEmptyOrSpaces(defaultValue) && parameter.getDefaultInSignature()) { @@ -182,15 +183,15 @@ else if (hadKeywordContainer) { } else { if (hadDefaultValue && !hadSingleStar && (!languageLevel.isPy3K() || !hadPositionalContainer)) { - return PyBundle.message("ANN.non.default.param.after.default"); + return PyLocalize.annNonDefaultParamAfterDefault().get(); } } } if (parameter.getOldIndex() < 0 && !parameter.getName().startsWith("*")) { if (StringUtil.isEmpty(info.defaultValueCodeFragment.getText())) - return PyBundle.message("refactoring.change.signature.dialog.validation.default.missing"); + return PyLocalize.refactoringChangeSignatureDialogValidationDefaultMissing().get(); if (StringUtil.isEmptyOrSpaces(parameter.getName())) - return PyBundle.message("refactoring.change.signature.dialog.validation.parameter.missing"); + return PyLocalize.refactoringChangeSignatureDialogValidationParameterMissing().get(); } } @@ -199,24 +200,25 @@ else if (hadKeywordContainer) { } @Override + @RequiredUIAccess protected ValidationInfo doValidate() { - final String message = validateAndCommitData(); - SwingUtilities.invokeLater(new Runnable() { - public void run() { - getRefactorAction().setEnabled(message == null); - getPreviewAction().setEnabled(message == null); - } + String message = validateAndCommitData(); + SwingUtilities.invokeLater(() -> { + getRefactorAction().setEnabled(message == null); + getPreviewAction().setEnabled(message == null); }); if (message != null) return new ValidationInfo(message); return super.doValidate(); } @Override + @RequiredUIAccess public JComponent getPreferredFocusedComponent() { return myNameField; } @Override + @RequiredReadAction protected String calculateSignature() { StringBuilder builder = new StringBuilder(); builder.append(getMethodName()); @@ -238,10 +240,11 @@ protected String calculateSignature() { @Override protected VisibilityPanelBase createVisibilityControl() { - return new ComboBoxVisibilityPanel(new String[0]); + return new ComboBoxVisibilityPanel<>(new String[0]); } @Override + @RequiredReadAction protected JComponent getRowPresentation(ParameterTableModelItemBase item, boolean selected, boolean focused) { String text = item.parameter.getName(); String defaultCallValue = item.defaultValueCodeFragment.getText(); @@ -295,20 +298,16 @@ public void prepareEditor(JTable table, int row) { private JPanel createDefaultValueCheckBox() { JPanel defaultValuePanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 4, 2, true, false)); - JBLabel inSignatureLabel = new JBLabel(PyBundle.message("refactoring.change.signature.dialog.default.value.checkbox"), - UIUtil.ComponentStyle.SMALL); + JBLabel inSignatureLabel = + new JBLabel(PyLocalize.refactoringChangeSignatureDialogDefaultValueCheckbox().get(), UIUtil.ComponentStyle.SMALL); defaultValuePanel.add(inSignatureLabel, BorderLayout.WEST); myDefaultInSignature = new JCheckBox(); myDefaultInSignature.setSelected( ((PyParameterTableModelItem)item).isDefaultInSignature()); - myDefaultInSignature.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent event) { - ((PyParameterTableModelItem)item) - .setDefaultInSignature(myDefaultInSignature.isSelected()); - } - }); + myDefaultInSignature.addItemListener( + event -> ((PyParameterTableModelItem)item).setDefaultInSignature(myDefaultInSignature.isSelected()) + ); myDefaultInSignature.addChangeListener(getSignatureUpdater()); myDefaultInSignature.setEnabled(item.parameter.getOldIndex() == -1); defaultValuePanel.add(myDefaultInSignature, BorderLayout.EAST); @@ -319,8 +318,8 @@ private JPanel createDefaultValuePanel() { JPanel defaultValuePanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 4, 2, true, false)); Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(item.defaultValueCodeFragment); myDefaultValueEditor = new EditorTextField(doc, getProject(), getFileType()); - JBLabel defaultValueLabel = new JBLabel(PyBundle.message("refactoring.change.signature.dialog.default.value.label"), - UIUtil.ComponentStyle.SMALL); + JBLabel defaultValueLabel = + new JBLabel(PyLocalize.refactoringChangeSignatureDialogDefaultValueLabel().get(), UIUtil.ComponentStyle.SMALL); defaultValuePanel.add(defaultValueLabel); defaultValuePanel.add(myDefaultValueEditor); myDefaultValueEditor.setPreferredWidth(t.getWidth() / 2); @@ -331,8 +330,8 @@ private JPanel createDefaultValuePanel() { private JPanel createParameterPanel() { JPanel namePanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 4, 2, true, false)); myNameEditor = new EditorTextField(item.parameter.getName(), getProject(), getFileType()); - JBLabel nameLabel = new JBLabel(PyBundle.message("refactoring.change.signature.dialog.name.label"), - UIUtil.ComponentStyle.SMALL); + JBLabel nameLabel = + new JBLabel(PyLocalize.refactoringChangeSignatureDialogNameLabel().get(), UIUtil.ComponentStyle.SMALL); namePanel.add(nameLabel); namePanel.add(myNameEditor); myNameEditor.setPreferredWidth(t.getWidth() / 2); @@ -351,18 +350,13 @@ public void documentChanged(DocumentEvent event) { @Override public JBTableRow getValue() { - return new JBTableRow() { - @Override - public Object getValueAt(int column) { - switch (column) { - case 0: - return myNameEditor.getText().trim(); - case 1: - return new Pair(item.defaultValueCodeFragment, - ((PyParameterTableModelItem)item).isDefaultInSignature()); - } - return null; - } + return column -> switch (column) { + case 0 -> myNameEditor.getText().trim(); + case 1 -> Pair.create( + item.defaultValueCodeFragment, + ((PyParameterTableModelItem) item).isDefaultInSignature() + ); + default -> null; }; } @@ -373,7 +367,7 @@ public JComponent getPreferredFocusedComponent() { @Override public JComponent[] getFocusableComponents() { - List focusable = new ArrayList(); + List focusable = new ArrayList<>(); focusable.add(myNameEditor.getFocusTarget()); if (myDefaultValueEditor != null) { focusable.add(myDefaultValueEditor.getFocusTarget()); diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/refactoring/classes/ui/PyClassCellRenderer.java b/python-impl/src/main/java/com/jetbrains/python/impl/refactoring/classes/ui/PyClassCellRenderer.java index 52c2cd82..c6a6176b 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/refactoring/classes/ui/PyClassCellRenderer.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/refactoring/classes/ui/PyClassCellRenderer.java @@ -17,6 +17,7 @@ import java.awt.Component; +import consulo.annotation.access.RequiredReadAction; import org.jspecify.annotations.Nullable; import javax.swing.DefaultListCellRenderer; import javax.swing.Icon; @@ -47,14 +48,17 @@ public PyClassCellRenderer(boolean showReadOnly) myShowReadOnly = showReadOnly; } - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) + @Override + @RequiredReadAction + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); return customizeRenderer(value, myShowReadOnly); } - public JLabel customizeRenderer(Object value, boolean showReadOnly) + @RequiredReadAction + public JLabel customizeRenderer(Object value, boolean showReadOnly) { PyClass aClass = (PyClass) value; setText(getClassText(aClass)); @@ -73,6 +77,7 @@ public JLabel customizeRenderer(Object value, boolean showReadOnly) } @Nullable + @RequiredReadAction public static String getClassText(PyClass aClass) { return aClass.getName(); diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/refactoring/introduce/IntroduceHandler.java b/python-impl/src/main/java/com/jetbrains/python/impl/refactoring/introduce/IntroduceHandler.java index 78ce1f1c..eebfe8c1 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/refactoring/introduce/IntroduceHandler.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/refactoring/introduce/IntroduceHandler.java @@ -17,7 +17,6 @@ import com.jetbrains.python.PyNames; import com.jetbrains.python.PyTokenTypes; -import com.jetbrains.python.impl.PyBundle; import com.jetbrains.python.impl.codeInsight.dataflow.scope.ScopeUtil; import com.jetbrains.python.impl.psi.PyStringLiteralUtil; import com.jetbrains.python.impl.psi.types.PyNoneType; @@ -29,7 +28,9 @@ import com.jetbrains.python.psi.resolve.PyResolveContext; import com.jetbrains.python.psi.types.PyType; import com.jetbrains.python.psi.types.TypeEvalContext; -import consulo.application.ApplicationManager; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; +import consulo.application.Application; import consulo.application.Result; import consulo.codeEditor.CaretModel; import consulo.codeEditor.Editor; @@ -55,15 +56,18 @@ import consulo.language.psi.PsiFile; import consulo.language.psi.PsiWhiteSpace; import consulo.language.psi.util.PsiTreeUtil; +import consulo.localize.LocalizeValue; import consulo.project.Project; +import consulo.python.impl.localize.PyLocalize; +import consulo.ui.annotation.RequiredUIAccess; +import consulo.util.lang.Couple; import consulo.util.lang.Pair; import org.jspecify.annotations.Nullable; import java.util.*; -import java.util.function.Consumer; -import static com.jetbrains.python.inspections.PyStringFormatParser.*; import static com.jetbrains.python.impl.psi.PyUtil.as; +import static com.jetbrains.python.inspections.PyStringFormatParser.*; /** * @author Alexey.Ivanov @@ -107,6 +111,7 @@ protected static void ensureName(IntroduceOperation operation) { } @Nullable + @RequiredReadAction protected static PsiElement findOccurrenceUnderCaret(List occurrences, Editor editor) { if (occurrences.isEmpty()) { return null; @@ -138,6 +143,7 @@ public enum InitPlace { } @Nullable + @RequiredWriteAction protected PsiElement replaceExpression(PsiElement expression, PyExpression newExpression, IntroduceOperation operation) { PyExpressionStatement statement = PsiTreeUtil.getParentOfType(expression, PyExpressionStatement.class); if (statement != null) { @@ -150,20 +156,25 @@ protected PsiElement replaceExpression(PsiElement expression, PyExpression newEx } private final IntroduceValidator myValidator; - protected final String myDialogTitle; + protected final LocalizeValue myDialogTitle; protected IntroduceHandler(IntroduceValidator validator, String dialogTitle) { myValidator = validator; - myDialogTitle = dialogTitle; + myDialogTitle = LocalizeValue.ofNullable(dialogTitle); } + @Override + @RequiredUIAccess public void invoke(Project project, Editor editor, PsiFile file, DataContext dataContext) { performAction(new IntroduceOperation(project, editor, file, null)); } + @Override + @RequiredUIAccess public void invoke(Project project, PsiElement[] elements, DataContext dataContext) { } + @RequiredReadAction public Collection getSuggestedNames(PyExpression expression) { Collection candidates = generateSuggestedNames(expression); @@ -187,8 +198,9 @@ public Collection getSuggestedNames(PyExpression expression) { return res; } + @RequiredReadAction protected Collection generateSuggestedNames(PyExpression expression) { - Collection candidates = new LinkedHashSet() { + Collection candidates = new LinkedHashSet<>() { @Override public boolean add(String s) { if (PyNames.isReserved(s)) { @@ -244,6 +256,7 @@ public boolean add(String s) { return candidates; } + @RequiredUIAccess public void performAction(IntroduceOperation operation) { PsiFile file = operation.getFile(); if (!CommonRefactoringUtil.checkReadOnlyStatus(file)) { @@ -357,15 +370,17 @@ private static boolean breaksRanges(List ranges, TextRange range) { return false; } + @RequiredUIAccess private void showCannotPerformError(Project project, Editor editor) { CommonRefactoringUtil.showErrorHint(project, editor, - PyBundle.message("refactoring.introduce.selection.error"), + PyLocalize.refactoringIntroduceSelectionError(), myDialogTitle, "refactoring.extractMethod"); } - private boolean smartIntroduce(final IntroduceOperation operation) { + @RequiredUIAccess + private boolean smartIntroduce(IntroduceOperation operation) { Editor editor = operation.getEditor(); PsiFile file = operation.getFile(); int offset = editor.getCaretModel().getOffset(); @@ -386,31 +401,31 @@ private boolean smartIntroduce(final IntroduceOperation operation) { } elementAtCaret = elementAtCaret.getParent(); } - if (expressions.size() == 1 || ApplicationManager.getApplication().isUnitTestMode()) { + if (expressions.size() == 1 || Application.get().isUnitTestMode()) { operation.setElement(expressions.get(0)); performActionOnElement(operation); return true; } else if (expressions.size() > 1) { - IntroduceTargetChooser.showChooser(editor, expressions, new Consumer() { - @Override - public void accept(PyExpression pyExpression) { - operation.setElement(pyExpression); - performActionOnElement(operation); - } - }, pyExpression -> pyExpression.getText()); + IntroduceTargetChooser.showChooser(editor, expressions, pyExpression -> { + operation.setElement(pyExpression); + performActionOnElement(operation); + }, PsiElement::getText); return true; } return false; } + @RequiredUIAccess protected boolean checkIntroduceContext(PsiFile file, Editor editor, PsiElement element) { if (!isValidIntroduceContext(element)) { - CommonRefactoringUtil.showErrorHint(file.getProject(), - editor, - PyBundle.message("refactoring.introduce.selection.error"), - myDialogTitle, - "refactoring.extractMethod"); + CommonRefactoringUtil.showErrorHint( + file.getProject(), + editor, + PyLocalize.refactoringIntroduceSelectionError(), + myDialogTitle, + "refactoring.extractMethod" + ); return false; } return true; @@ -436,6 +451,7 @@ private static boolean isValidIntroduceVariant(PsiElement element) { return true; } + @RequiredUIAccess private void performActionOnElement(IntroduceOperation operation) { if (!checkEnabled(operation)) { return; @@ -458,6 +474,7 @@ private void performActionOnElement(IntroduceOperation operation) { performActionOnElementOccurrences(operation); } + @RequiredUIAccess protected void performActionOnElementOccurrences(final IntroduceOperation operation) { Editor editor = operation.getEditor(); if (editor.getSettings().isVariableInplaceRenameEnabled()) { @@ -466,16 +483,14 @@ protected void performActionOnElementOccurrences(final IntroduceOperation operat performInplaceIntroduce(operation); } else { - OccurrencesChooser.simpleChooser(editor) - .showChooser(operation.getElement(), - operation.getOccurrences(), - new Consumer() { - @Override - public void accept(OccurrencesChooser.ReplaceChoice replaceChoice) { - operation.setReplaceAll(replaceChoice == OccurrencesChooser.ReplaceChoice.ALL); - performInplaceIntroduce(operation); - } - }); + OccurrencesChooser.simpleChooser(editor).showChooser( + operation.getElement(), + operation.getOccurrences(), + replaceChoice -> { + operation.setReplaceAll(replaceChoice == OccurrencesChooser.ReplaceChoice.ALL); + performInplaceIntroduce(operation); + } + ); } } else { @@ -483,6 +498,7 @@ public void accept(OccurrencesChooser.ReplaceChoice replaceChoice) { } } + @RequiredUIAccess protected void performInplaceIntroduce(IntroduceOperation operation) { PsiElement statement = performRefactoring(operation); if (statement instanceof PyAssignmentStatement) { @@ -496,10 +512,11 @@ protected void performInplaceIntroduce(IntroduceOperation operation) { } } + @RequiredUIAccess protected void performIntroduceWithDialog(IntroduceOperation operation) { Project project = operation.getProject(); if (operation.getName() == null) { - PyIntroduceDialog dialog = new PyIntroduceDialog(project, myDialogTitle, myValidator, getHelpId(), operation); + PyIntroduceDialog dialog = new PyIntroduceDialog(project, myDialogTitle.get(), myValidator, getHelpId(), operation); if (!dialog.showAndGet()) { return; } @@ -514,6 +531,7 @@ protected void performIntroduceWithDialog(IntroduceOperation operation) { editor.getSelectionModel().removeSelection(); } + @RequiredUIAccess protected PsiElement performRefactoring(IntroduceOperation operation) { PsiElement declaration = createDeclaration(operation); @@ -522,6 +540,7 @@ protected PsiElement performRefactoring(IntroduceOperation operation) { return declaration; } + @RequiredReadAction public PyAssignmentStatement createDeclaration(IntroduceOperation operation) { Project project = operation.getProject(); PyExpression initializer = operation.getInitializer(); @@ -534,6 +553,7 @@ public PyAssignmentStatement createDeclaration(IntroduceOperation operation) { private static class InitializerTextBuilder extends PyRecursiveElementVisitor { private final StringBuilder myResult = new StringBuilder(); + @RequiredReadAction public InitializerTextBuilder(PyExpression expression) { if (PsiTreeUtil.findChildOfType(expression, PsiComment.class) != null) { myResult.append(expression.getText()); @@ -551,6 +571,7 @@ public void visitWhiteSpace(PsiWhiteSpace space) { myResult.append(space.getText().replace('\n', ' ').replace("\\", "")); } + @RequiredReadAction @Override public void visitPyStringLiteralExpression(PyStringLiteralExpression node) { Pair data = node.getUserData(PyReplaceExpressionUtil.SELECTION_BREAKS_AST_NODE); @@ -558,7 +579,7 @@ public void visitPyStringLiteralExpression(PyStringLiteralExpression node) { PsiElement parent = data.getFirst(); String text = parent.getText(); Pair detectedQuotes = PyStringLiteralUtil.getQuotes(text); - Pair quotes = detectedQuotes != null ? detectedQuotes : Pair.create("'", "'"); + Pair quotes = detectedQuotes != null ? detectedQuotes : Couple.of("'", "'"); TextRange range = data.getSecond(); String substring = range.substring(text); myResult.append(quotes.getFirst()).append(substring).append(quotes.getSecond()); @@ -584,6 +605,7 @@ public void visitPyStringLiteralExpression(PyStringLiteralExpression node) { } @Override + @RequiredReadAction public void visitElement(PsiElement element) { if (element.getChildren().length == 0) { myResult.append(element.getText()); @@ -593,6 +615,7 @@ public void visitElement(PsiElement element) { } } + @RequiredReadAction private boolean needToWrapTopLevelExpressionInParenthesis(PyExpression node) { if (node instanceof PyGeneratorExpression) { PsiElement firstChild = node.getFirstChild(); @@ -610,6 +633,7 @@ public String result() { protected abstract String getHelpId(); + @RequiredReadAction protected PyAssignmentStatement createDeclaration(Project project, String assignmentText, PsiElement anchor) { LanguageLevel langLevel = ((PyFile)anchor.getContainingFile()).getLanguageLevel(); return PyElementGenerator.getInstance(project).createFromText(langLevel, PyAssignmentStatement.class, assignmentText); @@ -623,10 +647,13 @@ protected List getOccurrences(PsiElement element, PyExpression expre return PyRefactoringUtil.getOccurrences(expression, ScopeUtil.getScopeOwner(expression)); } + @RequiredUIAccess private PsiElement performReplace(final PsiElement declaration, final IntroduceOperation operation) { final PyExpression expression = operation.getInitializer(); final Project project = operation.getProject(); return new WriteCommandAction(project, expression.getContainingFile()) { + @Override + @RequiredWriteAction protected void run(Result result) throws Throwable { try { RefactoringEventData afterData = new RefactoringEventData(); @@ -696,13 +723,16 @@ protected void postRefactoring(PsiElement element) { private static class PyInplaceVariableIntroducer extends InplaceVariableIntroducer { private final PyTargetExpression myTarget; + @RequiredUIAccess public PyInplaceVariableIntroducer(PyTargetExpression target, IntroduceOperation operation, List occurrences) { - super(target, - operation.getEditor(), - operation.getProject(), - "Introduce Variable", - occurrences.toArray(new PsiElement[occurrences.size()]), - null); + super( + target, + operation.getEditor(), + operation.getProject(), + "Introduce Variable", + occurrences.toArray(new PsiElement[occurrences.size()]), + null + ); myTarget = target; } diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/refactoring/introduce/field/PyIntroduceFieldHandler.java b/python-impl/src/main/java/com/jetbrains/python/impl/refactoring/introduce/field/PyIntroduceFieldHandler.java index 51108f27..6b4c6014 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/refactoring/introduce/field/PyIntroduceFieldHandler.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/refactoring/introduce/field/PyIntroduceFieldHandler.java @@ -20,13 +20,15 @@ import com.jetbrains.python.impl.codeInsight.dataflow.scope.ScopeUtil; import com.jetbrains.python.impl.inspections.quickfix.AddFieldQuickFix; import com.jetbrains.python.impl.psi.PyUtil; -import com.jetbrains.python.psi.*; import com.jetbrains.python.impl.psi.impl.PyFunctionBuilder; import com.jetbrains.python.impl.refactoring.PyReplaceExpressionUtil; import com.jetbrains.python.impl.refactoring.introduce.IntroduceHandler; import com.jetbrains.python.impl.refactoring.introduce.IntroduceOperation; import com.jetbrains.python.impl.refactoring.introduce.variable.PyIntroduceVariableHandler; import com.jetbrains.python.impl.testing.PythonUnitTestUtil; +import com.jetbrains.python.psi.*; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.application.WriteAction; import consulo.codeEditor.CaretModel; import consulo.codeEditor.Editor; @@ -35,8 +37,8 @@ import consulo.document.Document; import consulo.ide.impl.idea.util.FunctionUtil; import consulo.language.ast.ASTNode; -import consulo.language.editor.refactoring.RefactoringBundle; import consulo.language.editor.refactoring.introduce.inplace.InplaceVariableIntroducer; +import consulo.language.editor.refactoring.localize.RefactoringLocalize; import consulo.language.editor.refactoring.util.CommonRefactoringUtil; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; @@ -44,9 +46,11 @@ import consulo.language.psi.scope.LocalSearchScope; import consulo.language.psi.search.ReferencesSearch; import consulo.language.psi.util.PsiTreeUtil; +import consulo.localize.LocalizeValue; import consulo.project.Project; - +import consulo.ui.annotation.RequiredUIAccess; import org.jspecify.annotations.Nullable; + import javax.swing.*; import java.util.ArrayList; import java.util.Collection; @@ -58,12 +62,12 @@ * @author Dennis.Ushakov */ public class PyIntroduceFieldHandler extends IntroduceHandler { - public PyIntroduceFieldHandler() { - super(new IntroduceFieldValidator(), RefactoringBundle.message("introduce.field.title")); + super(new IntroduceFieldValidator(), RefactoringLocalize.introduceFieldTitle().get()); } @Override + @RequiredUIAccess public void invoke(Project project, Editor editor, PsiFile file, DataContext dataContext) { IntroduceOperation operation = new IntroduceOperation(project, editor, file, null); operation.addAvailableInitPlace(InitPlace.CONSTRUCTOR); @@ -73,6 +77,7 @@ public void invoke(Project project, Editor editor, PsiFile file, DataContext dat performAction(operation); } + @RequiredReadAction private static boolean isTestClass(PsiFile file, Editor editor) { PsiElement element1 = null; SelectionModel selectionModel = editor.getSelectionModel(); @@ -97,6 +102,7 @@ private static boolean isTestClass(PsiFile file, Editor editor) { } @Override + @RequiredWriteAction protected PsiElement replaceExpression(PsiElement expression, PyExpression newExpression, IntroduceOperation operation) { if (operation.getInitPlace() != InitPlace.SAME_METHOD) { return PyReplaceExpressionUtil.replaceExpression(expression, newExpression); @@ -105,13 +111,16 @@ protected PsiElement replaceExpression(PsiElement expression, PyExpression newEx } @Override + @RequiredUIAccess protected boolean checkEnabled(IntroduceOperation operation) { if (PyUtil.getContainingClassOrSelf(operation.getElement()) == null) { - CommonRefactoringUtil.showErrorHint(operation.getProject(), - operation.getEditor(), - "Cannot introduce field: not in class", - myDialogTitle, - getHelpId()); + CommonRefactoringUtil.showErrorHint( + operation.getProject(), + operation.getEditor(), + LocalizeValue.localizeTODO("Cannot introduce field: not in class"), + myDialogTitle, + getHelpId() + ); return false; } if (dependsOnLocalScopeValues(operation.getElement())) { @@ -138,6 +147,7 @@ public ResolvingVisitor(ScopeOwner scope) { } @Override + @RequiredReadAction public void visitPyReferenceExpression(PyReferenceExpression node) { super.visitPyReferenceExpression(node); PsiElement result = node.getReference().resolve(); @@ -160,6 +170,7 @@ public void visitPyReferenceExpression(PyReferenceExpression node) { @Nullable @Override + @RequiredWriteAction protected PsiElement addDeclaration(PsiElement expression, PsiElement declaration, IntroduceOperation operation) { @@ -191,6 +202,7 @@ private static boolean inConstructor(PsiElement expression) { } @Nullable + @RequiredWriteAction private static PsiElement addFieldToSetUp(PyClass clazz, Function callback) { PyFunction init = clazz.findMethodByName(PythonUnitTestUtil.TESTCASE_SETUP_NAME, false, null); if (init != null) { @@ -206,6 +218,7 @@ private static PsiElement addFieldToSetUp(PyClass clazz, Function getOccurrences(PsiElement element, PyExpression expression) { if (isAssignedLocalVariable(element)) { PyFunction function = PsiTreeUtil.getParentOfType(element, PyFunction.class); @@ -223,6 +236,7 @@ protected List getOccurrences(PsiElement element, PyExpression expre } @Override + @RequiredReadAction protected PyExpression createExpression(Project project, String name, PsiElement declaration) { String text = declaration.getText(); String self_name = text.substring(0, text.indexOf('.')); @@ -230,6 +244,7 @@ protected PyExpression createExpression(Project project, String name, PsiElement } @Override + @RequiredReadAction protected PyAssignmentStatement createDeclaration(Project project, String assignmentText, PsiElement anchor) { PyFunction container = PsiTreeUtil.getParentOfType(anchor, PyFunction.class); String selfName = PyUtil.getFirstParameterName(container); @@ -238,6 +253,7 @@ protected PyAssignmentStatement createDeclaration(Project project, String assign } @Override + @RequiredWriteAction protected void postRefactoring(PsiElement element) { if (isAssignedLocalVariable(element)) { element.getParent().delete(); @@ -261,13 +277,16 @@ protected String getHelpId() { } @Override + @RequiredUIAccess protected boolean checkIntroduceContext(PsiFile file, Editor editor, PsiElement element) { if (element != null && isInStaticMethod(element)) { - CommonRefactoringUtil.showErrorHint(file.getProject(), - editor, - "Introduce Field refactoring cannot be used in static methods", - RefactoringBundle.message("introduce.field.title"), - "refactoring.extractMethod"); + CommonRefactoringUtil.showErrorHint( + file.getProject(), + editor, + LocalizeValue.localizeTODO("Introduce Field refactoring cannot be used in static methods"), + RefactoringLocalize.introduceFieldTitle(), + "refactoring.extractMethod" + ); return false; } return super.checkIntroduceContext(file, editor, element); @@ -298,6 +317,7 @@ private AddFieldDeclaration(PsiElement declaration) { } @Override + @RequiredReadAction public PyStatement apply(String self_name) { if (PyNames.CANONICAL_SELF.equals(self_name)) { return (PyStatement)myDeclaration; @@ -312,6 +332,7 @@ public PyStatement apply(String self_name) { } @Override + @RequiredWriteAction protected void performInplaceIntroduce(IntroduceOperation operation) { PsiElement statement = performRefactoring(operation); // put caret on identifier after "self." @@ -344,6 +365,7 @@ private static class PyInplaceFieldIntroducer extends InplaceVariableIntroducer< private final IntroduceOperation myOperation; private final PyIntroduceFieldPanel myPanel; + @RequiredUIAccess public PyInplaceFieldIntroducer(PyTargetExpression target, IntroduceOperation operation, List occurrences) { super(target, operation.getEditor(), @@ -372,6 +394,7 @@ protected JComponent getComponent() { } @Override + @RequiredUIAccess protected void moveOffsetAfter(boolean success) { if (success && (myPanel != null && myPanel.getInitPlace() != InitPlace.SAME_METHOD) || myOperation.getInplaceInitPlace() != InitPlace.SAME_METHOD) { WriteAction.run(() -> { diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/toolbox/ChainIterable.java b/python-impl/src/main/java/com/jetbrains/python/impl/toolbox/ChainIterable.java index 40a6d027..d0dad5c9 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/toolbox/ChainIterable.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/toolbox/ChainIterable.java @@ -69,6 +69,7 @@ public boolean isEmpty() { return (myPayload == null); } + @Override public Iterator iterator() { class IterMixedIn extends ChainIterationMixin> { IterMixedIn(ChainedListBase> link) { diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/toolbox/FP.java b/python-impl/src/main/java/com/jetbrains/python/impl/toolbox/FP.java index 0e61447e..416f28e4 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/toolbox/FP.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/toolbox/FP.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.jetbrains.python.impl.toolbox; import consulo.util.lang.Pair; @@ -22,11 +21,11 @@ /** * Tools of functional programming, the notorious half of implementation of Lisp. (And sometimes a shard or two of Haskell.) -* User: dcheryasov -* Date: Nov 6, 2009 10:06:50 AM + * +* @author dcheryasov +* @since 2009-11-06 */ public class FP { - private FP() { // do not instantiate } @@ -39,20 +38,22 @@ private FP() { * @return list of mapped values. */ public static Iterable map(final Lambda1 lambda, final Iterable source) { - - return new Iterable() { + return new Iterable<>() { final Iterator feeder = source.iterator(); + @Override public Iterator iterator() { - return new Iterator() { - + return new Iterator<>() { + @Override public boolean hasNext() { return feeder.hasNext(); } + @Override public R next() { return lambda.apply(feeder.next()); } + @Override public void remove() { throw new UnsupportedOperationException("Cannot remove from map()"); } @@ -68,17 +69,15 @@ public static Iterable map(Lambda1 lambda, S[] source) { return map(lambda, Arrays.asList(source)); } - /** * Same as {@link #map}, but non-lazy an returns a modifiable List. */ public static List mapList(Lambda1 lambda, Iterable source) { - List ret = new ArrayList(source instanceof Collection? ((Collection)source).size() : 10); + List ret = new ArrayList<>(source instanceof Collection? ((Collection)source).size() : 10); for (R what : map(lambda, source)) ret.add(what); return ret; } - /** * Apply a two-argument lambda to each sequence element and an accumulator. * @param lambda function to apply; accumulator is the first parameter, sequence item is the second @@ -125,12 +124,11 @@ public static Iterable> zip(Iterable one, Iterable * Same as {@link #zip(Iterable, Iterable)}, but non-lazy and returns a modifiable List. */ public static List> zipList(Iterable one, Iterable two) { - List> ret = new ArrayList>(proposeZippedListLength(one, two, false, false)); + List> ret = new ArrayList<>(proposeZippedListLength(one, two, false, false)); for (Pairwhat : zipInternal(one, two, null, null, false, false)) ret.add(what); return ret; } - /** * Zips together two sequences: [a, b,..] + [x, y,..] -> [(a, x), (b, y),..]. Fills missing second elements with filler. * Always uses up entire sequence one; if sequence two is longer, part of it is unused. @@ -148,12 +146,11 @@ public static Iterable> zip(Iterable one, Iterable * Same as {@link #zip(Iterable, Iterable, Object)}, but non-lazy and returns a modifiable List. */ public static List> zipList(Iterable one, Iterable two, R2 filler) { - List> ret = new ArrayList>(proposeZippedListLength(one, two, false, true)); + List> ret = new ArrayList<>(proposeZippedListLength(one, two, false, true)); for (Pairwhat : zipInternal(one, two, null, filler, false, true)) ret.add(what); return ret; } - /** * Zips together two sequences: [a, b,..] + [x, y,..] -> [(a, x), (b, y),..]. Fills all missing elements with filler. * Always uses up both sequences, using the appropriate filler for elements of the shorter sequences. @@ -172,7 +169,7 @@ public static Iterable> zip(Iterable one, Iterable * Same as {@link #zip(Iterable, Iterable, Object, Object)}, but non-lazy and returns a modifiable List. */ public static List> zipList(Iterable one, Iterable two, R1 filler1, R2 filler2) { - List> ret = new ArrayList>(proposeZippedListLength(one, two, true, true)); + List> ret = new ArrayList<>(proposeZippedListLength(one, two, true, true)); for (Pairwhat : zipInternal(one, two, filler1, filler2, true, true)) ret.add(what); return ret; } @@ -180,7 +177,7 @@ public static List> zipList(Iterable one, Iterable /** * Tries to determine the size of an array list of exactly the right size to accommodate * the result of {@link #zip(Iterable, Iterable, Object, Object)}. - * @param one first iterbale + * @param one first iterable * @param two second iterable * @param fill1 true if padding of iterable one is required * @param fill2 true if padding of iterable two is required @@ -216,32 +213,29 @@ private static Iterable> zipInternal( final Iterator one_iter = one.iterator(); final Iterator two_iter = two.iterator(); - return new Iterable>() { - public Iterator> iterator() { - - return new Iterator>() { - - public void remove() { - throw new UnsupportedOperationException("Cannot remove from zip()"); - } + return () -> new Iterator<>() { + @Override + public void remove() { + throw new UnsupportedOperationException("Cannot remove from zip()"); + } - public boolean hasNext() { - boolean one_has = one_iter.hasNext(); - boolean two_has = two_iter.hasNext(); - return ( - one_has && two_has || - fill1 && two_has || - fill2 && one_has - ); - } + @Override + public boolean hasNext() { + boolean one_has = one_iter.hasNext(); + boolean two_has = two_iter.hasNext(); + return ( + one_has && two_has || + fill1 && two_has || + fill2 && one_has + ); + } - public Pair next() { - if (one_iter.hasNext() && two_iter.hasNext()) return new Pair(one_iter.next(), two_iter.next()); - if (fill1 && two_iter.hasNext()) return new Pair(filler1, two_iter.next()); - if (fill2 && one_iter.hasNext()) return new Pair(one_iter.next(), filler2); - throw new NoSuchElementException(); - } - }; + @Override + public Pair next() { + if (one_iter.hasNext() && two_iter.hasNext()) return Pair.create(one_iter.next(), two_iter.next()); + if (fill1 && two_iter.hasNext()) return Pair.create(filler1, two_iter.next()); + if (fill2 && one_iter.hasNext()) return Pair.create(one_iter.next(), filler2); + throw new NoSuchElementException(); } }; } @@ -252,12 +246,8 @@ public Pair next() { * @param g second (outer) function * @return their combination, f o g */ - public static Lambda1 combine(final Lambda1 f, final Lambda1 g) { - return new Lambda1() { - public R2 apply(A1 arg) { - return g.apply(f.apply(arg)); - } - }; + public static Lambda1 combine(Lambda1 f, Lambda1 g) { + return arg -> g.apply(f.apply(arg)); } // TODO: add slices, array wrapping %) @@ -281,6 +271,7 @@ public interface Lambda2 { * Useful for {@link FP#fold(Lambda2, Iterable, Object) fold}ing into a string. Element's {@code .toString()} is appended to the string builder. */ public static class StringCollector implements FP.Lambda2 { + @Override public StringBuilder apply(StringBuilder builder, T arg2) { if (arg2 == null) { throw new IllegalArgumentException("Null item in list of strings to concatenate. Text so far: " + builder.toString()); @@ -288,5 +279,4 @@ public StringBuilder apply(StringBuilder builder, T arg2) { return builder.append(arg2.toString()); } } - } diff --git a/python-impl/src/main/java/com/jetbrains/python/impl/validation/PyAnnotatingVisitor.java b/python-impl/src/main/java/com/jetbrains/python/impl/validation/PyAnnotatingVisitor.java index f956a763..43babc3f 100644 --- a/python-impl/src/main/java/com/jetbrains/python/impl/validation/PyAnnotatingVisitor.java +++ b/python-impl/src/main/java/com/jetbrains/python/impl/validation/PyAnnotatingVisitor.java @@ -66,10 +66,11 @@ public PyAnnotatingVisitor() { } } + @Override public void annotate(PsiElement psiElement, AnnotationHolder holder) { PsiFile file = psiElement.getContainingFile(); for (PyAnnotator annotator : myAnnotators) { - if (file instanceof PyFileImpl && !((PyFileImpl)file).isAcceptedFor(annotator.getClass())) continue; + if (file instanceof PyFileImpl fileImpl && !fileImpl.isAcceptedFor(annotator.getClass())) continue; annotator.annotateElement(psiElement, holder); } } diff --git a/python-psi-api/src/main/java/com/jetbrains/python/psi/PyArgumentList.java b/python-psi-api/src/main/java/com/jetbrains/python/psi/PyArgumentList.java index 16a66f12..3fb75329 100644 --- a/python-psi-api/src/main/java/com/jetbrains/python/psi/PyArgumentList.java +++ b/python-psi-api/src/main/java/com/jetbrains/python/psi/PyArgumentList.java @@ -17,6 +17,7 @@ import java.util.Collection; +import consulo.annotation.access.RequiredWriteAction; import org.jspecify.annotations.Nullable; import consulo.language.ast.ASTNode; import com.jetbrains.python.FunctionParameter; @@ -28,7 +29,6 @@ */ public interface PyArgumentList extends PyElement { - /** * @return all argument list param expressions (keyword argument or nameless) */ @@ -48,10 +48,13 @@ public interface PyArgumentList extends PyElement * * @param arg argument to add */ + @RequiredWriteAction void addArgument(PyExpression arg); + @RequiredWriteAction void addArgumentFirst(PyExpression arg); + @RequiredWriteAction void addArgumentAfter(PyExpression argument, PyExpression afterThis); /** diff --git a/python-psi-api/src/main/java/com/jetbrains/python/psi/PyClass.java b/python-psi-api/src/main/java/com/jetbrains/python/psi/PyClass.java index 3e3c3f35..a8cd9639 100644 --- a/python-psi-api/src/main/java/com/jetbrains/python/psi/PyClass.java +++ b/python-psi-api/src/main/java/com/jetbrains/python/psi/PyClass.java @@ -15,24 +15,22 @@ */ package com.jetbrains.python.psi; -import java.util.List; -import java.util.Map; - - - -import org.jspecify.annotations.Nullable; +import com.jetbrains.python.codeInsight.controlflow.ScopeOwner; +import com.jetbrains.python.psi.stubs.PyClassStub; +import com.jetbrains.python.psi.types.PyClassLikeType; +import com.jetbrains.python.psi.types.PyType; +import com.jetbrains.python.psi.types.TypeEvalContext; import consulo.language.ast.ASTNode; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiNameIdentifierOwner; import consulo.language.psi.StubBasedPsiElement; import consulo.language.psi.resolve.PsiScopeProcessor; import consulo.util.collection.ArrayFactory; -import consulo.application.util.function.Processor; -import com.jetbrains.python.codeInsight.controlflow.ScopeOwner; -import com.jetbrains.python.psi.stubs.PyClassStub; -import com.jetbrains.python.psi.types.PyClassLikeType; -import com.jetbrains.python.psi.types.PyType; -import com.jetbrains.python.psi.types.TypeEvalContext; +import org.jspecify.annotations.Nullable; + +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; /** * Represents a class declaration in source. @@ -40,7 +38,7 @@ public interface PyClass extends PsiNameIdentifierOwner, PyStatement, PyDocStringOwner, StubBasedPsiElement, ScopeOwner, PyDecoratable, PyTypedElement, PyQualifiedNameOwner, PyStatementListContainer, PyWithAncestors { - ArrayFactory ARRAY_FACTORY = count -> new PyClass[count]; + ArrayFactory ARRAY_FACTORY = PyClass[]::new; @Nullable ASTNode getNameNode(); @@ -142,21 +140,21 @@ public interface PyClass extends PsiNameIdentifierOwner, PyStatement, PyDocStrin /** * Apply a processor to every method, looking at superclasses in method resolution order as needed. - * Consider using {@link PyClassLikeType#visitMembers(Processor, boolean, TypeEvalContext)} + * Consider using {@link PyClassLikeType#visitMembers(Predicate, boolean, TypeEvalContext)} * * @param processor what to apply * @param inherited true: search in superclasses, too. * @param context loose context will be used if no context provided - * @see PyClassLikeType#visitMembers(Processor, boolean, TypeEvalContext) + * @see PyClassLikeType#visitMembers(Predicate, boolean, TypeEvalContext) */ - boolean visitMethods(Processor processor, boolean inherited, @Nullable TypeEvalContext context); + boolean visitMethods(Predicate processor, boolean inherited, @Nullable TypeEvalContext context); /** - * Consider using {@link PyClassLikeType#visitMembers(Processor, boolean, TypeEvalContext)} + * Consider using {@link PyClassLikeType#visitMembers(Predicate, boolean, TypeEvalContext)} * - * @see PyClassLikeType#visitMembers(Processor, boolean, TypeEvalContext) + * @see PyClassLikeType#visitMembers(Predicate, boolean, TypeEvalContext) */ - boolean visitClassAttributes(Processor processor, boolean inherited, TypeEvalContext context); + boolean visitClassAttributes(Predicate processor, boolean inherited, TypeEvalContext context); /** * Effectively collects assignments inside the class body. @@ -214,7 +212,7 @@ public interface PyClass extends PsiNameIdentifierOwner, PyStatement, PyDocStrin * @return a property that processor accepted, or null. */ @Nullable - Property scanProperties(Processor processor, boolean inherited); + Property scanProperties(Predicate processor, boolean inherited); /** * Non-recursively searches for a property for which the given function is a getter, setter or deleter. @@ -251,6 +249,7 @@ public interface PyClass extends PsiNameIdentifierOwner, PyStatement, PyDocStrin List getOwnSlots(); @Nullable + @Override String getDocStringValue(); boolean processClassLevelDeclarations(PsiScopeProcessor processor); diff --git a/python-psi-api/src/main/java/com/jetbrains/python/psi/types/PyClassLikeType.java b/python-psi-api/src/main/java/com/jetbrains/python/psi/types/PyClassLikeType.java index 14530d9b..2682cf64 100644 --- a/python-psi-api/src/main/java/com/jetbrains/python/psi/types/PyClassLikeType.java +++ b/python-psi-api/src/main/java/com/jetbrains/python/psi/types/PyClassLikeType.java @@ -17,10 +17,11 @@ import java.util.List; import java.util.Set; +import java.util.function.Predicate; +import consulo.annotation.access.RequiredReadAction; import org.jspecify.annotations.Nullable; import consulo.language.psi.PsiElement; -import consulo.application.util.function.Processor; import com.jetbrains.python.psi.AccessDirection; import com.jetbrains.python.psi.PyExpression; import com.jetbrains.python.psi.PyWithAncestors; @@ -59,8 +60,9 @@ List resolveMember(String name, * @param context context to be used to resolve types * @see PyTypeUtil#getMembersOfType(PyClassLikeType, Class, TypeEvalContext) */ - void visitMembers(Processor processor, boolean inherited, TypeEvalContext context); + void visitMembers(Predicate processor, boolean inherited, TypeEvalContext context); + @RequiredReadAction Set getMemberNames(boolean inherited, TypeEvalContext context); boolean isValid(); diff --git a/python-psi-api/src/main/java/com/jetbrains/python/psi/types/PyType.java b/python-psi-api/src/main/java/com/jetbrains/python/psi/types/PyType.java index 1d802a79..a833459c 100644 --- a/python-psi-api/src/main/java/com/jetbrains/python/psi/types/PyType.java +++ b/python-psi-api/src/main/java/com/jetbrains/python/psi/types/PyType.java @@ -18,6 +18,7 @@ import java.util.List; import java.util.Set; +import consulo.annotation.access.RequiredReadAction; import org.jspecify.annotations.Nullable; import consulo.util.dataholder.Key; import consulo.language.psi.PsiElement; @@ -32,50 +33,51 @@ * * @author yole */ -public interface PyType -{ +public interface PyType { + /** + * Resolves an attribute of type. + * + * @param name attribute name + * @param location the expression of type qualifierType on which the member is being resolved (optional) + * @param direction + * @param resolveContext + * @return null if name definitely cannot be found (e.g. in a qualified reference), + * or an empty list if name is not found but other contexts are worth looking at, + * or a list of elements that define the name, a la multiResolve(). + */ + @Nullable + List resolveMember( + String name, + @Nullable PyExpression location, + AccessDirection direction, + PyResolveContext resolveContext + ); - /** - * Resolves an attribute of type. - * - * @param name attribute name - * @param location the expression of type qualifierType on which the member is being resolved (optional) - * @param direction - * @param resolveContext - * @return null if name definitely cannot be found (e.g. in a qualified reference), - * or an empty list if name is not found but other contexts are worth looking at, - * or a list of elements that define the name, a la multiResolve(). - */ - @Nullable - List resolveMember(String name, - @Nullable PyExpression location, - AccessDirection direction, - PyResolveContext resolveContext); + /** + * Proposes completion variants from type's attributes. + * + * @param location the reference on which the completion was invoked + * @param context to share state between nested invocations + * @return completion variants good for {@link com.intellij.psi.PsiReference#getVariants} return value. + */ + Object[] getCompletionVariants(String completionPrefix, PsiElement location, ProcessingContext context); - /** - * Proposes completion variants from type's attributes. - * - * @param location the reference on which the completion was invoked - * @param context to share state between nested invocations - * @return completion variants good for {@link com.intellij.psi.PsiReference#getVariants} return value. - */ - Object[] getCompletionVariants(String completionPrefix, PsiElement location, ProcessingContext context); + /** + * Context key for access to a set of names already found by variant search. + */ + Key> CTX_NAMES = new Key<>("Completion variants names"); - /** - * Context key for access to a set of names already found by variant search. - */ - Key> CTX_NAMES = new Key<>("Completion variants names"); + /** + * @return name of the type + */ + @Nullable + @RequiredReadAction + String getName(); - /** - * @return name of the type - */ - @Nullable - String getName(); + /** + * @return true if the type is a known built-in type. + */ + boolean isBuiltin(); - /** - * @return true if the type is a known built-in type. - */ - boolean isBuiltin(); - - void assertValid(String message); + void assertValid(String message); } diff --git a/python-rest/src/main/java/com/jetbrains/python/rest/run/docutils/DocutilsConfigurationProducer.java b/python-rest/src/main/java/com/jetbrains/python/rest/run/docutils/DocutilsConfigurationProducer.java index a2f0dfc2..d1592345 100644 --- a/python-rest/src/main/java/com/jetbrains/python/rest/run/docutils/DocutilsConfigurationProducer.java +++ b/python-rest/src/main/java/com/jetbrains/python/rest/run/docutils/DocutilsConfigurationProducer.java @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.jetbrains.python.rest.run.docutils; import com.jetbrains.rest.RestFileType; import com.jetbrains.python.rest.run.RestRunConfiguration; import com.jetbrains.python.rest.run.RestRunConfigurationType; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; import consulo.execution.RunnerAndConfigurationSettings; import consulo.execution.action.ConfigurationContext; @@ -26,7 +26,6 @@ import consulo.execution.action.RuntimeConfigurationProducer; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; -import consulo.language.util.ModuleUtilCore; import consulo.module.Module; import consulo.project.Project; import consulo.util.io.FileUtil; @@ -37,7 +36,7 @@ import java.util.List; /** - * User : catherine + * @author catherine */ @ExtensionImpl public class DocutilsConfigurationProducer extends RuntimeConfigurationProducer implements Cloneable { @@ -47,16 +46,19 @@ public DocutilsConfigurationProducer() { super(RestRunConfigurationType.getInstance().DOCUTILS_FACTORY); } + @Override public PsiElement getSourceElement() { return mySourceFile; } + @Override + @RequiredReadAction protected RunnerAndConfigurationSettings createConfigurationByElement(Location location, ConfigurationContext context) { PsiFile script = location.getPsiElement().getContainingFile(); if (script == null || script.getFileType() != RestFileType.INSTANCE) { return null; } - Module module = ModuleUtilCore.findModuleForPsiElement(script); + Module module = script.getModule(); mySourceFile = script; Project project = mySourceFile.getProject(); @@ -114,6 +116,7 @@ protected RunnerAndConfigurationSettings findExistingByElement(Location location return null; } + @Override public int compareTo(RuntimeConfigurationProducer o) { return PREFERED; }