/* eslint-disable no-useless-return */
// 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 ModuleBlock 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(`81: ${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(`89 expected 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(`112 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);
}

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(`145 missing ${k}}`);
    if (req.get(k) && not.get(k)) throw new Error(`146 dup ${k}`);
  });
}

type DataKind = 'module' | 'interface' | 'alias' | 'enum' | 'class';

interface Data {
  kind: DataKind;
  me: ts.Node;   // root node for this type
  name: string;  // Go name
  origname: string; // their name
  generics: ts.NodeArray<ts.TypeParameterDeclaration>;
  as: ts.NodeArray<ts.HeritageClause>;  // inheritance
  // Interface
  properties: ts.NodeArray<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, k: DataKind, origname: string): Data {
  return {
    kind: k,
    me: n, name: goName(nm), origname: origname,
    generics: ts.factory.createNodeArray<ts.TypeParameterDeclaration>(),
    as: ts.factory.createNodeArray<ts.HeritageClause>(),
    properties: ts.factory.createNodeArray<ts.PropertySignature>(), alias: undefined,
    statements: ts.factory.createNodeArray<ts.Statement>(),
    enums: ts.factory.createNodeArray<ts.EnumMember>(),
    members: ts.factory.createNodeArray<ts.PropertyDeclaration>(),
  };
}

// for debugging, produce a skeleton description
function strData(d: Data): string {
  if (!d) { return 'nil'; }
  const f = function (na: ts.NodeArray<any>): number {
    return na.length;
  };
  const nm = d.name == d.origname ? `${d.name}` : `${d.name}/${d.origname}`;
  return `g:${f(d.generics)} a:${f(d.as)} p:${f(d.properties)} s:${f(d.statements)} e:${f(d.enums)} m:${f(d.members)} a:${d.alias !== undefined} D(${nm}) k:${d.kind}`;
}

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

function setData(nm: string, d: Data) {
  const v = data.get(nm);
  if (!v) {
    data.set(nm, d);
    return;
  }
  // if there are multiple definitions of the same name, decide what to do.
  // For now the choices are only aliases and modules
  // alias is preferred unless the constant values are needed
  if (nm === 'PrepareSupportDefaultBehavior') {
    // want the alias, as we're going to change the type and can't afford a constant
    if (d.kind === 'alias') data.set(nm, d);
    else if (v.kind == 'alias') data.set(nm, v);
    else throw new Error(`208 ${d.kind} ${v.kind}`);
    return;
  }
  if (nm === 'CodeActionKind') {
    // want the module, need the constants
    if (d.kind === 'module') data.set(nm, d);
    else if (v.kind === 'module') data.set(nm, v);
    else throw new Error(`215 ${d.kind} ${v.kind}`);
  }
  if (v.kind === 'alias' && d.kind !== 'alias') return;
  if (d.kind === 'alias' && v.kind !== 'alias') {
    data.set(nm, d);
    return;
  }
  if (v.kind === 'alias' && d.kind === 'alias') return;
  // protocol/src/common/protocol.foldingRange.ts 44: 1 (39: 2) and
  // types/src/main.ts 397: 1 (392: 2)
  // for FoldingRangeKind
  if (d.me.getText() === v.me.getText()) return;
  // error messages for an unexpected case
  console.log(`228 ${strData(v)} ${loc(v.me)} for`);
  console.log(`229 ${v.me.getText().replace(/\n/g, '\\n')}`);
  console.log(`230 ${strData(d)} ${loc(d.me)}`);
  console.log(`231 ${d.me.getText().replace(/\n/g, '\\n')}`);
  throw new Error(`232 setData found ${v.kind} for ${d.kind}`);
}

