Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
小 白蛋
Intellij Community
Commits
19d8b45b
Commit
19d8b45b
authored
6 years ago
by
aleksei.kniazev
Browse files
Options
Download
Email Patches
Plain Diff
added a type for generic descriptor to improve type hints (PY-26187)
parent
562886e2
Branches unavailable
Tags unavailable
No related merge requests found
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
python/src/com/jetbrains/python/codeInsight/typing/PyTypingTypeProvider.java
+6
-5
...rains/python/codeInsight/typing/PyTypingTypeProvider.java
python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java
+4
-14
.../jetbrains/python/psi/impl/PyReferenceExpressionImpl.java
python/src/com/jetbrains/python/psi/types/PyDescriptorType.kt
+6
-0
...on/src/com/jetbrains/python/psi/types/PyDescriptorType.kt
python/src/com/jetbrains/python/psi/types/PyDescriptorTypeImpl.kt
+27
-0
...rc/com/jetbrains/python/psi/types/PyDescriptorTypeImpl.kt
python/src/com/jetbrains/python/psi/types/PyTypeChecker.java
+9
-0
python/src/com/jetbrains/python/psi/types/PyTypeChecker.java
python/testSrc/com/jetbrains/python/PyTypeTest.java
+26
-0
python/testSrc/com/jetbrains/python/PyTypeTest.java
with
78 additions
and
19 deletions
+78
-19
python/src/com/jetbrains/python/codeInsight/typing/PyTypingTypeProvider.java
+
6
-
5
View file @
19d8b45b
...
...
@@ -9,10 +9,7 @@ import com.intellij.openapi.util.Pair;
import
com.intellij.openapi.util.Ref
;
import
com.intellij.openapi.util.TextRange
;
import
com.intellij.openapi.util.text.StringUtil
;
import
com.intellij.psi.PsiComment
;
import
com.intellij.psi.PsiElement
;
import
com.intellij.psi.PsiFile
;
import
com.intellij.psi.ResolveResult
;
import
com.intellij.psi.*
;
import
com.intellij.psi.impl.source.resolve.FileContextUtil
;
import
com.intellij.psi.util.CachedValueProvider
;
import
com.intellij.psi.util.CachedValuesManager
;
...
...
@@ -636,7 +633,11 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
if
(
genericTypes
.
isEmpty
())
{
return
null
;
}
return
new
PyCollectionTypeImpl
(
cls
,
false
,
genericTypes
);
return
StreamEx
.
of
(
cls
.
getMethods
())
.
filterBy
(
PsiNamedElement:
:
getName
,
PyNames
.
GET
)
.
findAny
()
.<
PyType
>
map
(
getter
->
new
PyDescriptorTypeImpl
(
cls
,
false
,
context
.
getReturnType
(
getter
)))
.
orElseGet
(()
->
new
PyCollectionTypeImpl
(
cls
,
false
,
genericTypes
));
}
@NotNull
...
...
This diff is collapsed.
Click to expand it.
python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java
+
4
-
14
View file @
19d8b45b
...
...
@@ -252,6 +252,10 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere
@Nullable
private
Ref
<
PyType
>
getDescriptorType
(
@Nullable
PyType
typeFromTargets
,
@NotNull
TypeEvalContext
context
)
{
if
(
typeFromTargets
instanceof
PyDescriptorType
)
{
PyDescriptorType
descriptorType
=
(
PyDescriptorType
)
typeFromTargets
;
return
Ref
.
create
(
descriptorType
.
getMyGetterReturnType
());
}
if
(!
isQualified
())
return
null
;
final
PyClassLikeType
targetType
=
as
(
typeFromTargets
,
PyClassLikeType
.
class
);
if
(
targetType
==
null
)
return
null
;
...
...
@@ -265,20 +269,6 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere
.
map
((
callable
)
->
context
.
getReturnType
(
callable
))
.
toList
();
final
PyType
type
=
PyUnionType
.
union
(
types
);
if
(
PyTypeChecker
.
hasGenerics
(
type
,
context
))
{
PyAssignmentStatement
assignmentStatement
=
PyAssignmentStatementNavigator
.
getStatementByTarget
(
getReference
().
resolve
());
if
(
assignmentStatement
!=
null
&&
assignmentStatement
.
getAssignedValue
()
instanceof
PyCallExpression
)
{
PyCallExpression
callExpression
=
(
PyCallExpression
)
assignmentStatement
.
getAssignedValue
();
Map
<
PyGenericType
,
PyType
>
result
=
PyTypeChecker
.
unifyGenericCall
(
callExpression
,
Collections
.
emptyMap
(),
context
);
if
(!
ContainerUtil
.
isEmpty
(
result
))
{
PyType
actualType
=
PyTypeChecker
.
substitute
(
type
,
result
,
context
);
if
(
actualType
!=
null
)
{
return
Ref
.
create
(
actualType
);
}
}
}
}
return
Ref
.
create
(
type
);
}
...
...
This diff is collapsed.
Click to expand it.
python/src/com/jetbrains/python/psi/types/PyDescriptorType.kt
0 → 100644
+
6
-
0
View file @
19d8b45b
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package
com.jetbrains.python.psi.types
interface
PyDescriptorType
:
PyClassType
{
val
myGetterReturnType
:
PyType
?
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
python/src/com/jetbrains/python/psi/types/PyDescriptorTypeImpl.kt
0 → 100644
+
27
-
0
View file @
19d8b45b
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package
com.jetbrains.python.psi.types
import
com.jetbrains.python.psi.PyClass
class
PyDescriptorTypeImpl
(
source
:
PyClass
,
isDefinition
:
Boolean
,
override
val
myGetterReturnType
:
PyType
?)
:
PyClassTypeImpl
(
source
,
isDefinition
),
PyDescriptorType
{
override
fun
equals
(
other
:
Any
?):
Boolean
{
if
(
this
===
other
)
return
true
if
(
javaClass
!=
other
?.
javaClass
)
return
false
if
(!
super
.
equals
(
other
))
return
false
other
as
PyDescriptorTypeImpl
if
(
myGetterReturnType
!=
other
.
myGetterReturnType
)
return
false
return
true
}
override
fun
hashCode
():
Int
{
var
result
=
super
.
hashCode
()
result
=
31
*
result
+
(
myGetterReturnType
?.
hashCode
()
?:
0
)
return
result
}
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
python/src/com/jetbrains/python/psi/types/PyTypeChecker.java
+
9
-
0
View file @
19d8b45b
...
...
@@ -606,6 +606,10 @@ public class PyTypeChecker {
collectGenerics
(
elementType
,
context
,
collected
,
visited
);
}
}
else
if
(
type
instanceof
PyDescriptorType
)
{
PyDescriptorType
descriptor
=
(
PyDescriptorType
)
type
;
collectGenerics
(
descriptor
.
getMyGetterReturnType
(),
context
,
collected
,
visited
);
}
else
if
(
type
instanceof
PyCallableType
)
{
final
PyCallableType
callable
=
(
PyCallableType
)
type
;
final
List
<
PyCallableParameter
>
parameters
=
callable
.
getParameters
(
context
);
...
...
@@ -664,6 +668,11 @@ public class PyTypeChecker {
}
return
new
PyCollectionTypeImpl
(
collection
.
getPyClass
(),
collection
.
isDefinition
(),
substitutes
);
}
else
if
(
type
instanceof
PyDescriptorType
)
{
final
PyDescriptorType
descriptor
=
(
PyDescriptorType
)
type
;
PyType
newGetterReturnType
=
substitute
(
descriptor
.
getMyGetterReturnType
(),
substitutions
,
context
);
return
new
PyDescriptorTypeImpl
(
descriptor
.
getPyClass
(),
descriptor
.
isDefinition
(),
newGetterReturnType
);
}
else
if
(
type
instanceof
PyTupleType
)
{
final
PyTupleType
tupleType
=
(
PyTupleType
)
type
;
final
PyClass
tupleClass
=
tupleType
.
getPyClass
();
...
...
This diff is collapsed.
Click to expand it.
python/testSrc/com/jetbrains/python/PyTypeTest.java
+
26
-
0
View file @
19d8b45b
...
...
@@ -3418,6 +3418,32 @@ public class PyTypeTest extends PyTestCase {
);
}
// PY-26184
public
void
testGenericDescriptorFromTupleAssignment
()
{
runWithLanguageLevel
(
LanguageLevel
.
PYTHON37
,
()
->
doTest
(
"int"
,
"from typing import Generic, TypeVar\n"
+
"\n"
+
"T = TypeVar(\"T\")\n"
+
"U = TypeVar(\"U\")\n"
+
"class Descr(Generic[T]):\n"
+
" def __init__(self, one: T) -> None:\n"
+
" self.one = one\n"
+
"\n"
+
" def __get__(self, instance, owner) -> T:\n"
+
" return self.one\n"
+
"\n\n"
+
"def foo(one: T, two: U) -> (Descr[T], Descr[U]):\n"
+
" return Descr(one), Descr(two)"
+
"\n\n"
+
"class MyClass:\n"
+
" descr_target, irrelevant = foo(42, \"string\")\n"
+
"\n"
+
"expr = MyClass().descr_target"
)
);
}
private
static
List
<
TypeEvalContext
>
getTypeEvalContexts
(
@NotNull
PyExpression
element
)
{
return
ImmutableList
.
of
(
TypeEvalContext
.
codeAnalysis
(
element
.
getProject
(),
element
.
getContainingFile
()).
withTracing
(),
TypeEvalContext
.
userInitiated
(
element
.
getProject
(),
element
.
getContainingFile
()).
withTracing
());
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment
Menu
Projects
Groups
Snippets
Help