Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / internal / lsp / protocol / typescript / util.ts
1
2 // for us typescript ignorati, having an import makes this file a module
3 import * as fs from 'fs';
4 import * as ts from 'typescript';
5
6 // This file contains various utilities having to do with producing strings
7 // and managing output
8
9 // ------ create files
10 let dir = process.env['HOME'];
11 const srcDir = '/vscode-languageserver-node'
12 export const fnames = [
13   `${dir}${srcDir}/protocol/src/common/protocol.ts`,
14   `${dir}/${srcDir}/protocol/src/browser/main.ts`, `${dir}${srcDir}/types/src/main.ts`,
15   `${dir}${srcDir}/jsonrpc/src/node/main.ts`
16 ];
17 export const gitHash = '60a5a7825e6f54f57917091f394fd8db7d1724bc'
18 let outFname = 'tsprotocol.go';
19 let fda: number, fdb: number, fde: number;  // file descriptors
20
21 export function createOutputFiles() {
22   fda = fs.openSync('/tmp/ts-a', 'w')  // dump of AST
23   fdb = fs.openSync('/tmp/ts-b', 'w')  // unused, for debugging
24   fde = fs.openSync(outFname, 'w')     // generated Go
25 }
26 export function pra(s: string) {
27   return (fs.writeSync(fda, s))
28 }
29 export function prb(s: string) {
30   return (fs.writeSync(fdb, s))
31 }
32 export function prgo(s: string) {
33   return (fs.writeSync(fde, s))
34 }
35
36 // Get the hash value of the git commit
37 export function git(): string {
38   let a = fs.readFileSync(`${dir}${srcDir}/.git/HEAD`).toString();
39   // ref: refs/heads/foo, or a hash like
40   // cc12d1a1c7df935012cdef5d085cdba04a7c8ebe
41   if (a.charAt(a.length - 1) == '\n') {
42     a = a.substring(0, a.length - 1);
43   }
44   if (a.length == 40) {
45     return a  // a hash
46   }
47   if (a.substring(0, 5) == 'ref: ') {
48     const fname = `${dir}${srcDir}/.git/` + a.substring(5);
49     let b = fs.readFileSync(fname).toString()
50     if (b.length == 41) {
51       return b.substring(0, 40);
52     }
53   }
54   throw new Error('failed to find the git commit hash')
55 }
56
57 // Produce a header for Go output files
58 export function computeHeader(pkgDoc: boolean): string {
59   let lastMod = 0
60   let lastDate: Date
61   for (const f of fnames) {
62     const st = fs.statSync(f)
63     if (st.mtimeMs > lastMod) {
64       lastMod = st.mtimeMs
65       lastDate = st.mtime
66     }
67   }
68   const a =
69     `// Package protocol contains data types and code for LSP jsonrpcs\n` +
70     `// generated automatically from vscode-languageserver-node\n` +
71     `// commit: ${gitHash}\n` +
72     `// last fetched ${lastDate}\n`
73   const b = 'package protocol\n'
74   const c = `\n// Code generated (see typescript/README.md) DO NOT EDIT.\n\n`
75   if (pkgDoc) {
76     return a + b + c
77   }
78   else {
79     return b + a + c
80   }
81 };
82
83 // Turn a typescript name into an exportable Go name, and appease lint
84 export function goName(s: string): string {
85   let ans = s
86   if (s.charAt(0) == '_') {
87     ans = 'Inner' + s.substring(1)
88   }
89   else { ans = s.substring(0, 1).toUpperCase() + s.substring(1) };
90   ans = ans.replace(/Uri$/, 'URI')
91   ans = ans.replace(/Id$/, 'ID')
92   return ans
93 }
94
95 // Generate JSON tag for a struct field
96 export function JSON(n: ts.PropertySignature): string {
97   const json = `\`json:"${n.name.getText()}${
98     n.questionToken != undefined ? ',omitempty' : ''}"\``;
99   return json
100 }
101
102 // Generate modifying prefixes and suffixes to ensure
103 // consts are unique. (Go consts are package-level, but Typescript's are
104 // not.) Use suffixes to minimize changes to gopls.
105 export function constName(nm: string, type: string): string {
106   let pref = new Map<string, string>([
107     ['DiagnosticSeverity', 'Severity'], ['WatchKind', 'Watch'],
108     ['SignatureHelpTriggerKind', 'Sig'], ['CompletionItemTag', 'Compl']
109   ])  // typeName->prefix
110   let suff = new Map<string, string>([
111     ['CompletionItemKind', 'Completion'], ['InsertTextFormat', 'TextFormat'],
112     ['SymbolTag', 'Symbol']
113   ])
114   let ans = nm;
115   if (pref.get(type)) ans = pref.get(type) + ans;
116   if (suff.has(type)) ans = ans + suff.get(type)
117   return ans
118 }
119
120 // Find the comments associated with an AST node
121 export function getComments(node: ts.Node): string {
122   const sf = node.getSourceFile();
123   const start = node.getStart(sf, false)
124   const starta = node.getStart(sf, true)
125   const x = sf.text.substring(starta, start)
126   return x
127 }
128
129
130 // --------- printing the AST, for debugging
131
132 export function printAST(program: ts.Program) {
133   // dump the ast, for debugging
134   const f = function (n: ts.Node) {
135     describe(n, pra)
136   };
137   for (const sourceFile of program.getSourceFiles()) {
138     if (!sourceFile.isDeclarationFile) {
139       // walk the tree to do stuff
140       ts.forEachChild(sourceFile, f);
141     }
142   }
143   pra('\n')
144   for (const key of Object.keys(seenThings).sort()) {
145     pra(`${key}: ${seenThings[key]} \n`)
146   }
147 }
148
149 // Used in printing the AST
150 let seenThings = new Map<string, number>();
151 function seenAdd(x: string) {
152   seenThings[x] = (seenThings[x] === undefined ? 1 : seenThings[x] + 1)
153 }
154
155 function describe(node: ts.Node, pr: (s: string) => any) {
156   if (node === undefined) {
157     return
158   }
159   let indent = '';
160
161   function f(n: ts.Node) {
162     seenAdd(kinds(n))
163     if (ts.isIdentifier(n)) {
164       pr(`${indent} ${loc(n)} ${strKind(n)} ${n.text} \n`)
165     }
166     else if (ts.isPropertySignature(n) || ts.isEnumMember(n)) {
167       pra(`${indent} ${loc(n)} ${strKind(n)} \n`)
168     }
169     else if (ts.isTypeLiteralNode(n)) {
170       let m = n.members
171       pr(`${indent} ${loc(n)} ${strKind(n)} ${m.length} \n`)
172     }
173     else if (ts.isStringLiteral(n)) {
174       pr(`${indent} ${loc(n)} ${strKind(n)} ${n.text} \n`)
175     }
176     else { pr(`${indent} ${loc(n)} ${strKind(n)} \n`) };
177     indent += ' .'
178     ts.forEachChild(n, f)
179     indent = indent.slice(0, indent.length - 2)
180   }
181   f(node)
182 }
183
184
185 // For debugging, say where an AST node is in a file
186 export function loc(node: ts.Node): string {
187   const sf = node.getSourceFile();
188   const start = node.getStart()
189   const x = sf.getLineAndCharacterOfPosition(start)
190   const full = node.getFullStart()
191   const y = sf.getLineAndCharacterOfPosition(full)
192   let fn = sf.fileName
193   const n = fn.search(/-node./)
194   fn = fn.substring(n + 6)
195   return `${fn} ${x.line + 1}: ${x.character + 1} (${y.line + 1}: ${
196     y.character + 1})`
197 }
198 // --- various string stuff
199
200 // return a string of the kinds of the immediate descendants
201 // as part of printing the AST tree
202 function kinds(n: ts.Node): string {
203   let res = 'Seen ' + strKind(n);
204   function f(n: ts.Node): void { res += ' ' + strKind(n) };
205   ts.forEachChild(n, f)
206   return res
207 }
208
209 // What kind of AST node is it? This would just be typescript's
210 // SyntaxKind[n.kind] except that the default names for some nodes
211 // are misleading
212 export function strKind(n: ts.Node): string {
213   if (n == null || n == undefined) {
214     return 'null'
215   }
216   const x = ts.SyntaxKind[n.kind];
217   // some of these have two names
218   switch (x) {
219     default:
220       return x;
221     case 'FirstAssignment':
222       return 'EqualsToken';
223     case 'FirstBinaryOperator':
224       return 'LessThanToken';
225     case 'FirstCompoundAssignment':
226       return 'PlusEqualsToken';
227     case 'FirstContextualKeyword':
228       return 'AbstractKeyword';
229     case 'FirstLiteralToken':
230       return 'NumericLiteral';
231     case 'FirstNode':
232       return 'QualifiedName';
233     case 'FirstTemplateToken':
234       return 'NoSubstitutionTemplateLiteral';
235     case 'LastTemplateToken':
236       return 'TemplateTail';
237     case 'FirstTypeNode':
238       return 'TypePredicate';
239   }
240 }