Skip to content

Commit 13cbdb1

Browse files
author
nicosammito
committed
feat: implement getTypesFromNode function and corresponding tests for type resolution
1 parent bf2925e commit 13cbdb1

4 files changed

Lines changed: 193 additions & 1 deletion

File tree

src/extraction/getTypesFromFunction.ts

Whitespace-only changes.

src/extraction/getTypesFromNode.ts

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import ts from "typescript";
2+
import {Flow, NodeFunction, NodeParameter} from "@code0-tech/sagittarius-graphql-types";
3+
import {
4+
createCompilerHost,
5+
DEFAULT_COMPILER_OPTIONS,
6+
ExtendedDataType,
7+
ExtendedFunction,
8+
getParameterCode,
9+
getSharedTypeDeclarations,
10+
} from "../utils";
11+
import {getNodeValidation} from "../validation/getNodeValidation"; // Wieder hinzugefügt
12+
13+
export interface NodeTypes {
14+
parameters: string[];
15+
returnType: string;
16+
}
17+
18+
/**
19+
* Resolves the types of the parameters and the return type of a NodeFunction.
20+
*/
21+
export const getTypesFromNode = (
22+
node: NodeFunction,
23+
functions: ExtendedFunction[],
24+
dataTypes: ExtendedDataType[]
25+
): NodeTypes => {
26+
const funcMap = new Map(functions.map(f => [f.identifier, f]));
27+
const funcDef = funcMap.get(node.functionDefinition?.identifier);
28+
29+
if (!funcDef) {
30+
return {
31+
parameters: [],
32+
returnType: "any",
33+
};
34+
}
35+
36+
const mockFlow: Flow = {
37+
id: "gid://sagittarius/Flow/0" as any,
38+
nodes: { __typename: "NodeFunctionConnection", nodes: [node] }
39+
} as Flow;
40+
41+
const params = (node.parameters?.nodes as NodeParameter[]) || [];
42+
const paramCodes = params.map(param => getParameterCode(param, mockFlow, (f, n) => getNodeValidation(f, n, functions, dataTypes)));
43+
44+
const funcCallArgs = paramCodes.map(code => code === 'undefined' ? '({} as any)' : code).join(", ");
45+
46+
const signature = funcDef.signature;
47+
const sourceCode = `
48+
${getSharedTypeDeclarations(dataTypes)}
49+
declare function testFunc${signature};
50+
const result = testFunc(${funcCallArgs});
51+
`;
52+
53+
const fileName = "node_types_virtual.ts";
54+
const sourceFile = ts.createSourceFile(fileName, sourceCode, ts.ScriptTarget.Latest);
55+
const host = createCompilerHost(fileName, sourceCode, sourceFile);
56+
57+
const program = ts.createProgram([fileName], DEFAULT_COMPILER_OPTIONS, host);
58+
const checker = program.getTypeChecker();
59+
60+
let inferredReturnType = "any";
61+
let inferredParameterTypes: string[] = [];
62+
63+
const visitor = (n: ts.Node) => {
64+
if (ts.isVariableDeclaration(n) && n.name.getText() === "result") {
65+
const resultType = checker.getTypeAtLocation(n);
66+
inferredReturnType = checker.typeToString(
67+
resultType,
68+
n,
69+
ts.TypeFormatFlags.NoTruncation
70+
);
71+
72+
if (ts.isCallExpression(n.initializer!)) {
73+
const callExpr = n.initializer;
74+
const signature = checker.getResolvedSignature(callExpr);
75+
if (signature) {
76+
inferredParameterTypes = signature.getParameters().map(p => {
77+
const type = checker.getTypeOfSymbolAtLocation(p, callExpr);
78+
return checker.typeToString(
79+
type,
80+
callExpr,
81+
ts.TypeFormatFlags.NoTruncation
82+
);
83+
});
84+
}
85+
}
86+
}
87+
ts.forEachChild(n, visitor);
88+
};
89+
90+
visitor(sourceFile);
91+
92+
return {
93+
parameters: inferredParameterTypes,
94+
returnType: inferredReturnType,
95+
};
96+
};

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ export * from './extraction/getTypeVariant';
77
export * from './extraction/getValueFromType';
88
export * from './suggestion/getValueSuggestions';
99
export * from './validation/getValueValidation';
10-
10+
export * from './extraction/getTypesFromNode';

test/getTypesFromNode.test.ts

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import {describe, expect, it} from 'vitest';
2+
import {getTypesFromNode} from '../src/extraction/getTypesFromNode';
3+
import {FUNCTION_SIGNATURES, DATA_TYPES} from "./data";
4+
5+
describe('getTypesFromNode', () => {
6+
it('should resolve types for std::list::at with string array', () => {
7+
const node = {
8+
functionDefinition: {
9+
identifier: "std::list::at" as any
10+
},
11+
parameters: {
12+
nodes: [{
13+
value: {
14+
__typename: "LiteralValue",
15+
value: ["a", "b", "c"]
16+
}
17+
}, {
18+
value: {
19+
__typename: "LiteralValue",
20+
value: 1
21+
}
22+
}]
23+
}
24+
};
25+
const result = getTypesFromNode(node as any, FUNCTION_SIGNATURES, DATA_TYPES);
26+
27+
console.log(result)
28+
29+
expect(result.returnType).toBe("string");
30+
expect(result.parameters).toContain("LIST<string>");
31+
expect(result.parameters).toContain("number");
32+
});
33+
34+
it('should resolve types for std::list::at with string array', () => {
35+
const node = {
36+
functionDefinition: {
37+
identifier: "std::list::at" as any
38+
},
39+
parameters: {
40+
nodes: [{
41+
value: null
42+
}, {
43+
value: {
44+
__typename: "LiteralValue",
45+
value: 1
46+
}
47+
}]
48+
}
49+
};
50+
const result = getTypesFromNode(node as any, FUNCTION_SIGNATURES, DATA_TYPES);
51+
52+
console.log(result)
53+
54+
expect(result.returnType).toBe("unknown");
55+
expect(result.parameters).toContain("LIST<unknown>");
56+
expect(result.parameters).toContain("number");
57+
});
58+
59+
it('should resolve types for std::math::add', () => {
60+
const node = {
61+
functionDefinition: {
62+
identifier: "std::math::add" as any
63+
},
64+
parameters: {
65+
nodes: [{
66+
value: {
67+
__typename: "LiteralValue",
68+
value: 5
69+
}
70+
}, {
71+
value: {
72+
__typename: "LiteralValue",
73+
value: 10
74+
}
75+
}]
76+
}
77+
};
78+
const result = getTypesFromNode(node as any, FUNCTION_SIGNATURES, DATA_TYPES);
79+
80+
expect(result.returnType).toBe("number");
81+
expect(result.parameters).toEqual(["number", "number"]);
82+
});
83+
84+
it('should return any for unknown function', () => {
85+
const node = {
86+
functionDefinition: {
87+
identifier: "unknown::func" as any
88+
}
89+
};
90+
const result = getTypesFromNode(node as any, FUNCTION_SIGNATURES, DATA_TYPES);
91+
92+
expect(result.returnType).toBe("any");
93+
expect(result.parameters).toEqual([]);
94+
});
95+
});
96+

0 commit comments

Comments
 (0)