let's have separate modules for python-psi-api (that will go into upsource later) and python-openapi (which will contain UI stuff and more)

This commit is contained in:
Dmitry Jemerov
2012-08-08 10:28:35 +02:00
parent e4df653995
commit 718ec7e372
144 changed files with 995 additions and 2 deletions
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="core-api" />
</component>
</module>
@@ -0,0 +1,157 @@
package com.jetbrains.python;
import com.intellij.psi.TokenType;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.jetbrains.python.psi.PyElementType;
public class PyTokenTypes {
private PyTokenTypes() {
}
public static final PyElementType IDENTIFIER = new PyElementType("IDENTIFIER");
public static final PyElementType LINE_BREAK = new PyElementType("LINE_BREAK");
public static final PyElementType STATEMENT_BREAK = new PyElementType("STATEMENT_BREAK");
public static final PyElementType SPACE = new PyElementType("SPACE");
public static final PyElementType TAB = new PyElementType("TAB");
public static final PyElementType FORMFEED = new PyElementType("FORMFEED");
public static final IElementType BAD_CHARACTER = TokenType.BAD_CHARACTER;
public static final PyElementType INCONSISTENT_DEDENT = new PyElementType("INCONSISTENT_DEDENT");
public static final PyElementType END_OF_LINE_COMMENT = new PyElementType("END_OF_LINE_COMMENT");
public static final PyElementType AND_KEYWORD = new PyElementType("AND_KEYWORD");
public static final PyElementType AS_KEYWORD = new PyElementType("AS_KEYWORD");
public static final PyElementType ASSERT_KEYWORD = new PyElementType("ASSERT_KEYWORD");
public static final PyElementType BREAK_KEYWORD = new PyElementType("BREAK_KEYWORD");
public static final PyElementType CLASS_KEYWORD = new PyElementType("CLASS_KEYWORD");
public static final PyElementType CONTINUE_KEYWORD = new PyElementType("CONTINUE_KEYWORD");
public static final PyElementType DEF_KEYWORD = new PyElementType("DEF_KEYWORD");
public static final PyElementType DEL_KEYWORD = new PyElementType("DEL_KEYWORD");
public static final PyElementType ELIF_KEYWORD = new PyElementType("ELIF_KEYWORD");
public static final PyElementType ELSE_KEYWORD = new PyElementType("ELSE_KEYWORD");
public static final PyElementType EXCEPT_KEYWORD = new PyElementType("EXCEPT_KEYWORD");
public static final PyElementType EXEC_KEYWORD = new PyElementType("EXEC_KEYWORD");
public static final PyElementType FINALLY_KEYWORD = new PyElementType("FINALLY_KEYWORD");
public static final PyElementType FOR_KEYWORD = new PyElementType("FOR_KEYWORD");
public static final PyElementType FROM_KEYWORD = new PyElementType("FROM_KEYWORD");
public static final PyElementType GLOBAL_KEYWORD = new PyElementType("GLOBAL_KEYWORD");
public static final PyElementType IF_KEYWORD = new PyElementType("IF_KEYWORD");
public static final PyElementType IMPORT_KEYWORD = new PyElementType("IMPORT_KEYWORD");
public static final PyElementType IN_KEYWORD = new PyElementType("IN_KEYWORD", "__contains__");
public static final PyElementType IS_KEYWORD = new PyElementType("IS_KEYWORD");
public static final PyElementType LAMBDA_KEYWORD = new PyElementType("LAMBDA_KEYWORD");
public static final PyElementType NOT_KEYWORD = new PyElementType("NOT_KEYWORD");
public static final PyElementType OR_KEYWORD = new PyElementType("OR_KEYWORD");
public static final PyElementType PASS_KEYWORD = new PyElementType("PASS_KEYWORD");
public static final PyElementType PRINT_KEYWORD = new PyElementType("PRINT_KEYWORD");
public static final PyElementType RAISE_KEYWORD = new PyElementType("RAISE_KEYWORD");
public static final PyElementType RETURN_KEYWORD = new PyElementType("RETURN_KEYWORD");
public static final PyElementType TRY_KEYWORD = new PyElementType("TRY_KEYWORD");
public static final PyElementType WITH_KEYWORD = new PyElementType("WITH_KEYWORD");
public static final PyElementType WHILE_KEYWORD = new PyElementType("WHILE_KEYWORD");
public static final PyElementType YIELD_KEYWORD = new PyElementType("YIELD_KEYWORD");
// new keywords in Python 3
public static final PyElementType NONE_KEYWORD = new PyElementType("NONE_KEYWORD");
public static final PyElementType TRUE_KEYWORD = new PyElementType("TRUE_KEYWORD");
public static final PyElementType FALSE_KEYWORD = new PyElementType("FALSE_KEYWORD");
public static final PyElementType NONLOCAL_KEYWORD = new PyElementType("NONLOCAL_KEYWORD");
public static final PyElementType DEBUG_KEYWORD = new PyElementType("DEBUG_KEYWORD");
public static final PyElementType INTEGER_LITERAL = new PyElementType("INTEGER_LITERAL");
public static final PyElementType FLOAT_LITERAL = new PyElementType("FLOAT_LITERAL");
public static final PyElementType IMAGINARY_LITERAL = new PyElementType("IMAGINARY_LITERAL");
public static final PyElementType SINGLE_QUOTED_STRING = new PyElementType("SINGLE_QUOTED_STRING");
public static final PyElementType TRIPLE_QUOTED_STRING = new PyElementType("TRIPLE_QUOTED_STRING");
public static final PyElementType SINGLE_QUOTED_UNICODE = new PyElementType("SINGLE_QUOTED_UNICODE");
public static final PyElementType TRIPLE_QUOTED_UNICODE = new PyElementType("TRIPLE_QUOTED_UNICODE");
public static final PyElementType DOCSTRING = new PyElementType("DOCSTRING");
public static final TokenSet UNICODE_NODES = TokenSet.create(TRIPLE_QUOTED_UNICODE, SINGLE_QUOTED_UNICODE);
public static final TokenSet TRIPLE_NODES = TokenSet.create(TRIPLE_QUOTED_UNICODE, TRIPLE_QUOTED_STRING);
public static final TokenSet STRING_NODES = TokenSet.orSet(UNICODE_NODES, TokenSet.create(SINGLE_QUOTED_STRING,
TRIPLE_QUOTED_STRING, DOCSTRING));
// Operators
public static final PyElementType PLUS = new PyElementType("PLUS", "__add__");// +
public static final PyElementType MINUS = new PyElementType("MINUS", "__sub__");// -
public static final PyElementType MULT = new PyElementType("MULT", "__mul__");// *
public static final PyElementType EXP = new PyElementType("EXP", "__pow__");// **
public static final PyElementType DIV = new PyElementType("DIV", "__div__"); // /
public static final PyElementType FLOORDIV = new PyElementType("FLOORDIV", "__floordiv__"); // //
public static final PyElementType PERC = new PyElementType("PERC", "__mod__");// %
public static final PyElementType LTLT = new PyElementType("LTLT", "__lshift__");// <<
public static final PyElementType GTGT = new PyElementType("GTGT", "__rshift__");// >>
public static final PyElementType AND = new PyElementType("AND", "__and__");// &
public static final PyElementType OR = new PyElementType("OR", "__or__");// |
public static final PyElementType XOR = new PyElementType("XOR", "__xor__");// ^
public static final PyElementType TILDE = new PyElementType("TILDE", "__invert__");// ~
public static final PyElementType LT = new PyElementType("LT", "__lt__");// <
public static final PyElementType GT = new PyElementType("GT", "__gt__");// >
public static final PyElementType LE = new PyElementType("LE", "__le__");// <=
public static final PyElementType GE = new PyElementType("GE", "__ge__");// >=
public static final PyElementType EQEQ = new PyElementType("EQEQ", "__eq__");// ==
public static final PyElementType NE = new PyElementType("NE", "__ne__");// !=
public static final PyElementType NE_OLD = new PyElementType("NE_OLD", "__ne__");// <>
// Delimiters
public static final PyElementType LPAR = new PyElementType("LPAR");// (
public static final PyElementType RPAR = new PyElementType("RPAR");// )
public static final PyElementType LBRACKET = new PyElementType("LBRACKET");// [
public static final PyElementType RBRACKET = new PyElementType("RBRACKET");// ]
public static final PyElementType LBRACE = new PyElementType("LBRACE");// {
public static final PyElementType RBRACE = new PyElementType("RBRACE");// }
public static final PyElementType AT = new PyElementType("AT");// @
public static final PyElementType COMMA = new PyElementType("COMMA");// ,
public static final PyElementType COLON = new PyElementType("COLON");// :
public static final PyElementType DOT = new PyElementType("DOT");// .
public static final PyElementType TICK = new PyElementType("TICK");// `
public static final PyElementType EQ = new PyElementType("EQ");// =
public static final PyElementType SEMICOLON = new PyElementType("SEMICOLON");// ;
public static final PyElementType PLUSEQ = new PyElementType("PLUSEQ");// +=
public static final PyElementType MINUSEQ = new PyElementType("MINUSEQ");// -=
public static final PyElementType MULTEQ = new PyElementType("MULTEQ");// *=
public static final PyElementType DIVEQ = new PyElementType("DIVEQ"); // /=
public static final PyElementType FLOORDIVEQ = new PyElementType("FLOORDIVEQ"); // //=
public static final PyElementType PERCEQ = new PyElementType("PERCEQ");// %=
public static final PyElementType ANDEQ = new PyElementType("ANDEQ");// &=
public static final PyElementType OREQ = new PyElementType("OREQ");// |=
public static final PyElementType XOREQ = new PyElementType("XOREQ");// ^=
public static final PyElementType LTLTEQ = new PyElementType("LTLTEQ");// <<=
public static final PyElementType GTGTEQ = new PyElementType("GTGTEQ");// >>=
public static final PyElementType EXPEQ = new PyElementType("EXPEQ");// **=
public static final TokenSet OPERATIONS = TokenSet.create(
PLUS, MINUS, MULT, EXP, DIV, FLOORDIV, PERC, LTLT, GTGT, AND, OR,
XOR, TILDE, LT, GT, LE, GE, EQEQ, NE, NE_OLD, AT, COLON, TICK, EQ,
PLUSEQ, MINUSEQ,
MULTEQ, DIVEQ, FLOORDIVEQ, PERCEQ, ANDEQ, OREQ, XOREQ, LTLTEQ, GTGTEQ,
EXPEQ);
public static final TokenSet COMPARISON_OPERATIONS = TokenSet.create(
LT, GT, EQEQ, GE, LE, NE, NE_OLD, IN_KEYWORD, IS_KEYWORD, NOT_KEYWORD);
public static final TokenSet SHIFT_OPERATIONS = TokenSet.create(LTLT, GTGT);
public static final TokenSet ADDITIVE_OPERATIONS = TokenSet.create(PLUS, MINUS);
public static final TokenSet MULTIPLICATIVE_OPERATIONS = TokenSet.create(MULT, FLOORDIV, DIV, PERC);
public static final TokenSet MULTIPLICATIVE_OR_EXP = TokenSet.create(MULT, FLOORDIV, DIV, PERC, EXP);
public static final TokenSet UNARY_OPERATIONS = TokenSet.create(PLUS, MINUS, TILDE);
public static final TokenSet BITWISE_OPERATIONS = TokenSet.create(AND, OR, XOR);
public static final TokenSet EQUALITY_OPERATIONS = TokenSet.create(EQEQ, NE, NE_OLD);
public static final TokenSet RELATIONAL_OPERATIONS = TokenSet.create(LT, GT, LE, GE);
public static final TokenSet END_OF_STATEMENT = TokenSet.create(STATEMENT_BREAK, SEMICOLON);
public static final TokenSet WHITESPACE = TokenSet.create(SPACE, TAB, FORMFEED);
public static final TokenSet WHITESPACE_OR_LINEBREAK = TokenSet.create(SPACE, TAB, FORMFEED, LINE_BREAK);
public static final TokenSet OPEN_BRACES = TokenSet.create(LBRACKET, LBRACE, LPAR);
public static final TokenSet CLOSE_BRACES = TokenSet.create(RBRACKET, RBRACE, RPAR);
public static final TokenSet AUG_ASSIGN_OPERATIONS = TokenSet.create(PLUSEQ, MINUSEQ, MULTEQ, DIVEQ,
PERCEQ, EXPEQ, GTGTEQ, LTLTEQ, ANDEQ, OREQ, XOREQ, FLOORDIVEQ);
public static final PyElementType BACKSLASH = new PyElementType("BACKSLASH");
public static final PyElementType INDENT = new PyElementType("INDENT");
public static final PyElementType DEDENT = new PyElementType("DEDENT");
}
@@ -0,0 +1,18 @@
package com.jetbrains.python;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.psi.tree.TokenSet;
/**
* @author vlan
*/
public interface PythonDialectsTokenSetContributor {
ExtensionPointName<PythonDialectsTokenSetContributor> EP_NAME = ExtensionPointName.create("Pythonid.dialectsTokenSetContributor");
TokenSet getStatementTokens();
TokenSet getExpressionTokens();
TokenSet getNameDefinerTokens();
TokenSet getKeywordTokens();
TokenSet getParameterTokens();
TokenSet getFunctionDeclarationTokens();
}
@@ -0,0 +1,118 @@
package com.jetbrains.python;
import com.intellij.lang.Language;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author yole
*/
public class PythonFileType extends LanguageFileType {
private static final Pattern ENCODING_PATTERN = Pattern.compile("coding[:=]\\s*([-\\w.]+)");
public static PythonFileType INSTANCE = new PythonFileType();
private final Icon _icon;
public PythonFileType() {
this(new PythonLanguage());
}
public PythonFileType(Language language) {
super(language);
_icon = IconLoader.getIcon("/com/jetbrains/python/icons/pythonFile.png");
}
@NotNull
public String getName() {
return "Python";
}
@NotNull
public String getDescription() {
return "Python files";
}
@NotNull
public String getDefaultExtension() {
return "py";
}
@NotNull
public Icon getIcon() {
return _icon;
}
@Override
public String getCharset(@NotNull VirtualFile file, byte[] content) {
if (CharsetToolkit.hasUTF8Bom(content)) {
return CharsetToolkit.UTF8;
}
ByteBuffer bytes = ByteBuffer.wrap(content, 0, Math.min(256, content.length));
String decoded = CharsetToolkit.UTF8_CHARSET.decode(bytes).toString();
return getCharsetFromEncodingDeclaration(StringUtil.convertLineSeparators(decoded));
}
@Override
public Charset extractCharsetFromFileContent(@Nullable Project project, @Nullable VirtualFile file, @NotNull String content) {
final String charsetName = getCharsetFromEncodingDeclaration(content);
if (charsetName == null) {
return null;
}
try {
return Charset.forName(charsetName);
}
catch (IllegalCharsetNameException e) {
return null;
}
catch (UnsupportedCharsetException e) {
return null;
}
}
@Nullable
public static String getCharsetFromEncodingDeclaration(String content) {
if (!content.contains("coding")) {
return null;
}
final List<String> lines = StringUtil.split(content, "\n");
int count = 0;
for (String line : lines) {
final Matcher matcher = ENCODING_PATTERN.matcher(line);
if (matcher.find()) {
final String charset = matcher.group(1);
return normalizeCharset(charset);
}
count++;
if (count == 2) break;
}
return null;
}
@Nullable
private static String normalizeCharset(String charset) {
if (charset == null) {
return null;
}
charset = charset.toLowerCase();
if ("latin-1".equals(charset)) {
return "iso-8859-1";
}
return charset;
}
}
@@ -0,0 +1,21 @@
package com.jetbrains.python;
import com.intellij.lang.Language;
/**
* @author yole
*/
public class PythonLanguage extends Language {
public static PythonLanguage getInstance() {
return (PythonLanguage)PythonFileType.INSTANCE.getLanguage();
}
@Override
public boolean isCaseSensitive() {
return true; // http://jetbrains-feed.appspot.com/message/372001
}
protected PythonLanguage() {
super("Python");
}
}
@@ -0,0 +1,12 @@
package com.jetbrains.python.codeInsight.controlflow;
import com.jetbrains.python.psi.PyElement;
/**
* Marker interface for Python elements which define a scope.
*
* @see ControlFlowCache
* @author oleg
*/
public interface ScopeOwner extends PyElement {
}
@@ -0,0 +1,38 @@
package com.jetbrains.python.psi;
import com.intellij.psi.PsiElement;
/** How we refer to a name */
public enum AccessDirection {
/** Reference */
READ,
/** Target of assignment */
WRITE,
/** Target of del statement */
DELETE;
/**
* @param element
* @return the access direction of element, judging from surrounding statements.
*/
public static AccessDirection of(PyElement element) {
final PsiElement parent = element.getParent();
if (element instanceof PyTargetExpression) {
return WRITE;
}
else if (parent instanceof PyAssignmentStatement) {
for (PyExpression target : ((PyAssignmentStatement)parent).getTargets()) {
if (target == element) {
return WRITE;
}
}
}
else if (parent instanceof PyDelStatement) {
return DELETE;
}
return READ;
}
}
@@ -0,0 +1,94 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
/**
* Result of analysis of argument list application to the callee.
* Contains neatly arranged lists and mappings between arguments and parameters,
* including error diagnostics.
*/
public interface CallArgumentsMapping {
/**
* @return A mapping argument->parameter for non-starred parameters (but includes starred argument).
*/
@NotNull
Map<PyExpression, PyNamedParameter> getPlainMappedParams();
/**
* Consider a piece of Python 2.x code:
* <pre>
* def f(a, (b, c,), d):
* ...
*
* x = (1, 2)
* f(10, x, 20)
* </pre>
* Here, argument <tt>x</tt> successfully maps to both <tt>b</tt> and <tt>c</tt> parameters.
* This case is rare, so a separate method is introduced, to keep {@link CallArgumentsMapping#getPlainMappedParams()} simple.
* @return mapping of arguments to nested parameters that get collectively mapped to that argument.
*/
@NotNull Map<PyExpression, List<PyNamedParameter>> getNestedMappedParams();
/**
* @return First *arg, or null.
*/
@Nullable
PyStarArgument getTupleArg();
/**
* @return A list of parameters mapped to a *arg.
*/
@NotNull List<PyNamedParameter> getTupleMappedParams();
/**
* @return First **arg, or null.
*/
@Nullable
PyStarArgument getKwdArg();
/**
* @return A list of parameters mapped to an **arg.
*/
@NotNull List<PyNamedParameter> getKwdMappedParams();
/**
* @return A list of parameters for which no arguments were found ('missing').
*/
@NotNull
List<PyNamedParameter> getUnmappedParams();
/**
* @return Lists all args with their flags.
* @see com.jetbrains.python.psi.CallArgumentsMapping.ArgFlag
*/
Map<PyExpression, EnumSet<ArgFlag>> getArgumentFlags();
boolean hasProblems();
/**
* @return result of a resolveCallee() against the function call to which the parameter list belongs.
*/
@Nullable
PyCallExpression.PyMarkedCallee getMarkedCallee();
PyArgumentList getArgumentList();
/**
* Flags to mark analysis results for an argument.
* Theoretically can be used together, but currently only make sense as a single value per argument.
*/
enum ArgFlag {
/** duplicate plain */ IS_DUP,
/** unexpected */ IS_UNMAPPED,
/** duplicate **arg */ IS_DUP_KWD,
/** duplicate *arg */ IS_DUP_TUPLE,
/** positional past keyword */ IS_POS_PAST_KWD,
/** *param is too long */ IS_TOO_LONG,
}
}
@@ -0,0 +1,34 @@
package com.jetbrains.python.psi;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Something that can be called, passed parameters to, and return something back.
* <br/>
* User: dcheryasov
* Date: May 15, 2010 3:22:30 PM
*/
public interface Callable extends PyElement {
/**
* @return a list of parameters passed to this callable, possibly empty.
*/
@NotNull
PyParameterList getParameterList();
/**
* @return the type of returned value.
*/
@Nullable
PyType getReturnType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite);
/**
* @return a methods returns itself, non-method callables return null.
*/
@Nullable
PyFunction asMethod();
}
@@ -0,0 +1,7 @@
package com.jetbrains.python.psi;
/**
* @author yole
*/
public interface ComprehensionComponent {
}
@@ -0,0 +1,11 @@
package com.jetbrains.python.psi;
/**
* The "for" part of list comprehensions and generators.
* User: dcheryasov
* Date: Jul 31, 2008
*/
public interface ComprhForComponent extends ComprehensionComponent {
PyExpression getIteratorVariable();
PyExpression getIteratedList();
}
@@ -0,0 +1,13 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.Nullable;
/**
* The "if" part of list comprehensions and generators.
* User: dcheryasov
* Date: Jul 31, 2008
*/
public interface ComprhIfComponent extends ComprehensionComponent {
@Nullable
PyExpression getTest();
}
@@ -0,0 +1,78 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.NotNull;
/**
* Lists interesting features importable from __future__.
* <code>.toString()</code> returns the Python name of the feature.
* <br/>
* User: dcheryasov
*/
public enum FutureFeature {
GENERATORS("generators", 22, 23), // historical
DIVISION("division", 22, 30),
ABSOLUTE_IMPORT("absolute_import", 25, 27),
WITH_STATEMENT("with_statement", 25, 26),
PRINT_FUNCTION("print_function", 26, 30),
UNICODE_LITERALS("unicode_literals", 26, 30),
BARRY_AS_FLUFL("barry_as_FLUFL", 31, 39), // last as of CPython 3.2
// NOTE: only add new features to the end unless you want to break existing stubs that rely on ordinal
;
// TODO: link it to LanguageLevel
private final String myName;
private final int myOptionalVersion;
private final int myRequiredVersion;
/**
* @param name what is imported from __future__
* @param proposed version in which the feature has become importable
* @param included version in which the feature is included by default
*/
FutureFeature(final @NotNull String name, final int proposed, final int included) {
myName = name;
myOptionalVersion = proposed;
myRequiredVersion = included;
}
/**
* @return the Python importable name of the feature.
*/
@Override
public String toString() {
return myName;
}
/**
* @return Version since which it is possible to import the feature from __future__
*/
public int getOptionalVersion() {
return myOptionalVersion;
}
/**
* @return Version since which the feature is built into the language (required from the language).
*/
public int getRequiredVersion() {
return myRequiredVersion;
}
/**
* @param level
* @return true iff the feature can either be imported from __future__ at given level, or is already built-in.
*/
public boolean availableAt(LanguageLevel level) {
return level.getVersion() >= myOptionalVersion;
}
/**
* @param level
* @return true iff the feature is already present (required) at given level, and there's no need to import it.
*/
public boolean requiredAt(LanguageLevel level) {
return level.getVersion() >= myRequiredVersion;
}
public static final FutureFeature[] ALL = {
GENERATORS, DIVISION, ABSOLUTE_IMPORT, WITH_STATEMENT, PRINT_FUNCTION, UNICODE_LITERALS, BARRY_AS_FLUFL
};
}
@@ -0,0 +1,140 @@
package com.jetbrains.python.psi;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
public enum LanguageLevel {
PYTHON24(24, false, true, false, false),
PYTHON25(25, false, true, false, false),
PYTHON26(26, true, true, false, false),
PYTHON27(27, true, true, true, false),
PYTHON30(30, true, false, false, true),
PYTHON31(31, true, false, true, true),
PYTHON32(32, true, false, true, true),
PYTHON33(33, true, false, true, true);
public static LanguageLevel FORCE_LANGUAGE_LEVEL = null;
public static LanguageLevel getDefault() {
return PYTHON26;
}
private final int myVersion;
private final boolean myHasWithStatement;
private final boolean myHasPrintStatement;
private final boolean mySupportsSetLiterals;
private final boolean myIsPy3K;
LanguageLevel(int version, boolean hasWithStatement, boolean hasPrintStatement, boolean supportsSetLiterals, boolean isPy3K) {
myVersion = version;
myHasWithStatement = hasWithStatement;
myHasPrintStatement = hasPrintStatement;
mySupportsSetLiterals = supportsSetLiterals;
myIsPy3K = isPy3K;
}
/**
* @return an int where major and minor version are represented decimally: "version 2.5" is 25.
*/
public int getVersion() {
return myVersion;
}
public boolean hasWithStatement() {
return myHasWithStatement;
}
public boolean hasPrintStatement() {
return myHasPrintStatement;
}
public boolean supportsSetLiterals() {
return mySupportsSetLiterals;
}
public boolean isPy3K() {
return myIsPy3K;
}
public boolean isOlderThan(@NotNull LanguageLevel other) {
return myVersion < other.myVersion;
}
public boolean isAtLeast(@NotNull LanguageLevel other) {
return myVersion >= other.myVersion;
}
public static LanguageLevel fromPythonVersion(@NotNull String pythonVersion) {
if (pythonVersion.startsWith("2.7")) {
return PYTHON27;
}
if (pythonVersion.startsWith("2.6")) {
return PYTHON26;
}
if (pythonVersion.startsWith("2.5")) {
return PYTHON25;
}
if (pythonVersion.startsWith("3")) {
if (pythonVersion.startsWith("3.0")) {
return PYTHON30;
}
if (pythonVersion.startsWith("3.1")) {
return PYTHON31;
}
if (pythonVersion.startsWith("3.2")) {
return PYTHON32;
}
return PYTHON33;
}
return PYTHON24;
}
public static final Key<LanguageLevel> KEY = new Key<LanguageLevel>("python.language.level");
@NotNull
public static LanguageLevel forFile(@NotNull VirtualFile virtualFile) {
// Most of the cases should be handled by this one, PyLanguageLevelPusher pushes folders only
final VirtualFile folder = virtualFile.getParent();
if (folder != null) {
final LanguageLevel level = folder.getUserData(KEY);
if (level != null) return level;
}
else {
// However this allows us to setup language level per file manually
// in case when it is LightVirtualFile
final LanguageLevel level = virtualFile.getUserData(KEY);
if (level != null) return level;
if (ApplicationManager.getApplication().isUnitTestMode()) {
final LanguageLevel languageLevel = FORCE_LANGUAGE_LEVEL;
if (languageLevel != null) {
return languageLevel;
}
}
}
return getDefault();
}
@NotNull
public static LanguageLevel forElement(@NotNull PsiElement element) {
final PsiFile containingFile = element.getContainingFile();
if (containingFile instanceof PyFile) {
return ((PyFile) containingFile).getLanguageLevel();
}
return getDefault();
}
@Override
public String toString() {
return myVersion / 10 + "." + myVersion % 10;
}
}
@@ -0,0 +1,57 @@
package com.jetbrains.python.psi;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* PSI element that (re)defnies names in following namespace, e.g. as assignment statement does.
*
* NOTE: When declaring additional elements as name definers, please also adjust the token set via
* {@link PythonDialectsTokenSetContributor#getNameDefinerTokens()}.
*
* @author dcheryasov
*/
public interface NameDefiner extends PsiElement {
/**
* @return an iterator that iterates over defined names, in order of definition.
* Complex targets count, too: "(y, x[1]) = (1, 2)" return both "y" and "x[1]".
*/
@NotNull
Iterable<PyElement> iterateNames();
/**
* @param name an unqualified name.
* @return an element which is defined under that name in this instance, or null.
*/
@Nullable
PsiElement getElementNamed(String name);
/**
* @return true if names found inside its children cannot be resolved to names defined by this statement.
* E.g. name <tt>a</tt> is defined in statement <tt>a = a + 1</tt> but the <tt>a</tt> on the right hand side
* must not resolve to the <tt>a</tt> on the left hand side.
*/
boolean mustResolveOutside();
class IterHelper { // TODO: rename sanely; move to a proper place.
private IterHelper() {}
@Nullable
public static PyElement findName(Iterable<PyElement> it, String name) {
PyElement ret = null;
for (PyElement elt : it) {
if (elt != null) {
// qualified refs don't match by last name, and we're not checking FQNs here
if (elt instanceof PyQualifiedExpression && ((PyQualifiedExpression)elt).getQualifier() != null) continue;
if (name.equals(elt.getName())) { // plain name matches
ret = elt;
break;
}
}
}
return ret;
}
}
}
@@ -0,0 +1,54 @@
package com.jetbrains.python.psi;
import com.jetbrains.python.toolbox.Maybe;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Describes a property, result of either a call to property() or application of @property and friends.
* This is <i>not</i> a node of PSI tree.
* <br/>
* User: dcheryasov
* Date: May 31, 2010 5:18:10 PM
*/
public interface Property {
String getName();
/**
* @return the setter: a method or null if defined, or something else callable if undefined.
*/
@NotNull
Maybe<Callable> getSetter();
/**
* @return the getter: a method or null if defined, or something else callable if undefined.
*/
@NotNull
Maybe<Callable> getGetter();
/**
* @return the deleter: a method or null if defined, or something else callable if undefined.
*/
@NotNull
Maybe<Callable> getDeleter();
/**
* @return doc string as known to property() call. If null, see getter's doc.
*/
@Nullable
String getDoc();
/**
* @return the target to which the result of property() call is assigned. For things defined via @property, it is null.
*/
@Nullable
PyTargetExpression getDefinitionSite();
/**
* @param direction how the property is accessed
* @return getter, setter, or deleter.
*/
@NotNull
Maybe<Callable> getByDirection(@NotNull AccessDirection direction);
}
@@ -0,0 +1,15 @@
package com.jetbrains.python.psi;
import com.intellij.psi.StubBasedPsiElement;
import com.jetbrains.python.psi.stubs.PyAnnotationStub;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public interface PyAnnotation extends PyElement, StubBasedPsiElement<PyAnnotationStub> {
PyExpression getValue();
@Nullable
PyClass resolveToClass();
}
@@ -0,0 +1,44 @@
package com.jetbrains.python.psi;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Represents an argument list of a function call.
*
* @author yole
*/
public interface PyArgumentList extends PyElement {
@NotNull PyExpression[] getArguments();
@Nullable PyKeywordArgument getKeywordArgument(String name);
void addArgument(PyExpression arg);
void addArgumentFirst(PyExpression arg);
void addArgumentAfter(PyExpression argument, PyExpression afterThis);
/**
* @return the call expression to which this argument list belongs; not null in correctly parsed cases.
*/
@Nullable
PyCallExpression getCallExpression();
/**
* Tries to map the argument list to callee's idea of parameters.
* @return a result object with mappings and diagnostic flags.
* @param resolveContext the reference resolution context
* @param implicitOffset known from the context implicit offset
*/
@NotNull
CallArgumentsMapping analyzeCall(PyResolveContext resolveContext, int implicitOffset);
@NotNull
CallArgumentsMapping analyzeCall(PyResolveContext resolveContext);
@Nullable
ASTNode getClosingParen();
}
@@ -0,0 +1,8 @@
package com.jetbrains.python.psi;
/**
* @author yole
*/
public interface PyAssertStatement extends PyStatement {
PyExpression[] getArguments();
}
@@ -0,0 +1,65 @@
package com.jetbrains.python.psi;
import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* Describes an assignment statement.
*/
public interface PyAssignmentStatement extends PyStatement, NameDefiner {
/**
* @return the left-hand side of the statement; each item may consist of many elements.
*/
PyExpression[] getTargets();
/**
* Return all expressions which are considered assignment targets (to the left of the last = sign in the statement).
* Doesn't unpack tuples, parentheses or anything.
*
* @return the list of assignment target expressions
*/
@NotNull
PyExpression[] getRawTargets();
/**
* @return right-hand side of the statement; may as well consist of many elements.
*/
@Nullable
PyExpression getAssignedValue();
/**
* Applies a visitor to every element of left-hand side. Tuple elements are flattened down to their most nested
* parts. E.g. if the target is <tt>a, b[1], (c(2).d, e.f)</tt>, then expressions
* <tt>a</tt>, <tt>b[1]</tt>, <tt>c(2).d</tt>, <tt>e.f</tt> will be visited.
* Order of visiting is not guaranteed.
* @param visitor its {@link PyElementVisitor#visitPyExpression} method will be called for each elementary target expression
*/
//void visitElementaryTargets(PyElementVisitor visitor);
/**
* Maps target expressions to assigned values, unpacking tuple expressions.
* For "{@code a, (b, c) = 1, (2, 'foo')}" the result will be [(a,1), (b:2), (c:'foo')].
* <br/>
* If there's a number of LHS targets, the RHS expression is mapped to every target.
* For "{@code a = b = c = 1}" the result will be [(a,1), (b,1), (c,1)].
* <br/>
* Elements of tuples and tuples themselves may get interspersed in complex mappings.
* For "{@code a = b,c = 1,2}" the result will be [(a,(1,2)), (b,1), (c,2)].
* <br/>
* If RHS and LHS are mis-balanced, certain target or value expressions may be null.
* If source is severely incorrect, the returned mapping is empty.
* @return a list of [target, value] pairs; either part of a pair may be null, but not both.
*/
@NotNull
List<Pair<PyExpression, PyExpression>> getTargetsToValuesMapping();
@Nullable
PyExpression getLeftHandSideExpression();
}
@@ -0,0 +1,14 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public interface PyAugAssignmentStatement extends PyStatement {
@NotNull
PyExpression getTarget();
@Nullable
PyExpression getValue();
}
@@ -0,0 +1,23 @@
package com.jetbrains.python.psi;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public interface PyBinaryExpression extends PyQualifiedExpression, PyReferenceOwner {
PyExpression getLeftExpression();
@Nullable PyExpression getRightExpression();
@Nullable
PyElementType getOperator();
@Nullable
PsiElement getPsiOperator();
boolean isOperator(String chars);
PyExpression getOppositeExpression(PyExpression expression)
throws IllegalArgumentException;
}
@@ -0,0 +1,8 @@
package com.jetbrains.python.psi;
/**
* @author yole
*/
public interface PyBoolLiteralExpression extends PyLiteralExpression {
boolean getValue();
}
@@ -0,0 +1,11 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public interface PyBreakStatement extends PyStatement {
@Nullable
PyLoopStatement getLoopStatement();
}
@@ -0,0 +1,143 @@
package com.jetbrains.python.psi;
import com.intellij.psi.PsiElement;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Represents an entire call expression, like <tt>foo()</tt> or <tt>foo.bar[1]('x')</tt>.
*/
public interface PyCallExpression extends PyExpression {
/**
* @return the expression representing the object being called (reference to a function).
*/
@Nullable
PyExpression getCallee();
/**
* @return ArgumentList used in the call.
*/
@Nullable
PyArgumentList getArgumentList();
/**
* @return The array of call arguments, or an empty array if the call has no argument list.
*/
@NotNull
PyExpression[] getArguments();
/**
* If the list of arguments has at least {@code index} elements and the index'th element is of type argClass,
* returns it. Otherwise, returns null.
*
* @param index argument index
* @param argClass argument expected type
* @return the argument or null
*/
@Nullable
<T extends PsiElement> T getArgument(int index, Class<T> argClass);
/**
* Returns the argument at the specified position or the argument marked with the specified keyword, if one is present in the list.
*
* @param index argument index
* @param keyword the argument keyword
* @param argClass argument expected type
* @return the argument or null
*/
@Nullable
<T extends PsiElement> T getArgument(int index, String keyword, Class<T> argClass);
@Nullable
PyExpression getKeywordArgument(String keyword);
void addArgument(PyExpression expression);
/**
* Resolves callee down to particular function (standalone, method, or constructor).
* Return's function part contains a function, never null.
* Return's flag part marks the particulars of the call, esp. the implicit first arg situation.
* Return is null if callee cannot be resolved.
*
* @param resolveContext the reference resolve context
*/
@Nullable
PyMarkedCallee resolveCallee(PyResolveContext resolveContext);
/**
* Resolves callee down to particular function (standalone, method, or constructor).
* Return is null if callee cannot be resolved.
*
* @param resolveContext the reference resolve context
*/
@Nullable
Callable resolveCalleeFunction(PyResolveContext resolveContext);
/**
*
* @param resolveContext the reference resolve context
* @param implicitOffset known from the context implicit offset
*/
@Nullable
PyMarkedCallee resolveCallee(PyResolveContext resolveContext, int implicitOffset);
/**
* Checks if the unqualified name of the callee matches any of the specified names
*
* @param nameCandidates the names to check
* @return true if matches, false otherwise
*/
boolean isCalleeText(@NotNull String... nameCandidates);
/**
* Couples function with a flag describing the way it is called.
*/
class PyMarkedCallee {
@NotNull final Callable myCallable;
PyFunction.Modifier myModifier;
int myImplicitOffset;
boolean myImplicitlyResolved;
/**
* Method-oriented constructor.
*
* @param function the method (or any other callable, but why bother then).
* @param modifier classmethod or staticmethod modifier
* @param offset implicit argument offset; parameters up to this are implicitly filled in the call.
* @param implicitlyResolved value for {@link #isImplicitlyResolved()}
*/
public PyMarkedCallee(@NotNull Callable function, PyFunction.Modifier modifier, int offset, boolean implicitlyResolved) {
myCallable = function;
myModifier = modifier;
myImplicitOffset = offset;
myImplicitlyResolved = implicitlyResolved;
}
@NotNull
public Callable getCallable() {
return myCallable;
}
public PyFunction.Modifier getModifier() {
return myModifier;
}
/**
* @return number of implicitly passed positional parameters; 0 means no parameters are passed implicitly.
* Note that a <tt>*args</tt> is never marked as passed implicitly.
* E.g. for a function like <tt>foo(a, b, *args)</tt> always holds <tt>getImplicitOffset() < 2</tt>.
*/
public int getImplicitOffset() {
return myImplicitOffset;
}
/**
* @return true iff the result is resolved based on divination and name similarity rather than by proper resolution process.
*/
public boolean isImplicitlyResolved() {
return myImplicitlyResolved;
}
}
}
@@ -0,0 +1,168 @@
package com.jetbrains.python.psi;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNameIdentifierOwner;
import com.intellij.psi.StubBasedPsiElement;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.util.ArrayFactory;
import com.intellij.util.Processor;
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
import com.jetbrains.python.psi.stubs.PyClassStub;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* Represents a class declaration in source.
*/
public interface PyClass extends PsiNameIdentifierOwner, PyStatement, NameDefiner, PyDocStringOwner, StubBasedPsiElement<PyClassStub>,
ScopeOwner, PyDecoratable, PyTypedElement {
ArrayFactory<PyClass> ARRAY_FACTORY = new ArrayFactory<PyClass>() {
@Override
public PyClass[] create(int count) {
return new PyClass[count];
}
};
@Nullable
ASTNode getNameNode();
@NotNull
PyStatementList getStatementList();
@Nullable
PyArgumentList getSuperClassExpressionList();
@NotNull
PyExpression[] getSuperClassExpressions();
@NotNull
PsiElement[] getSuperClassElements();
@NotNull
PyClass[] getSuperClasses();
@NotNull
PyFunction[] getMethods();
/**
* Finds a method with given name.
* @param name what to look for
* @param inherited true: search in superclasses; false: only look for methods defined in this class.
* @return
*/
@Nullable
PyFunction findMethodByName(@Nullable @NonNls final String name, boolean inherited);
/**
* Finds either __init__ or __new__, whichever is defined for given class.
* If __init__ is defined, it is found first. This mimics the way initialization methods
* are searched for and called by Python when a constructor call is made.
* Since __new__ only makes sense for new-style classes, an old-style class never finds it with this method.
* @param inherited true: search in superclasses, too.
* @return a method that would be called first when an instance of this class is instantiated.
*/
@Nullable
PyFunction findInitOrNew(boolean inherited);
/**
* @param name of the property
* @return descriptor of property accessors, or null if such property does not exist.
*/
@Nullable
Property findProperty(@NotNull String name);
/**
* Apply a processor to every method, looking at superclasses in method resolution order as needed.
* @param processor what to apply
* @param inherited true: search in superclasses, too.
*/
boolean visitMethods(Processor<PyFunction> processor, boolean inherited);
boolean visitClassAttributes(Processor<PyTargetExpression> processor, boolean inherited);
List<PyTargetExpression> getClassAttributes();
PyTargetExpression findClassAttribute(@NotNull String name, boolean inherited);
List<PyTargetExpression> getInstanceAttributes();
@Nullable
PyTargetExpression findInstanceAttribute(String name, boolean inherited);
PyClass[] getNestedClasses();
@Nullable
PyClass findNestedClass(String name, boolean inherited);
/**
* @return true if the class is new-style and descends from 'object'.
*/
boolean isNewStyleClass();
/**
* A lazy way to list ancestor classes width first, *not* in method-resolution order.
* @return an iterable of ancestor classes.
*/
Iterable<PyClassRef> iterateAncestors();
Iterable<PyClass> iterateAncestorClasses();
/**
* Return the method resolution order list for this class.
* <br/>
* see http://www.python.org/download/releases/2.3/mro/
* <br/>
* <i>Note: the list begins with this class.</i> It ends with the builtin 'object'.
* If class hierarchy is incorrect, e.g. badly looped, assertions may fail in implementation.
* @return list of classes in method resolution order for this class, at least one element long.
*/
@NotNull List<PyClass> getMRO();
/**
* Scan properties in order of definition, until processor returns true for one of them.
* @param processor to check properties
* @param inherited whether inherited properties need to be scanned, too
* @return a property that processor accepted, or null.
*/
@Nullable
Property scanProperties(Processor<Property> processor, boolean inherited);
/**
* Non-recursively searches for a property for which the given function is a getter, setter or deleter.
*
* @param function the function which may be an accessor
* @return the property, or null
*/
@Nullable
Property findPropertyByFunction(PyFunction function);
/**
* @param parent
* @return True iff this and parent are the same or parent is one of our superclasses.
*/
boolean isSubclass(PyClass parent);
boolean isSubclass(@NotNull String superClassQName);
@Nullable
String getQualifiedName();
/**
* Returns the list of names in the class' __slots__ attribute, or null if the class
* does not define such an attribute.
*
* @return the list of names or null.
*/
@Nullable
List<String> getSlots();
@Nullable
String getDocStringValue();
boolean processClassLevelDeclarations(@NotNull PsiScopeProcessor processor);
boolean processInstanceLevelDeclarations(@NotNull PsiScopeProcessor processor, @Nullable PyExpression location);
}
@@ -0,0 +1,75 @@
package com.jetbrains.python.psi;
import com.intellij.psi.PsiElement;
import com.jetbrains.python.psi.impl.PyQualifiedName;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public class PyClassRef {
@Nullable
private final PsiElement myElement;
@Nullable
private final String myQName;
public PyClassRef(PsiElement element) {
myElement = element;
myQName = null;
}
public PyClassRef(String qName) {
myElement = null;
myQName = qName;
}
@Nullable
public PyClass getPyClass() {
return myElement instanceof PyClass ? (PyClass) myElement : null;
}
@Nullable
public PsiElement getElement() {
return myElement;
}
@Nullable
public String getClassName() {
if (myElement instanceof PyClass) {
return ((PyClass)myElement).getName();
}
if (myQName != null) {
final PyQualifiedName qname = PyQualifiedName.fromDottedString(myQName);
if (qname != null) {
return qname.getLastComponent();
}
}
return null;
}
@Nullable
public String getQualifiedName() {
if (myQName != null) {
return myQName;
}
return myElement instanceof PyClass ? ((PyClass)myElement).getQualifiedName() : null;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PyClassRef that = (PyClassRef)o;
if (myElement != null ? !myElement.equals(that.myElement) : that.myElement != null) return false;
return true;
}
@Override
public int hashCode() {
return myElement != null ? myElement.hashCode() : 0;
}
}
@@ -0,0 +1,13 @@
package com.jetbrains.python.psi;
import java.util.List;
/**
* @author yole
*/
public interface PyComprehensionElement extends PyExpression, NameDefiner {
PyExpression getResultExpression();
List<ComprehensionComponent> getComponents();
List<ComprhForComponent> getForComponents();
List<ComprhIfComponent> getIfComponents();
}
@@ -0,0 +1,16 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public interface PyConditionalExpression extends PyExpression {
PyExpression getTruePart();
@Nullable
PyExpression getCondition();
@Nullable
PyExpression getFalsePart();
}
@@ -0,0 +1,16 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.Nullable;
/**
* A statement part that has a condition before it.
* User: dcheryasov
* Date: Mar 16, 2009 4:44:25 AM
*/
public interface PyConditionalStatementPart extends PyStatementPart {
/**
* @return the condition expression.
*/
@Nullable
PyExpression getCondition();
}
@@ -0,0 +1,11 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public interface PyContinueStatement extends PyStatement {
@Nullable
PyLoopStatement getLoopStatement();
}
@@ -0,0 +1,13 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.Nullable;
/**
* TODO: Add description
* User: dcheryasov
* Date: Jul 8, 2010 3:48:14 AM
*/
public interface PyDecoratable {
@Nullable
PyDecoratorList getDecoratorList();
}
@@ -0,0 +1,43 @@
package com.jetbrains.python.psi;
import com.intellij.psi.StubBasedPsiElement;
import com.jetbrains.python.psi.impl.PyQualifiedName;
import com.jetbrains.python.psi.stubs.PyDecoratorStub;
import org.jetbrains.annotations.Nullable;
/**
* Covers a decorator call, e.g. <tt>@staticmethod</tt>.
* Decorators happen contextually above the function definition, but are stored inside it for convenience.
* <b>Note:</b>
* In <code>@foo</code> form, <code>PyCallExpression</code>'s methods are related to invocation of <code>foo</code>
* as decorator. In <code>@foo(...)</code> form, these very methods are related to the call that returns the decorator
* to be applied. In either case, they are related to an invocation of <code>foo</code>.
* User: dcheryasov
* Date: Sep 26, 2008
*/
public interface PyDecorator extends PyCallExpression, StubBasedPsiElement<PyDecoratorStub> {
/**
* @return the function being decorated, or null.
*/
@Nullable
PyFunction getTarget();
/**
* True if the annotating function is a builtin, useful togeter with getName(). Implementation uses stub info.
* @see com.jetbrains.python.psi.PyElement#getName()
*/
boolean isBuiltin();
/**
* @return true if invocation has a form of <code>@foo(...)</code>.
*/
boolean hasArgumentList();
/**
* For cases when decorators are referenced via a qualified name, e.g. @property.setter.
* @return dot-separated qualified name, or just {@link #getName()}'s value if no qualifiers are present.
*/
@Nullable
PyQualifiedName getQualifiedName();
}
@@ -0,0 +1,21 @@
package com.jetbrains.python.psi;
import com.intellij.psi.StubBasedPsiElement;
import com.jetbrains.python.psi.stubs.PyDecoratorListStub;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* A list of function decorators.
* @author dcheryasov
*/
public interface PyDecoratorList extends PyElement, StubBasedPsiElement<PyDecoratorListStub> {
/**
* @return decorators of function, in order of declaration (outermost first).
*/
@NotNull
PyDecorator[] getDecorators();
@Nullable
PyDecorator findDecorator(String name);
}
@@ -0,0 +1,11 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
public interface PyDelStatement extends PyStatement {
@NotNull
PyExpression[] getTargets();
}
@@ -0,0 +1,9 @@
package com.jetbrains.python.psi;
/**
* Dict comprehension: {x:x+1 for x in range(10)}
*
* @author yole
*/
public interface PyDictCompExpression extends PyComprehensionElement {
}
@@ -0,0 +1,11 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.NotNull;
/**
* Represents a literal dict expression, e.g. <tt>{'a': 1}</tt>
*/
public interface PyDictLiteralExpression extends PySequenceExpression {
@NotNull
PyKeyValueExpression[] getElements();
}
@@ -0,0 +1,8 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.Nullable;
public interface PyDocStringOwner extends PyElement {
@Nullable
PyStringLiteralExpression getDocStringExpression();
}
@@ -0,0 +1,12 @@
package com.jetbrains.python.psi;
import com.intellij.psi.NavigatablePsiElement;
public interface PyElement extends NavigatablePsiElement {
/**
* An empty array to return cheaply without allocating it anew.
*/
PyElement[] EMPTY_ARRAY = new PyElement[0];
}
@@ -0,0 +1,83 @@
package com.jetbrains.python.psi;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class PyElementGenerator {
public static PyElementGenerator getInstance(Project project) {
return ServiceManager.getService(project, PyElementGenerator.class);
}
public abstract ASTNode createNameIdentifier(String name);
/**
* str must have quotes around it and be fully escaped.
*/
public abstract PyStringLiteralExpression createStringLiteralAlreadyEscaped(String str);
/**
* Creates a string literal, adding appropriate quotes, properly escaping characters inside.
* @param destination where the literal is destined to; used to determine the encoding.
* @param unescaped the string
* @return a newly created literal
*/
public abstract PyStringLiteralExpression createStringLiteralFromString(@Nullable PsiFile destination, String unescaped);
public abstract PyStringLiteralExpression createStringLiteralFromString(@NotNull String unescaped);
public abstract PyListLiteralExpression createListLiteral();
public abstract ASTNode createComma();
public abstract ASTNode createDot();
public abstract PyBinaryExpression createBinaryExpression(String s, PyExpression expr, PyExpression listLiteral);
/**
* @deprecated use the overload with language level specified
* @param text the text to create an expression from
* @return the expression
*/
public abstract PyExpression createExpressionFromText(String text);
public abstract PyExpression createExpressionFromText(final LanguageLevel languageLevel, String text);
public abstract PsiElement insertItemIntoList(PyElement list, @Nullable PyExpression afterThis, PyExpression toInsert)
throws IncorrectOperationException;
@NotNull
public abstract PyCallExpression createCallExpression(final LanguageLevel langLevel, String functionName);
public abstract PyImportStatement createImportStatementFromText(String text);
public abstract PyImportElement createImportElement(String name);
@NotNull
public abstract <T> T createFromText(LanguageLevel langLevel, Class<T> aClass, final String text);
/**
* Creates an arbitrary PSI element from text, by creating a bigger construction and then cutting the proper subelement.
* Will produce all kinds of exceptions if the path or class would not match the PSI tree.
* @param langLevel the language level to use for parsing the text
* @param aClass class of the PSI element; may be an interface not descending from PsiElement, as long as target node can be cast to it
* @param text text to parse
* @param path a sequence of numbers, each telling which child to select at current tree level; 0 means first child, etc.
* @return the newly created PSI element
*/
@NotNull
public abstract <T> T createFromText(LanguageLevel langLevel, Class<T> aClass, final String text, final int[] path);
public abstract PyNamedParameter createParameter(@NotNull String name);
public abstract PsiFile createDummyFile(LanguageLevel langLevel, String contents);
public abstract PyExpressionStatement createDocstring(String content);
}
@@ -0,0 +1,62 @@
package com.jetbrains.python.psi;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import com.jetbrains.python.PythonFileType;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Constructor;
public class PyElementType extends IElementType {
protected Class<? extends PsiElement> myPsiElementClass;
private static final Class[] PARAMETER_TYPES = new Class[]{ASTNode.class};
private Constructor<? extends PsiElement> myConstructor;
private String mySpecialMethodName;
public PyElementType(@NotNull @NonNls String debugName) {
super(debugName, PythonFileType.INSTANCE.getLanguage());
}
public PyElementType(@NotNull @NonNls String debugName, @NotNull Class<? extends PsiElement> psiElementClass) {
this(debugName);
myPsiElementClass = psiElementClass;
}
public PyElementType(@NotNull @NonNls String debugName, @NotNull @NonNls String specialMethodName) {
this(debugName);
mySpecialMethodName = specialMethodName;
}
@NotNull
public PsiElement createElement(@NotNull ASTNode node) {
if (myPsiElementClass == null) {
throw new IllegalStateException("Cannot create an element for " + node.getElementType() + " without element class");
}
try {
if (myConstructor == null) {
myConstructor = myPsiElementClass.getConstructor(PARAMETER_TYPES);
}
return myConstructor.newInstance(node);
}
catch (Exception e) {
throw new IllegalStateException("No necessary constructor for " + node.getElementType(), e);
}
}
/**
* @return name of special method for operation marked by this token; e.g. "__add__" for "+".
*/
@Nullable
public String getSpecialMethodName() {
return mySpecialMethodName;
}
@Override
public String toString() {
return "Py:" + super.toString();
}
}
@@ -0,0 +1,256 @@
package com.jetbrains.python.psi;
import com.intellij.psi.PsiElementVisitor;
/**
* Visitor for python-specific nodes.
*/
public class PyElementVisitor extends PsiElementVisitor {
public void visitPyElement(final PyElement node) {
visitElement(node);
}
public void visitPyReferenceExpression(final PyReferenceExpression node) {
visitPyExpression(node);
}
public void visitPyTargetExpression(final PyTargetExpression node) {
visitPyExpression(node);
}
public void visitPyCallExpression(final PyCallExpression node) {
visitPyExpression(node);
}
public void visitPyDecoratorList(final PyDecoratorList node) {
visitElement(node);
}
public void visitPyComprehensionElement(final PyComprehensionElement node) {
visitPyExpression(node);
}
public void visitPyGeneratorExpression(final PyGeneratorExpression node) {
visitPyComprehensionElement(node);
}
public void visitPyBinaryExpression(final PyBinaryExpression node) {
visitPyExpression(node);
}
public void visitPyPrefixExpression(final PyPrefixExpression node) {
visitPyExpression(node);
}
public void visitPySequenceExpression(final PySequenceExpression node) {
visitPyExpression(node);
}
public void visitPyTupleExpression(final PyTupleExpression node) {
visitPySequenceExpression(node);
}
public void visitPyParenthesizedExpression(final PyParenthesizedExpression node) {
visitPyExpression(node);
}
public void visitPyDictLiteralExpression(final PyDictLiteralExpression node) {
visitPyExpression(node);
}
public void visitPyListLiteralExpression(final PyListLiteralExpression node) {
visitPySequenceExpression(node);
}
public void visitPySetLiteralExpression(final PySetLiteralExpression node) {
visitPyExpression(node);
}
public void visitPyListCompExpression(final PyListCompExpression node) {
visitPyComprehensionElement(node);
}
public void visitPyDictCompExpression(final PyDictCompExpression node) {
visitPyComprehensionElement(node);
}
public void visitPySetCompExpression(final PySetCompExpression node) {
visitPyComprehensionElement(node);
}
public void visitPyLambdaExpression(final PyLambdaExpression node) {
visitPyExpression(node);
}
public void visitPyAssignmentStatement(final PyAssignmentStatement node) {
visitPyStatement(node);
}
public void visitPyAugAssignmentStatement(final PyAugAssignmentStatement node) {
visitPyStatement(node);
}
public void visitPyDelStatement(final PyDelStatement node) {
visitPyStatement(node);
}
public void visitPyReturnStatement(final PyReturnStatement node) {
visitPyStatement(node);
}
public void visitPyYieldExpression(final PyYieldExpression node) {
visitPyExpression(node);
}
public void visitPyTryExceptStatement(final PyTryExceptStatement node) {
visitPyStatement(node);
}
public void visitPyRaiseStatement(final PyRaiseStatement node) {
visitPyStatement(node);
}
public void visitPyBreakStatement(final PyBreakStatement node) {
visitPyStatement(node);
}
public void visitPyContinueStatement(final PyContinueStatement node) {
visitPyStatement(node);
}
public void visitPyGlobalStatement(final PyGlobalStatement node) {
visitPyStatement(node);
}
public void visitPyFromImportStatement(final PyFromImportStatement node) {
visitPyStatement(node);
}
public void visitPyIfStatement(final PyIfStatement node) {
visitPyStatement(node);
}
public void visitPyForStatement(final PyForStatement node) {
visitPyStatement(node);
}
public void visitPyWhileStatement(final PyWhileStatement node) {
visitPyStatement(node);
}
public void visitPyWithStatement(final PyWithStatement node) {
visitPyStatement(node);
}
public void visitPyExpressionStatement(final PyExpressionStatement node) {
visitPyStatement(node);
}
public void visitPyStatement(final PyStatement node) {
visitPyElement(node);
}
public void visitPyExpression(final PyExpression node) {
visitPyElement(node);
}
public void visitPyParameterList(final PyParameterList node) {
visitPyElement(node);
}
public void visitPyParameter(final PyParameter node) {
visitPyElement(node);
}
public void visitPyNamedParameter(final PyNamedParameter node) {
visitPyParameter(node);
}
public void visitPyTupleParameter(final PyTupleParameter node) {
visitPyParameter(node);
}
public void visitPyArgumentList(final PyArgumentList node) {
visitPyElement(node);
}
public void visitPyStatementList(final PyStatementList node) {
visitPyElement(node);
}
public void visitPyExceptBlock(final PyExceptPart node) {
visitPyElement(node);
}
public void visitPyFunction(final PyFunction node) {
visitPyElement(node);
}
public void visitPyClass(final PyClass node) {
visitPyElement(node);
}
public void visitPyFile(final PyFile node) {
visitPyElement(node);
}
public void visitPyStringLiteralExpression(final PyStringLiteralExpression node) {
visitPyElement(node);
}
public void visitPyNumericLiteralExpression(final PyNumericLiteralExpression node) {
visitPyElement(node);
}
public void visitPyPrintStatement(final PyPrintStatement node) {
visitPyStatement(node);
}
public void visitPyImportStatement(PyImportStatement node) {
visitPyStatement(node);
}
public void visitPyReprExpression(PyReprExpression node) {
visitPyExpression(node);
}
public void visitPyNonlocalStatement(PyNonlocalStatement node) {
visitPyStatement(node);
}
public void visitPyStarExpression(PyStarExpression node) {
visitPyExpression(node);
}
public void visitPySubscriptionExpression(PySubscriptionExpression node) {
visitPyExpression(node);
}
public void visitPyImportElement(PyImportElement node) {
visitPyElement(node);
}
public void visitPyStarImportElement(PyStarImportElement node) {
visitPyElement(node);
}
public void visitPyConditionalStatementPart(PyConditionalStatementPart node) {
visitPyElement(node);
}
public void visitPyAssertStatement(final PyAssertStatement node) {
visitPyElement(node);
}
public void visitPyNoneLiteralExpression(final PyNoneLiteralExpression node) {
visitPyElement(node);
}
public void visitPyBoolLiteralExpression(final PyBoolLiteralExpression node) {
visitPyElement(node);
}
public void visitPyConditionalExpression(PyConditionalExpression node) {
visitPyElement(node);
}
}
@@ -0,0 +1,16 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.Nullable;
/**
* The 'else:' part of various compound statements.
* User: dcheryasov
* Date: Mar 15, 2009 9:34:51 PM
*/
public interface PyElsePart extends PyStatementPart {
/**
* @return the body of the 'else' part.
*/
@Nullable
PyStatementList getStatementList();
}
@@ -0,0 +1,7 @@
package com.jetbrains.python.psi;
/**
* @author yole
*/
public interface PyEmptyExpression extends PyExpression {
}
@@ -0,0 +1,18 @@
package com.jetbrains.python.psi;
import com.intellij.psi.StubBasedPsiElement;
import com.jetbrains.python.psi.stubs.PyExceptPartStub;
import org.jetbrains.annotations.Nullable;
/**
* @author dcheryasov
*/
public interface PyExceptPart extends PyElement, StubBasedPsiElement<PyExceptPartStub>, NameDefiner, PyStatementPart {
PyExceptPart[] EMPTY_ARRAY = new PyExceptPart[0];
@Nullable
PyExpression getExceptClass();
@Nullable
PyExpression getTarget();
}
@@ -0,0 +1,7 @@
package com.jetbrains.python.psi;
/**
* @author yole
*/
public interface PyExecStatement extends PyStatement {
}
@@ -0,0 +1,10 @@
package com.jetbrains.python.psi;
/**
* Describes a generalized expression, possibly typed.
*
* @author yole
*/
public interface PyExpression extends PyTypedElement {
PyExpression[] EMPTY_ARRAY = new PyExpression[0];
}
@@ -0,0 +1,5 @@
package com.jetbrains.python.psi;
public interface PyExpressionCodeFragment extends PyFile {
}
@@ -0,0 +1,11 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
public interface PyExpressionStatement extends PyStatement {
@NotNull
PyExpression getExpression();
}
@@ -0,0 +1,52 @@
package com.jetbrains.python.psi;
import com.intellij.psi.PsiFile;
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public interface PyFile extends PyElement, PsiFile, PyDocStringOwner, ScopeOwner, NameDefiner {
List<PyStatement> getStatements();
List<PyClass> getTopLevelClasses();
List<PyFunction> getTopLevelFunctions();
List<PyTargetExpression> getTopLevelAttributes();
@Nullable
PyFunction findTopLevelFunction(String name);
@Nullable
PyClass findTopLevelClass(String name);
@Nullable
PyTargetExpression findTopLevelAttribute(String name);
LanguageLevel getLanguageLevel();
List<PyFromImportStatement> getFromImports();
List<PyImportElement> getImportTargets();
/**
* Returns the list of names in the __all__ declaration, or null if there is no such declaration in the module.
*
* @return the list of names or null.
*/
@Nullable
List<String> getDunderAll();
/**
* Return true if the file contains a 'from __future__ import ...' statement with given feature.
*/
boolean hasImportFromFuture(FutureFeature feature);
/**
* If the function raises a DeprecationWarning or a PendingDeprecationWarning, returns the explanation text provided for the warning..
*
* @return the deprecation message or null if the function is not deprecated.
*/
String getDeprecationMessage();
}
@@ -0,0 +1,10 @@
package com.jetbrains.python.psi;
/**
* The 'finally' part.
* @see PyTryPart
* User: dcheryasov
* Date: Mar 16, 2009 6:29:22 AM
*/
public interface PyFinallyPart extends PyStatementPart {
}
@@ -0,0 +1,23 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.Nullable;
/**
* Main part of a 'for' statement
* User: dcheryasov
* Date: Mar 15, 2009 8:55:22 PM
*/
public interface PyForPart extends PyStatementPart {
/**
* @return target: the "x" in "<code>for x in (1, 2, 3)</code>".
*/
@Nullable
PyExpression getTarget();
/**
* @return source of iteration: the "(1, 2, 3)" in "<code>for x in (1, 2, 3)</code>".
*/
@Nullable
PyExpression getSource();
}
@@ -0,0 +1,10 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.NotNull;
/**
* The 'for/else' statement.
*/
public interface PyForStatement extends PyLoopStatement, PyStatementWithElse, NameDefiner {
@NotNull PyForPart getForPart();
}
@@ -0,0 +1,76 @@
package com.jetbrains.python.psi;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFileSystemItem;
import com.intellij.psi.StubBasedPsiElement;
import com.jetbrains.python.psi.impl.PyQualifiedName;
import com.jetbrains.python.psi.stubs.PyFromImportStatementStub;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* Describes "from ... import" statements.
*/
public interface PyFromImportStatement extends PyImportStatementBase, StubBasedPsiElement<PyFromImportStatementStub> {
boolean isStarImport();
/**
* Returns a reference the module from which import is required.
* @return reference to module. If the 'from' reference is relative and consists entirely of dots, null is returned.
*/
@Nullable PyReferenceExpression getImportSource();
@Nullable
PyQualifiedName getImportSourceQName();
/**
* @return the star in "from ... import *"
*/
@Nullable PyStarImportElement getStarImportElement();
/**
* @return number of dots in relative "from" clause, or 0 in absolute import.
*/
int getRelativeLevel();
/**
* @return true iff the statement is an import from __future__.
*/
boolean isFromFuture();
/**
* If the from ... import statement uses an import list in parentheses, returns the opening parenthesis.
*
* @return opening parenthesis token or null
*/
@Nullable
PsiElement getLeftParen();
/**
* If the from ... import statement uses an import list in parentheses, returns the closing parenthesis.
*
* @return closing parenthesis token or null
*/
@Nullable
PsiElement getRightParen();
/**
* Resolves the import source qualified name to a file or directory. Note: performs a Python only resolve,
* doesn't handle extension points such as import from Java classes.
*
* @return the resolved import source (file or directory containing __init__.py), or null if the import is unresolved.
*/
@Nullable
PsiFileSystemItem resolveImportSource();
/**
* Resolves the import source qualified name to a number of possible files or directories. Note: performs a Python only resolve,
* doesn't handle extension points such as import from Java classes.
*
* @return possible candidates the resolved import source (file or directory containing __init__.py), or an empty list if the import is unresolved.
*/
@NotNull
List<PsiFileSystemItem> resolveImportSourceCandidates();
}
@@ -0,0 +1,92 @@
package com.jetbrains.python.psi;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiNameIdentifierOwner;
import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.StubBasedPsiElement;
import com.intellij.util.ArrayFactory;
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
import com.jetbrains.python.psi.stubs.PyFunctionStub;
import com.jetbrains.python.psi.types.PyType;
import org.jetbrains.annotations.Nullable;
/**
* Function declaration in source (the <code>def</code> and everything within).
*
* @author yole
*/
public interface PyFunction
extends
PsiNamedElement, StubBasedPsiElement<PyFunctionStub>,
PsiNameIdentifierOwner, PyStatement, Callable, NameDefiner, PyDocStringOwner, ScopeOwner, PyDecoratable, PyTypedElement {
PyFunction[] EMPTY_ARRAY = new PyFunction[0];
ArrayFactory<PyFunction> ARRAY_FACTORY = new ArrayFactory<PyFunction>() {
@Override
public PyFunction[] create(int count) {
return new PyFunction[count];
}
};
/**
* Returns the AST node for the function name identifier.
*
* @return the node, or null if the function is incomplete (only the "def"
* keyword was typed)
*/
@Nullable
ASTNode getNameNode();
@Nullable
PyStatementList getStatementList();
@Nullable
PyClass getContainingClass();
@Nullable
PyType getReturnTypeFromDocString();
@Nullable
String getDocStringValue();
/**
* If the function raises a DeprecationWarning or a PendingDeprecationWarning, returns the explanation text provided for the warning..
*
* @return the deprecation message or null if the function is not deprecated.
*/
@Nullable
String getDeprecationMessage();
/**
* Looks for two standard decorators to a function, or a wrapping assignment that closely follows it.
*
* @return a flag describing what was detected.
*/
@Nullable
Modifier getModifier();
/**
* Flags that mark common alterations of a function: decoration by and wrapping in classmethod() and staticmethod().
*/
enum Modifier {
/**
* Function is decorated with @classmethod, its first param is the class.
*/
CLASSMETHOD,
/**
* Function is decorated with {@code @staticmethod}, its first param is as in a regular function.
*/
STATICMETHOD,
}
/**
* Returns a property for which this function is a getter, setter or deleter.
*
* @return the corresponding property, or null if there isn't any.
*/
@Nullable
Property getProperty();
@Nullable
PyAnnotation getAnnotation();
}
@@ -0,0 +1,9 @@
package com.jetbrains.python.psi;
/**
* Generator expression PSI.
*
* @author yole
*/
public interface PyGeneratorExpression extends PyComprehensionElement {
}
@@ -0,0 +1,12 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
public interface PyGlobalStatement extends PyStatement, NameDefiner {
@NotNull PyTargetExpression[] getGlobals();
void addGlobal(String name);
}
@@ -0,0 +1,16 @@
package com.jetbrains.python.psi;
/**
* Branches of an 'if' statement.
* @see PyElsePart
* User: dcheryasov
* Date: Mar 12, 2009 2:16:00 AM
*/
public interface PyIfPart extends PyConditionalStatementPart {
PyIfPart[] EMPTY_ARRAY = new PyIfPart[0];
/**
* @return true for a 'elif' part.
*/
boolean isElif();
}
@@ -0,0 +1,11 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.NotNull;
/**
* The 'if/elif/else' statement.
*/
public interface PyIfStatement extends PyStatementWithElse {
@NotNull PyIfPart getIfPart();
@NotNull PyIfPart[] getElifParts();
}
@@ -0,0 +1,35 @@
package com.jetbrains.python.psi;
import com.intellij.psi.PsiElement;
import com.intellij.psi.StubBasedPsiElement;
import com.jetbrains.python.psi.impl.PyQualifiedName;
import com.jetbrains.python.psi.stubs.PyImportElementStub;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public interface PyImportElement extends PyElement, NameDefiner, StubBasedPsiElement<PyImportElementStub> {
@Nullable
PyReferenceExpression getImportReferenceExpression();
@Nullable
PyQualifiedName getImportedQName();
@Nullable
PyTargetExpression getAsNameElement();
@Nullable
String getAsName();
/**
* @return name under which the element is visible, that is, "as name" is there is one, or just name.
*/
@Nullable
String getVisibleName();
PyStatement getContainingImportStatement();
@Nullable
PsiElement getElementNamed(String name, boolean resolveImportElement);
}
@@ -0,0 +1,10 @@
package com.jetbrains.python.psi;
import com.intellij.psi.StubBasedPsiElement;
import com.jetbrains.python.psi.stubs.PyImportStatementStub;
/**
* @author yole
*/
public interface PyImportStatement extends PyImportStatementBase, StubBasedPsiElement<PyImportStatementStub> {
}
@@ -0,0 +1,14 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
public interface PyImportStatementBase extends PyStatement {
/**
* @return elements that constitute the "import" clause
*/
@NotNull
PyImportElement[] getImportElements();
}
@@ -0,0 +1,17 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public interface PyKeyValueExpression extends PyExpression {
PyKeyValueExpression[] EMPTY_ARRAY = new PyKeyValueExpression[0];
@NotNull
PyExpression getKey();
@Nullable
PyExpression getValue();
}
@@ -0,0 +1,18 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.Nullable;
import com.intellij.lang.ASTNode;
/**
* @author yole
*/
public interface PyKeywordArgument extends PyExpression {
@Nullable
String getKeyword();
@Nullable
PyExpression getValueExpression();
@Nullable
ASTNode getKeywordNode();
}
@@ -0,0 +1,14 @@
package com.jetbrains.python.psi;
import com.intellij.openapi.extensions.ExtensionPointName;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public interface PyKnownDecoratorProvider {
ExtensionPointName<PyKnownDecoratorProvider> EP_NAME = ExtensionPointName.create("Pythonid.knownDecoratorProvider");
@Nullable
String toKnownDecorator(String decoratorName);
}
@@ -0,0 +1,12 @@
package com.jetbrains.python.psi;
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public interface PyLambdaExpression extends PyExpression, Callable, ScopeOwner {
@Nullable
PyExpression getBody();
}
@@ -0,0 +1,9 @@
package com.jetbrains.python.psi;
/**
* List comprehension PSI.
*
* @author yole
*/
public interface PyListCompExpression extends PyComprehensionElement {
}
@@ -0,0 +1,7 @@
package com.jetbrains.python.psi;
/**
* @author yole
*/
public interface PyListLiteralExpression extends PySequenceExpression {
}
@@ -0,0 +1,7 @@
package com.jetbrains.python.psi;
/**
* @author yole
*/
public interface PyLiteralExpression extends PyExpression {
}
@@ -0,0 +1,7 @@
package com.jetbrains.python.psi;
/**
* @author yole
*/
public interface PyLoopStatement extends PyStatement {
}
@@ -0,0 +1,28 @@
package com.jetbrains.python.psi;
import com.intellij.psi.PsiNameIdentifierOwner;
import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.StubBasedPsiElement;
import com.jetbrains.python.psi.stubs.PyNamedParameterStub;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Represents a named parameter, as opposed to a tuple parameter.
*/
public interface PyNamedParameter extends PyParameter, PsiNamedElement, PsiNameIdentifierOwner, PyExpression, StubBasedPsiElement<PyNamedParameterStub> {
boolean isPositionalContainer();
boolean isKeywordContainer();
/**
* @param includeDefaultValue if true, include the default value after an " = ".
* @return Canonical representation of parameter. Includes asterisks for *param and **param, and name.
*/
@NotNull
String getRepr(boolean includeDefaultValue);
@Nullable
PyAnnotation getAnnotation();
}
@@ -0,0 +1,9 @@
package com.jetbrains.python.psi;
/**
* Used for literal None and literal ... (Ellipsis).
*
* @author yole
*/
public interface PyNoneLiteralExpression extends PyLiteralExpression {
}
@@ -0,0 +1,11 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
public interface PyNonlocalStatement extends PyStatement {
@NotNull
PyTargetExpression[] getVariables();
}
@@ -0,0 +1,29 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.Nullable;
import java.math.BigInteger;
import java.math.BigDecimal;
public interface PyNumericLiteralExpression extends PyLiteralExpression {
/**
* Returns the value of this literal as a long (with any fraction truncated).
* This method will return {@code null} if the value is too large or too
* small to be represented as a long.
*/
@Nullable
Long getLongValue();
/**
* Returns the value of this literal as a {@code BigInteger} (with any
* fraction truncated).
*/
BigInteger getBigIntegerValue();
/**
* Returns the exact value of this literal.
*/
BigDecimal getBigDecimalValue();
boolean isIntegerLiteral();
}
@@ -0,0 +1,29 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.Nullable;
/**
* Abstract function parameter; may cover either a named parameter or a tuple of parameters.
* @see com.jetbrains.python.psi.impl.ParamHelper
* User: dcheryasov
* Date: Jul 5, 2009 8:30:13 PM
*/
public interface PyParameter extends PyElement {
/**
* @return the named parameter which is represented by this parameter, or null if the parameter is a tuple.
*/
@Nullable
PyNamedParameter getAsNamed();
/**
* @return the tuple parameter which is represented by this parameter, or null if the parameter is named.
*/
@Nullable
PyTupleParameter getAsTuple();
@Nullable
PyExpression getDefaultValue();
boolean hasDefaultValue();
}
@@ -0,0 +1,54 @@
package com.jetbrains.python.psi;
import com.intellij.psi.StubBasedPsiElement;
import com.jetbrains.python.psi.stubs.PyParameterListStub;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Represents function parameter list.
* Date: 29.05.2005
*/
public interface PyParameterList extends PyElement, StubBasedPsiElement<PyParameterListStub> {
/**
* Extracts the individual parameters.
* Note that tuple parameters are flattened by this method.
* @return a possibly empty array of named paramaters.
*/
PyParameter[] getParameters();
@Nullable
PyNamedParameter findParameterByName(@NotNull String name);
/**
* Adds a paramter to list, after all other parameters.
* @param param what to add
*/
void addParameter(PyNamedParameter param);
/**
* @return true iff this list contains an '*args'-type parameter.
*/
boolean hasPositionalContainer();
/**
* @return true iff this list contains a '**kwargs'-type parameter.
*/
boolean hasKeywordContainer();
/**
* Checks is this parameter list is the same or is a superset of another parameter list.
* (The reverse is only true is the lists are the same.)
* @param another what to compare to
* @return true if this list is a superset of another.
*/
boolean isCompatibleTo(@NotNull PyParameterList another);
String getPresentableText(boolean includeDefaultValue);
@Nullable
PyFunction getContainingFunction();
}
@@ -0,0 +1,8 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.Nullable;
public interface PyParenthesizedExpression extends PyExpression {
@Nullable
PyExpression getContainedExpression();
}
@@ -0,0 +1,7 @@
package com.jetbrains.python.psi;
/**
* @author yole
*/
public interface PyPassStatement extends PyStatement {
}
@@ -0,0 +1,12 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public interface PyPrefixExpression extends PyQualifiedExpression, PyReferenceOwner {
@Nullable
PyExpression getOperand();
PyElementType getOperator();
}
@@ -0,0 +1,7 @@
package com.jetbrains.python.psi;
/**
* @author yole
*/
public interface PyPrintStatement extends PyStatement {
}
@@ -0,0 +1,7 @@
package com.jetbrains.python.psi;
/**
* @author yole
*/
public interface PyPrintTarget extends PyElement {
}
@@ -0,0 +1,30 @@
package com.jetbrains.python.psi;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.Nullable;
/**
* Represents a qualified expression, that is, of "a.b.c..." sort.
* User: dcheryasov
* Date: Oct 18, 2008
*/
public interface PyQualifiedExpression extends PyExpression {
@Nullable
PyExpression getQualifier();
/**
* Returns the name to the right of the qualifier.
*
* @return the name referenced by the expression.
*/
@Nullable
String getReferencedName();
/**
* Returns the element representing the name (to the right of the qualifier).
*
* @return the name element.
*/
@Nullable
ASTNode getNameElement();
}
@@ -0,0 +1,11 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
public interface PyRaiseStatement extends PyStatement {
@NotNull
PyExpression[] getExpressions();
}
@@ -0,0 +1,12 @@
package com.jetbrains.python.psi;
import com.intellij.psi.PsiElement;
/**
* @author yole
*/
public class PyRecursiveElementVisitor extends PyElementVisitor {
public void visitElement(final PsiElement element) {
element.acceptChildren(this);
}
}
@@ -0,0 +1,36 @@
package com.jetbrains.python.psi;
import com.intellij.psi.PsiPolyVariantReference;
import com.jetbrains.python.psi.impl.PyQualifiedName;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.resolve.QualifiedResolveResult;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public interface PyReferenceExpression extends PyQualifiedExpression, PyReferenceOwner {
PyReferenceExpression[] EMPTY_ARRAY = new PyReferenceExpression[0];
/**
* Goes through a chain of assignment statements until a non-assignment expression is encountered.
* Starts at this, expecting it to resolve to a target of an assignment.
* <i>Note: currently limited to non-branching definite assignments.</i>
* @return value that is assigned to this element via a chain of definite assignments, or an empty resolve result.
* <i>Note: will return null if the assignment chain ends in a target of a non-assignment statement such as 'for'.</i>
*
* @param resolveContext the resolve context
*/
@NotNull
QualifiedResolveResult followAssignmentsChain(PyResolveContext resolveContext);
@Nullable
PyQualifiedName asQualifiedName();
@NotNull
PsiPolyVariantReference getReference();
@NotNull
PsiPolyVariantReference getReference(PyResolveContext resolveContext);
}
@@ -0,0 +1,13 @@
package com.jetbrains.python.psi;
import com.intellij.psi.PsiPolyVariantReference;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public interface PyReferenceOwner extends PyElement {
@Nullable
PsiPolyVariantReference getReference(PyResolveContext context);
}
@@ -0,0 +1,11 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public interface PyReprExpression extends PyExpression {
@Nullable
PyExpression getExpression();
}
@@ -0,0 +1,10 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public interface PyReturnStatement extends PyStatement {
@Nullable PyExpression getExpression();
}
@@ -0,0 +1,11 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
public interface PySequenceExpression extends PyExpression{
@NotNull
PyExpression[] getElements();
}
@@ -0,0 +1,9 @@
package com.jetbrains.python.psi;
/**
* Set comprehension: {x for x in range(10)}
*
* @author yole
*/
public interface PySetCompExpression extends PyComprehensionElement {
}
@@ -0,0 +1,9 @@
package com.jetbrains.python.psi;
/**
* Represents a Python 3 set literal expression, for example, <tt>{1, 2, 3}</tt>
*
* @author yole
*/
public interface PySetLiteralExpression extends PySequenceExpression {
}
@@ -0,0 +1,13 @@
package com.jetbrains.python.psi;
import com.intellij.psi.StubBasedPsiElement;
import com.jetbrains.python.psi.stubs.PySingleStarParameterStub;
/**
* Represents a single star (keyword-only parameter delimiter) appearing in the
* parameter list of a Py3K function.
*
* @author yole
*/
public interface PySingleStarParameter extends PyParameter, StubBasedPsiElement<PySingleStarParameterStub> {
}
@@ -0,0 +1,15 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public interface PySliceExpression extends PyExpression {
@NotNull
PyExpression getOperand();
@Nullable
PySliceItem getSliceItem();
}
@@ -0,0 +1,17 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public interface PySliceItem extends PyElement {
@Nullable
PyExpression getLowerBound();
@Nullable
PyExpression getUpperBound();
@Nullable
PyExpression getStride();
}
@@ -0,0 +1,8 @@
package com.jetbrains.python.psi;
/**
* @author yole
*/
public interface PyStarArgument extends PyExpression {
boolean isKeyword();
}
@@ -0,0 +1,11 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.Nullable;
/**
* @author: Alexey.Ivanov
*/
public interface PyStarExpression extends PyExpression {
@Nullable
PyExpression getExpression();
}
@@ -0,0 +1,9 @@
package com.jetbrains.python.psi;
/**
* Marks the star in "from foo import *".
* User: dcheryasov
* Date: Jul 28, 2008
*/
public interface PyStarImportElement extends PyElement, NameDefiner {
}
@@ -0,0 +1,8 @@
package com.jetbrains.python.psi;
/**
* Everything that may be an element of a statement list.
*/
public interface PyStatement extends PyElement {
PyStatement[] EMPTY_ARRAY = new PyStatement[0];
}
@@ -0,0 +1,10 @@
package com.jetbrains.python.psi;
/**
* @author yole
*/
public interface PyStatementList extends PyElement {
PyStatementList[] EMPTY_ARRAY = new PyStatementList[0];
PyStatement[] getStatements();
}
@@ -0,0 +1,18 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.Nullable;
/**
* Abstract part of a multipart statement.
* User: dcheryasov
* Date: Mar 16, 2009 4:34:59 AM
*/
public interface PyStatementPart extends PyElement {
PyStatementPart[] EMPTY_ARRAY = new PyStatementPart[0];
/**
* @return the body of the part.
*/
@Nullable
PyStatementList getStatementList();
}

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