1+ import * as assert from 'assert' ;
2+ import * as vsc from 'vscode' ;
3+ import { getDataTypeContainer , DataType , PythonType } from "../../src/python" ;
4+ import { TypingHintProvider } from "../../src/typingHintProvider" ;
5+ import { TypeHintSettings } from '../../src/settings' ;
6+ import { SetupError , varSearchResult , messageFor , TestCase } from '../common' ;
7+
8+ suite ( 'TypingHintProvider' , ( ) => {
9+
10+ const importTyping : string = "import x\nimport typing" ;
11+ const importTypingAsX : string = "import x\nimport typing as x" ;
12+ const fromTypingImport : string = "import x\nfrom typing import List" ;
13+ const typeContainer = getDataTypeContainer ( ) ;
14+
15+ suite ( 'containsTyping' , ( ) => {
16+
17+ test ( "returns true for 'import typing'" , async ( ) => {
18+ const provider = new TypingHintProvider ( importTyping , typeContainer ) ;
19+ const actual = await provider . containsTyping ( ) ;
20+ assert . equal ( actual , true ) ;
21+ } ) ;
22+
23+ test ( "returns true for 'import typing as x'" , async ( ) => {
24+ const provider = new TypingHintProvider ( importTypingAsX , typeContainer ) ;
25+ const actual = await provider . containsTyping ( ) ;
26+ assert . equal ( actual , true ) ;
27+ } ) ;
28+
29+ test ( "returns true for 'from typing import x'" , async ( ) => {
30+ const provider = new TypingHintProvider ( fromTypingImport , typeContainer ) ;
31+ const actual = await provider . containsTyping ( ) ;
32+ assert . equal ( actual , true ) ;
33+ } ) ;
34+ } ) ;
35+
36+ suite ( "getTypingHint" , ( ) => {
37+
38+ test ( "returns typing.Type[" , async ( ) => {
39+ const provider = new TypingHintProvider ( importTyping , typeContainer ) ;
40+ const expected = "typing.List[" ;
41+ providerTest ( getTypingHint , await provider . containsTyping ( ) , provider , expected ) ;
42+ } ) ;
43+
44+ test ( "returns x.Type[ for 'import typing as x'" , async ( ) => {
45+ const provider = new TypingHintProvider ( importTypingAsX , typeContainer ) ;
46+ const expected = "x.List[" ;
47+ providerTest ( getTypingHint , await provider . containsTyping ( ) , provider , expected ) ;
48+ } ) ;
49+
50+ test ( "returns Type[ for 'from typing' import" , async ( ) => {
51+ const provider = new TypingHintProvider ( fromTypingImport , typeContainer ) ;
52+ const expected = "List[" ;
53+ providerTest ( getTypingHint , await provider . containsTyping ( ) , provider , expected ) ;
54+ } ) ;
55+
56+ function getTypingHint ( provider : TypingHintProvider , expected : string ) {
57+ const actual = provider . getTypingHint ( PythonType . List ) ;
58+ assert . equal ( actual , expected ) ;
59+ }
60+ } ) ;
61+
62+ suite ( "getTypingHints" , ( ) => {
63+
64+ const provider = new TypingHintProvider ( fromTypingImport , typeContainer ) ;
65+ let typingImported : boolean ;
66+
67+ setup ( async ( ) => {
68+ typingImported = await provider . containsTyping ( ) ;
69+ } ) ;
70+
71+ test ( "returns Type[ for empty collection" , ( ) => {
72+ const data = "[]" ;
73+ const expected = [ "List[" ] ;
74+ providerTest ( getTypingHints , typingImported , provider , { data, expected } , PythonType . List ) ;
75+ } ) ;
76+
77+ test ( "returns Dict[ and 'Dict[key,' for dicts" , ( ) => {
78+ let data = "{ 1: 2 }" ;
79+ let expected = [ "Dict[" , "Dict[int" ] ;
80+ providerTest ( getTypingHints , typingImported , provider , { data, expected } , PythonType . Dict ) ;
81+ } ) ;
82+
83+ test ( "handles nestled dicts" , ( ) => {
84+ let data = "[ { 1: 2 } ]" ;
85+ let expected = [ "List[" , "List[Dict[int" ] ;
86+ providerTest ( getTypingHints , typingImported , provider , { data, expected } , PythonType . List ) ;
87+ } ) ;
88+
89+ test ( "returns Type[ and Type[type] for non-dicts" , ( ) => {
90+ let data = "['str']" ;
91+ let expected = [ "List[" , "List[str]" ] ;
92+ providerTest ( getTypingHints , typingImported , provider , { data, expected } , PythonType . List ) ;
93+
94+ data = "(1, {'ignore': 'this'})" ;
95+ expected = [ "Tuple[" , "Tuple[int]" ] ;
96+ providerTest ( getTypingHints , typingImported , provider , { data, expected } , PythonType . Tuple ) ;
97+
98+ data = "{ 1, 2 }" ;
99+ expected = [ "Set[" , "Set[int]" ] ;
100+ providerTest ( getTypingHints , typingImported , provider , { data, expected } , PythonType . Set ) ;
101+ } ) ;
102+
103+ test ( "adds typing prefixes for 'import typing' imports" , async ( ) => {
104+ let p = new TypingHintProvider ( importTyping , typeContainer ) ;
105+ let data = "[ { 1: 2 } ]" ;
106+ let expected = [ "typing.List[" , "typing.List[typing.Dict[int" ] ;
107+ providerTest ( getTypingHints , await p . containsTyping ( ) , p , { data, expected } , PythonType . List ) ;
108+ } ) ;
109+
110+ function getTypingHints ( provider : TypingHintProvider , testCase : TestCase , type : PythonType ) {
111+ const actual = provider . getTypingHints ( varSearchResult ( type , testCase . data ) ) ;
112+ assert . deepEqual ( actual , testCase . expected , messageFor ( testCase , actual ) ) ;
113+ }
114+ } ) ;
115+
116+ function providerTest ( test : ( ...params : any ) => void , typingDetected : boolean , ...args : any ) {
117+ if ( typingDetected ) {
118+ test ( ...args ) ;
119+ } else {
120+ throw new SetupError ( "The provider failed to detect a typing import." ) ;
121+ }
122+ }
123+ } ) ;
0 commit comments