Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Trofimov
2013-09-18 16:53:56 +02:00
7 changed files with 40 additions and 16 deletions
@@ -389,6 +389,7 @@
<xml.xmlExtension implementation="com.jetbrains.pyramid.templates.highlighting.ChameleonXmlExtension" order="first"/>
<highlightErrorFilter implementation="com.jetbrains.pyramid.templates.highlighting.ChameleonErrorFilter"/>
<psi.fileReferenceHelper implementation="com.jetbrains.pyramid.templates.ref.PyramidStaticFileReferenceHelper"/>
<lang.commenter language="Chameleon" implementationClass="com.jetbrains.pyramid.templates.editor.ChameleonCommenter"/>
</extensions>
<extensionPoints>
@@ -39,7 +39,9 @@ public class PyParameterInfoHandler implements ParameterInfoHandler<PyArgumentLi
public PyArgumentList findElementForParameterInfo(final CreateParameterInfoContext context) {
PyArgumentList arglist = findArgumentList(context);
if (arglist != null) {
CallArgumentsMapping result = arglist.analyzeCall(PyResolveContext.noImplicits());
final TypeEvalContext typeEvalContext = TypeEvalContext.userInitiated(arglist.getContainingFile());
final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(typeEvalContext);
CallArgumentsMapping result = arglist.analyzeCall(resolveContext);
if (result.getMarkedCallee() != null) {
context.setItemsToShow(new Object[] { result });
return arglist;
@@ -3,18 +3,20 @@ package com.jetbrains.python.inspections;
import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiReference;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.inspections.quickfix.AddMethodQuickFix;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.types.PyClassLikeType;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyClassTypeImpl;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* User: ktisha
* See pylint W0232
@@ -42,12 +44,14 @@ public class PyClassHasNoInitInspection extends PyInspection {
@Override
public void visitPyClass(PyClass node) {
final PyExpression[] classes = node.getSuperClassExpressions();
for (PyExpression pyClass : classes) {
final PsiReference reference = pyClass.getReference();
if (reference == null || reference.resolve() == null) return;
if (reference.getCanonicalText().contains(PyNames.TEST_CASE)) return;
final List<PyClassLikeType> types = node.getSuperClassTypes(myTypeEvalContext);
for (PyClassLikeType type : types) {
if (type == null) return;
final String qName = type.getClassQName();
if (qName != null && qName.contains(PyNames.TEST_CASE)) return;
if (!(type instanceof PyClassType)) return;
}
final PyFunction init = node.findInitOrNew(true);
if (init == null) {
registerProblem(node.getNameIdentifier(), PyBundle.message("INSP.class.has.no.init"),
@@ -62,6 +62,7 @@ public class PyOldStyleClassesInspection extends PyInspection {
if (klass != null && !klass.isNewStyleClass()) {
final List<PyClassLikeType> types = klass.getSuperClassTypes(myTypeEvalContext);
for (PyClassLikeType type : types) {
if (type == null) return;
final String qName = type.getClassQName();
if (qName != null && qName.contains("PyQt")) return;
if (!(type instanceof PyClassType)) return;
@@ -79,12 +79,12 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
PyNamedParameter kwd_par = null; // **param
PyNamedParameter tuple_par = null; // *param
Set<PyExpression> mapped_args = new HashSet<PyExpression>();
final int implicit_offset = resolved_callee.getImplicitOffset();
final int implicitOffset = resolved_callee.getImplicitOffset();
int positional_index = 0; // up to this index parameters are positional
// check positional arguments, fill slots
int i = 0;
for (PyParameter par : parameters) {
if (tuple_par == null && kwd_par == null && positional_index < implicit_offset) {
if (tuple_par == null && kwd_par == null && positional_index < implicitOffset) {
positional_index += 1;
continue;
}
@@ -107,14 +107,14 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
i += 1;
}
// rule out 'self' or other implicit params
for (i=0; i < implicit_offset && i < parameters.size(); i+=1) {
for (i=0; i < implicitOffset && i < parameters.size(); i+=1) {
slots.remove(parameters.get(i).getAsNamed());
positional_index += 1;
}
// now params to the left of positional_index are positional.
// map positional args to positional params.
// we assume that implicitly skipped parameters are never nested tuples. no idea when they could ever be.
int cnt = implicit_offset;
int cnt = implicitOffset;
int positional_bound = arguments.length; // to the right of this pos args are verboten
ListIterator<PyExpression> unmatched_arg_iter = unmatched_args.listIterator();
while (unmatched_arg_iter.hasNext()) {
@@ -290,10 +290,12 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
}
// map unmapped named params to **kwarg
if (myKwdArg != null) {
for (PyParameter par : parameters) {
PyNamedParameter n_par = par.getAsNamed();
if (n_par != null && !n_par.isKeywordContainer() && !n_par.isPositionalContainer() && slots.get(n_par) == null) {
slots.put(n_par, myKwdArg);
for (int j = implicitOffset; j != parameters.size(); ++j) {
final PyParameter par = parameters.get(j);
final PyNamedParameter namedParameter = par.getAsNamed();
if (namedParameter != null && !namedParameter.isKeywordContainer()
&& !namedParameter.isPositionalContainer() && slots.get(namedParameter) == null) {
slots.put(namedParameter, myKwdArg);
}
}
}
@@ -0,0 +1,9 @@
class A:
def foo(self, e):
self.kw = {}
self.add_comm(**self<arg1>.kw)
def add_comm(self, **kw):
self.kw = []
@@ -132,6 +132,11 @@ public class PyParameterInfoTest extends LightMarkedTestCase {
feignCtrlP(marks.get("<arg2a>").getTextOffset()).check("a, b, c", new String[]{"b, ","c"});
}
public void testKwdArgInClass() {
Map<String, PsiElement> marks = loadTest(1);
feignCtrlP(marks.get("<arg1>").getTextOffset()).check("self, **kw", new String[]{"**kw"}, new String[]{"self, "});
}
public void testKwdArgOutOfOrder() {
Map<String, PsiElement> marks = loadTest(3);