Merge remote-tracking branch 'origin/master'

This commit is contained in:
Ekaterina Tuzova
2013-02-19 15:43:49 +04:00
43 changed files with 589 additions and 349 deletions
+5 -3
View File
@@ -136,7 +136,8 @@ class PyDBCommandThread(PyDBDaemonThread):
if self.killReceived:
return
threading.settrace(None) # no debugging on this thread
self.pyDb.SetTrace(None) # no debugging on this thread
try:
while not self.killReceived:
@@ -164,7 +165,7 @@ class PyDBCheckAliveThread(PyDBDaemonThread):
self.setName('pydevd.CheckAliveThread')
def OnRun(self):
pydevd_tracing.SetTrace(None) # no debugging on this thread
self.pyDb.SetTrace(None) # no debugging on this thread
while True:
if not self.pyDb.haveAliveThreads():
pydev_log.debug("No alive threads, finishing debug session")
@@ -203,7 +204,7 @@ class NewThreadStartup:
def __call__(self):
global_debugger = GetGlobalDebugger()
pydevd_tracing.SetTrace(global_debugger.trace_dispatch)
global_debugger.SetTrace(global_debugger.trace_dispatch)
self.original_func(*self.args, **self.kwargs)
thread.NewThreadStartup = NewThreadStartup
@@ -277,6 +278,7 @@ class PyDB:
self._finishDebuggingSession = False
self.force_post_mortem_stop = 0
self.signature_factory = None
self.SetTrace = pydevd_tracing.SetTrace
#this is a dict of thread ids pointing to thread ids. Whenever a command is passed to the java end that
#acknowledges that a thread was created, the thread id should be passed here -- and if at some time we do not
@@ -6,4 +6,5 @@ package com.jetbrains.python.psi;
* @author yole
*/
public interface PyNoneLiteralExpression extends PyLiteralExpression {
boolean isEllipsis();
}
@@ -81,6 +81,8 @@ public class MultiProcessDebugger implements ProcessDebugger {
myMainDebugger.waitForConnect();
disposeAcceptor();
myDebugProcessAcceptor = new DebuggerProcessAcceptor(this, myServerSocket);
ApplicationManager.getApplication().executeOnPooledThread(myDebugProcessAcceptor);
}
@@ -109,15 +111,34 @@ public class MultiProcessDebugger implements ProcessDebugger {
return serverSocket;
}
@Override
public void close() {
for (ProcessDebugger d : allDebuggers()) {
d.close();
}
disposeAcceptor();
}
private List<RemoteDebugger> allDebuggers() {
List<RemoteDebugger> result = Lists.newArrayList(myMainDebugger);
synchronized (myOtherDebuggers) {
result.addAll(myOtherDebuggers);
}
return result;
}
@Override
public void disconnect() {
myMainDebugger.disconnect();
for (ProcessDebugger d : Lists.newArrayList(myOtherDebuggers)) {
for (ProcessDebugger d : allDebuggers()) {
d.disconnect();
}
disposeAcceptor();
}
private void disposeAcceptor() {
if (myDebugProcessAcceptor != null) {
myDebugProcessAcceptor.disconnect();
myDebugProcessAcceptor = null;
}
}
@@ -230,7 +251,7 @@ public class MultiProcessDebugger implements ProcessDebugger {
private void cleanOtherDebuggers() {
synchronized (myOtherDebuggers) {
removeDisconnected(Lists.newArrayList(myOtherDebuggers));
removeDisconnected(getOtherDebuggers());
}
}
@@ -249,13 +270,15 @@ public class MultiProcessDebugger implements ProcessDebugger {
}
}
myOtherDebuggers.clear();
myOtherDebuggers.addAll(newList);
synchronized (myOtherDebuggers) {
myOtherDebuggers.clear();
myOtherDebuggers.addAll(newList);
}
}
}
private void collectAndRegisterOtherDebuggersThreads(List<PyThreadInfo> threads) {
for (RemoteDebugger d : Lists.newArrayList(myOtherDebuggers)) {
for (RemoteDebugger d : getOtherDebuggers()) {
threads.addAll(d.getThreads());
for (PyThreadInfo t : d.getThreads()) {
myThreadRegistry.register(t.getId(), d);
@@ -263,19 +286,23 @@ public class MultiProcessDebugger implements ProcessDebugger {
}
}
private ArrayList<RemoteDebugger> getOtherDebuggers() {
synchronized (myOtherDebuggers) {
return Lists.newArrayList(myOtherDebuggers);
}
}
@Override
public void execute(@NotNull AbstractCommand command) {
myMainDebugger.execute(command);
for (ProcessDebugger d : Lists.newArrayList(myOtherDebuggers)) {
for (ProcessDebugger d : allDebuggers()) {
d.execute(command);
}
}
@Override
public void suspendAllThreads() {
myMainDebugger.suspendAllThreads();
for (ProcessDebugger d : myOtherDebuggers) {
for (ProcessDebugger d : allDebuggers()) {
d.suspendAllThreads();
}
}
@@ -285,14 +312,6 @@ public class MultiProcessDebugger implements ProcessDebugger {
debugger(threadId).suspendThread(threadId);
}
@Override
public void close() {
myMainDebugger.close();
for (ProcessDebugger d : Lists.newArrayList(myOtherDebuggers)) {
d.close();
}
}
@Override
public void run() throws PyDebuggerException {
myMainDebugger.run();
@@ -310,32 +329,28 @@ public class MultiProcessDebugger implements ProcessDebugger {
@Override
public void setTempBreakpoint(String type, String file, int line) {
myMainDebugger.setTempBreakpoint(type, file, line);
for (ProcessDebugger d : myOtherDebuggers) {
for (ProcessDebugger d : allDebuggers()) {
d.setTempBreakpoint(type, file, line);
}
}
@Override
public void removeTempBreakpoint(String file, int line) {
myMainDebugger.removeTempBreakpoint(file, line);
for (ProcessDebugger d : myOtherDebuggers) {
for (ProcessDebugger d : allDebuggers()) {
d.removeTempBreakpoint(file, line);
}
}
@Override
public void setBreakpoint(String typeId, String file, int line, String condition, String logExpression) {
myMainDebugger.setBreakpoint(typeId, file, line, condition, logExpression);
for (ProcessDebugger d : myOtherDebuggers) {
for (ProcessDebugger d : allDebuggers()) {
d.setBreakpoint(typeId, file, line, condition, logExpression);
}
}
@Override
public void removeBreakpoint(String typeId, String file, int line) {
myMainDebugger.removeBreakpoint(typeId, file, line);
for (ProcessDebugger d : Lists.newArrayList(myOtherDebuggers)) {
for (ProcessDebugger d : allDebuggers()) {
d.removeBreakpoint(typeId, file, line);
}
}
@@ -428,8 +443,9 @@ public class MultiProcessDebugger implements ProcessDebugger {
catch (IOException ignore) {
}
myServerSocket = null;
myShouldAccept = false;
}
myShouldAccept = false;
myMultiProcessDebugger = null;
}
}
@@ -450,18 +466,14 @@ public class MultiProcessDebugger implements ProcessDebugger {
@Override
public void addExceptionBreakpoint(ExceptionBreakpointCommandFactory factory) {
myMainDebugger.execute(factory.createAddCommand(myMainDebugger));
for (RemoteDebugger d : Lists.newArrayList(myOtherDebuggers)) {
for (RemoteDebugger d : allDebuggers()) {
d.execute(factory.createAddCommand(d));
}
}
@Override
public void removeExceptionBreakpoint(ExceptionBreakpointCommandFactory factory) {
myMainDebugger.execute(factory.createRemoveCommand(myMainDebugger));
for (RemoteDebugger d : Lists.newArrayList(myOtherDebuggers)) {
for (RemoteDebugger d : allDebuggers()) {
d.execute(factory.createRemoveCommand(d));
}
}
@@ -15,12 +15,6 @@ import java.util.List;
* @author traff
*/
public interface ProcessDebugger {
boolean isConnected();
void waitForConnect() throws Exception;
void disconnect();
String handshake() throws PyDebuggerException;
PyDebugValue evaluate(String threadId,
@@ -55,8 +49,20 @@ public interface ProcessDebugger {
void suspendThread(String threadId);
/**
* Disconnects current debug process. Closes all resources.
*/
void close();
boolean isConnected();
void waitForConnect() throws Exception;
/**
* Disconnects currently connected process. After that it can wait for the next.
*/
void disconnect();
void run() throws PyDebuggerException;
void smartStepInto(String threadId, String functionName);
@@ -96,23 +96,6 @@ public class RemoteDebugger implements ProcessDebugger {
}
}
@Override
public void disconnect() {
synchronized (mySocketObject) {
myConnected = false;
if (mySocket != null && !mySocket.isClosed()) {
try {
mySocket.close();
}
catch (IOException ignore) {
}
}
}
cleanUp();
}
@Override
public String handshake() throws PyDebuggerException {
final VersionCommand command = new VersionCommand(this, LOCAL_VERSION, SystemInfo.isUnix ? "UNIX" : "WIN");
@@ -366,6 +349,23 @@ public class RemoteDebugger implements ProcessDebugger {
fireCloseEvent();
}
@Override
public void disconnect() {
synchronized (mySocketObject) {
myConnected = false;
if (mySocket != null && !mySocket.isClosed()) {
try {
mySocket.close();
}
catch (IOException ignore) {
}
}
}
cleanUp();
}
@Override
public void run() throws PyDebuggerException {
new RunCommand(this).execute();
@@ -3,7 +3,6 @@ package com.jetbrains.python.codeInsight.stdlib;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.psi.PsiElement;
import com.jetbrains.python.codeInsight.PyDynamicMember;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFile;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import com.jetbrains.python.psi.impl.PyQualifiedName;
@@ -24,10 +23,10 @@ public class PyStdlibModuleMembersProvider extends PyModuleMembersProvider {
if (qName.equals("os")) {
final List<PyDynamicMember> results = new ArrayList<PyDynamicMember>();
PsiElement path = null;
PyClass osError = null;
PsiElement osError = null;
if (module != null) {
final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(module);
osError = builtinCache.getClass("OSError");
osError = builtinCache.getByName("OSError");
final String pathModuleName = SystemInfo.isWindows ? "ntpath" : "posixpath";
path = ResolveImportUtil.resolveModuleInRoots(PyQualifiedName.fromDottedString(pathModuleName), module);
@@ -20,6 +20,7 @@ import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.Disposer;
import icons.PythonIcons;
import org.jetbrains.annotations.NotNull;
@@ -53,6 +54,9 @@ public class PythonDebugLanguageConsoleView extends JPanel implements ConsoleVie
add(myPydevConsoleView.getComponent(), PYDEV_CONSOLE_PANEL);
showDebugConsole(PyConsoleOptionsProvider.getInstance(project).isShowDebugConsoleByDefault());
Disposer.register(this, myPydevConsoleView);
Disposer.register(this, myTextConsole);
}
public PythonDebugLanguageConsoleView(final Project project, Sdk sdk) {
@@ -249,4 +253,6 @@ public class PythonDebugLanguageConsoleView extends JPanel implements ConsoleVie
}
}
}
}
@@ -18,7 +18,7 @@ import org.jetbrains.annotations.Nullable;
/**
* User: catherine
*
* Inspection to detect assignment that can be replaced with augmented assignment.
* Inspection to detect assignments that can be replaced with augmented assignments.
*/
public class PyAugmentAssignmentInspection extends PyInspection {
@Nls
@@ -43,15 +43,18 @@ public class PyAugmentAssignmentInspection extends PyInspection {
@Override
public void visitPyAssignmentStatement(final PyAssignmentStatement node) {
if (node.getAssignedValue() instanceof PyBinaryExpression) {
final PyExpression value = node.getAssignedValue();
if (value instanceof PyBinaryExpression) {
final PyExpression target = node.getLeftHandSideExpression();
final PyBinaryExpression expression = (PyBinaryExpression)node.getAssignedValue();
if (expression == null) return;
final PyBinaryExpression expression = (PyBinaryExpression)value;
PyExpression leftExpression = expression.getLeftExpression();
PyExpression rightExpression = expression.getRightExpression();
if (rightExpression instanceof PyParenthesizedExpression)
if (rightExpression instanceof PyParenthesizedExpression) {
rightExpression = ((PyParenthesizedExpression)rightExpression).getContainedExpression();
if (rightExpression == null || target == null) return;
}
if (rightExpression == null || target == null) {
return;
}
boolean changedParts = false;
final String targetText = target.getText();
final String rightText = rightExpression.getText();
@@ -64,31 +67,31 @@ public class PyAugmentAssignmentInspection extends PyInspection {
final PyElementType op = expression.getOperator();
final TokenSet operations = TokenSet.create(PyTokenTypes.PLUS, PyTokenTypes.MINUS, PyTokenTypes.MULT,
PyTokenTypes.FLOORDIV, PyTokenTypes.DIV, PyTokenTypes.PERC, PyTokenTypes.AND, PyTokenTypes.OR,
PyTokenTypes.XOR, PyTokenTypes.LTLT, PyTokenTypes.GTGT, PyTokenTypes.EXP);
PyTokenTypes.FLOORDIV, PyTokenTypes.DIV, PyTokenTypes.PERC, PyTokenTypes.AND,
PyTokenTypes.OR, PyTokenTypes.XOR, PyTokenTypes.LTLT, PyTokenTypes.GTGT,
PyTokenTypes.EXP);
final TokenSet commutativeOperations = TokenSet.create(PyTokenTypes.PLUS, PyTokenTypes.MULT);
if ((operations.contains(op) && !changedParts) || (changedParts && commutativeOperations.contains(op))) {
if ((leftExpression instanceof PyReferenceExpression || leftExpression instanceof PySubscriptionExpression)) {
if (leftExpression.getText().equals(targetText)) {
if (rightExpression instanceof PyNumericLiteralExpression) {
final AugmentedAssignmentQuickFix quickFix = new AugmentedAssignmentQuickFix();
registerProblem(node, "Assignment can be replaced with augmented assignment", quickFix);
}
else {
final PyType type = myTypeEvalContext.getType(rightExpression);
if (type != null) {
final PyBuiltinCache cache = PyBuiltinCache.getInstance(rightExpression);
if (PyTypeChecker.match(cache.getComplexType(), type, myTypeEvalContext) ||
(PyTypeChecker.match(cache.getStringType(LanguageLevel.forElement(rightExpression)), type,
myTypeEvalContext) && !changedParts)) {
registerProblem(node, "Assignment can be replaced with augmented assignment", new AugmentedAssignmentQuickFix());
}
}
if (leftExpression instanceof PyReferenceExpression || leftExpression instanceof PySubscriptionExpression) {
final PyType type = myTypeEvalContext.getType(rightExpression);
if (type != null && !PyTypeChecker.isUnknown(type)) {
final PyBuiltinCache cache = PyBuiltinCache.getInstance(rightExpression);
final LanguageLevel languageLevel = LanguageLevel.forElement(rightExpression);
if (isNumeric(type, cache) || (isString(type, cache, languageLevel) && !changedParts)) {
registerProblem(node, "Assignment can be replaced with augmented assignment", new AugmentedAssignmentQuickFix());
}
}
}
}
}
}
private boolean isString(PyType type, PyBuiltinCache cache, LanguageLevel level) {
return PyTypeChecker.match(cache.getStringType(level), type, myTypeEvalContext);
}
private boolean isNumeric(PyType type, PyBuiltinCache cache) {
return PyTypeChecker.match(cache.getComplexType(), type, myTypeEvalContext);
}
}
}
@@ -240,7 +240,7 @@ public class PyCompatibilityInspection extends PyInspection {
}
final String errorMessage = "This syntax available only since py3";
final boolean isPy3 = LanguageLevel.forElement(node).isPy3K();
if (compatibleWithPy2() || !isPy3) {
if (shouldBeCompatibleWithPy2() || !isPy3) {
for (final PyElement problemElement : problemElements)
myHolder.registerProblem(problemElement, errorMessage, isPy3? ProblemHighlightType.GENERIC_ERROR_OR_WARNING :
ProblemHighlightType.GENERIC_ERROR);
@@ -72,6 +72,9 @@ public class ExpressionParsing extends Parsing {
parseReprExpression(myBuilder);
return true;
}
else if (parseEllipsis()) {
return true;
}
return false;
}
@@ -97,7 +100,7 @@ public class ExpressionParsing extends Parsing {
expr.done(PyElementTypes.LIST_LITERAL_EXPRESSION);
return;
}
if (!parseSingleExpression(isTargetExpression, false)) {
if (!parseSingleExpression(isTargetExpression)) {
builder.error(message("PARSE.expected.expression"));
}
if (builder.getTokenType() == PyTokenTypes.FOR_KEYWORD) {
@@ -111,7 +114,7 @@ public class ExpressionParsing extends Parsing {
if (atToken(PyTokenTypes.RBRACKET)) {
break;
}
if (!parseSingleExpression(isTargetExpression, false)) {
if (!parseSingleExpression(isTargetExpression)) {
builder.error(message("PARSE.expected.expr.or.comma.or.bracket"));
break;
}
@@ -154,7 +157,7 @@ public class ExpressionParsing extends Parsing {
result = parseORTestExpression(false, false);
}
else {
result = parseTupleExpression(false, false, true, false);
result = parseTupleExpression(false, false, true);
}
if (!result) {
myBuilder.error("expression expected");
@@ -172,7 +175,7 @@ public class ExpressionParsing extends Parsing {
}
final PsiBuilder.Marker firstExprMarker = myBuilder.mark();
if (!parseSingleExpression(false, false)) {
if (!parseSingleExpression(false)) {
myBuilder.error("expression expected");
firstExprMarker.drop();
expr.done(PyElementTypes.DICT_LITERAL_EXPRESSION);
@@ -198,7 +201,7 @@ public class ExpressionParsing extends Parsing {
}
private void parseDictLiteralTail(PsiBuilder.Marker startMarker, PsiBuilder.Marker firstKeyValueMarker) {
if (!parseSingleExpression(false, false)) {
if (!parseSingleExpression(false)) {
myBuilder.error("expression expected");
firstKeyValueMarker.done(PyElementTypes.KEY_VALUE_EXPRESSION);
if (atToken(PyTokenTypes.RBRACE)) {
@@ -225,12 +228,12 @@ public class ExpressionParsing extends Parsing {
private boolean parseKeyValueExpression() {
final PsiBuilder.Marker marker = myBuilder.mark();
if (!parseSingleExpression(false, false)) {
if (!parseSingleExpression(false)) {
marker.drop();
return false;
}
checkMatches(PyTokenTypes.COLON, message("PARSE.expected.colon"));
if (!parseSingleExpression(false, false)) {
if (!parseSingleExpression(false)) {
myBuilder.error("value expression expected");
marker.drop();
return false;
@@ -242,7 +245,7 @@ public class ExpressionParsing extends Parsing {
private void parseSetLiteralTail(PsiBuilder.Marker startMarker) {
while (myBuilder.getTokenType() != PyTokenTypes.RBRACE) {
checkMatches(PyTokenTypes.COMMA, message("PARSE.expected.comma"));
if (!parseSingleExpression(false, false)) {
if (!parseSingleExpression(false)) {
break;
}
}
@@ -325,7 +328,7 @@ public class ExpressionParsing extends Parsing {
parseSliceEnd(expr, sliceItemStart);
}
else {
boolean hadExpression = parseSingleExpression(false, true);
boolean hadExpression = parseSingleExpression(false);
if (atToken(PyTokenTypes.COLON)) {
sliceOrTupleStart.drop();
parseSliceEnd(expr, sliceItemStart);
@@ -334,7 +337,7 @@ public class ExpressionParsing extends Parsing {
sliceItemStart.done(PyElementTypes.SLICE_ITEM);
if (!parseSliceListTail(expr, sliceOrTupleStart)) {
sliceOrTupleStart.rollbackTo();
if (!parseTupleExpression(false, false, false, true)) {
if (!parseTupleExpression(false, false, false)) {
myBuilder.error("tuple expression expected");
}
checkMatches(PyTokenTypes.RBRACKET, message("PARSE.expected.rbracket"));
@@ -404,13 +407,13 @@ public class ExpressionParsing extends Parsing {
sliceMarker.done(PyElementTypes.EMPTY_EXPRESSION);
}
else {
parseSingleExpression(false, true);
parseSingleExpression(false);
}
if (!BRACKET_COLON_COMMA.contains(myBuilder.getTokenType())) {
myBuilder.error(message("PARSE.expected.colon.or.rbracket"));
}
if (matchToken(PyTokenTypes.COLON)) {
parseSingleExpression(false, true);
parseSingleExpression(false);
}
sliceItemStart.done(PyElementTypes.SLICE_ITEM);
@@ -427,12 +430,12 @@ public class ExpressionParsing extends Parsing {
while (atToken(PyTokenTypes.COMMA)) {
nextToken();
PsiBuilder.Marker sliceItemStart = myBuilder.mark();
parseTestExpression(false, false, true);
parseTestExpression(false, false);
if (matchToken(PyTokenTypes.COLON)) {
inSlice = true;
parseTestExpression(false, false, true);
parseTestExpression(false, false);
if (matchToken(PyTokenTypes.COLON)) {
parseTestExpression(false, false, true);
parseTestExpression(false, false);
}
}
sliceItemStart.done(PyElementTypes.SLICE_ITEM);
@@ -479,7 +482,7 @@ public class ExpressionParsing extends Parsing {
if (myBuilder.getTokenType() == PyTokenTypes.MULT || myBuilder.getTokenType() == PyTokenTypes.EXP) {
final PsiBuilder.Marker starArgMarker = myBuilder.mark();
myBuilder.advanceLexer();
if (!parseSingleExpression(false, false)) {
if (!parseSingleExpression(false)) {
myBuilder.error(message("PARSE.expected.expression"));
}
starArgMarker.done(PyElementTypes.STAR_ARGUMENT_EXPRESSION);
@@ -490,7 +493,7 @@ public class ExpressionParsing extends Parsing {
myBuilder.advanceLexer();
if (myBuilder.getTokenType() == PyTokenTypes.EQ) {
myBuilder.advanceLexer();
if (!parseSingleExpression(false, false)) {
if (!parseSingleExpression(false)) {
myBuilder.error(message("PARSE.expected.expression"));
}
keywordArgMarker.done(PyElementTypes.KEYWORD_ARGUMENT_EXPRESSION);
@@ -498,7 +501,7 @@ public class ExpressionParsing extends Parsing {
}
keywordArgMarker.rollbackTo();
}
if (!parseSingleExpression(false, false)) {
if (!parseSingleExpression(false)) {
myBuilder.error(message("PARSE.expected.expression"));
break;
}
@@ -513,11 +516,11 @@ public class ExpressionParsing extends Parsing {
}
public boolean parseExpressionOptional() {
return parseTupleExpression(false, false, false, false);
return parseTupleExpression(false, false, false);
}
public boolean parseExpressionOptional(boolean isTargetExpression) {
return parseTupleExpression(false, isTargetExpression, false, false);
return parseTupleExpression(false, isTargetExpression, false);
}
public void parseExpression() {
@@ -527,7 +530,7 @@ public class ExpressionParsing extends Parsing {
}
public void parseExpression(boolean stopOnIn, boolean isTargetExpression) {
if (!parseTupleExpression(stopOnIn, isTargetExpression, false, false)) {
if (!parseTupleExpression(stopOnIn, isTargetExpression, false)) {
myBuilder.error(message("PARSE.expected.expression"));
}
}
@@ -538,7 +541,7 @@ public class ExpressionParsing extends Parsing {
myBuilder.advanceLexer();
if (myBuilder.getTokenType() == PyTokenTypes.FROM_KEYWORD) {
myBuilder.advanceLexer();
final boolean parsed = parseTupleExpression(false, isTargetExpression, false, false);
final boolean parsed = parseTupleExpression(false, isTargetExpression, false);
if (!parsed) {
myBuilder.error(message("PARSE.expected.expression"));
}
@@ -546,19 +549,19 @@ public class ExpressionParsing extends Parsing {
return parsed;
}
else {
parseTupleExpression(false, isTargetExpression, false, false);
parseTupleExpression(false, isTargetExpression, false);
yieldExpr.done(PyElementTypes.YIELD_EXPRESSION);
return true;
}
}
else {
return parseTupleExpression(false, isTargetExpression, false, false);
return parseTupleExpression(false, isTargetExpression, false);
}
}
protected boolean parseTupleExpression(boolean stopOnIn, boolean isTargetExpression, final boolean oldTest, boolean allowEllipsis) {
protected boolean parseTupleExpression(boolean stopOnIn, boolean isTargetExpression, final boolean oldTest) {
PsiBuilder.Marker expr = myBuilder.mark();
boolean exprParseResult = oldTest ? parseOldTestExpression() : parseTestExpression(stopOnIn, isTargetExpression, allowEllipsis);
boolean exprParseResult = oldTest ? parseOldTestExpression() : parseTestExpression(stopOnIn, isTargetExpression);
if (!exprParseResult) {
expr.drop();
return false;
@@ -567,7 +570,7 @@ public class ExpressionParsing extends Parsing {
while (myBuilder.getTokenType() == PyTokenTypes.COMMA) {
myBuilder.advanceLexer();
PsiBuilder.Marker expr2 = myBuilder.mark();
exprParseResult = oldTest ? parseOldTestExpression() : parseTestExpression(stopOnIn, isTargetExpression, allowEllipsis);
exprParseResult = oldTest ? parseOldTestExpression() : parseTestExpression(stopOnIn, isTargetExpression);
if (!exprParseResult) {
expr2.rollbackTo();
break;
@@ -582,8 +585,8 @@ public class ExpressionParsing extends Parsing {
return true;
}
public boolean parseSingleExpression(boolean isTargetExpression, boolean allowEllipsis) {
return parseTestExpression(false, isTargetExpression, allowEllipsis);
public boolean parseSingleExpression(boolean isTargetExpression) {
return parseTestExpression(false, isTargetExpression);
}
public boolean parseOldExpression() {
@@ -593,13 +596,10 @@ public class ExpressionParsing extends Parsing {
return parseORTestExpression(false, false);
}
private boolean parseTestExpression(boolean stopOnIn, boolean isTargetExpression, boolean allowEllipsis) {
private boolean parseTestExpression(boolean stopOnIn, boolean isTargetExpression) {
if (myBuilder.getTokenType() == PyTokenTypes.LAMBDA_KEYWORD) {
return parseLambdaExpression(false);
}
if (allowEllipsis && parseEllipsis()) {
return true;
}
PsiBuilder.Marker condExpr = myBuilder.mark();
if (!parseORTestExpression( stopOnIn, isTargetExpression)) {
condExpr.drop();
@@ -616,7 +616,7 @@ public class ExpressionParsing extends Parsing {
}
else {
myBuilder.advanceLexer();
if (!parseTestExpression(stopOnIn, isTargetExpression, allowEllipsis)) {
if (!parseTestExpression(stopOnIn, isTargetExpression)) {
myBuilder.error(message("PARSE.expected.expression"));
}
}
@@ -640,7 +640,7 @@ public class ExpressionParsing extends Parsing {
PsiBuilder.Marker expr = myBuilder.mark();
myBuilder.advanceLexer();
getFunctionParser().parseParameterListContents(PyTokenTypes.COLON, false, true);
boolean parseExpressionResult = oldTest ? parseOldTestExpression() : parseSingleExpression(false, false);
boolean parseExpressionResult = oldTest ? parseOldTestExpression() : parseSingleExpression(false);
if (!parseExpressionResult) {
myBuilder.error(message("PARSE.expected.expression"));
}
@@ -65,7 +65,7 @@ public class FunctionParsing extends Parsing {
PsiBuilder.Marker maybeReturnAnnotation = myBuilder.mark();
nextToken();
if (matchToken(PyTokenTypes.GT)) {
if (!myContext.getExpressionParser().parseSingleExpression(false, false)) {
if (!myContext.getExpressionParser().parseSingleExpression(false)) {
myBuilder.error(message("PARSE.expected.expression"));
}
maybeReturnAnnotation.done(PyElementTypes.ANNOTATION);
@@ -195,13 +195,13 @@ public class FunctionParsing extends Parsing {
if (!isLambda && myContext.getLanguageLevel().isPy3K() && atToken(PyTokenTypes.COLON)) {
PsiBuilder.Marker annotationMarker = myBuilder.mark();
nextToken();
if (!getExpressionParser().parseSingleExpression(false, false)) {
if (!getExpressionParser().parseSingleExpression(false)) {
myBuilder.error(message("PARSE.expected.expression"));
}
annotationMarker.done(PyElementTypes.ANNOTATION);
}
if (!isStarParameter && matchToken(PyTokenTypes.EQ)) {
if (!getExpressionParser().parseSingleExpression(false, false)) {
if (!getExpressionParser().parseSingleExpression(false)) {
PsiBuilder.Marker invalidElements = myBuilder.mark();
while(!atAnyOfTokens(endToken, PyTokenTypes.LINE_BREAK, PyTokenTypes.COMMA, null)) {
nextToken();
@@ -251,7 +251,7 @@ public class FunctionParsing extends Parsing {
}
if (myBuilder.getTokenType() == PyTokenTypes.EQ) {
myBuilder.advanceLexer();
getExpressionParser().parseSingleExpression(false, false);
getExpressionParser().parseSingleExpression(false);
}
tuple.done(PyElementTypes.TUPLE_PARAMETER);
}
@@ -278,18 +278,18 @@ public class StatementParsing extends Parsing implements ITokenTypeRemapper {
if (builder.getTokenType() == PyTokenTypes.GTGT) {
final PsiBuilder.Marker target = builder.mark();
builder.advanceLexer();
getExpressionParser().parseSingleExpression(false, false);
getExpressionParser().parseSingleExpression(false);
target.done(PyElementTypes.PRINT_TARGET);
}
else {
getExpressionParser().parseSingleExpression(false, false);
getExpressionParser().parseSingleExpression(false);
}
while (builder.getTokenType() == PyTokenTypes.COMMA) {
builder.advanceLexer();
if (getEndOfStatementsTokens().contains(builder.getTokenType())) {
break;
}
getExpressionParser().parseSingleExpression(false, false);
getExpressionParser().parseSingleExpression(false);
}
checkEndOfStatement(scope);
statement.done(PyElementTypes.PRINT_STATEMENT);
@@ -317,13 +317,13 @@ public class StatementParsing extends Parsing implements ITokenTypeRemapper {
assertCurrentToken(PyTokenTypes.DEL_KEYWORD);
final PsiBuilder.Marker delStatement = myBuilder.mark();
myBuilder.advanceLexer();
if (!getExpressionParser().parseSingleExpression(false, false)) {
if (!getExpressionParser().parseSingleExpression(false)) {
myBuilder.error("Expression expected");
}
while (myBuilder.getTokenType() == PyTokenTypes.COMMA) {
myBuilder.advanceLexer();
if (!getEndOfStatementsTokens().contains(myBuilder.getTokenType())) {
if (!getExpressionParser().parseSingleExpression(false, false)) {
if (!getExpressionParser().parseSingleExpression(false)) {
myBuilder.error("Expression expected");
}
}
@@ -338,18 +338,18 @@ public class StatementParsing extends Parsing implements ITokenTypeRemapper {
final PsiBuilder.Marker raiseStatement = myBuilder.mark();
myBuilder.advanceLexer();
if (!getEndOfStatementsTokens().contains(myBuilder.getTokenType())) {
getExpressionParser().parseSingleExpression(false, false);
getExpressionParser().parseSingleExpression(false);
if (myBuilder.getTokenType() == PyTokenTypes.COMMA) {
myBuilder.advanceLexer();
getExpressionParser().parseSingleExpression(false, false);
getExpressionParser().parseSingleExpression(false);
if (myBuilder.getTokenType() == PyTokenTypes.COMMA) {
myBuilder.advanceLexer();
getExpressionParser().parseSingleExpression(false, false);
getExpressionParser().parseSingleExpression(false);
}
}
else if (myBuilder.getTokenType() == PyTokenTypes.FROM_KEYWORD) {
myBuilder.advanceLexer();
if (!getExpressionParser().parseSingleExpression(false, false)) {
if (!getExpressionParser().parseSingleExpression(false)) {
myBuilder.error("Expression expected");
}
}
@@ -362,10 +362,10 @@ public class StatementParsing extends Parsing implements ITokenTypeRemapper {
assertCurrentToken(PyTokenTypes.ASSERT_KEYWORD);
final PsiBuilder.Marker assertStatement = myBuilder.mark();
myBuilder.advanceLexer();
if (getExpressionParser().parseSingleExpression(false, false)) {
if (getExpressionParser().parseSingleExpression(false)) {
if (myBuilder.getTokenType() == PyTokenTypes.COMMA) {
myBuilder.advanceLexer();
if (!getExpressionParser().parseSingleExpression(false, false)) {
if (!getExpressionParser().parseSingleExpression(false)) {
myContext.getBuilder().error(EXPRESSION_EXPECTED);
}
}
@@ -562,10 +562,10 @@ public class StatementParsing extends Parsing implements ITokenTypeRemapper {
getExpressionParser().parseExpression(true, false);
if (myBuilder.getTokenType() == PyTokenTypes.IN_KEYWORD) {
myBuilder.advanceLexer();
getExpressionParser().parseSingleExpression(false, false);
getExpressionParser().parseSingleExpression(false);
if (myBuilder.getTokenType() == PyTokenTypes.COMMA) {
myBuilder.advanceLexer();
getExpressionParser().parseSingleExpression(false, false);
getExpressionParser().parseSingleExpression(false);
}
}
checkEndOfStatement(inSuite);
@@ -646,7 +646,7 @@ public class StatementParsing extends Parsing implements ITokenTypeRemapper {
final PsiBuilder.Marker statement = myBuilder.mark();
final PsiBuilder.Marker whilePart = myBuilder.mark();
myBuilder.advanceLexer();
if (!getExpressionParser().parseSingleExpression(false, false)) {
if (!getExpressionParser().parseSingleExpression(false)) {
myBuilder.error(EXPRESSION_EXPECTED);
}
parseColonAndSuite(scope);
@@ -677,13 +677,13 @@ public class StatementParsing extends Parsing implements ITokenTypeRemapper {
final PsiBuilder.Marker exceptBlock = myBuilder.mark();
myBuilder.advanceLexer();
if (myBuilder.getTokenType() != PyTokenTypes.COLON) {
if (!getExpressionParser().parseSingleExpression(false, false)) {
if (!getExpressionParser().parseSingleExpression(false)) {
myBuilder.error(EXPRESSION_EXPECTED);
}
setExpectAsKeyword(true);
if (myBuilder.getTokenType() == PyTokenTypes.COMMA || myBuilder.getTokenType() == PyTokenTypes.AS_KEYWORD) {
myBuilder.advanceLexer();
if (!getExpressionParser().parseSingleExpression(true, false)) {
if (!getExpressionParser().parseSingleExpression(true)) {
myBuilder.error(EXPRESSION_EXPECTED);
}
}
@@ -738,7 +738,7 @@ public class StatementParsing extends Parsing implements ITokenTypeRemapper {
setExpectAsKeyword(true);
if (myBuilder.getTokenType() == PyTokenTypes.AS_KEYWORD) {
myBuilder.advanceLexer();
getExpressionParser().parseSingleExpression(true, false); // 'as' is followed by a target
getExpressionParser().parseSingleExpression(true); // 'as' is followed by a target
}
withItem.done(PyElementTypes.WITH_ITEM);
if (!matchToken(PyTokenTypes.COMMA)) {
@@ -624,6 +624,23 @@ public class PyUtil {
return false;
}
@NotNull
public static AccessDirection getPropertyAccessDirection(@NotNull PyFunction function) {
final Property property = function.getProperty();
if (property != null) {
if (property.getGetter().valueOrNull() == function) {
return AccessDirection.READ;
}
if (property.getSetter().valueOrNull() == function) {
return AccessDirection.WRITE;
}
else if (property.getDeleter().valueOrNull() == function) {
return AccessDirection.DELETE;
}
}
return AccessDirection.READ;
}
public static class KnownDecoratorProviderHolder {
public static PyKnownDecoratorProvider[] KNOWN_DECORATOR_PROVIDERS = Extensions.getExtensions(PyKnownDecoratorProvider.EP_NAME);
@@ -1,6 +1,7 @@
package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.psi.PyElementVisitor;
import com.jetbrains.python.psi.PyNoneLiteralExpression;
import com.jetbrains.python.psi.types.PyNoneType;
@@ -24,4 +25,9 @@ public class PyNoneLiteralExpressionImpl extends PyElementImpl implements PyNone
protected void acceptPyVisitor(PyElementVisitor pyVisitor) {
pyVisitor.visitPyNoneLiteralExpression(this);
}
@Override
public boolean isEllipsis() {
return getNode().findChildByType(PyTokenTypes.DOT) != null;
}
}
@@ -4,8 +4,7 @@ import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.util.Processor;
import com.intellij.util.QueryExecutor;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.*;
import org.jetbrains.annotations.NotNull;
/**
@@ -21,6 +20,15 @@ public class PyOverridingMethodsSearchExecutor implements QueryExecutor<PyFuncti
PyFunction overridingMethod;
try {
overridingMethod = pyClass.findMethodByName(baseMethod.getName(), false);
if (overridingMethod != null) {
final Property baseProperty = baseMethod.getProperty();
final Property overridingProperty = overridingMethod.getProperty();
if (baseProperty != null && overridingProperty != null) {
final AccessDirection direction = PyUtil.getPropertyAccessDirection(baseMethod);
final Callable callable = overridingProperty.getByDirection(direction).valueOrNull();
overridingMethod = (callable instanceof PyFunction) ? (PyFunction)callable : null;
}
}
}
finally {
accessToken.finish();
@@ -3,8 +3,7 @@ package com.jetbrains.python.psi.search;
import com.intellij.psi.PsiElement;
import com.intellij.util.Processor;
import com.intellij.util.QueryExecutor;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.*;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
@@ -33,9 +32,20 @@ public class PySuperMethodsSearchExecutor implements QueryExecutor<PsiElement, P
}
}
PyFunction superMethod = superClass.findMethodByName(name, false);
if (superMethod != null) {
final Property property = func.getProperty();
final Property superProperty = superMethod.getProperty();
if (property != null && superProperty != null) {
final AccessDirection direction = PyUtil.getPropertyAccessDirection(func);
final Callable callable = superProperty.getByDirection(direction).valueOrNull();
superMethod = (callable instanceof PyFunction) ? (PyFunction)callable : null;
}
}
if (superMethod != null) {
foundMethodContainingClasses.add(superClass);
if (!consumer.process(superMethod)) return false;
if (!consumer.process(superMethod)) {
return false;
}
}
}
}
@@ -511,6 +511,20 @@ public abstract class CompatibilityVisitor extends PyAnnotator {
}
}
@Override
public void visitPyNoneLiteralExpression(PyNoneLiteralExpression node) {
if (shouldBeCompatibleWithPy2() && node.isEllipsis()) {
final PySubscriptionExpression subscription = PsiTreeUtil.getParentOfType(node, PySubscriptionExpression.class);
if (subscription != null && PsiTreeUtil.isAncestor(subscription.getIndexExpression(), node, false)) {
return;
}
final PySliceItem sliceItem = PsiTreeUtil.getParentOfType(node, PySliceItem.class);
if (sliceItem != null) {
return;
}
registerProblem(node, "Python versions < 3.0 do not support '...' outside of sequence slicings.");
}
}
private static class YieldVisitor extends PyElementVisitor {
private boolean _haveYield = false;
@@ -536,12 +550,6 @@ public abstract class CompatibilityVisitor extends PyAnnotator {
// do not go to nested functions
}
}
private boolean shouldBeCompatibleWithPy3() {
if (myVersionsToProcess.contains(LanguageLevel.PYTHON30) || myVersionsToProcess.contains(LanguageLevel.PYTHON31)
|| myVersionsToProcess.contains(LanguageLevel.PYTHON32))
return true;
return false;
}
protected abstract void registerProblem(PsiElement node, String s, @Nullable LocalQuickFix localQuickFix, boolean asError);
@@ -581,13 +589,26 @@ public abstract class CompatibilityVisitor extends PyAnnotator {
@Override
public void visitPyNonlocalStatement(final PyNonlocalStatement node) {
if (compatibleWithPy2()) {
if (shouldBeCompatibleWithPy2()) {
registerProblem(node, "nonlocal keyword available only since py3", null, false);
}
}
protected boolean compatibleWithPy2() {
return myVersionsToProcess.contains(LanguageLevel.PYTHON24) || myVersionsToProcess.contains(LanguageLevel.PYTHON25) ||
myVersionsToProcess.contains(LanguageLevel.PYTHON26) || myVersionsToProcess.contains(LanguageLevel.PYTHON27);
protected boolean shouldBeCompatibleWithPy2() {
for (LanguageLevel level : myVersionsToProcess) {
if (level.isOlderThan(LanguageLevel.PYTHON30)) {
return true;
}
}
return false;
}
private boolean shouldBeCompatibleWithPy3() {
for (LanguageLevel level : myVersionsToProcess) {
if (level.isPy3K()) {
return true;
}
}
return false;
}
}
@@ -0,0 +1,7 @@
def foo(c, x, y):
if c:
z = x
else:
z = ''
y = z + y # pass
return y
@@ -0,0 +1,2 @@
def foo():
<warning descr="Python versions < 3.0 do not support '...' outside of sequence slicings.">...</warning>
@@ -0,0 +1,5 @@
import numpy
x = numpy.zeros((3, 4, 5))
y = x[..., 0] # pass
y = x[..., 0, :] # pass
@@ -0,0 +1,8 @@
class B:
def foo(self, **kwargs):
pass
class C(B):
def foo(self, arg1=None, **kwargs): # pass
pass
@@ -0,0 +1,28 @@
class B1:
def foo(self, a, b):
pass
class C1(B1):
def foo(self, *b):
pass
class B2:
def foo(self, **kwargs):
pass
class C2(B2):
def foo(self):
pass
class B3:
def foo(self, *args):
pass
class C3(B3):
def foo(self):
pass
@@ -0,0 +1,23 @@
class B:
def foo(self, a):
pass
class C1(B):
def foo(self, *a):
pass
class C2(B):
def foo<warning descr="Signature of method 'C2.foo()' does not match signature of base method in class 'B'">(self)</warning>:
pass
class C3(B):
def foo(self, **a):
pass
class C4(B):
def foo(self, a):
pass
@@ -0,0 +1,23 @@
class B1:
def foo(self, *args, **kwargs):
raise NotImplementedError()
class C1(B1):
def foo(self): # pass
pass
class C2(B1):
def foo(self, arg1): # pass
pass
class B3:
def foo(self, arg1, *args, **kwargs):
raise NotImplementedError()
class C3(B3):
def foo<warning descr="Signature of method 'C3.foo()' does not match signature of base method in class 'B3'">(self, arg1, arg2=None)</warning>: # fail
pass
@@ -0,0 +1,8 @@
class B:
def foo(self, arg1):
pass
class C(B):
def foo(self, arg1, arg2=None): #pass
pass
@@ -0,0 +1,8 @@
class B:
def foo(self, x=1):
pass
class C(B):
def foo(self, **kwargs):
pass
@@ -0,0 +1,20 @@
class B:
def __init__(self):
pass
def __new__(self):
pass
def foo(self, a):
pass
class C(B):
def __init__(self, a): # different but ok because __init__ is special
pass
def __new__(self, p, q): # different but ok because __new__ is special
pass
def foo<warning descr="Signature of method 'C.foo()' does not match signature of base method in class 'B'">(self, s, t)</warning>:
pass
@@ -0,0 +1,8 @@
class B:
def foo(self, arg1, arg2=None):
pass
class C(B):
def foo<warning descr="Signature of method 'C.foo()' does not match signature of base method in class 'B'">(self, arg1=None)</warning>: #fail
pass
@@ -0,0 +1,8 @@
class B:
def foo(self, arg1, arg2=None, arg3=None, arg4=None):
pass
class C(B):
def foo(self, arg1, arg2=None, arg3=None, **kwargs): #pass
pass
@@ -0,0 +1,7 @@
class B:
pass
class C(B):
def foo(self):
pass
@@ -0,0 +1,18 @@
class B(object):
@property
def foo(self):
return 'foo'
@foo.setter
def foo(self, value):
pass
class C(B):
@property
def foo(self):
return 'bar'
@foo.setter
def foo(self, value): # pass
pass
@@ -0,0 +1,9 @@
class B:
def foo(self):
pass
class C(B):
def foo<warning descr="Signature of method 'C.foo()' does not match signature of base method in class 'B'">(self, p1, **kwargs)</warning>: #fail
pass
@@ -1,144 +0,0 @@
class c1:
def foo(self, a):
pass
class c2(c1):
def foo(self, *a):
pass
class c3(c1):
def foo<warning descr="Signature of method 'c3.foo()' does not match signature of base method in class 'c1'">(self)</warning>:
pass
class c4(c1):
def foo(self, **a):
pass
class c5(c1):
def foo(self, a):
pass
class c6:
pass
class c7(c6):
def foo(self):
pass
class c8:
def __init__(self):
pass
def __new__(self):
pass
def foo(self, a):
pass
class c9(c8):
def __init__(self, a): # different but ok because __init__ is special
pass
def __new__(self, p, q): # different but ok because __new__ is special
pass
def foo<warning descr="Signature of method 'c9.foo()' does not match signature of base method in class 'c8'">(self, s, t)</warning>:
pass
class c10:
def foo(self, a, b):
pass
class c11(c10):
def foo(self, *b):
pass
class c12(c4):
def foo(self):
pass
class c13:
def foo(self, *args):
pass
class c14(c13):
def foo(self):
pass
class c15: # PY-1083
def foo(self, x = 1):
pass
class c16:
def foo(self, **kwargs):
pass
# PY-6700
class c17:
def foo(self, **kwargs):
pass
class c18(c17):
def foo(self, arg1=None, **kwargs): # pass
pass
class c19:
def foo(self, *args, **kwargs):
raise NotImplementedError()
class c20(c19):
def foo(self): # pass
pass
class c21(c19):
def foo(self, arg1): # pass
pass
class c22:
def foo(self, arg1, *args, **kwargs):
raise NotImplementedError()
class c23(c22):
def foo<warning descr="Signature of method 'c23.foo()' does not match signature of base method in class 'c22'">(self, arg1, arg2=None)</warning>: # fail
pass
# PY-7157
class c24:
def foo(self, arg1):
pass
class c25(c24):
def foo(self, arg1, arg2=None): #pass
pass
# PY-7162
class c26:
def foo(self, arg1, arg2=None):
pass
class c27(c26):
def foo<warning descr="Signature of method 'c27.foo()' does not match signature of base method in class 'c26'">(self, arg1=None)</warning>: #fail
pass
# PY-7159
class c28:
def foo(self):
pass
class c29(c28):
def foo<warning descr="Signature of method 'c29.foo()' does not match signature of base method in class 'c28'">(self, p1, **kwargs)</warning>: #fail
pass
class c30:
def foo(self, arg1, arg2=None, arg3=None, arg4=None):
pass
class c31(c30):
def foo(self, arg1, arg2=None, arg3=None, **kwargs): #pass
pass
@@ -1,5 +0,0 @@
def a():
... # <- highlighted as "Statement seems to have no effect"
pass
a()
@@ -1,33 +0,0 @@
PyFile:EllipsisAsStatement.py
PyFunction('a')
PsiElement(Py:DEF_KEYWORD)('def')
PsiWhiteSpace(' ')
PsiElement(Py:IDENTIFIER)('a')
PyParameterList
PsiElement(Py:LPAR)('(')
PsiElement(Py:RPAR)(')')
PsiElement(Py:COLON)(':')
PsiWhiteSpace('\n ')
PyStatementList
PsiElement(Py:DOT)('.')
PsiErrorElement:Statement expected, found Py:DOT
<empty list>
PsiElement(Py:DOT)('.')
PsiErrorElement:Statement expected, found Py:DOT
<empty list>
PsiElement(Py:DOT)('.')
PsiErrorElement:Statement expected, found Py:DOT
<empty list>
PsiWhiteSpace(' ')
PsiComment(Py:END_OF_LINE_COMMENT)('# <- highlighted as "Statement seems to have no effect"')
PsiWhiteSpace('\n ')
PyPassStatement
PsiElement(Py:PASS_KEYWORD)('pass')
PsiWhiteSpace('\n\n')
PyExpressionStatement
PyCallExpression: a
PyReferenceExpression: a
PsiElement(Py:IDENTIFIER)('a')
PyArgumentList
PsiElement(Py:LPAR)('(')
PsiElement(Py:RPAR)(')')
+5
View File
@@ -0,0 +1,5 @@
...
x = ...
[1, 2, ...]
def f():
...
+50
View File
@@ -0,0 +1,50 @@
PyFile:EllipsisPython3.py
PyExpressionStatement
PyNoneLiteralExpression
PsiElement(Py:DOT)('.')
PsiElement(Py:DOT)('.')
PsiElement(Py:DOT)('.')
PsiWhiteSpace('\n')
PyAssignmentStatement
PyTargetExpression: x
PsiElement(Py:IDENTIFIER)('x')
PsiWhiteSpace(' ')
PsiElement(Py:EQ)('=')
PsiWhiteSpace(' ')
PyNoneLiteralExpression
PsiElement(Py:DOT)('.')
PsiElement(Py:DOT)('.')
PsiElement(Py:DOT)('.')
PsiWhiteSpace('\n')
PyExpressionStatement
PyListLiteralExpression
PsiElement(Py:LBRACKET)('[')
PyNumericLiteralExpression
PsiElement(Py:INTEGER_LITERAL)('1')
PsiElement(Py:COMMA)(',')
PsiWhiteSpace(' ')
PyNumericLiteralExpression
PsiElement(Py:INTEGER_LITERAL)('2')
PsiElement(Py:COMMA)(',')
PsiWhiteSpace(' ')
PyNoneLiteralExpression
PsiElement(Py:DOT)('.')
PsiElement(Py:DOT)('.')
PsiElement(Py:DOT)('.')
PsiElement(Py:RBRACKET)(']')
PsiWhiteSpace('\n')
PyFunction('f')
PsiElement(Py:DEF_KEYWORD)('def')
PsiWhiteSpace(' ')
PsiElement(Py:IDENTIFIER)('f')
PyParameterList
PsiElement(Py:LPAR)('(')
PsiElement(Py:RPAR)(')')
PsiElement(Py:COLON)(':')
PsiWhiteSpace('\n ')
PyStatementList
PyExpressionStatement
PyNoneLiteralExpression
PsiElement(Py:DOT)('.')
PsiElement(Py:DOT)('.')
PsiElement(Py:DOT)('.')
@@ -0,0 +1,72 @@
package com.jetbrains.python;
import com.jetbrains.python.fixtures.PyTestCase;
import com.jetbrains.python.inspections.PyMethodOverridingInspection;
/**
* @author vlan
*/
public class PyMethodOverridingInspectionTest extends PyTestCase {
private static final String TEST_DIRECTORY = "inspections/PyMethodOverridingInspection/";
public void testArgsKwargsOverrideArg() {
doTest();
}
public void testNotOverridingMethod() {
doTest();
}
public void testInitNew() {
doTest();
}
public void testArgsKwargsAsAllowAnything() {
doTest();
}
// PY-1083
public void testExtraKwargs() {
doTest();
}
// PY-6700
public void testBothArgsKwargs() {
doTest();
}
// PY-6700
public void testArgAndKwargs() {
doTest();
}
// PY-7157
public void testDefaultArgument() {
doTest();
}
// PY-7162
public void testLessArgumentsPlusDefaults() {
doTest();
}
public void testLessParametersAndKwargs() {
doTest();
}
// PY-7159
public void testRequiredParameterAndKwargs() {
doTest();
}
// PY-7725
public void testPropertySetter() {
doTest();
}
private void doTest() {
myFixture.configureByFile(TEST_DIRECTORY + getTestName(false) + ".py");
myFixture.enableInspections(PyMethodOverridingInspection.class);
myFixture.checkHighlighting(true, false, false);
}
}
@@ -95,6 +95,7 @@ public class PythonAllTestsSuite {
PyUnresolvedReferencesInspectionTest.class,
PyCallingNonCallableInspectionTest.class,
PyUnboundLocalVariableInspectionTest.class,
PyMethodOverridingInspectionTest.class,
PyUnusedImportTest.class,
PyDeprecationTest.class,
PythonHighlightingLexerTest.class,
@@ -62,11 +62,6 @@ public class PythonInspectionsTest extends PyTestCase {
doTest(getTestName(false), inspection);
}
public void testPyMethodOverridingInspection() {
LocalInspectionTool inspection = new PyMethodOverridingInspection();
doHighlightingTest(inspection);
}
public void testPyTrailingSemicolonInspection() {
LocalInspectionTool inspection = new PyTrailingSemicolonInspection();
doTest(getTestName(false), inspection);
@@ -356,10 +356,6 @@ public class PythonParsingTest extends ParsingTestCase {
doTest();
}
public void testEllipsisAsStatement() { // PY-7763
doTest();
}
// PY-8606
public void testEllipsisInSliceList() {
doTest();
@@ -374,6 +370,11 @@ public class PythonParsingTest extends ParsingTestCase {
doTest();
}
// PY-8752
public void testEllipsisPython3() {
doTest(LanguageLevel.PYTHON33);
}
public void doTest(LanguageLevel languageLevel) {
LanguageLevel prev = myLanguageLevel;
myLanguageLevel = languageLevel;
@@ -47,6 +47,11 @@ public class PyAugmentAssignmentInspectionTest extends PyTestCase {
doTest();
}
// PY-7605
public void testStrOrUnknownFirstArg() {
doTest();
}
private void doTest() {
myFixture.configureByFile("inspections/PyAugmentAssignmentInspection/" + getTestName(true) + ".py");
myFixture.enableInspections(PyAugmentAssignmentInspection.class);
@@ -2,6 +2,7 @@ package com.jetbrains.python.inspections;
import com.jetbrains.python.fixtures.PyTestCase;
import com.jetbrains.python.psi.LanguageLevel;
import org.jetbrains.annotations.NotNull;
/**
* User : catherine
@@ -119,6 +120,25 @@ public class PyCompatibilityInspectionTest extends PyTestCase {
doTest();
}
// PY-7763
public void testEllipsisAsStatementPy2() {
doTest(LanguageLevel.PYTHON33);
}
// PY-8606
public void testEllipsisInSubscriptionPy2() {
doTest(LanguageLevel.PYTHON33);
}
private void doTest(@NotNull LanguageLevel level) {
runWithLanguageLevel(level, new Runnable() {
@Override
public void run() {
doTest();
}
});
}
private void doTest() {
myFixture.configureByFile("inspections/PyCompatibilityInspection/" + getTestName(true) + ".py");
myFixture.enableInspections(PyCompatibilityInspection.class);