some deletions
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / internal / lsp / protocol / typescript / code.ts
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201028153306-37f0764111ff/internal/lsp/protocol/typescript/code.ts b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201028153306-37f0764111ff/internal/lsp/protocol/typescript/code.ts
deleted file mode 100644 (file)
index 39cea15..0000000
+++ /dev/null
@@ -1,1178 +0,0 @@
-// read files from vscode-languageserver-node, and generate Go rpc stubs
-// and data definitions. (and maybe someday unmarshaling code)
-
-// The output is 3 files, tsprotocol.go contains the type definitions
-// while tsclient.go and tsserver.go contain the LSP API and stub. An LSP server
-// uses both APIs. To read the code, start in this file's main() function.
-
-// The code is rich in heuristics and special cases, some of which are to avoid
-// extensive changes to gopls, and some of which are due to the mismatch between
-// typescript and Go types. In particular, there is no Go equivalent to union
-// types, so each case ought to be considered separately. The Go equivalent of A
-// & B could frequently be struct{A;B;}, or it could be the equivalent type
-// listing all the members of A and B. Typically the code uses the former, but
-// especially if A and B have elements with the same name, it does a version of
-// the latter. ClientCapabilities has to be expanded, and ServerCapabilities is
-// expanded to make the generated code easier to read.
-
-// for us typescript ignorati, having an import makes this file a module
-import * as fs from 'fs';
-import * as ts from 'typescript';
-import * as u from './util';
-import { constName, getComments, goName, loc, strKind } from './util';
-
-var program: ts.Program;
-
-function parse() {
-  // this won't complain if some fnames don't exist
-  program = ts.createProgram(
-    u.fnames,
-    { target: ts.ScriptTarget.ES2018, module: ts.ModuleKind.CommonJS });
-  program.getTypeChecker();  // finish type checking and assignment
-}
-
-// ----- collecting information for RPCs
-let req = new Map<string, ts.NewExpression>();               // requests
-let not = new Map<string, ts.NewExpression>();               // notifications
-let ptypes = new Map<string, [ts.TypeNode, ts.TypeNode]>();  // req, resp types
-let receives = new Map<string, 'server' | 'client'>();         // who receives it
-let rpcTypes = new Set<string>();  // types seen in the rpcs
-
-function findRPCs(node: ts.Node) {
-  if (!ts.isModuleDeclaration(node)) {
-    return
-  }
-  if (!ts.isIdentifier(node.name)) {
-    throw new Error(
-      `expected Identifier, got ${strKind(node.name)} at ${loc(node)}`)
-  }
-  let reqnot = req
-  let v = node.name.getText()
-  if (v.endsWith('Notification')) reqnot = not;
-  else if (!v.endsWith('Request')) return;
-
-  if (!ts.isModuleBlock(node.body)) {
-    throw new Error(
-      `expected ModuleBody got ${strKind(node.body)} at ${loc(node)}`)
-  }
-  let x: ts.ModuleBlock = node.body
-  // The story is to expect const method = 'textDocument/implementation'
-  // const type = new ProtocolRequestType<...>(method)
-  // but the method may be an explicit string
-  let rpc: string = '';
-  let newNode: ts.NewExpression;
-  for (let i = 0; i < x.statements.length; i++) {
-    const uu = x.statements[i];
-    if (!ts.isVariableStatement(uu)) continue;
-    const dl: ts.VariableDeclarationList = uu.declarationList;
-    if (dl.declarations.length != 1)
-      throw new Error(`expected a single decl at ${loc(dl)}`);
-    const decl: ts.VariableDeclaration = dl.declarations[0];
-    const name = decl.name.getText()
-    // we want the initializers
-    if (name == 'method') {  // mostly StringLiteral but NoSubstitutionTemplateLiteral in protocol.semanticTokens.ts
-      if (!ts.isStringLiteral(decl.initializer)) {
-        if (!ts.isNoSubstitutionTemplateLiteral(decl.initializer)) {
-          console.log(`${decl.initializer.getText()}`);
-          throw new Error(`expect StringLiteral at ${loc(decl)} got ${strKind(decl.initializer)}`);
-        }
-      }
-      rpc = decl.initializer.getText()
-    }
-    else if (name == 'type') {  // NewExpression
-      if (!ts.isNewExpression(decl.initializer))
-        throw new Error(`expecte new at ${loc(decl)}`);
-      const nn: ts.NewExpression = decl.initializer
-      newNode = nn
-      const mtd = nn.arguments[0];
-      if (ts.isStringLiteral(mtd)) rpc = mtd.getText();
-      switch (nn.typeArguments.length) {
-        case 1:  // exit
-          ptypes.set(rpc, [nn.typeArguments[0], null])
-          break;
-        case 2:  // notifications
-          ptypes.set(rpc, [nn.typeArguments[0], null])
-          break;
-        case 4:  // request with no parameters
-          ptypes.set(rpc, [null, nn.typeArguments[0]])
-          break;
-        case 5:  // request req, resp, partial(?)
-          ptypes.set(rpc, [nn.typeArguments[0], nn.typeArguments[1]])
-          break;
-        default:
-          throw new Error(`${nn.typeArguments.length} at ${loc(nn)}`)
-      }
-    }
-  }
-  if (rpc == '') throw new Error(`no name found at ${loc(x)}`);
-  // remember the implied types
-  const [a, b] = ptypes.get(rpc);
-  const add = function (n: ts.Node) {
-    rpcTypes.add(goName(n.getText()))
-  };
-  underlying(a, add);
-  underlying(b, add);
-  rpc = rpc.substring(1, rpc.length - 1);  // 'exit'
-  reqnot.set(rpc, newNode)
-}
-
-// handle missing typeArguments
-function lookUp(n: ts.NewExpression): ts.NodeArray<ts.TypeNode> {
-  // parent should be VariableDeclaration. its children should be
-  // Identifier('type') ???
-  // TypeReference: [Identifier('RequestType1), ]
-  // NewExpression (us)
-  const p = n.parent;
-  if (!ts.isVariableDeclaration(p)) throw new Error(`not variable decl`);
-  const tr = p.type;
-  if (!ts.isTypeReferenceNode(tr)) throw new Error(`not TypeReference`);
-  return tr.typeArguments;
-}
-
-function setReceives() {
-  // mark them all as server, then adjust the client ones.
-  // it would be nice to have some independent check on this
-  // (this logic fails if the server ever sends $/canceRequest
-  //  or $/progress)
-  req.forEach((_, k) => { receives.set(k, 'server') });
-  not.forEach((_, k) => { receives.set(k, 'server') });
-  receives.set('window/showMessage', 'client');
-  receives.set('window/showMessageRequest', 'client');
-  receives.set('window/logMessage', 'client');
-  receives.set('telemetry/event', 'client');
-  receives.set('client/registerCapability', 'client');
-  receives.set('client/unregisterCapability', 'client');
-  receives.set('workspace/workspaceFolders', 'client');
-  receives.set('workspace/configuration', 'client');
-  receives.set('workspace/applyEdit', 'client');
-  receives.set('textDocument/publishDiagnostics', 'client');
-  receives.set('window/workDoneProgress/create', 'client');
-  receives.set('$/progress', 'client');
-  // a small check
-  receives.forEach((_, k) => {
-    if (!req.get(k) && !not.get(k)) throw new Error(`missing ${k}}`);
-    if (req.get(k) && not.get(k)) throw new Error(`dup ${k}`);
-  })
-}
-
-interface Data {
-  me: ts.Node;   // root node for this type
-  name: string;  // Go name
-  generics: ts.NodeArray<ts.TypeParameterDeclaration>;
-  as: ts.NodeArray<ts.HeritageClause>;  // inheritance
-  // Interface
-  properties: ts.NodeArray<ts.TypeElement>;  // ts.PropertySignature
-  alias: ts.TypeNode;                        // type alias
-  // module
-  statements: ts.NodeArray<ts.Statement>;
-  enums: ts.NodeArray<ts.EnumMember>;
-  // class
-  members: ts.NodeArray<ts.PropertyDeclaration>;
-}
-function newData(n: ts.Node, nm: string): Data {
-  return {
-    me: n, name: goName(nm),
-    generics: ts.createNodeArray<ts.TypeParameterDeclaration>(), as: ts.createNodeArray<ts.HeritageClause>(),
-    properties: ts.createNodeArray<ts.TypeElement>(), alias: undefined,
-    statements: ts.createNodeArray<ts.Statement>(),
-    enums: ts.createNodeArray<ts.EnumMember>(),
-    members: ts.createNodeArray<ts.PropertyDeclaration>(),
-  }
-}
-
-// for debugging, produce a skeleton description
-function strData(d: Data): string {
-  const f = function (na: ts.NodeArray<any>): number {
-    return na.length
-  };
-  return `D(${d.name}) g;${f(d.generics)} a:${f(d.as)} p:${f(d.properties)} s:${
-    f(d.statements)} e:${f(d.enums)} m:${f(d.members)} ${
-    d.alias != undefined}`
-}
-
-let data = new Map<string, Data>();            // parsed data types
-let seenTypes = new Map<string, Data>();       // type names we've seen
-let extraTypes = new Map<string, string[]>();  // to avoid struct params
-
-// look at top level data definitions
-function genTypes(node: ts.Node) {
-  // Ignore top-level items that can't produce output
-  if (ts.isExpressionStatement(node) || ts.isFunctionDeclaration(node) ||
-    ts.isImportDeclaration(node) || ts.isVariableStatement(node) ||
-    ts.isExportDeclaration(node) || ts.isEmptyStatement(node) ||
-    ts.isExportAssignment(node) || ts.isImportEqualsDeclaration(node) ||
-    ts.isBlock(node) || node.kind == ts.SyntaxKind.EndOfFileToken) {
-    return;
-  }
-  if (ts.isInterfaceDeclaration(node)) {
-    const v: ts.InterfaceDeclaration = node;
-    // need to check the members, many of which are disruptive
-    let mems: ts.TypeElement[] = [];
-    const f = function (t: ts.TypeElement) {
-      if (ts.isPropertySignature(t)) {
-        mems.push(t);
-      } else if (ts.isMethodSignature(t) || ts.isCallSignatureDeclaration(t)) {
-        return;
-      } else if (ts.isIndexSignatureDeclaration(t)) {
-        // probably safe to ignore these
-        // [key: string]: boolean | number | string | undefined;
-        // and InitializeResult: [custom: string]: any;]
-        return
-      } else
-        throw new Error(`217 unexpected ${strKind(t)}`)
-    };
-    v.members.forEach(f);
-    if (mems.length == 0 && !v.heritageClauses &&
-      v.name.getText() != 'InitializedParams') {
-      return  // really? (Don't seem to need any of these)
-    };
-    // Found one we want
-    let x = newData(v, goName(v.name.getText()));
-    x.properties = ts.createNodeArray<ts.TypeElement>(mems);
-    if (v.typeParameters) x.generics = v.typeParameters;
-    if (v.heritageClauses) x.as = v.heritageClauses;
-    if (x.generics.length > 1) {  // Unneeded
-      // Item interface Item<K, V>...
-      return
-    };
-    if (data.has(x.name)) {  // modifying one we've seen
-      x = dataMerge(x, data.get(x.name));
-    }
-    data.set(x.name, x);
-  } else if (ts.isTypeAliasDeclaration(node)) {
-    const v: ts.TypeAliasDeclaration = node;
-    let x = newData(v, v.name.getText());
-    x.alias = v.type;
-    // if type is a union of constants, we (mostly) don't want it
-    // (at the top level)
-    // Unfortunately this is false for TraceValues
-    if (ts.isUnionTypeNode(v.type) &&
-      v.type.types.every((n: ts.TypeNode) => ts.isLiteralTypeNode(n))) {
-      if (x.name != 'TraceValues') return;
-    }
-    if (v.typeParameters) {
-      x.generics = v.typeParameters;
-    }
-    if (data.has(x.name)) x = dataMerge(x, data.get(x.name));
-    if (x.generics.length > 1) {
-      return
-    };
-    data.set(x.name, x);
-  } else if (ts.isModuleDeclaration(node)) {
-    const v: ts.ModuleDeclaration = node;
-    if (!ts.isModuleBlock(v.body)) {
-      throw new Error(`${loc(v)} not ModuleBlock, but ${strKind(v.body)}`)
-    }
-    const b: ts.ModuleBlock = v.body;
-    var s: ts.Statement[] = [];
-    // we don't want most of these
-    const fx = function (x: ts.Statement) {
-      if (ts.isFunctionDeclaration(x)) {
-        return
-      };
-      if (ts.isTypeAliasDeclaration(x) || ts.isModuleDeclaration(x)) {
-        return
-      };
-      if (!ts.isVariableStatement(x))
-        throw new Error(
-          `expected VariableStatment ${loc(x)} ${strKind(x)} ${x.getText()}`);
-      if (hasNewExpression(x)) {
-        return
-      };
-      s.push(x);
-    };
-    b.statements.forEach(fx)
-    if (s.length == 0) {
-      return
-    };
-    let m = newData(node, v.name.getText());
-    m.statements = ts.createNodeArray<ts.Statement>(s);
-    if (data.has(m.name)) m = dataMerge(m, data.get(m.name));
-    data.set(m.name, m);
-  } else if (ts.isEnumDeclaration(node)) {
-    const nm = node.name.getText();
-    let v = newData(node, nm);
-    v.enums = node.members;
-    if (data.has(nm)) {
-      v = dataMerge(v, data.get(nm));
-    }
-    data.set(nm, v);
-  } else if (ts.isClassDeclaration(node)) {
-    const v: ts.ClassDeclaration = node;
-    var d: ts.PropertyDeclaration[] = [];
-    // look harder at the PropertyDeclarations.
-    const wanted = function (c: ts.ClassElement): string {
-      if (ts.isConstructorDeclaration(c)) {
-        return ''
-      };
-      if (ts.isMethodDeclaration(c)) {
-        return ''
-      };
-      if (ts.isGetAccessor(c)) {
-        return ''
-      };
-      if (ts.isSetAccessor(c)) {
-        return ''
-      };
-      if (ts.isPropertyDeclaration(c)) {
-        d.push(c);
-        return strKind(c)
-      };
-      throw new Error(`Class decl ${strKind(c)} `)
-    };
-    v.members.forEach((c, i) => wanted(c));
-    if (d.length == 0) {
-      return
-    };  // don't need it, maybe
-    let c = newData(v, v.name.getText());
-    c.members = ts.createNodeArray<ts.PropertyDeclaration>(d);
-    if (v.typeParameters) {
-      c.generics = v.typeParameters
-    }
-    if (c.generics.length > 1) {
-      return
-    }
-    if (v.heritageClauses) {
-      c.as = v.heritageClauses
-    }
-    if (data.has(c.name))
-      throw new Error(`Class dup ${loc(c.me)} and ${loc(data.get(c.name).me)}`);
-    data.set(c.name, c);
-  } else {
-    throw new Error(`338 unexpected ${strKind(node)} ${loc(node)} `)
-  }
-}
-
-// Typescript can accumulate
-function dataMerge(a: Data, b: Data): Data {
-  // maybe they are textually identical? (it happens)
-  const [at, bt] = [a.me.getText(), b.me.getText()];
-  if (at == bt) {
-    return a;
-  }
-  const ax = `(${a.statements.length},${a.properties.length})`
-  const bx = `(${b.statements.length},${b.properties.length})`
-  switch (a.name) {
-    case 'InitializeError':
-    case 'MessageType':
-    case 'CompletionItemTag':
-    case 'SymbolTag':
-    case 'CodeActionKind':
-      // want the Module
-      return a.statements.length > 0 ? a : b;
-    case 'CancellationToken':
-    case 'CancellationStrategy':
-      // want the Interface
-      return a.properties.length > 0 ? a : b;
-    case 'TextDocumentContentChangeEvent':  // almost the same
-    case 'TokenFormat':
-      return a;
-  }
-  console.log(
-    `367 ${strKind(a.me)} ${strKind(b.me)} ${a.name} ${loc(a.me)} ${loc(b.me)}`)
-  throw new Error(`Fix dataMerge for ${a.name}`)
-}
-
-// is a node an ancestor of a NewExpression
-function hasNewExpression(n: ts.Node): boolean {
-  let ans = false;
-  n.forEachChild((n: ts.Node) => {
-    if (ts.isNewExpression(n)) ans = true;
-  })
-  return ans
-}
-
-function checkOnce() {
-  // Data for all the rpc types?
-  rpcTypes.forEach(s => {
-    if (!data.has(s)) throw new Error(`checkOnce, ${s}?`)
-  });
-}
-
-// helper function to find underlying types
-function underlying(n: ts.Node, f: (n: ts.Node) => void) {
-  if (!n) return;
-  const ff = function (n: ts.Node) {
-    underlying(n, f)
-  };
-  if (ts.isIdentifier(n)) {
-    f(n)
-  } else if (
-    n.kind == ts.SyntaxKind.StringKeyword ||
-    n.kind == ts.SyntaxKind.NumberKeyword ||
-    n.kind == ts.SyntaxKind.AnyKeyword ||
-    n.kind == ts.SyntaxKind.NullKeyword ||
-    n.kind == ts.SyntaxKind.BooleanKeyword ||
-    n.kind == ts.SyntaxKind.ObjectKeyword ||
-    n.kind == ts.SyntaxKind.VoidKeyword) {
-    // nothing to do
-  } else if (ts.isTypeReferenceNode(n)) {
-    f(n.typeName)
-  } else if (ts.isArrayTypeNode(n)) {
-    underlying(n.elementType, f)
-  } else if (ts.isHeritageClause(n)) {
-    n.types.forEach(ff);
-  } else if (ts.isExpressionWithTypeArguments(n)) {
-    underlying(n.expression, f)
-  } else if (ts.isPropertySignature(n)) {
-    underlying(n.type, f)
-  } else if (ts.isTypeLiteralNode(n)) {
-    n.members.forEach(ff)
-  } else if (ts.isUnionTypeNode(n) || ts.isIntersectionTypeNode(n)) {
-    n.types.forEach(ff)
-  } else if (ts.isIndexSignatureDeclaration(n)) {
-    underlying(n.type, f)
-  } else if (ts.isParenthesizedTypeNode(n)) {
-    underlying(n.type, f)
-  } else if (
-    ts.isLiteralTypeNode(n) || ts.isVariableStatement(n) ||
-    ts.isTupleTypeNode(n)) {
-    // we only see these in moreTypes, but they are handled elsewhere
-    return;
-  } else if (ts.isEnumMember(n)) {
-    if (ts.isStringLiteral(n.initializer)) return;
-    throw new Error(`EnumMember ${strKind(n.initializer)} ${n.name.getText()}`)
-  } else {
-    throw new Error(`saw ${strKind(n)} in underlying. ${n.getText()}`)
-  }
-}
-
-// find all the types implied by seenTypes.
-// Simplest way to the transitive closure is to stabilize the size of seenTypes
-// but it is slow
-function moreTypes() {
-  const extra = function (s: string) {
-    if (!data.has(s)) throw new Error(`moreTypes needs ${s}`);
-    seenTypes.set(s, data.get(s))
-  };
-  rpcTypes.forEach(extra);  // all the types needed by the rpcs
-  // needed in enums.go (or elsewhere)
-  extra('InitializeError')
-  extra('WatchKind')
-  extra('FoldingRangeKind')
-  // not sure why these weren't picked up
-  extra('FileSystemWatcher')
-  extra('DidChangeWatchedFilesRegistrationOptions')
-  extra('WorkDoneProgressBegin')
-  extra('WorkDoneProgressReport')
-  extra('WorkDoneProgressEnd')
-  let old = 0
-  do {
-    old = seenTypes.size
-
-    const m = new Map<string, Data>();
-    const add = function (n: ts.Node) {
-      const nm = goName(n.getText());
-      if (seenTypes.has(nm) || m.has(nm)) return;
-      // For generic parameters, this might set it to undefined
-      m.set(nm, data.get(nm));
-    };
-    // expect all the heritage clauses have single Identifiers
-    const h = function (n: ts.Node) {
-      underlying(n, add);
-    };
-    const f = function (x: ts.NodeArray<ts.Node>) {
-      x.forEach(h)
-    };
-    seenTypes.forEach((d: Data) => d && f(d.as))
-    // find the types in the properties
-    seenTypes.forEach((d: Data) => d && f(d.properties))
-    // and in the alias and in the statements and in the enums
-    seenTypes.forEach((d: Data) => d && underlying(d.alias, add))
-    seenTypes.forEach((d: Data) => d && f(d.statements))
-    seenTypes.forEach((d: Data) => d && f(d.enums))
-    m.forEach((d, k) => seenTypes.set(k, d))
-  }
-  while (seenTypes.size != old)
-    ;
-}
-
-let typesOut = new Array<string>();
-let constsOut = new Array<string>();
-
-// generate Go types
-function toGo(d: Data, nm: string) {
-  if (!d) return;  // this is probably a generic T
-  if (d.alias) {
-    goTypeAlias(d, nm);
-  } else if (d.statements.length > 0) {
-    goModule(d, nm);
-  } else if (d.enums.length > 0) {
-    goEnum(d, nm);
-  } else if (
-    d.properties.length > 0 || d.as.length > 0 || nm == 'InitializedParams') {
-    goInterface(d, nm);
-  } else
-    throw new Error(
-      `more cases in toGo ${nm} ${d.as.length} ${d.generics.length} `)
-}
-
-// these fields need a *
-var starred: [string, string][] = [
-  ['TextDocumentContentChangeEvent', 'range'], ['CodeAction', 'command'],
-  ['DidSaveTextDocumentParams', 'text'], ['CompletionItem', 'command']
-];
-
-// generate Go code for an interface
-function goInterface(d: Data, nm: string) {
-  let ans = `type ${goName(nm)} struct {\n`;
-
-  // generate the code for each member
-  const g = function (n: ts.TypeElement) {
-    if (!ts.isPropertySignature(n))
-      throw new Error(`expected PropertySignature got ${strKind(n)} `);
-    ans = ans.concat(getComments(n));
-    const json = u.JSON(n);
-    // SelectionRange is a recursive type
-    let gt = goType(n.type, n.name.getText(), nm);
-    if (gt == d.name) gt = '*' + gt;  // avoid recursive types
-    // there are several cases where a * is needed
-    starred.forEach(([a, b]) => {
-      if (d.name == a && n.name.getText() == b) {
-        gt = '*' + gt;
-      };
-    })
-    ans = ans.concat(`${goName(n.name.getText())} ${gt}`, json, '\n')
-  };
-  d.properties.forEach(g)
-  // heritage clauses become embedded types
-  // check they are all Identifiers
-  const f = function (n: ts.ExpressionWithTypeArguments) {
-    if (!ts.isIdentifier(n.expression))
-      throw new Error(`Interface ${nm} heritage ${strKind(n.expression)} `);
-    ans = ans.concat(goName(n.expression.getText()), '\n')
-  };
-  d.as.forEach((n: ts.HeritageClause) => n.types.forEach(f))
-  ans = ans.concat(`}\n`);
-  typesOut.push(getComments(d.me))
-  typesOut.push(ans)
-}
-
-// generate Go code for a module (const declarations)
-// Generates type definitions, and named constants
-function goModule(d: Data, nm: string) {
-  if (d.generics.length > 0 || d.as.length > 0) {
-    throw new Error(`goModule: unexpected for ${nm}
-  `)
-  }
-  // all the statements should be export const <id>: value
-  //   or value = value
-  // They are VariableStatements with x.declarationList having a single
-  //   VariableDeclaration
-  let isNumeric = false;
-  const f = function (n: ts.Statement, i: number) {
-    if (!ts.isVariableStatement(n)) {
-      throw new Error(` ${nm} ${i} expected VariableStatement,
-      got ${strKind(n)}`);
-    }
-    const c = getComments(n)
-    const v = n.declarationList.declarations[0];  // only one
-
-    if (!v.initializer)
-      throw new Error(`no initializer ${nm} ${i} ${v.name.getText()}`);
-    isNumeric = strKind(v.initializer) == 'NumericLiteral';
-    if (c != '') constsOut.push(c);  // no point if there are no comments
-    // There are duplicates.
-    const cname = constName(goName(v.name.getText()), nm);
-    let val = v.initializer.getText()
-    val = val.split('\'').join('"')  // useless work for numbers
-    constsOut.push(`${cname} ${nm} = ${val}`)
-  };
-  d.statements.forEach(f)
-  typesOut.push(getComments(d.me))
-  // Or should they be type aliases?
-  typesOut.push(`type ${nm} ${isNumeric ? 'float64' : 'string'}`)
-}
-
-// generate Go code for an enum. Both types and named constants
-function goEnum(d: Data, nm: string) {
-  let isNumeric = false
-  const f = function (v: ts.EnumMember, j: number) {  // same as goModule
-    if (!v.initializer)
-      throw new Error(`goEnum no initializer ${nm} ${j} ${v.name.getText()}`);
-    isNumeric = strKind(v.initializer) == 'NumericLiteral';
-    const c = getComments(v);
-    const cname = constName(goName(v.name.getText()), nm);
-    let val = v.initializer.getText()
-    val = val.split('\'').join('"')  // replace quotes. useless work for numbers
-    constsOut.push(`${c}${cname} ${nm} = ${val}`)
-  };
-  d.enums.forEach(f)
-  typesOut.push(getComments(d.me))
-  // Or should they be type aliases?
-  typesOut.push(`type ${nm} ${isNumeric ? 'float64' : 'string'}`)
-}
-
-// generate code for a type alias
-function goTypeAlias(d: Data, nm: string) {
-  if (d.as.length != 0 || d.generics.length != 0) {
-    if (nm != 'ServerCapabilities')
-      throw new Error(`${nm} has extra fields(${d.as.length},${
-        d.generics.length}) ${d.me.getText()}`);
-  }
-  typesOut.push(getComments(d.me))
-  // d.alias doesn't seem to have comments
-  let aliasStr = goName(nm) == 'DocumentURI' ? ' ' : ' = '
-  typesOut.push(`type ${goName(nm)}${aliasStr}${goType(d.alias, nm)}\n`)
-}
-
-// return a go type and maybe an assocated javascript tag
-function goType(n: ts.TypeNode, nm: string, parent?: string): string {
-  if (n.getText() == 'T') return 'interface{}';  // should check it's generic
-  if (ts.isTypeReferenceNode(n)) {
-    return goName(n.typeName.getText());  // avoid <T>
-  } else if (ts.isUnionTypeNode(n)) {
-    return goUnionType(n, nm, parent);
-  } else if (ts.isIntersectionTypeNode(n)) {
-    return goIntersectionType(n, nm);
-  } else if (strKind(n) == 'StringKeyword') {
-    return 'string';
-  } else if (strKind(n) == 'NumberKeyword') {
-    return 'float64';
-  } else if (strKind(n) == 'BooleanKeyword') {
-    return 'bool';
-  } else if (strKind(n) == 'AnyKeyword') {
-    return 'interface{}';
-  } else if (strKind(n) == 'NullKeyword') {
-    return 'nil'
-  } else if (strKind(n) == 'VoidKeyword' || strKind(n) == 'NeverKeyword') {
-    return 'void'
-  } else if (strKind(n) == 'ObjectKeyword') {
-    return 'interface{}'
-  } else if (ts.isArrayTypeNode(n)) {
-    if (nm === 'arguments') {
-      // Command and ExecuteCommandParams
-      return '[]json.RawMessage';
-    }
-    return `[]${goType(n.elementType, nm)}`
-  } else if (ts.isParenthesizedTypeNode(n)) {
-    return goType(n.type, nm)
-  } else if (ts.isLiteralTypeNode(n)) {
-    return strKind(n.literal) == 'StringLiteral' ? 'string' : 'float64';
-  } else if (ts.isTypeLiteralNode(n)) {
-    // these are anonymous structs
-    const v = goTypeLiteral(n, nm);
-    return v
-  } else if (ts.isTupleTypeNode(n)) {
-    if (n.getText() == '[number, number]') return '[]float64';
-    throw new Error(`goType unexpected Tuple ${n.getText()}`)
-  }
-  throw new Error(`${strKind(n)} goType unexpected ${n.getText()} for ${nm}`)
-}
-
-// The choice is uniform interface{}, or some heuristically assigned choice,
-// or some better sytematic idea I haven't thought of. Using interface{}
-// is, in practice, impossibly complex in the existing code.
-function goUnionType(n: ts.UnionTypeNode, nm: string, parent?: string): string {
-  let help = `/*${n.getText()}*/`  // show the original as a comment
-  // There are some bad cases with newlines:
-  // range?: boolean | {\n     };
-  // full?: boolean | {\n              /**\n            * The server supports deltas for full documents.\n              */\n           delta?: boolean;\n      }
-  // These are handled specially:
-  if (parent == 'SemanticTokensOptions') {
-    if (nm == 'range') help = help.replace(/\n/, '');
-    if (nm == 'full') help = '/*boolean | <elided struct>*/';
-  }
-  // handle all the special cases
-  switch (n.types.length) {
-    case 2:
-      const a = strKind(n.types[0])
-      const b = strKind(n.types[1])
-      if (a == 'NumberKeyword' && b == 'StringKeyword') {  // ID
-        return `interface{} ${help}`
-      }
-      if (b == 'NullKeyword') {
-        if (nm == 'textDocument/codeAction') {
-          // (Command | CodeAction)[] | null
-          return `[]CodeAction ${help}`
-        }
-        let v = goType(n.types[0], 'a')
-        if (v.startsWith(`[]interface`)) v = v.slice(2, v.length)
-        return `${v} ${help}`
-      }
-      if (a == 'BooleanKeyword') {  // usually want bool
-        if (nm == 'codeActionProvider') return `interface{} ${help}`;
-        if (nm == 'renameProvider') return `interface{} ${help}`;
-        if (nm == 'save') return `${goType(n.types[1], '680')} ${help}`;
-        return `${goType(n.types[0], 'b')} ${help}`
-      }
-      if (b == 'ArrayType') return `${goType(n.types[1], 'c')} ${help}`;
-      if (help.includes('InsertReplaceEdit') && n.types[0].getText() == 'TextEdit') {
-        return `*TextEdit ${help}`
-      }
-      if (a == 'TypeReference' && a == b) return `interface{} ${help}`;
-      if (a == 'StringKeyword') return `string ${help}`;
-      if (a == 'TypeLiteral' && nm == 'TextDocumentContentChangeEvent') {
-        return `${goType(n.types[0], nm)}`
-      }
-      throw new Error(`691 ${a} ${b} ${n.getText()} ${loc(n)}`);
-    case 3:
-      const aa = strKind(n.types[0])
-      const bb = strKind(n.types[1])
-      const cc = strKind(n.types[2])
-      if (nm == 'textDocument/prepareRename') {
-        // want Range, not interface{}
-        return `${goType(n.types[0], nm)} ${help}`
-      }
-      if (nm == 'DocumentFilter') {
-        // not really a union. the first is enough, up to a missing
-        // omitempty but avoid repetitious comments
-        return `${goType(n.types[0], 'g')}`
-      }
-      if (nm == 'textDocument/documentSymbol') {
-        return `[]interface{} ${help}`
-      }
-      if (aa == 'TypeReference' && bb == 'ArrayType' && cc == 'NullKeyword') {
-        return `${goType(n.types[0], 'd')} ${help}`
-      }
-      if (aa == 'TypeReference' && bb == aa && cc == 'ArrayType') {
-        // should check that this is Hover.Contents
-        return `${goType(n.types[0], 'e')} ${help}`
-      }
-      if (aa == 'ArrayType' && bb == 'TypeReference' && cc == 'NullKeyword') {
-        // check this is nm == 'textDocument/completion'
-        return `${goType(n.types[1], 'f')} ${help}`
-      }
-      if (aa == 'LiteralType' && bb == aa && cc == aa) return `string ${help}`;
-      break;
-    case 4:
-      if (nm == 'documentChanges') return `TextDocumentEdit ${help} `;
-      if (nm == 'textDocument/prepareRename') return `Range ${help} `;
-    default:
-      throw new Error(`goUnionType len=${n.types.length} nm=${nm}`)
-  }
-
-  // Result will be interface{} with a comment
-  let isLiteral = true;
-  let literal = 'string';
-  let res = `interface{} /* `
-  n.types.forEach((v: ts.TypeNode, i: number) => {
-    // might get an interface inside:
-    //  (Command | CodeAction)[] | null
-    let m = goType(v, nm);
-    if (m.indexOf('interface') != -1) {
-      // avoid nested comments
-      m = m.split(' ')[0];
-    }
-    m = m.split('\n').join('; ')  // sloppy: struct{;
-    res = res.concat(`${i == 0 ? '' : ' | '}`, m)
-    if (!ts.isLiteralTypeNode(v)) isLiteral = false;
-    else literal = strKind(v.literal) == 'StringLiteral' ? 'string' : 'number';
-  });
-  if (!isLiteral) {
-    return res + '*/';
-  }
-  // trace?: 'off' | 'messages' | 'verbose' should get string
-  return `${literal} /* ${n.getText()} */`
-}
-
-// some of the intersection types A&B are ok as struct{A;B;} and some
-// could be expanded, and ClientCapabilites has to be expanded,
-// at least for workspace. It's possible to check algorithmically,
-// but much simpler just to check explicity.
-function goIntersectionType(n: ts.IntersectionTypeNode, nm: string): string {
-  if (nm == 'ClientCapabilities') return expandIntersection(n);
-  if (nm == 'ServerCapabilities') return expandIntersection(n);
-  let inner = '';
-  n.types.forEach(
-    (t: ts.TypeNode) => { inner = inner.concat(goType(t, nm), '\n') });
-  return `struct{ \n${inner}} `
-}
-
-// for each of the itersected types, extract its components (each will
-// have a Data with properties) extract the properties, and keep track
-// of them by name. The names that occur once can be output. The names
-// that occur more than once need to be combined.
-function expandIntersection(n: ts.IntersectionTypeNode): string {
-  const bad = function (n: ts.Node, s: string) {
-    return new Error(`expandIntersection ${strKind(n)} ${s}`)
-  };
-  let props = new Map<string, ts.PropertySignature[]>();
-  for (const tp of n.types) {
-    if (!ts.isTypeReferenceNode(tp)) throw bad(tp, 'A');
-    const d = data.get(goName(tp.typeName.getText()));
-    for (const p of d.properties) {
-      if (!ts.isPropertySignature(p)) throw bad(p, 'B');
-      let v = props.get(p.name.getText()) || [];
-      v.push(p);
-      props.set(p.name.getText(), v);
-    }
-  }
-  let ans = 'struct {\n';
-  for (const [k, v] of Array.from(props)) {
-    if (v.length == 1) {
-      const a = v[0];
-      ans = ans.concat(getComments(a));
-      ans = ans.concat(`${goName(k)} ${goType(a.type, k)} ${u.JSON(a)}\n`)
-      continue
-    }
-    ans = ans.concat(`${goName(k)} struct {\n`)
-    for (let i = 0; i < v.length; i++) {
-      const a = v[i];
-      if (ts.isTypeReferenceNode(a.type)) {
-        ans = ans.concat(getComments(a))
-        ans = ans.concat(goName(a.type.typeName.getText()), '\n');
-      } else if (ts.isTypeLiteralNode(a.type)) {
-        if (a.type.members.length != 1) throw bad(a.type, 'C');
-        const b = a.type.members[0];
-        if (!ts.isPropertySignature(b)) throw bad(b, 'D');
-        ans = ans.concat(getComments(b));
-        ans = ans.concat(
-          goName(b.name.getText()), ' ', goType(b.type, 'a'), u.JSON(b), '\n')
-      } else if (a.type.kind == ts.SyntaxKind.ObjectKeyword) {
-        ans = ans.concat(getComments(a))
-        ans = ans.concat(
-          goName(a.name.getText()), ' ', 'interface{}', u.JSON(a), '\n')
-      } else {
-        throw bad(a.type, `E ${a.getText()} in ${goName(k)} at ${loc(a)}`)
-      }
-    }
-    ans = ans.concat('}\n');
-  }
-  ans = ans.concat('}\n');
-  return ans
-}
-
-function goTypeLiteral(n: ts.TypeLiteralNode, nm: string): string {
-  let ans: string[] = [];  // in case we generate a new extra type
-  let res = 'struct{\n'    // the actual answer usually
-  const g = function (nx: ts.TypeElement) {
-    // add the json, as in goInterface(). Strange inside union types.
-    if (ts.isPropertySignature(nx)) {
-      let json = u.JSON(nx);
-      let typ = goType(nx.type, nx.name.getText())
-      const v = getComments(nx) || '';
-      starred.forEach(([a, b]) => {
-        if (a != nm || b != typ.toLowerCase()) return;
-        typ = '*' + typ;
-        json = json.substring(0, json.length - 2) + ',omitempty"`'
-      })
-      res = res.concat(`${v} ${goName(nx.name.getText())} ${typ}`, json, '\n')
-      ans.push(`${v}${goName(nx.name.getText())} ${typ} ${json}\n`)
-    } else if (ts.isIndexSignatureDeclaration(nx)) {
-      if (nx.getText() == '[uri: string]: TextEdit[];') {
-        res = 'map[string][]TextEdit';
-        ans.push(`map[string][]TextEdit`);  // this is never used
-        return
-      }
-      throw new Error(` handle ${nx.getText()}`)
-    } else
-      throw new Error(`TypeLiteral had ${strKind(nx)}`)
-  };
-  n.members.forEach(g)
-  // for some the generated type is wanted, for others it's not needed
-  if (!nm.startsWith('workspace')) {
-    if (res.startsWith('struct')) return res + '}';  // map[] is special
-    return res
-  }
-  extraTypes.set(goName(nm) + 'Gn', ans)
-  return goName(nm) + 'Gn'
-}
-
-// print all the types and constants and extra types
-function outputTypes() {
-  // generate go types alphabeticaly
-  let v = Array.from(seenTypes.keys());
-  v.sort();
-  v.forEach((x) => toGo(seenTypes.get(x), x))
-  u.prgo(u.computeHeader(true))
-  u.prgo(`import "encoding/json"\n\n`);
-  typesOut.forEach((s) => {
-    u.prgo(s);
-    // it's more convenient not to have to think about trailing newlines
-    // when generating types, but doc comments can't have an extra \n
-    if (s.indexOf('/**') < 0) u.prgo('\n');
-  })
-  u.prgo('\nconst (\n');
-  constsOut.forEach((s) => {
-    u.prgo(s);
-    u.prgo('\n')
-  })
-  u.prgo(')\n');
-  u.prgo('// Types created to name formal parameters and embedded structs\n')
-  extraTypes.forEach((v, k) => {
-    u.prgo(` type ${k} struct {\n`)
-    v.forEach((s) => {
-      u.prgo(s);
-      u.prgo('\n')
-    });
-    u.prgo('}\n')
-  });
-}
-
-// client and server ------------------
-
-interface side {
-  methods: string[];
-  cases: string[];
-  calls: string[];
-  name: string;    // client or server
-  goName: string;  // Client or Server
-  outputFile?: string;
-  fd?: number
-}
-let client: side = {
-  methods: [],
-  cases: [],
-  calls: [],
-  name: 'client',
-  goName: 'Client',
-};
-let server: side = {
-  methods: [],
-  cases: [],
-  calls: [],
-  name: 'server',
-  goName: 'Server',
-};
-
-// commonly used output
-const notNil = `if len(r.Params()) > 0 {
-  return true, reply(ctx, nil, errors.Errorf("%w: expected no params", jsonrpc2.ErrInvalidParams))
-}`;
-
-// Go code for notifications. Side is client or server, m is the request
-// method
-function goNot(side: side, m: string) {
-  if (m == '$/cancelRequest') return;  // handled specially in protocol.go
-  const n = not.get(m);
-  const a = goType(n.typeArguments[0], m);
-  const nm = methodName(m);
-  side.methods.push(sig(nm, a, ''));
-  const caseHdr = ` case "${m}":  // notif`;
-  let case1 = notNil;
-  if (a != '' && a != 'void') {
-    case1 = `var params ${a}
-    if err := json.Unmarshal(r.Params(), &params); err != nil {
-      return true, sendParseError(ctx, reply, err)
-    }
-    err:= ${side.name}.${nm}(ctx, &params)
-    return true, reply(ctx, nil, err)`
-  } else {
-    case1 = `err := ${side.name}.${nm}(ctx)
-    return true, reply(ctx, nil, err)`;
-  }
-  side.cases.push(`${caseHdr}\n${case1}`);
-
-  const arg3 = a == '' || a == 'void' ? 'nil' : 'params';
-  side.calls.push(`
-  func (s *${side.name}Dispatcher) ${sig(nm, a, '', true)} {
-    return s.Conn.Notify(ctx, "${m}", ${arg3})
-  }`);
-}
-
-// Go code for requests.
-function goReq(side: side, m: string) {
-  const n = req.get(m);
-  const nm = methodName(m);
-  let a = goType(n.typeArguments[0], m);
-  let b = goType(n.typeArguments[1], m);
-  if (n.getText().includes('Type0')) {
-    b = a;
-    a = '';  // workspace/workspaceFolders and shutdown
-  }
-  u.prb(`${side.name} req ${a != ''}, ${b != ''} ${nm} ${m} ${loc(n)} `)
-  side.methods.push(sig(nm, a, b));
-
-  const caseHdr = `case "${m}": // req`;
-  let case1 = notNil;
-  if (a != '') {
-    if (extraTypes.has('Param' + nm)) a = 'Param' + nm
-    case1 = `var params ${a}
-    if err := json.Unmarshal(r.Params(), &params); err != nil {
-      return true, sendParseError(ctx, reply, err)
-    }`;
-  }
-  const arg2 = a == '' ? '' : ', &params';
-  let case2 = `if err := ${side.name}.${nm}(ctx${arg2}); err != nil {
-    event.Error(ctx, "", err)
-  }`;
-  if (b != '' && b != 'void') {
-    case2 = `resp, err := ${side.name}.${nm}(ctx${arg2})
-    return true, reply(ctx, resp, err)`;
-  } else {  // response is nil
-    case2 = `err := ${side.name}.${nm}(ctx${arg2})
-    return true, reply(ctx, nil, err)`
-  }
-
-  side.cases.push(`${caseHdr}\n${case1}\n${case2}`);
-
-  const callHdr = `func (s *${side.name}Dispatcher) ${sig(nm, a, b, true)} {`;
-  let callBody = `return Call(ctx, s.Conn, "${m}", nil, nil)\n}`;
-  if (b != '' && b != 'void') {
-    const p2 = a == '' ? 'nil' : 'params';
-    const returnType = indirect(b) ? `*${b}` : b;
-    callBody = `var result ${returnType}
-                       if err := Call(ctx, s.Conn, "${m}", ${
-      p2}, &result); err != nil {
-                               return nil, err
-      }
-      return result, nil
-    }`;
-  } else if (a != '') {
-    callBody = `return Call(ctx, s.Conn, "${m}", params, nil) // Call, not Notify
-  }`
-  }
-  side.calls.push(`${callHdr}\n${callBody}\n`);
-}
-
-// make sure method names are unique
-let seenNames = new Set<string>();
-function methodName(m: string): string {
-  let i = m.indexOf('/');
-  let s = m.substring(i + 1);
-  let x = s[0].toUpperCase() + s.substring(1);
-  for (let j = x.indexOf('/'); j >= 0; j = x.indexOf('/')) {
-    let suffix = x.substring(j + 1)
-    suffix = suffix[0].toUpperCase() + suffix.substring(1)
-    let prefix = x.substring(0, j)
-    x = prefix + suffix
-  }
-  if (seenNames.has(x)) {
-    // Resolve, ResolveCodeLens, ResolveDocumentLink
-    if (!x.startsWith('Resolve')) throw new Error(`expected Resolve, not ${x}`)
-    x += m[0].toUpperCase() + m.substring(1, i)
-  }
-  seenNames.add(x);
-  return x;
-}
-
-// used in sig and in goReq
-function indirect(s: string): boolean {
-  if (s == '' || s == 'void') return false;
-  const skip = (x: string) => s.startsWith(x);
-  if (skip('[]') || skip('interface') || skip('Declaration') ||
-    skip('Definition') || skip('DocumentSelector'))
-    return false;
-  return true
-}
-
-// Go signatures for methods.
-function sig(nm: string, a: string, b: string, names?: boolean): string {
-  if (a.indexOf('struct') != -1) {
-    const v = a.split('\n')
-    extraTypes.set(`Param${nm}`, v.slice(1, v.length - 1))
-    a = 'Param' + nm
-  }
-  if (a == 'void')
-    a = '';
-  else if (a != '') {
-    if (names)
-      a = ', params *' + a;
-    else
-      a = ', *' + a;
-  }
-  let ret = 'error';
-  if (b != '' && b != 'void') {
-    // avoid * when it is senseless
-    if (indirect(b)) b = '*' + b;
-    ret = `(${b}, error)`;
-  }
-  let start = `${nm}(`;
-  if (names) {
-    start = start + 'ctx ';
-  }
-  return `${start}context.Context${a}) ${ret}`;
-}
-
-// write the request/notification code
-function output(side: side) {
-  // make sure the output file exists
-  if (!side.outputFile) {
-    side.outputFile = `ts${side.name}.go`;
-    side.fd = fs.openSync(side.outputFile, 'w');
-  }
-  const f = function (s: string) {
-    fs.writeSync(side.fd, s);
-    fs.writeSync(side.fd, '\n');
-  };
-  f(u.computeHeader(false));
-  f(`
-        import (
-          "context"
-          "encoding/json"
-
-          "golang.org/x/tools/internal/jsonrpc2"
-          errors "golang.org/x/xerrors"
-        )
-        `);
-  const a = side.name[0].toUpperCase() + side.name.substring(1)
-  f(`type ${a} interface {`);
-  side.methods.forEach((v) => { f(v) });
-  f('}\n');
-  f(`func ${side.name}Dispatch(ctx context.Context, ${side.name} ${a}, reply jsonrpc2.Replier, r jsonrpc2.Request) (bool, error) {
-          switch r.Method() {`);
-  side.cases.forEach((v) => { f(v) });
-  f(`
-        default:
-          return false, nil
-        }
-      }`);
-  side.calls.forEach((v) => { f(v) });
-}
-
-// Handling of non-standard requests, so we can add gopls-specific calls.
-function nonstandardRequests() {
-  server.methods.push(
-    'NonstandardRequest(ctx context.Context, method string, params interface{}) (interface{}, error)')
-  server.calls.push(
-    `func (s *serverDispatcher) NonstandardRequest(ctx context.Context, method string, params interface{}) (interface{}, error) {
-      var result interface{}
-      if err := Call(ctx, s.Conn, method, params, &result); err != nil {
-        return nil, err
-      }
-      return result, nil
-    }
-  `)
-}
-
-// ----- remember it's a scripting language
-function main() {
-  if (u.gitHash != u.git()) {
-    throw new Error(
-      `git hash mismatch, wanted\n${u.gitHash} but source is at\n${u.git()}`);
-  }
-  u.createOutputFiles()
-  parse()
-  u.printAST(program)
-  // find the Requests and Nofificatations
-  for (const sourceFile of program.getSourceFiles()) {
-    if (!sourceFile.isDeclarationFile) {
-      ts.forEachChild(sourceFile, findRPCs)
-    }
-  }
-  // separate RPCs into client and server
-  setReceives();
-  // visit every sourceFile collecting top-level type definitions
-  for (const sourceFile of program.getSourceFiles()) {
-    if (!sourceFile.isDeclarationFile) {
-      ts.forEachChild(sourceFile, genTypes)
-    }
-  }
-  // check that each thing occurs exactly once, and put pointers into
-  // seenTypes
-  checkOnce();
-  // for each of Client and Server there are 3 parts to the output:
-  // 1. type X interface {methods}
-  // 2. func (h *serverHandler) Deliver(...) { switch r.method }
-  // 3. func (x *xDispatcher) Method(ctx, parm)
-  not.forEach(  // notifications
-    (v, k) => {
-      receives.get(k) == 'client' ? goNot(client, k) : goNot(server, k)
-    });
-  req.forEach(  // requests
-    (v, k) => {
-      receives.get(k) == 'client' ? goReq(client, k) : goReq(server, k)
-    });
-  nonstandardRequests();
-  // find all the types implied by seenTypes and rpcs to try to avoid
-  // generating types that aren't used
-  moreTypes();
-  // and print the Go code
-  outputTypes()
-  console.log(`seen ${seenTypes.size + extraTypes.size}`)
-  output(client);
-  output(server);
-}
-
-main()