@@ -4,7 +4,26 @@ import { EndpointType } from "../../method";
44
55const memberTokenRegex = / ^ M e m b e r \[ ( .+ ) ] $ / ;
66
7- export function parsePythonAccessPath ( path : string ) : {
7+ // In Python, the type can contain both the package name and the type name.
8+ export function parsePythonType ( type : string ) {
9+ // The first part is always the package name. All remaining parts are the type
10+ // name.
11+
12+ const parts = type . split ( "." ) ;
13+ const packageName = parts . shift ( ) ?? "" ;
14+
15+ return {
16+ packageName,
17+ typeName : parts . join ( "." ) ,
18+ } ;
19+ }
20+
21+ // The type name can also be specified in the type, so this will combine
22+ // the already parsed type name and the type name from the access path.
23+ export function parsePythonAccessPath (
24+ path : string ,
25+ shortTypeName : string ,
26+ ) : {
827 typeName : string ;
928 methodName : string ;
1029 endpointType : EndpointType ;
@@ -13,8 +32,12 @@ export function parsePythonAccessPath(path: string): {
1332 const tokens = parseAccessPathTokens ( path ) ;
1433
1534 if ( tokens . length === 0 ) {
35+ const typeName = shortTypeName . endsWith ( "!" )
36+ ? shortTypeName . slice ( 0 , - 1 )
37+ : shortTypeName ;
38+
1639 return {
17- typeName : "" ,
40+ typeName,
1841 methodName : "" ,
1942 endpointType : EndpointType . Method ,
2043 path : "" ,
@@ -23,6 +46,10 @@ export function parsePythonAccessPath(path: string): {
2346
2447 const typeParts = [ ] ;
2548 let endpointType = EndpointType . Function ;
49+ // If a short type name was given and it doesn't end in a `!`, then this refers to a method.
50+ if ( shortTypeName !== "" && ! shortTypeName . endsWith ( "!" ) ) {
51+ endpointType = EndpointType . Method ;
52+ }
2653
2754 let remainingTokens : typeof tokens = [ ] ;
2855
@@ -32,6 +59,7 @@ export function parsePythonAccessPath(path: string): {
3259 if ( memberMatch ) {
3360 typeParts . push ( memberMatch [ 1 ] ) ;
3461 } else if ( token . text === "Instance" ) {
62+ // Alternative way of specifying that this refers to a method.
3563 endpointType = EndpointType . Method ;
3664 } else {
3765 remainingTokens = tokens . slice ( i ) ;
@@ -40,9 +68,22 @@ export function parsePythonAccessPath(path: string): {
4068 }
4169
4270 const methodName = typeParts . pop ( ) ?? "" ;
43- const typeName = typeParts . join ( "." ) ;
71+ let typeName = typeParts . join ( "." ) ;
4472 const remainingPath = remainingTokens . map ( ( token ) => token . text ) . join ( "." ) ;
4573
74+ if ( shortTypeName !== "" ) {
75+ if ( shortTypeName . endsWith ( "!" ) ) {
76+ // The actual type name is the name without the `!`.
77+ shortTypeName = shortTypeName . slice ( 0 , - 1 ) ;
78+ }
79+
80+ if ( typeName !== "" ) {
81+ typeName = `${ shortTypeName } .${ typeName } ` ;
82+ } else {
83+ typeName = shortTypeName ;
84+ }
85+ }
86+
4687 return {
4788 methodName,
4889 typeName,
@@ -51,53 +92,59 @@ export function parsePythonAccessPath(path: string): {
5192 } ;
5293}
5394
54- export function pythonMethodSignature ( typeName : string , methodName : string ) {
55- return `${ typeName } #${ methodName } ` ;
56- }
95+ export function parsePythonTypeAndPath (
96+ type : string ,
97+ path : string ,
98+ ) : {
99+ packageName : string ;
100+ typeName : string ;
101+ methodName : string ;
102+ endpointType : EndpointType ;
103+ path : string ;
104+ } {
105+ const { packageName, typeName : shortTypeName } = parsePythonType ( type ) ;
106+ const {
107+ typeName,
108+ methodName,
109+ endpointType,
110+ path : remainingPath ,
111+ } = parsePythonAccessPath ( path , shortTypeName ) ;
57112
58- function pythonTypePath ( typeName : string ) {
59- if ( typeName === "" ) {
60- return "" ;
61- }
113+ return {
114+ packageName,
115+ typeName,
116+ methodName,
117+ endpointType,
118+ path : remainingPath ,
119+ } ;
120+ }
62121
63- return typeName
64- . split ( "." )
65- . map ( ( part ) => `Member[${ part } ]` )
66- . join ( "." ) ;
122+ export function pythonMethodSignature ( typeName : string , methodName : string ) {
123+ return `${ typeName } #${ methodName } ` ;
67124}
68125
69- export function pythonMethodPath (
126+ export function pythonType (
127+ packageName : string ,
70128 typeName : string ,
71- methodName : string ,
72129 endpointType : EndpointType ,
73130) {
74- if ( methodName = == "" ) {
75- return pythonTypePath ( typeName ) ;
131+ if ( typeName !== "" && packageName ! == "" ) {
132+ return ` ${ packageName } . ${ typeName } ${ endpointType === EndpointType . Function ? "!" : "" } ` ;
76133 }
77134
78- const typePath = pythonTypePath ( typeName ) ;
79-
80- let result = typePath ;
81- if ( typePath !== "" && endpointType === EndpointType . Method ) {
82- result += ".Instance" ;
83- }
135+ return `${ packageName } ${ typeName } ` ;
136+ }
84137
85- if ( result !== "" ) {
86- result += "." ;
138+ export function pythonMethodPath ( methodName : string ) {
139+ if ( methodName === "" ) {
140+ return "" ;
87141 }
88142
89- result += `Member[${ methodName } ]` ;
90-
91- return result ;
143+ return `Member[${ methodName } ]` ;
92144}
93145
94- export function pythonPath (
95- typeName : string ,
96- methodName : string ,
97- endpointType : EndpointType ,
98- path : string ,
99- ) {
100- const methodPath = pythonMethodPath ( typeName , methodName , endpointType ) ;
146+ export function pythonPath ( methodName : string , path : string ) {
147+ const methodPath = pythonMethodPath ( methodName ) ;
101148 if ( methodPath === "" ) {
102149 return path ;
103150 }
@@ -111,7 +158,24 @@ export function pythonPath(
111158
112159export function pythonEndpointType (
113160 method : Omit < MethodDefinition , "endpointType" > ,
161+ endpointKind : string | undefined ,
114162) : EndpointType {
163+ switch ( endpointKind ) {
164+ case "Function" :
165+ return EndpointType . Function ;
166+ case "InstanceMethod" :
167+ return EndpointType . Method ;
168+ case "ClassMethod" :
169+ return EndpointType . ClassMethod ;
170+ case "StaticMethod" :
171+ return EndpointType . StaticMethod ;
172+ case "InitMethod" :
173+ return EndpointType . Constructor ;
174+ case "Class" :
175+ return EndpointType . Class ;
176+ }
177+
178+ // Legacy behavior for when the kind column is missing.
115179 if (
116180 method . methodParameters . startsWith ( "(self," ) ||
117181 method . methodParameters === "(self)"
@@ -120,3 +184,12 @@ export function pythonEndpointType(
120184 }
121185 return EndpointType . Function ;
122186}
187+
188+ export function hasPythonSelfArgument ( endpointType : EndpointType ) : boolean {
189+ // Instance methods and class methods both use `Argument[self]` for the first parameter. The first
190+ // parameter after self is called `Argument[0]`.
191+ return (
192+ endpointType === EndpointType . Method ||
193+ endpointType === EndpointType . ClassMethod
194+ ) ;
195+ }
0 commit comments