/**
* Copyright (c) 2005-2013 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Eclipse Public License (EPL).
* Please see the license.txt included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
/*
* Created on Sep 21, 2006
* @author Fabio
*/
package com.python.pydev.analysis;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.text.Document;
import org.python.pydev.core.ICompletionState;
import org.python.pydev.core.IPythonNature;
import org.python.pydev.core.MisconfigurationException;
import org.python.pydev.core.TestDependent;
import org.python.pydev.editor.autoedit.TestIndentPrefs;
import org.python.pydev.editor.codecompletion.revisited.modules.AbstractModule;
import org.python.pydev.editor.codecompletion.revisited.modules.SourceModule;
import org.python.pydev.shared_core.callbacks.CallbackWithListeners;
import org.python.pydev.shared_core.callbacks.ICallbackListener;
import org.python.pydev.shared_core.io.FileUtils;
import org.python.pydev.shared_core.string.StringUtils;
import com.python.pydev.analysis.messages.IMessage;
public class OccurrencesAnalyzer2Test extends AnalysisTestsBase {
public static void main(String[] args) {
try {
OccurrencesAnalyzer2Test analyzer2 = new OccurrencesAnalyzer2Test();
analyzer2.setUp();
analyzer2.testParameterAnalysis27a();
analyzer2.tearDown();
System.out.println("finished");
junit.textui.TestRunner.run(OccurrencesAnalyzer2Test.class);
System.out.println("finished all");
} catch (Throwable e) {
e.printStackTrace();
}
System.exit(0);
}
@Override
public void setUp() throws Exception {
super.setUp();
prefs.severityForArgumentsMismatch = IMarker.SEVERITY_ERROR;
}
public void testErrorNotShownOnDynamicClass() {
doc = new Document("from extendable.noerr import importer\n" +
"print importer.getWithAttr.whatever\n");
checkNoError();
}
public void testErrorNotShownOnDynamicClass2() {
doc = new Document("from extendable.noerr import importer\n" +
"print importer.getWithAttr.whatever.other\n");
checkNoError();
}
public void testErrorNotShownOnDynamicClass3() {
doc = new Document("from extendable.noerr import importer\n" +
"print importer.childGetWithAttr.whatever\n"
+
"print importer.childGetWithAttr.whatever.other\n");
checkNoError();
}
public void testErrorNotShownOnClassFromMethod() {
doc = new Document("from extendable.noerr import importer\n" +
"print importer.logger.debug('10')\n");
checkNoError();
}
public void testErrorNotShownOnNoneClass() {
doc = new Document("from extendable.noerr import importer\n" +
"print importer.initialNone.foo\n");
checkNoError();
}
public void testErrorNotShownOnDynamicClass4() {
doc = new Document("from extendable.noerr import importer\n" +
"print importer.globals_struct.bar\n");
checkNoError();
}
public void testErrorNotShownOnDynamicClass5() {
doc = new Document("from extendable.noerr import importer\n" +
"print importer.Struct.bar\n");
checkNoError();
}
public void testErrorNotShownOnDynamicClass6() {
doc = new Document("from extendable.noerr.importer import WithGetAttr2\n" +
"print WithGetAttr2.anything\n");
checkNoError();
}
public void testErrorNotShownOnDynamicClass7() {
doc = new Document("from extendable.noerr.importer import Struct\n" +
"print Struct.anything\n");
checkNoError();
}
public void testErrorNotShownOnDynamicClass8() {
doc = new Document("from extendable.noerr.importer import StructSub\n" +
"print StructSub.anything\n");
checkNoError();
}
public void testErrorShownOnInitialSetClass() {
doc = new Document("from extendable.noerr import importer\n" +
"print importer.initialSet.m1\n"
+
"print importer.initialSet.m2\n"//has error
);
IMessage[] messages = checkError(1);
assertEquals("Undefined variable from import: m2", messages[0].getMessage());
}
public void testNoErrorPathInPackage() {
doc = new Document("import extendable\n" +
"print extendable.__path__\n");
checkNoError();
}
public void testErrorPathNotInModule() {
doc = new Document("from extendable import static\n" +
"print static.__path__\n");
IMessage[] messages = checkError(1);
assertEquals("Undefined variable from import: __path__", messages[0].getMessage());
}
public void testErrorPathNotInModule2() {
doc = new Document("from extendable import * #@UnusedWildImport\n" +
"__path__\n");
//__path__ does not come on "import *"
IMessage[] messages = checkError(1);
assertEquals("Undefined variable: __path__", messages[0].getMessage());
}
public void testNoEffectInException() {
doc = new Document("def raise_exception():\n" +
" x = None\n" +
" raise Exception, '%(number)s' % {\n"
+
" 'number': x is None,\n" +
" }\n");
checkNoError();
}
public void testNoEffectInGenExp() {
doc = new Document("for val in (3 in (1, 2), 'something else'):\n" +
" print 'val was', val\n");
checkNoError();
}
public void testPathFound() throws IOException, MisconfigurationException {
analyzer = new OccurrencesAnalyzer();
File file = new File(TestDependent.TEST_PYSRC_LOC +
"extendable/with_path.py");
Document doc = new Document(FileUtils.getFileContents(file));
msgs = analyzer.analyzeDocument(nature,
(SourceModule) AbstractModule.createModule("extendable.with_path", file, nature, true), prefs, doc,
new NullProgressMonitor(), new TestIndentPrefs(true, 4));
printMessages(msgs, 0);
}
public void testPathFound2() throws IOException, MisconfigurationException {
analyzer = new OccurrencesAnalyzer();
File file = new File(TestDependent.TEST_PYSRC_LOC +
"extendable/__init__.py");
Document doc = new Document(FileUtils.getFileContents(file));
msgs = analyzer.analyzeDocument(nature,
(SourceModule) AbstractModule.createModule("extendable.__init__", file, nature, true), prefs, doc,
new NullProgressMonitor(), new TestIndentPrefs(true, 4));
printMessages(msgs, 0);
}
public void testInitDef() throws IOException {
doc = new Document("from extendable import help\n" +
"print help.about\n");
checkNoError();
}
public void testNoStaticComplain() throws IOException {
doc = new Document("class SomeClass(object):\n" +
" @staticmethod\n" +
" def m1(cls):\n"
+
" pass\n");
checkNoError();
}
public void testNoStaticComplain2() throws IOException {
doc = new Document("class SomeClass(object):\n" +
" @staticmethod\n" +
" def m1():\n" +
" pass\n");
checkNoError();
}
public void testNoStaticComplain3() throws IOException {
doc = new Document("class SomeClass(object):\n" +
" @staticmethod\n" +
" def m1(self):\n"
+
" pass\n");
checkNoError();
}
public void testInnerAndOuterScopeReference() throws IOException {
doc = new Document("EnumType = lambda: EnumType\n" +
"print(EnumType())\n");
checkNoError();
}
public void testInnerAndOuterScopeReference2() throws IOException {
doc = new Document("def m1():\n" +
" c = lambda: a\n" +
" a = 10\n" +
" print c\n" +
"\n");
checkNoError();
}
public void testAssignNotAcknowledged() throws IOException {
doc = new Document("def m1():\n" +
" c = object()\n" +
" c.x += 1\n" +
"\n");
checkNoError();
}
public void testNoLeakageInGenerator() throws IOException {
doc = new Document("(a for a in range(5))\n" +
"print a\n");
checkError(1);
}
public void testLeakageInListComp() throws IOException {
doc = new Document("[b for b in range(5)]\n" +
"print b\n");
checkNoError();
}
public void testLeakageInListComp2() throws IOException {
doc = new Document("[x for x in [y for y in range(3)]]\n" +
"print x, y\n");
checkNoError();
}
public void testListCompFalsePositive() throws IOException {
doc = new Document("alist = []\n" +
"blist = []\n"
+
"clist = [c for c in (a + b for b in blist for a in alist)]\n");
checkNoError();
}
public void testParameterAnalysis() throws IOException {
doc = new Document("def m1():\n" +
" pass\n" +
"m1(20)");
IMessage[] messages = checkError(1);
assertContainsMsg("m1: arguments don't match", messages);
}
public void testParameterAnalysis2() throws IOException {
doc = new Document("def m1(a):\n" +
" pass\n" +
"m1()");
IMessage[] messages = checkError(1);
assertContainsMsg("m1: arguments don't match", messages);
}
public void testParameterAnalysis3() throws IOException {
doc = new Document("def m1(*args):\n" +
" pass\n" +
"m1()");
checkNoError();
}
public void testParameterAnalysis4() throws IOException {
doc = new Document("def m1(**args):\n" +
" pass\n" +
"m1()");
checkNoError();
}
public void testParameterAnalysis5() throws IOException {
doc = new Document("def m1(a=10):\n" +
" pass\n" +
"m1()");
checkNoError();
}
public void testParameterAnalysis6() throws IOException {
doc = new Document("def m1(a=10):\n" +
" pass\n" +
"m1(a=20)");
checkNoError();
}
public void testParameterAnalysis7() throws IOException {
doc = new Document("def m1(a=10):\n" +
" pass\n" +
"m1(b=20)");
checkError(1);
}
public void testParameterAnalysis8() throws IOException {
doc = new Document("from extendable.calltips.mod1.sub1 import method1\n" + //method1(a, b)
"method1(10)");
IMessage[] errors = checkError(1);
IMessage msg = errors[0];
assertEquals(msg.getMessage(), "method1: arguments don't match");
assertEquals(msg.getStartCol(doc), 8);
assertEquals(msg.getEndCol(doc), 12);
assertEquals(msg.getStartLine(doc), 2);
assertEquals(msg.getEndLine(doc), 2);
}
public void testParameterAnalysis8a() throws IOException {
doc = new Document("from extendable.calltips.mod1.sub1 import method1\n" +
"method1(\n" +
" 10)");
IMessage[] errors = checkError(1);
IMessage msg = errors[0];
assertEquals(msg.getMessage(), "method1: arguments don't match");
assertEquals(msg.getStartCol(doc), 8);
assertEquals(msg.getEndCol(doc), 11);
assertEquals(msg.getStartLine(doc), 2);
assertEquals(msg.getEndLine(doc), 3);
}
public void testParameterAnalysis9() throws IOException {
doc = new Document("from extendable.calltips.mod1.sub1 import method1\n" +
"method1(10, 20)");
checkNoError();
}
public void testParameterAnalysis10() throws IOException {
doc = new Document("def m1(a):\n" +
" pass\n" +
"\n" +
"d={'a':20}\n" +
"m1(**d)");
checkNoError();
}
public void testParameterAnalysis11() throws IOException {
doc = new Document("def m1(a):\n" +
" pass\n" +
"\n" +
"d=[20]\n" +
"m1(*d)");
checkNoError();
}
public void testParameterAnalysis12() throws IOException {
doc = new Document("def m1(a, **kwargs):\n" +
" pass\n" +
"\n" +
"d=[20]\n" +
"m1(10, *d)");
checkError(1);
}
public void testParameterAnalysis13() throws IOException {
doc = new Document("def m1(a, *args):\n" +
" pass\n" +
"\n" +
"d=[20]\n" +
"m1(10, *d)");
checkNoError();
}
public void testParameterAnalysis14() throws IOException {
doc = new Document("def m1(a=10, **args):\n" +
" pass\n" +
"\n" +
"d=[20]\n" +
"m1(*d)");
checkNoError();
}
public void testParameterAnalysis15() throws IOException {
int original = GRAMMAR_TO_USE_FOR_PARSING;
GRAMMAR_TO_USE_FOR_PARSING = IPythonNature.GRAMMAR_PYTHON_VERSION_3_0;
try {
doc = new Document("def w(a=10, *, b):\n" +
" pass\n" +
"\n" +
"w(20, b=10)\n");
checkNoError();
} finally {
GRAMMAR_TO_USE_FOR_PARSING = original;
}
}
public void testParameterAnalysis16() throws IOException {
int original = GRAMMAR_TO_USE_FOR_PARSING;
GRAMMAR_TO_USE_FOR_PARSING = IPythonNature.GRAMMAR_PYTHON_VERSION_3_0;
try {
doc = new Document("def w(a=10, *, b):\n" +
" pass\n" +
"\n" +
"w(20, 10)\n" //b must be keyword parameter
);
checkError(1);
} finally {
GRAMMAR_TO_USE_FOR_PARSING = original;
}
}
public void testParameterAnalysis17() throws IOException {
doc = new Document("class Foo:\n" +
" def __init__(self, a):\n" +
" pass\n" +
"Foo()\n");
checkError(1);
}
public void testParameterAnalysis17a() throws IOException {
doc = new Document("class Foo:\n" +
" def __init__(self, a):\n" +
" pass\n" +
"Foo(10)\n");
checkNoError();
}
public void testParameterAnalysis18() throws IOException {
doc = new Document("from testOtherImports.f2 import SomeOtherTest\n" + //class with __init__ == __init__(self, a, b)
"SomeOtherTest()\n");
checkError("SomeOtherTest: arguments don't match");
}
public void testParameterAnalysis19() throws IOException {
doc = new Document("from extendable.parameters_check.check import Foo\n" + //class with __init__ == __init__(self, a, b)
"foo = Foo(10, 20)\n" +
"foo.Method()\n" //Method(self, a)
);
checkError("foo.Method: arguments don't match");
}
public void testParameterAnalysis19a() throws IOException {
doc = new Document("from extendable.parameters_check.check import Foo\n" + //class with __init__ == __init__(self, a, b)
"foo = Foo(10, 20)\n" +
"Foo.Method(foo, 10)\n" //Method(self, a)
);
checkNoError();
}
public void testParameterAnalysis19b() throws IOException {
doc = new Document("from extendable.parameters_check.check import Foo\n" + //class with __init__ == __init__(self, a, b)
"Foo.Method(10)\n" //Method(self, a)
);
checkError("Foo.Method: arguments don't match");
}
public void testParameterAnalysis19c() throws IOException {
doc = new Document("from extendable.parameters_check import Foo\n" + //class with __init__ == __init__(self, a, b)
"foo = Foo(10, 20)\n" +
"Foo.Method(foo, 10)\n" //Method(self, a)
);
checkNoError();
}
public void testParameterAnalysis19d() throws IOException {
doc = new Document("from extendable.parameters_check import Foo\n" + //class with __init__ == __init__(self, a, b)
"foo = Foo(10, 20)\n" +
"foo.Method(10)\n" //Method(self, a)
);
checkNoError();
}
public void testParameterAnalysis19e() throws IOException {
doc = new Document("from extendable.parameters_check import Foo\n" + //class with __init__ == __init__(self, a, b)
"foo = Foo(10, 20)\n" +
"Foo.Method(10)\n" //Method(self, a)
);
checkError("Foo.Method: arguments don't match");
}
public void testParameterAnalysis19f() throws IOException {
doc = new Document("from extendable.parameters_check import Foo\n" + //class with __init__ == __init__(self, a, b)
"foo = Foo(10, 20)\n" +
"foo.Method(foo, 10)\n" //Method(self, a)
);
checkError("foo.Method: arguments don't match");
}
public void testParameterAnalysis20() throws IOException {
doc = new Document("from extendable.parameters_check.check import Foo\n" + //class with __init__ == __init__(self, a, b)
"foo = Foo(10, 20)\n" +
"foo.Method(10)\n");
checkNoError();
}
public void testParameterAnalysis21() throws IOException {
doc = new Document("class Bar(object):\n" +
" @classmethod\n" +
" def Method(cls, a, b):\n"
+
" pass\n" +
"Bar.Method(10, 20)\n");
checkNoError();
}
public void testParameterAnalysis22() throws IOException {
doc = new Document("class Bar(object):\n" +
" @classmethod\n" +
" def Method(cls, a, b):\n"
+
" pass\n" +
"Bar.Method(20)\n");
checkError("Bar.Method: arguments don't match");
}
public void testParameterAnalysis23() throws IOException {
doc = new Document("class Bar(object):\n" +
" def Method(cls, a, b):\n" +
" pass\n"
+
" Method = classmethod(Method)\n" +
"Bar.Method(20, 20, 20)\n");
checkError("Bar.Method: arguments don't match");
}
public void testParameterAnalysis22a() throws IOException {
doc = new Document("class Bar(object):\n" +
" @staticmethod\n" +
" def Method(cls, a, b):\n"
+
" pass\n" +
"Bar.Method(20, 21)\n");
checkError("Bar.Method: arguments don't match");
}
public void testParameterAnalysis23a() throws IOException {
doc = new Document("class Bar(object):\n" +
" def Method(cls, a, b):\n" +
" pass\n"
+
" Method = staticmethod(Method)\n" +
"Bar.Method(20, 20, 20)\n");
checkNoError();
}
public void testParameterAnalysis23b() throws IOException {
doc = new Document("class Bar(object):\n" +
" @staticmethod\n" +
" def Method(cls, a, b):\n"
+
" pass\n" +
"Bar.Method(20, 20, 20)\n");
checkNoError();
}
public void testParameterAnalysis24() throws IOException {
doc = new Document("from extendable.parameters_check import Foo\n"
+ //class with __init__ == __init__(self, a, b)
"\n" +
"class X(object):\n" +
"\n" +
" def __init__(self, a, b):\n"
+
" Foo.__init__(self, a, b)\n" +
"\n" +
"\n" +
"\n" +
"class B(object):\n" +
"\n"
+
" def __init__(self, a, b, c):\n" +
" pass\n" +
"\n" +
" @classmethod\n"
+
" def Create(cls):\n" +
" return B(1, 2, 3)\n");
checkNoError();
}
public void testParameterAnalysis24a() throws IOException {
doc = new Document("class B(object):\n" +
"\n" +
" def __init__(self, a, b, c):\n" +
" pass\n" +
"\n"
+
" @classmethod\n" +
" def Create(cls):\n" +
" return B(1, 2)\n");
checkError("B: arguments don't match");
}
public void testParameterAnalysis25() throws IOException {
doc = new Document("class Bar(object):\n" +
"\n" +
" def __init__(self):\n" +
" pass\n" +
"\n"
+
"class Foo(Bar):\n" +
" pass\n" +
"\n" +
"Foo()\n" +
"Foo()\n");
checkNoError();
}
public void testParameterAnalysis26() throws IOException {
doc = new Document("class Foo(object):\n" +
" def Method(self):\n" +
" pass\n" +
"\n"
+
" def Method2(self):\n" +
" self.Method()\n");
checkNoError();
}
public void testParameterAnalysis26a() throws IOException {
doc = new Document("class Foo(object):\n" +
" def Method(self):\n" +
" pass\n" +
"\n"
+
" def Method2(self):\n" +
" self.Method(1)\n");
checkError("self.Method: arguments don't match");
}
public void testParameterAnalysis27() throws IOException {
doc = new Document("class Bounds(object):\n" +
"\n" +
" def Method(self):\n" +
" pass\n" +
"\n"
+
"class Bar(object):\n" +
"\n" +
" def __init__(self):\n" +
" self.bounds = Bounds()\n"
+
"\n" +
" def testGetDiagonalLength(self):\n" +
" self.bounds.Method()\n" +
"\n");
checkNoError();
}
public void testParameterAnalysis27a() throws IOException {
doc = new Document("class Bounds(object):\n" +
"\n" +
" def Method(self):\n" +
" pass\n" +
"\n"
+
"class Bar(object):\n" +
"\n" +
" def __init__(self):\n" +
" self.Bounds = Bounds\n" +
"\n"
+
" def testGetDiagonalLength(self):\n" +
" self.Bounds.Method()\n" +
"\n");
checkError("self.Bounds.Method: arguments don't match");
}
List<String> findDefinitionDone = new ArrayList<String>();
private ICallbackListener<ICompletionState> listener = new ICallbackListener<ICompletionState>() {
@Override
public Object call(ICompletionState obj) {
findDefinitionDone.add(obj.getActivationToken());
return null;
}
};
private void registerOnFindDefinitionListener() {
SourceModule.onFindDefinition = new CallbackWithListeners<ICompletionState>();
SourceModule.onFindDefinition.registerListener(listener);
}
private void unregisterFindDefinitionListener(String... expected) {
SourceModule.onFindDefinition = null;
if (expected.length != findDefinitionDone.size()) {
fail(StringUtils.format(
"Expected: %s (%s) find definition call(s). Found: %s (%s)", expected.length,
Arrays.asList(expected), findDefinitionDone.size(), findDefinitionDone));
}
}
public void testParameterAnalysisOptimization() throws IOException {
registerOnFindDefinitionListener();
try {
doc = new Document("def method():\n" +
" \n" +
"method()\n" + //
"method()\n");
checkNoError();
} finally {
unregisterFindDefinitionListener();
}
}
public void testParameterAnalysisOptimization2() throws IOException {
registerOnFindDefinitionListener();
try {
doc = new Document("def method():\n" +
" \n" +
"b = method\n" +
"b()\n" + //
"b()\n");
checkNoError();
} finally {
unregisterFindDefinitionListener();
}
}
public void testParameterAnalysisOptimization3() throws IOException {
registerOnFindDefinitionListener();
try {
doc = new Document("class Foo:\n" +
" def __init__(self, a):\n" +
" pass\n" +
"Foo()\n");
checkError("Foo: arguments don't match");
} finally {
unregisterFindDefinitionListener();
}
}
public void testParameterAnalysisOptimization4() throws IOException {
registerOnFindDefinitionListener();
try {
doc = new Document("class Foo:\n" +
" def __init__(self, a):\n" +
" pass\n" +
"Bar = Foo\n"
+
"Bar(1)\n");
checkNoError();
} finally {
unregisterFindDefinitionListener();
}
}
public void testParameterAnalysisOptimization5a() throws IOException {
registerOnFindDefinitionListener();
try {
doc = new Document("from extendable.parameters_check.check import Foo\n" + //class with __init__ == __init__(self, a, b)
"foo = Foo(10, 20)\n" +
"foo.Method(10)\n");
checkNoError();
} finally {
unregisterFindDefinitionListener("Foo", "foo.Method", "foo"); //TODO: This must be improved!
}
}
public void testParameterAnalysisOptimization5() throws IOException {
prefs.severityForArgumentsMismatch = IMarker.SEVERITY_INFO; //Nothing will be analyzed and the checks should be skipped!
registerOnFindDefinitionListener();
try {
doc = new Document("from extendable.parameters_check.check import Foo\n" + //class with __init__ == __init__(self, a, b)
"foo = Foo(10, 20, 20)\n" +
"foo.Method(10, 30)\n" //error here, but check is disabled!
);
checkNoError();
} finally {
unregisterFindDefinitionListener();
}
}
public void testParameterAnalysisOptimization6() throws IOException {
registerOnFindDefinitionListener();
try {
doc = new Document("from extendable.parameters_check import check\n" + //class with __init__ == __init__(self, a, b)
"foo = check.Foo(10, 20, 20)\n" +
"foo.Method(10, 20)\n");
checkError("foo.Method: arguments don't match");
} finally {
unregisterFindDefinitionListener("", "check.Foo", "foo.Method", "foo");
}
}
protected Closeable setGrammar(int grammarVersion) {
final int initial = GRAMMAR_TO_USE_FOR_PARSING;
GRAMMAR_TO_USE_FOR_PARSING = grammarVersion;
return new Closeable() {
@Override
public void close() throws IOException {
GRAMMAR_TO_USE_FOR_PARSING = initial;
}
};
}
public void testUsedVariable() throws Exception {
try (Closeable x = setGrammar(IPythonNature.GRAMMAR_PYTHON_VERSION_3_0)) {
doc = new Document("def foo():\n" +
" a = []\n" +
" my = [*a]\n" +
"");
checkError("Unused variable: my");
}
}
// public void testNonDefaultAfterDefault() throws IOException{
// doc = new Document(
// "def m1(a=20, 20):\n"+ //non-default after default
// " pass\n"
// );
// checkError(1);
// }
}