// 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.PropertySignature[] = [];
    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;]
      } else
        throw new Error(`259 unexpected ${strKind(t)}`);
    };
    v.members.forEach(f);
    if (mems.length == 0 && !v.heritageClauses &&
      v.name.getText() != 'InitializedParams') {
      return;  // Don't seem to need any of these [Logger, PipTransport, ...]
    }
    // Found one we want
    let x = newData(v, goName(v.name.getText()), 'interface', v.name.getText());
    x.properties = ts.factory.createNodeArray<ts.PropertySignature>(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 = dataChoose(x, data.get(x.name));
    }
    setData(x.name, x);
  } else if (ts.isTypeAliasDeclaration(node)) {
    const v: ts.TypeAliasDeclaration = node;
    let x = newData(v, v.name.getText(), 'alias', 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 = dataChoose(x, data.get(x.name));
    if (x.generics.length > 1) {
      return;
    }
    setData(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(
          `315 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(), 'module', v.name.getText());
    m.statements = ts.factory.createNodeArray<ts.Statement>(s);
    if (data.has(m.name)) m = dataChoose(m, data.get(m.name));
    setData(m.name, m);
  } else if (ts.isEnumDeclaration(node)) {
    const nm = node.name.getText();
    let v = newData(node, nm, 'enum', node.name.getText());
    v.enums = node.members;
    if (data.has(nm)) {
      v = dataChoose(v, data.get(nm));
    }
    setData(nm, v);
  } else if (ts.isClassDeclaration(node)) {
    const v: ts.ClassDeclaration = node;
    var d: ts.PropertyDeclaration[] = [];
    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) => wanted(c));
    if (d.length == 0) {
      return;
    }  // don't need it
    let c = newData(v, v.name.getText(), 'class', v.name.getText());
    c.members = ts.factory.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)}`);
    setData(c.name, c);
  } else {
    throw new Error(`378 unexpected ${strKind(node)} ${loc(node)} `);
  }
}

// Typescript can accumulate, but this chooses one or the other
function dataChoose(a: Data, b: Data): Data {
  // maybe they are textually identical? (e.g., FoldingRangeKind)
  const [at, bt] = [a.me.getText(), b.me.getText()];
  if (at == bt) {
    return a;
  }
  switch (a.name) {
    case 'InitializeError':
    case 'CompletionItemTag':
    case 'SymbolTag':
    case 'CodeActionKind':
    case 'Integer':
    case 'Uinteger':
    case 'Decimal':
      // want the Module, if anything
      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':
    case 'PrepareSupportDefaultBehavior':
      return a;
  }
  console.log(
    `409 ${strKind(a.me)} ${strKind(b.me)} ${a.name} ${loc(a.me)} ${loc(b.me)}`);
  throw new Error(`410 Fix dataChoose 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
// eslint-disable-next-line no-unused-vars
function underlying(n: ts.Node | undefined, 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.UnknownKeyword ||
    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
  } else if (ts.isEnumMember(n)) {
    if (ts.isStringLiteral(n.initializer)) return;
    throw new Error(`472 EnumMember ${strKind(n.initializer)} ${n.name.getText()}`);
  } else {
    throw new Error(`474 saw ${strKind(n)} in underlying. ${n.getText()} at ${loc(n)}`);
  }
}

// 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('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;
      if (data.get(nm)) {
        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)
    ;
}

function cleanData() { // middle pass
  // seenTypes contains all the top-level types.
  seenTypes.forEach((d) => {
    if (d.kind == 'alias') mergeAlias(d);
  });
}

function sameType(a: ts.TypeNode, b: ts.TypeNode): boolean {
  if (a.kind !== b.kind) return false;
  if (a.kind === ts.SyntaxKind.BooleanKeyword) return true;
  if (ts.isTypeReferenceNode(a) && ts.isTypeReferenceNode(b) &&
    a.typeName.getText() === b.typeName.getText()) return true;
  if (ts.isArrayTypeNode(a) && ts.isArrayTypeNode(b)) return sameType(a.elementType, b.elementType);
  if (ts.isTypeLiteralNode(a) && ts.isTypeLiteralNode(b)) {
    if (a.members.length !== b.members.length) return false;
    if (a.members.length === 1) return a.members[0].name.getText() === b.members[0].name.getText();
    if (loc(a) === loc(b)) return true;
  }
  throw new Error(`546 sameType? ${strKind(a)} ${strKind(b)}`);
}
type CreateMutable<Type> = {
  -readonly [Property in keyof Type]: Type[Property];
};
type propMap = Map<string, ts.PropertySignature>;
function propMapSet(pm: propMap, name: string, v: ts.PropertySignature) {
  if (!pm.get(name)) {
    try { getComments(v); } catch (e) { console.log(`552 ${name} ${e}`); }
    pm.set(name, v);
    return;
  }
  const a = pm.get(name).type;
  const b = v.type;
  if (sameType(a, b)) {
    return;
  }
  if (ts.isTypeReferenceNode(a) && ts.isTypeLiteralNode(b)) {
    const x = mergeTypeRefLit(a, b);
    const fake: CreateMutable<ts.PropertySignature> = v;
    fake['type'] = x;
    check(fake as ts.PropertySignature, '565');
    pm.set(name, fake as ts.PropertySignature);
    return;
  }
  if (ts.isTypeLiteralNode(a) && ts.isTypeLiteralNode(b)) {
    const x = mergeTypeLitLit(a, b);
    const fake: CreateMutable<ts.PropertySignature> = v;
    fake['type'] = x;
    check(fake as ts.PropertySignature, '578');
    pm.set(name, fake as ts.PropertySignature);
    return;
  }
  console.log(`577 ${pm.get(name).getText()}\n${v.getText()}`);
  throw new Error(`578 should merge ${strKind(a)} and ${strKind(b)} for ${name}`);
}
function addToProperties(pm: propMap, tn: ts.TypeNode | undefined, prefix = '') {
  if (!tn) return;
  if (ts.isTypeReferenceNode(tn)) {
    const d = seenTypes.get(goName(tn.typeName.getText()));
    if (tn.typeName.getText() === 'T') return;
    if (!d) throw new Error(`584 ${tn.typeName.getText()} not found`);
    if (d.properties.length === 0 && d.alias === undefined) return;
    if (d.alias !== undefined) {
      if (ts.isIntersectionTypeNode(d.alias)) {
        d.alias.types.forEach((tn) => addToProperties(pm, tn, prefix)); // prefix?
        return;
      }
    }
    d.properties.forEach((ps) => {
      const name = `${prefix}.${ps.name.getText()}`;
      propMapSet(pm, name, ps);
      addToProperties(pm, ps.type, name);
    });
  } else if (strKind(tn) === 'TypeLiteral') {
    if (!ts.isTypeLiteralNode(tn)) new Error(`598 ${strKind(tn)}`);
    tn.forEachChild((child: ts.Node) => {
      if (!ts.isPropertySignature(child)) throw new Error(`600 ${strKind(child)}`);
      const name = `${prefix}.${child.name.getText()}`;
      propMapSet(pm, name, child);
      addToProperties(pm, child.type, name);
    });
  }
}
function deepProperties(d: Data): propMap | undefined {
  let properties: propMap = new Map<string, ts.PropertySignature>();
  if (!d.alias || !ts.isIntersectionTypeNode(d.alias)) return undefined;
  d.alias.types.forEach((ts) => addToProperties(properties, ts));
  return properties;
}

function mergeAlias(d: Data) {
  const props = deepProperties(d);
  if (!props) return; // nothing merged
  // now each element of props should have length 1
  // change d to merged, toss its alias field, fill in its properties
  const v: ts.PropertySignature[] = [];
  props.forEach((ps, nm) => {
    const xlen = nm.split('.').length;
    if (xlen !== 2) return; // not top-level
    v.push(ps);
  });
  d.kind = 'interface';
  d.alias = undefined;
  d.properties = ts.factory.createNodeArray(v);
}

function mergeTypeLitLit(a: ts.TypeLiteralNode, b: ts.TypeLiteralNode): ts.TypeLiteralNode {
  const v = new Map<string, ts.TypeElement>(); // avoid duplicates
  a.members.forEach((te) => v.set(te.name.getText(), te));
  b.members.forEach((te) => v.set(te.name.getText(), te));
  const x: ts.TypeElement[] = [];
  v.forEach((te) => x.push(te));
  const fake: CreateMutable<ts.TypeLiteralNode> = a;
  fake['members'] = ts.factory.createNodeArray(x);
  check(fake as ts.TypeLiteralNode, '643');
  return fake as ts.TypeLiteralNode;
}

function mergeTypeRefLit(a: ts.TypeReferenceNode, b: ts.TypeLiteralNode): ts.TypeLiteralNode {
  const d = seenTypes.get(goName(a.typeName.getText()));
  if (!d) throw new Error(`644 name ${a.typeName.getText()} not found`);
  const typ = d.me;
  if (!ts.isInterfaceDeclaration(typ)) throw new Error(`646 got ${strKind(typ)} not InterfaceDecl`);
  const v = new Map<string, ts.TypeElement>(); // avoid duplicates
  typ.members.forEach((te) => v.set(te.name.getText(), te));
  b.members.forEach((te) => v.set(te.name.getText(), te));
  const x: ts.TypeElement[] = [];
  v.forEach((te) => x.push(te));

  const w = ts.factory.createNodeArray(x);
  const fk: CreateMutable<ts.TypeLiteralNode> = b;
  fk['members'] = w;
  (fk['members'] as { pos: number })['pos'] = b.members.pos;
  (fk['members'] as { end: number })['end'] = b.members.end;
  check(fk as ts.TypeLiteralNode, '662');
  return fk as ts.TypeLiteralNode;
}

// check that constructed nodes still have associated text
function check(n: ts.Node, loc: string) {
  try { getComments(n); } catch (e) { console.log(`check at ${loc} ${e}`); }
  try { n.getText(); } catch (e) { console.log(`text check at ${loc}`); }
}

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.name.startsWith('Inner') || d.name === 'WindowClientCapabilities') return; // removed by alias processing
  if (d.name === 'Integer' || d.name === 'Uinteger') return; // unneeded
  switch (d.kind) {
    case 'alias':
      goTypeAlias(d, nm); break;
    case 'module': goModule(d, nm); break;
    case 'enum': goEnum(d, nm); break;
    case 'interface': goInterface(d, nm); break;
    default:
      throw new Error(
        `672: more cases in toGo ${nm} ${d.kind}`);
  }
}

// these fields need a * and are not covered by the code
// that calls isStructType.
var starred: [string, string][] = [
  ['TextDocumentContentChangeEvent', 'range'], ['CodeAction', 'command'],
  ['CodeAction', 'disabled'],
  ['DidSaveTextDocumentParams', 'text'], ['CompletionItem', 'command'],
  ['Diagnostic', 'codeDescription']
];

// 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.PropertySignature) {
    if (!ts.isPropertySignature(n))
      throw new Error(`expected PropertySignature got ${strKind(n)} `);
    ans = ans.concat(getComments(n));
    const json = u.JSON(n);
    let gt = goType(n.type, n.name.getText());
    if (gt == d.name) gt = '*' + gt; // avoid recursive types (SelectionRange)
    // there are several cases where a * is needed
    // (putting * in front of too many things breaks uses of CodeActionKind)
    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(`743 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(`753 ${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(`760 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' ? ' ' : ' = ';
  if (nm == 'PrepareSupportDefaultBehavior') {
    // code-insiders is sending a bool, not a number. PJW: check this after Feb/2021
    // (and gopls never looks at it anyway)
    typesOut.push(`type ${goName(nm)}${aliasStr}interface{}\n`);
    return;
  }
  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 | undefined, nm: string): string {
  if (!n) throw new Error(`goType undefined for ${nm}`);
  if (n.getText() == 'T') return 'interface{}';  // should check it's generic
  if (ts.isTypeReferenceNode(n)) {
    switch (n.getText()) {
      case 'integer': return 'int32';
      case 'uinteger': return 'uint32';
      default: 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' || strKind(n) == 'UnknownKeyword') {
    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 {
  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 (nm == 'range') help = help.replace(/\n/, '');
  if (nm == 'full' && help.indexOf('\n') != -1) {
    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' || n.types[1].getText() === 'null') {
        // PJW: fix this. it looks like 'null' is now being parsed as LiteralType
        // and check the other keyword cases
        if (nm == 'textDocument/codeAction') {
          // (Command | CodeAction)[] | null
          return `[]CodeAction ${help}`;
        }
        let v = goType(n.types[0], 'a');
        return `${v} ${help}`;
      }
      if (a == 'BooleanKeyword') {  // usually want bool
        if (nm == 'codeActionProvider') return `interface{} ${help}`;
        if (nm == 'renameProvider') return `interface{} ${help}`;
        if (nm == 'full') return `interface{} ${help}`; // there's a struct
        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') {
        if (nm == 'edits') return `${goType(n.types[0], '715')} ${help}`;
        if (a == b) return `interface{} ${help}`;
        if (nm == 'code') return `interface{} ${help}`;
      }
      if (a == 'StringKeyword') return `string ${help}`;
      if (a == 'TypeLiteral' && nm == 'TextDocumentContentChangeEvent') {
        return `${goType(n.types[0], nm)}`;
      }
      console.log(`911 ${n.types[1].getText()} ${loc(n.types[1])}`);
      throw new Error(`912 ${nm}: a:${a} b:${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 == '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} `;
    // eslint-disable-next-line no-fallthrough
    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 + '*/';
  }
  // I don't think we get here
  // 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 explicitly.
function goIntersectionType(n: ts.IntersectionTypeNode, nm: string): string {
  if (nm == 'ClientCapabilities') return expandIntersection(n);
  //if (nm == 'ServerCapabilities') return expandIntersection(n); // save for later consideration
  let inner = '';
  n.types.forEach(
    (t: ts.TypeNode) => { inner = inner.concat(goType(t, nm), '\n'); });
  return `struct{ \n${inner}} `;
}

// for each of the intersected 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 {
        throw bad(a.type, `E ${a.getText()} in ${goName(k)} at ${loc(a)}`);
      }
    }
    ans = ans.concat('}\n');
  }
  ans = ans.concat('}\n');
  return ans;
}

// Does it make sense to use a pointer?
function isStructType(te: ts.TypeNode): boolean {
  switch (strKind(te)) {
    case 'UnionType': // really need to know which type will be chosen
    case 'BooleanKeyword':
    case 'StringKeyword':
    case 'ArrayType':
      return false;
    case 'TypeLiteral': return false; // true makes for difficult compound constants
    // but think more carefully to understands why starred is needed.
    case 'TypeReference': {
      if (!ts.isTypeReferenceNode(te)) throw new Error(`1047 impossible ${strKind(te)}`);
      const d = seenTypes.get(goName(te.typeName.getText()));
      if (d.properties.length > 1) return true;
      // alias or interface with a single property (The alias is Uinteger, which we ignore later)
      if (d.alias) return false;
      const x = d.properties[0].type;
      return isStructType(x);
    }
    default: throw new Error(`1055 indirectable> ${strKind(te)}`);
  }
}

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"`';
      });
      if (typ[0] !== '*' && isStructType(nx.type)) typ = '*' + typ;
      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;
      }
      if (nx.getText() == '[id: string /* ChangeAnnotationIdentifier */]: ChangeAnnotation;') {
        res = 'map[string]ChangeAnnotationIdentifier';
        ans.push(res);
        return;
      }
      throw new Error(`1087 handle ${nx.getText()} ${loc(nx)}`);
    } 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;
  }
  // these names have to be made unique
  const genName = `${goName(nm)}${extraTypes.size}Gn`;
  extraTypes.set(genName, ans);
  return genName;
}

// 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';
  // if case2 is not explicitly typed string, typescript makes it a union of strings
  let case2: string = `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();
  // do merging
  cleanData();
  // and print the Go code
  outputTypes();
  console.log(`seen ${seenTypes.size + extraTypes.size}`);
  output(client);
  output(server);
}

main();
