Merge branch 'union-types-syntax'

This commit is contained in:
Andrey Vlasovskikh
2013-07-19 18:12:58 +04:00
9 changed files with 110 additions and 23 deletions
@@ -288,7 +288,7 @@ public class PyRequirement {
@NotNull
private static List<PyRequirement> parse(@NotNull String s, @Nullable VirtualFile anchor, @NotNull Set<VirtualFile> visited) {
final List<PyRequirement> result = new ArrayList<PyRequirement>();
final Set<PyRequirement> result = new LinkedHashSet<PyRequirement>();
for (String line : StringUtil.splitByLines(s)) {
final String trimmed = line.trim();
if (!trimmed.isEmpty()) {
@@ -301,7 +301,7 @@ public class PyRequirement {
}
}
}
return result;
return new ArrayList<PyRequirement>(result);
}
@NotNull
@@ -26,6 +26,6 @@ import static com.jetbrains.python.psi.types.PyTypeTokenTypes.*;
[\r\n]+ { return NL; }
[\ \t] { return SPACE; }
(":py"?":class:`"[~!]?)|("`")|([A-Z]"{")|("}") { return MARKUP; }
("or")|("of")|("from")|("to")|[,\(\)\.] { return OP; }
("or")|("of")|("from")|("to")|[,\(\)\.\[\]|] { return OP; }
[T-Z] { return PARAMETER; }
[A-Za-z_][A-Za-z_0-9]* { return IDENTIFIER; }
@@ -253,6 +253,9 @@ public class PyTypeChecker {
final Map<PyGenericType, PyType> substitutions = collectCallGenerics(function, receiver, context);
for (Map.Entry<PyExpression, PyNamedParameter> entry : arguments.entrySet()) {
final PyNamedParameter p = entry.getValue();
if (p.isPositionalContainer() || p.isKeywordContainer()) {
continue;
}
final PyType argType = context.getType(entry.getKey());
final PyType paramType = context.getType(p);
if (!match(paramType, argType, context, substitutions)) {
@@ -1,4 +1,4 @@
/* The following code was generated by JFlex 1.4.3 on 6/24/13 5:23 PM */
/* The following code was generated by JFlex 1.4.3 on 7/19/13 2:41 PM */
package com.jetbrains.python.psi.types;
@@ -11,7 +11,7 @@ import static com.jetbrains.python.psi.types.PyTypeTokenTypes.*;
/**
* This class is a scanner generated by
* <a href="http://www.jflex.de/">JFlex</a> 1.4.3
* on 6/24/13 5:23 PM from the specification file
* on 7/19/13 2:41 PM from the specification file
* <tt>/home/user/src/idea/tools/lexer/../../python/src/com/jetbrains/python/psi/types/PyType.flex</tt>
*/
public class PyTypeLexer implements FlexLexer {
@@ -37,9 +37,9 @@ public class PyTypeLexer implements FlexLexer {
private static final String ZZ_CMAP_PACKED =
"\11\0\1\2\1\1\2\0\1\1\22\0\1\2\1\13\6\0\2\24"+
"\2\0\1\24\1\0\1\24\1\0\12\27\1\3\6\0\23\14\7\25"+
"\4\0\1\26\1\12\1\10\1\26\1\6\2\26\1\21\5\26\1\7"+
"\1\22\1\26\1\17\1\4\1\26\1\20\1\11\1\23\4\26\1\5"+
"\1\26\1\15\1\0\1\16\1\13\uff81\0";
"\1\24\1\0\1\24\1\0\1\26\1\12\1\10\1\26\1\6\2\26"+
"\1\21\5\26\1\7\1\22\1\26\1\17\1\4\1\26\1\20\1\11"+
"\1\23\4\26\1\5\1\26\1\15\1\24\1\16\1\13\uff81\0";
/**
* Translates characters to character classes
@@ -254,7 +254,7 @@ public class PyTypeLexer implements FlexLexer {
char [] map = new char[0x10000];
int i = 0; /* index in packed string */
int j = 0; /* index in unpacked array */
while (i < 92) {
while (i < 98) {
int count = packed.charAt(i++);
char value = packed.charAt(i++);
do map[j++] = value; while (--count > 0);
@@ -161,24 +161,50 @@ public class PyTypeParser {
.named("simple-expr");
final FunctionalParser<ParseResult, PyElementType> paramExpr =
simpleExpr.thenSkip(op("of")).then(simpleExpr)
.map(new Function<Pair<ParseResult, ParseResult>, ParseResult>() {
simpleExpr.thenSkip(op("[")).then(typeExpr).then(many(op(",").skipThen(typeExpr))).thenSkip(op("]"))
.map(new Function<Pair<Pair<ParseResult, ParseResult>, List<ParseResult>>, ParseResult>() {
@Override
public ParseResult fun(Pair<ParseResult, ParseResult> value) {
final ParseResult firstResult = value.getFirst();
final ParseResult secondResult = value.getSecond();
final ParseResult result = firstResult.merge(secondResult);
final PyType firstType = firstResult.getType();
final PyType secondType = secondResult.getType();
if (firstType != null) {
if (firstType instanceof PyClassType && secondType != null) {
return result.withType(new PyCollectionTypeImpl(((PyClassType)firstType).getPyClass(), false, secondType));
public ParseResult fun(Pair<Pair<ParseResult, ParseResult>, List<ParseResult>> value) {
final Pair<ParseResult, ParseResult> firstPair = value.getFirst();
final ParseResult first = firstPair.getFirst();
final ParseResult second = firstPair.getSecond();
final List<ParseResult> third = value.getSecond();
final PyType firstType = first.getType();
if (firstType instanceof PyClassType) {
final List<PyType> tupleTypes = new ArrayList<PyType>();
tupleTypes.add(second.getType());
ParseResult result = first;
result = result.merge(second);
for (ParseResult r : third) {
tupleTypes.add(r.getType());
result = result.merge(r);
}
return result.withType(firstType);
final PyType elementType = third.isEmpty() ? second.getType() :
PyTupleType.create(anchor, tupleTypes.toArray(new PyType[tupleTypes.size()]));
final PyCollectionTypeImpl type = new PyCollectionTypeImpl(((PyClassType)firstType).getPyClass(), false, elementType);
return result.withType(type);
}
return EMPTY_RESULT;
}
})
.or(simpleExpr.thenSkip(op("of")).then(simpleExpr)
.map(new Function<Pair<ParseResult, ParseResult>, ParseResult>() {
@Override
public ParseResult fun(Pair<ParseResult, ParseResult> value) {
final ParseResult firstResult = value.getFirst();
final ParseResult secondResult = value.getSecond();
final ParseResult result = firstResult.merge(secondResult);
final PyType firstType = firstResult.getType();
final PyType secondType = secondResult.getType();
if (firstType != null) {
if (firstType instanceof PyClassType && secondType != null) {
return result.withType(new PyCollectionTypeImpl(((PyClassType)firstType).getPyClass(), false, secondType));
}
return result.withType(firstType);
}
return EMPTY_RESULT;
}
}))
.or(simpleExpr.thenSkip(op("from")).then(simpleExpr).thenSkip(op("to")).then(simpleExpr)
.map(new Function<Pair<Pair<ParseResult, ParseResult>, ParseResult>, ParseResult>() {
@Override
@@ -200,7 +226,7 @@ public class PyTypeParser {
.named("param-expr");
final FunctionalParser<ParseResult, PyElementType> unionExpr =
paramExpr.then(many(op("or").skipThen(paramExpr)))
paramExpr.then(many(op("or").or(op("|")).skipThen(paramExpr)))
.map(new Function<Pair<ParseResult, List<ParseResult>>, ParseResult>() {
@Override
public ParseResult fun(Pair<ParseResult, List<ParseResult>> value) {
@@ -0,0 +1,10 @@
from distutils.core import setup
requires = [
'mynose'
]
setup(name='foo',
version=0.1,
install_requires=requires,
tests_require=requires)
@@ -0,0 +1,2 @@
<warning descr="Package requirement 'mynose' is not satisfied">print("Hello, World!")
</warning>
@@ -184,4 +184,47 @@ public class PyTypeParserTest extends PyTestCase {
final PyType bound = genericType.getBound();
assertInstanceOf(bound, PyUnionType.class);
}
public void testBracketSingleParam() {
myFixture.configureByFile("typeParser/typeParser.py");
final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "list[int]");
assertInstanceOf(type, PyCollectionType.class);
final PyCollectionType collectionType = (PyCollectionType)type;
assertNotNull(collectionType);
assertEquals("list", collectionType.getName());
final PyType elementType = collectionType.getElementType(TypeEvalContext.codeInsightFallback());
assertNotNull(elementType);
assertEquals("int", elementType.getName());
}
public void testBracketMultipleParams() {
myFixture.configureByFile("typeParser/typeParser.py");
final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "dict[str, int]");
assertInstanceOf(type, PyCollectionType.class);
final PyCollectionType collectionType = (PyCollectionType)type;
assertNotNull(collectionType);
assertEquals("dict", collectionType.getName());
final PyType elementType = collectionType.getElementType(TypeEvalContext.codeInsightFallback());
assertNotNull(elementType);
assertInstanceOf(elementType, PyTupleType.class);
final PyTupleType tupleType = (PyTupleType)elementType;
final PyType first = tupleType.getElementType(0);
assertNotNull(first);
assertEquals("str", first.getName());
final PyType second = tupleType.getElementType(1);
assertNotNull(second);
assertEquals("int", second.getName());
}
public void testUnionOrOperator() {
myFixture.configureByFile("typeParser/typeParser.py");
final PyUnionType type = (PyUnionType)PyTypeParser.getTypeByName(myFixture.getFile(), "MyObject | str | unicode");
assertNotNull(type);
final Collection<PyType> members = type.getMembers();
assertEquals(3, members.size());
final List<PyType> list = new ArrayList<PyType>(members);
assertClassType(list.get(0), "MyObject");
assertClassType(list.get(1), "str");
assertClassType(list.get(2), "unicode");
}
}
@@ -7,6 +7,8 @@ import com.intellij.openapi.projectRoots.SdkType;
import com.intellij.openapi.projectRoots.impl.ProjectJdkImpl;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.psi.stubs.StubUpdatingIndex;
import com.intellij.util.indexing.FileBasedIndex;
import com.jetbrains.python.codeInsight.userSkeletons.PyUserSkeletonsUtil;
import com.jetbrains.python.sdk.PythonSdkType;
import org.jetbrains.annotations.NonNls;
@@ -59,8 +61,9 @@ public class PythonMockSdk {
String mock_stubs_path = mock_path + PythonSdkType.SKELETON_DIR_NAME;
sdkModificator.addRoot(LocalFileSystem.getInstance().refreshAndFindFileByPath(mock_stubs_path), PythonSdkType.BUILTIN_ROOT_TYPE);
//PythonSdkType.setupSdkPaths(sdkModificator, null);
sdkModificator.commitChanges();
FileBasedIndex.getInstance().requestRebuild(StubUpdatingIndex.INDEX_ID);
return sdk;
}
}