// 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
      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)) {
    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))
  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, fmt.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);
  const j = x.indexOf('/')
  if (j >= 0) {
    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"
          "fmt"

          "golang.org/x/tools/internal/jsonrpc2"
        )
        `);
  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()
