// 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') {  // StringLiteral
      if (!ts.isStringLiteral(decl.initializer))
        throw new Error(`expect StringLiteral at ${loc(decl)}`);
      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());
    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): 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);
  } 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): string {
  const help = `/*${n.getText()}*/`  // show the original as a comment
  // 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} `;
    default:
      throw new Error(`goUnionType ${n.types.length} `)
  }

  // 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()
