generate-stubs.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. const fs = require("fs")
  2. const path = require("path")
  3. const { Project, SyntaxKind } = require("ts-morph")
  4. function traverse(container, output, prefix = "") {
  5. for (const node of container.getStatements()) {
  6. const kind = node.getKind()
  7. if (kind === SyntaxKind.ModuleDeclaration) {
  8. const name = node.getName().replace(/^['"]|['"]$/g, "")
  9. var fullPrefix
  10. if (prefix) {
  11. fullPrefix = `${prefix}.${name}`
  12. } else {
  13. fullPrefix = name
  14. }
  15. output.push(`${fullPrefix} = {};`)
  16. const body = node.getBody()
  17. if (body && body.getKind() === SyntaxKind.ModuleBlock) {
  18. traverse(body, output, fullPrefix)
  19. }
  20. } else if (kind === SyntaxKind.FunctionDeclaration) {
  21. const name = node.getName()
  22. const params = node.getParameters().map((p, i) => sanitizeParam(p.getName(), i))
  23. const typeNode = node.getReturnTypeNode()
  24. const returnType = typeNode ? typeNode.getText() : ""
  25. const ret = mapReturn(returnType)
  26. output.push(
  27. `${prefix}.${name} = function(${params.join(", ")}) { console.log('Called stubbed function: ${prefix}.${name}'); ${ret} };`,
  28. )
  29. } else if (kind === SyntaxKind.EnumDeclaration) {
  30. const name = node.getName()
  31. const members = node.getMembers().map((m) => m.getName())
  32. output.push(`${prefix}.${name} = { ${members.map((m) => `${m}: 0`).join(", ")} };`)
  33. } else if (kind === SyntaxKind.VariableStatement) {
  34. for (const decl of node.getDeclarations()) {
  35. const name = decl.getName()
  36. output.push(`${prefix}.${name} = createStub("${prefix}.${name}");`)
  37. }
  38. } else if (kind === SyntaxKind.ClassDeclaration) {
  39. const name = node.getName()
  40. output.push(
  41. `${prefix}.${name} = class { constructor(...args) {
  42. console.log('Constructed stubbed class: new ${prefix}.${name}(', args, ')');
  43. return createStub(${prefix}.${name});
  44. }};`,
  45. )
  46. } else if (kind === SyntaxKind.TypeAliasDeclaration || kind === SyntaxKind.InterfaceDeclaration) {
  47. //console.log("Skipping", SyntaxKind[kind], node.getName())
  48. // Skip interfaces and type aliases because they are only used at compile time by typescript.
  49. } else {
  50. console.log("Can't handle: ", SyntaxKind[kind])
  51. }
  52. }
  53. }
  54. function mapReturn(typeStr) {
  55. if (!typeStr) {
  56. return ""
  57. }
  58. if (typeStr.includes("void")) {
  59. return ""
  60. }
  61. if (typeStr.includes("string")) {
  62. return `return '';`
  63. }
  64. if (typeStr.includes("number")) {
  65. return `return 0;`
  66. }
  67. if (typeStr.includes("boolean")) {
  68. return `return false;`
  69. }
  70. if (typeStr.includes("[]")) {
  71. return `return [];`
  72. }
  73. if (typeStr.includes("Thenable")) {
  74. return `return Promise.resolve(null);`
  75. }
  76. return `return createStub("unknown");`
  77. }
  78. function sanitizeParam(name, index) {
  79. return name || `arg${index}`
  80. }
  81. async function main() {
  82. const inputPath = "node_modules/@types/vscode/index.d.ts"
  83. const outputPath = "standalone/runtime-files/vscode/vscode-stubs.js"
  84. const project = new Project()
  85. const sourceFile = project.addSourceFileAtPath(inputPath)
  86. const output = []
  87. output.push("// GENERATED CODE -- DO NOT EDIT!")
  88. output.push('console.log("Loading stubs...");')
  89. output.push('const { createStub } = require("./stub-utils")')
  90. traverse(sourceFile, output)
  91. output.push("module.exports = vscode;")
  92. output.push('console.log("Finished loading stubs");')
  93. fs.mkdirSync(path.dirname(outputPath), { recursive: true })
  94. fs.writeFileSync(outputPath, output.join("\n"))
  95. console.log(`Wrote vscode SDK stubs to ${outputPath}`)
  96. }
  97. main().catch((err) => {
  98. console.error(err)
  99. process.exit(1)
  100. })