import * as fs from 'fs';
import * as ts from 'typescript';

// 1. Everything that returns a Go thing should have unusable?: boolean
// 2. Remember what gets exported, and don't print the others (so _ can stay)
// 3. Merge all intersection types, and probably Heritage types too
interface Const {
  typeName: string  // repeated in each const
  goType: string
  me: ts.Node
  name: string   // constant's name
  value: string  // constant's value
}
let Consts: Const[] = [];
let seenConstTypes = new Map<string, boolean>();

interface Struct {
  me: ts.Node
  name: string
  embeds?: string[]
  fields?: Field[];
  extends?: string[]
}
let Structs: Struct[] = [];

interface Field {
  me: ts.Node
  id: ts.Identifier
  goName: string
  optional: boolean
  goType: string
  json: string
  gostuff?: string
  substruct?: Field[]  // embedded struct from TypeLiteral
}

interface Type {
  me: ts.Node
  goName: string
  goType: string
  stuff: string
}
let Types: Type[] = [];

// Used in printing the AST
let seenThings = new Map<string, number>();
function seenAdd(x: string) {
  seenThings[x] = (seenThings[x] === undefined ? 1 : seenThings[x] + 1)
}

let dir = process.env['HOME'];
const srcDir = '/vscode-languageserver-node'
let fnames = [
  `${srcDir}/protocol/src/protocol.ts`, `${srcDir}/types/src/main.ts`,
  `${srcDir}/jsonrpc/src/main.ts`
];
let outFname = '/tmp/tsprotocol.go';
let fda: number, fdb: number, fde: number;  // file descriptors

function createOutputFiles() {
  fda = fs.openSync('/tmp/ts-a', 'w')  // dump of AST
  fdb = fs.openSync('/tmp/ts-b', 'w')  // unused, for debugging
  fde = fs.openSync(outFname, 'w')     // generated Go
}
function pra(s: string) {
  return (fs.writeSync(fda, s))
}
function prb(s: string) {
  return (fs.writeSync(fdb, s))
}
function prgo(s: string) {
  return (fs.writeSync(fde, s))
}

// struct names that don't need to go in the output
let dontEmit = new Map<string, boolean>();

function generate(files: string[], options: ts.CompilerOptions): void {
  let program = ts.createProgram(files, options);
  program.getTypeChecker();  // used for side-effects

  // dump the ast, for debugging
  for (const sourceFile of program.getSourceFiles()) {
    if (!sourceFile.isDeclarationFile) {
      // walk the tree to do stuff
      ts.forEachChild(sourceFile, describe);
    }
  }
  pra('\n')
  for (const key of Object.keys(seenThings).sort()) {
    pra(`${key}: ${seenThings[key]}\n`)
  }

  // visit every sourceFile in the program, generating types
  for (const sourceFile of program.getSourceFiles()) {
    if (!sourceFile.isDeclarationFile) {
      ts.forEachChild(sourceFile, genTypes)
    }
  }
  return;

  function genTypes(node: ts.Node) {
    // Ignore top-level items that produce no output
    if (ts.isExpressionStatement(node) || ts.isFunctionDeclaration(node) ||
        ts.isImportDeclaration(node) || ts.isVariableStatement(node) ||
        ts.isExportDeclaration(node) ||
        node.kind == ts.SyntaxKind.EndOfFileToken) {
      return;
    }
    if (ts.isInterfaceDeclaration(node)) {
      doInterface(node)
      return;
    } else if (ts.isTypeAliasDeclaration(node)) {
      doTypeAlias(node)
    } else if (ts.isModuleDeclaration(node)) {
      doModuleDeclaration(node)
    } else if (ts.isEnumDeclaration(node)) {
      doEnumDecl(node)
    } else if (ts.isClassDeclaration(node)) {
      doClassDeclaration(node)
    } else {
      throw new Error(`unexpected ${strKind(node)} ${loc(node)}`)
    }
  }

  function doClassDeclaration(node: ts.ClassDeclaration) {
    let id: ts.Identifier = node.name;
    let props = new Array<ts.PropertyDeclaration>()
    let extend: ts.HeritageClause;
    let bad = false
    node.forEachChild((n: ts.Node) => {
      if (ts.isIdentifier(n)) {
        return
      }
      if (ts.isPropertyDeclaration(n)) {
        props.push(n);
        return
      }
      if (n.kind == ts.SyntaxKind.ExportKeyword) {
        return
      }
      if (n.kind == ts.SyntaxKind.Constructor || ts.isMethodDeclaration(n) ||
          ts.isGetAccessor(n) || ts.isSetAccessor(n) ||
          ts.isTypeParameterDeclaration(n)) {
        bad = true;
        return
      }
      if (ts.isHeritageClause(n)) {
        return
      }
      if (n.kind == ts.SyntaxKind.AbstractKeyword) {
        bad = true;  // we think all of these are useless, but are unsure
        return;
      }
      throw new Error(`doClass ${loc(n)} ${kinds(n)}`)
    })
    if (bad) {
      // the class is not useful for Go.
      return
    }
    let fields: Field[] = [];
    for (const pr of props) {
      fields.push(fromPropDecl(pr))
    }
    let ans = {
      me: node,
      name: toGoName(getText(id)),
      extends: heritageStrs(extend),
      fields: fields
    };
    Structs.push(ans)
  }

  function fromPropDecl(node: ts.PropertyDeclaration): Field {
    let id: ts.Identifier = (ts.isIdentifier(node.name) && node.name);
    let opt = node.questionToken != undefined;
    let typ: ts.Node = node.type;
    const computed = computeType(typ);
    let goType = computed.goType
    let ans = {
      me: node,
      id: id,
      goName: toGoName(getText(id)),
      optional: opt,
      goType: goType,
      json: `\`json:"${id.text}${opt ? ',omitempty' : ''}"\``,
      substruct: computed.fields
    };
    return ans
  }

  function doInterface(node: ts.InterfaceDeclaration) {
    // name: Identifier;
    // typeParameters?: NodeArray<TypeParameterDeclaration>;
    // heritageClauses?: NodeArray<HeritageClause>;
    // members: NodeArray<TypeElement>;

    // find the Identifier from children
    // process the PropertySignature children
    // the members might have generic info, but so do the children
    let id: ts.Identifier = node.name
    let extend: ts.HeritageClause
    let generid: ts.Identifier
    let properties = new Array<ts.PropertySignature>()
    let index: ts.IndexSignatureDeclaration  // generate some sort of map
    let bad = false;  // maybe we don't care about this one at all
    node.forEachChild((n: ts.Node) => {
      if (n.kind == ts.SyntaxKind.ExportKeyword || ts.isMethodSignature(n)) {
        // ignore
      } else if (ts.isIdentifier(n)) {
      } else if (ts.isHeritageClause(n)) {
        extend = n;
      } else if (ts.isTypeParameterDeclaration(n)) {
        // Act as if this is <T = any>
        generid = n.name;
      } else if (ts.isPropertySignature(n)) {
        properties.push(n);
      } else if (ts.isIndexSignatureDeclaration(n)) {
        if (index !== undefined) {
          throw new Error(`${loc(n)} multiple index expressions`)
        }
        index = n
      } else if (n.kind == ts.SyntaxKind.CallSignature) {
        bad = true;
      } else {
        throw new Error(`${loc(n)} doInterface ${strKind(n)} `)
      }
    })
    if (bad) return;
    let fields: Field[] = [];
    for (const p of properties) {
      fields.push(genProp(p, generid))
    }
    if (index != undefined) {
      fields.push(fromIndexSignature(index))
    }
    const ans = {
      me: node,
      name: toGoName(getText(id)),
      extends: heritageStrs(extend),
      fields: fields
    };

    Structs.push(ans)
  }

  function heritageStrs(node: ts.HeritageClause): string[] {
    // ExpressionWithTypeArguments+, and each is an Identifier
    let ans: string[] = [];
    if (node == undefined) {
      return ans
    }
    let x: ts.ExpressionWithTypeArguments[] = []
    node.forEachChild((n: ts.Node) => {
      if (ts.isExpressionWithTypeArguments(n)) x.push(n)
    })
    for (const p of x) {
      p.forEachChild((n: ts.Node) => {
        if (ts.isIdentifier(n)) {
          ans.push(toGoName(getText(n)));
          return;
        }
        if (ts.isTypeReferenceNode(n)) {
          // don't want these, ignore them
          return;
        }
        throw new Error(`expected Identifier ${loc(n)} ${kinds(p)} `)
      })
    }
    return ans
  }

  function genProp(node: ts.PropertySignature, gen: ts.Identifier): Field {
    let id: ts.Identifier
    let thing: ts.Node
    let opt = false
    node.forEachChild((n: ts.Node) => {
      if (ts.isIdentifier(n)) {
        id = n
      } else if (n.kind == ts.SyntaxKind.QuestionToken) {
        opt = true
      } else if (n.kind == ts.SyntaxKind.ReadonlyKeyword) {
        return
      } else {
        if (thing !== undefined) {
          throw new Error(`${loc(n)} weird`)
        }
        thing = n
      }
    })
    let goName = toGoName(id.text)
    let {goType, gostuff, optional, fields} = computeType(thing)
    // Generics
    if (gen && gen.text == goType) goType = 'interface{}';
    opt = opt || optional;
    let ans = {
      me: node,
      id: id,
      goName: goName,
      optional: opt,
      goType: goType,
      gostuff: gostuff,
      substruct: fields,
      json: `\`json:"${id.text}${opt ? ',omitempty' : ''}"\``
    };
    // These are not structs, so '*' would be wrong.
    switch (goType) {
      case 'CompletionItemKind':
      case 'TextDocumentSyncKind':
      case 'CodeActionKind':
      case 'FailureHandlingKind':  // string
      case 'InsertTextFormat':     // float64
      case 'DiagnosticSeverity':
        ans.optional = false
    }
    return ans
  }

  function doModuleDeclaration(node: ts.ModuleDeclaration) {
    // Export Identifier ModuleBlock
    let id: ts.Identifier = (ts.isIdentifier(node.name) && node.name);
    // Don't want FunctionDeclarations
    // some of the VariableStatement are consts, and want their comments
    // and each VariableStatement is Export, VariableDeclarationList
    // and each VariableDeclarationList is a single VariableDeclaration
    let v: ts.VariableDeclaration[] = [];
    function f(n: ts.Node) {
      if (ts.isVariableDeclaration(n)) {
        v.push(n);
        return
      }
      if (ts.isFunctionDeclaration(n)) {
        return
      }
      n.forEachChild(f)
    }
    f(node)
    for (const vx of v) {
      if (hasNewExpression(vx)) {
        return
      }
      buildConst(getText(id), vx)
    }
  }

  function buildConst(tname: string, node: ts.VariableDeclaration): Const {
    // node is Identifier, optional-goo, (FirstLiteralToken|StringLiteral)
    let id: ts.Identifier = (ts.isIdentifier(node.name) && node.name);
    let str: string
    let first: string
    node.forEachChild((n: ts.Node) => {
      if (ts.isStringLiteral(n)) {
        str = getText(n)
      } else if (n.kind == ts.SyntaxKind.NumericLiteral) {
        first = getText(n)
      }
    })
    if (str == undefined && first == undefined) {
      return
    }  // various
    const ty = (str != undefined) ? 'string' : 'float64'
    const val = (str != undefined) ? str.replace(/'/g, '"') : first
    const name = toGoName(getText(id))
    const c = {
      typeName: tname,
      goType: ty,
      me: node.parent.parent,
      name: name,
      value: val
    };
    Consts.push(c)
    return c
  }

  // is 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 doEnumDecl(node: ts.EnumDeclaration) {
    // Generates Consts. Identifier EnumMember+
    // EnumMember: Identifier StringLiteral
    let id: ts.Identifier = node.name
    let mems = node.members
    let theType = 'string';
    for (const m of mems) {
      let name: string
      let value: string
      m.forEachChild((n: ts.Node) => {
        if (ts.isIdentifier(n)) {
          name = getText(n)
        } else if (ts.isStringLiteral(n)) {
          value = getText(n).replace(/'/g, '"')
        } else if (ts.isNumericLiteral(n)) {
          value = getText(n);
          theType = 'float64';
        } else {
          throw new Error(`in doEnumDecl ${strKind(n)} ${loc(n)}`)
        }
      })
      let ans = {
        typeName: getText(id),
        goType: theType,
        me: m,
        name: name,
        value: value
      };
      Consts.push(ans)
    }
  }

  // top-level TypeAlias
  function doTypeAlias(node: ts.TypeAliasDeclaration) {
    // these are all Export Identifier alias
    let id: ts.Identifier = node.name;
    let alias: ts.Node = node.type;
    let ans = {
      me: node,
      id: id,
      goName: toGoName(getText(id)),
      goType: '?',  // filled in later in this function
      stuff: ''
    };
    if (ts.isUnionTypeNode(alias)) {
      ans.goType = weirdUnionType(alias)
      if (id.text == 'DocumentFilter')
      if (ans.goType == undefined) {
        // these are mostly redundant; maybe sort them out later
        return
      }
      Types.push(ans)
      return
    }
    if (ts.isIntersectionTypeNode(alias)) {  // a Struct, not a Type
      let embeds: string[] = []
      alias.forEachChild((n: ts.Node) => {
        if (ts.isTypeReferenceNode(n)) {
          const s = toGoName(computeType(n).goType)
          embeds.push(s)
          // It's here just for embedding, and not used independently
          dontEmit.set(s, true);
        } else
          throw new Error(`expected TypeRef ${strKind(n)} ${loc(n)}`)
      })
      let ans = {me: node, name: toGoName(getText(id)), embeds: embeds};
      Structs.push(ans)
      return
    }
    if (ts.isArrayTypeNode(alias)) {  // []DocumentFilter
      ans.goType = '[]DocumentFilter';
      Types.push(ans)
      return
    }
    if (ts.isLiteralTypeNode(alias)) {
      return  // type A = 1, so nope
    }
    if (ts.isTypeLiteralNode(alias)) {
      return;  // type A = {...}
    }
    if (ts.isTypeReferenceNode(alias)) {
      ans.goType = computeType(alias).goType
      if (ans.goType.match(/und/) != null) throw new Error('396')
      Types.push(ans)  // type A B
      return
    }
    if (alias.kind == ts.SyntaxKind.StringKeyword) {  // type A string
      ans.goType = 'string';
      Types.push(ans);
      return
    }
    throw new Error(
        `in doTypeAlias ${loc(alias)} ${kinds(node)}: ${strKind(alias)}\n`)
  }

  // string, or number, or DocumentFilter
  function weirdUnionType(node: ts.UnionTypeNode): string {
    let bad = false;
    let aNumber = false;
    let aString = false;
    let tl: ts.TypeLiteralNode[] = []
    node.forEachChild((n: ts.Node) => {
      if (ts.isTypeLiteralNode(n)) {
        tl.push(n);
        return;
      }
      if (ts.isLiteralTypeNode(n)) {
        n.literal.kind == ts.SyntaxKind.NumericLiteral ? aNumber = true :
                                                         aString = true;
        return;
      }
      bad = true
    })
    if (bad) return;  // none of these are useful (so far)
    if (aNumber) {
      if (aString)
        throw new Error(
            `weirdUnionType is both number and string ${loc(node)}`);
      return 'float64';
    }
    if (aString) return 'string';
    let x = computeType(tl[0])
    x.fields[0].json = x.fields[0].json.replace(/"`/, ',omitempty"`')
    let out: string[] = [];
    for (const f of x.fields) {
      out.push(strField(f))
    }
    out.push('}\n')
    let ans = 'struct {\n'.concat(...out);
    return ans
  }

  function computeType(node: ts.Node):
      {goType: string, gostuff?: string, optional?: boolean, fields?: Field[]} {
    switch (node.kind) {
      case ts.SyntaxKind.AnyKeyword:
      case ts.SyntaxKind.ObjectKeyword:
        return {goType: 'interface{}'};
      case ts.SyntaxKind.BooleanKeyword:
        return {goType: 'bool'};
      case ts.SyntaxKind.NumberKeyword:
        return {goType: 'float64'};
      case ts.SyntaxKind.StringKeyword:
        return {goType: 'string'};
      case ts.SyntaxKind.NullKeyword:
      case ts.SyntaxKind.UndefinedKeyword:
        return {goType: 'nil'};
    }
    if (ts.isArrayTypeNode(node)) {
      let {goType, gostuff, optional} = computeType(node.elementType)
      return ({goType: '[]' + goType, gostuff: gostuff, optional: optional})
    } else if (ts.isTypeReferenceNode(node)) {
      // typeArguments?: NodeArray<TypeNode>;typeName: EntityName;
      // typeArguments won't show up in the generated Go
      // EntityName: Identifier|QualifiedName
      let tn: ts.EntityName = node.typeName;
      if (ts.isQualifiedName(tn)) {
        throw new Error(`qualified name at ${loc(node)}`);
      } else if (ts.isIdentifier(tn)) {
        return {goType: tn.text};
      } else {
        throw new Error(
            `expected identifier got ${strKind(node.typeName)} at ${loc(tn)}`)
      }
    } else if (ts.isLiteralTypeNode(node)) {
      // string|float64 (are there other possibilities?)
      const txt = getText(node);
      let typ = 'float64'
      if (txt.charAt(0) == '\'') {
        typ = 'string'
      }
      return {goType: typ, gostuff: getText(node)};
    } else if (ts.isTypeLiteralNode(node)) {
      let x: Field[] = [];
      let indexCnt = 0
      node.forEachChild((n: ts.Node) => {
        if (ts.isPropertySignature(n)) {
          x.push(genProp(n, undefined))
          return
        } else if (ts.isIndexSignatureDeclaration(n)) {
          indexCnt++
          x.push(fromIndexSignature(n))
          return
        }
        throw new Error(`${loc(n)} gotype ${strKind(n)}, not expected`)
      });
      if (indexCnt > 0) {
        if (indexCnt != 1 || x.length != 1)
          throw new Error(`undexpected Index ${loc(x[0].me)}`)
          // instead of {map...} just the map
          return ({goType: x[0].goType, gostuff: x[0].gostuff})
      }
      return ({goType: 'embedded!', fields: x})
    } else if (ts.isUnionTypeNode(node)) {
      let x = new Array<{goType: string, gostuff?: string, optiona?: boolean}>()
      node.forEachChild((n: ts.Node) => {x.push(computeType(n))})
      if (x.length == 2 && x[1].goType == 'nil') {
        return x[0]  // make it optional somehow? TODO
      }
      if (x[0].goType == 'bool') {  // take it
        if (x[1].goType == 'RenameOptions') {
          return ({goType: 'RenameOptions', gostuff: getText(node)})
        }
        return ({goType: 'bool', gostuff: getText(node)})
      }
      // these are special cases from looking at the source
      let gostuff = getText(node);
      if (x[0].goType == `"off"` || x[0].goType == 'string') {
        return ({goType: 'string', gostuff: gostuff})
      }
      if (x[0].goType == 'TextDocumentSyncOptions') {
        return ({goType: 'interface{}', gostuff: gostuff})
      }
      if (x[0].goType == 'float64' && x[1].goType == 'string') {
        return {
          goType: 'interface{}', gostuff: gostuff
        }
      }
      if (x[0].goType == 'MarkupContent' && x[1].goType == 'MarkedString') {
        return {
          goType: 'MarkupContent', gostuff: gostuff
        }
      }
      if (x[0].goType == 'RequestMessage' && x[1].goType == 'ResponseMessage') {
        return {
          goType: 'interface{}', gostuff: gostuff
        }
      }
      // Fail loudly
      console.log(`UnionType ${loc(node)}`)
      for (const v of x) {
        console.log(`${v.goType}`)
      }
      throw new Error('in UnionType, weird')
    } else if (ts.isParenthesizedTypeNode(node)) {
      // check that this is (TextDocumentEdit | CreateFile | RenameFile |
      // DeleteFile) TODO(pjw)
      return {
        goType: 'TextDocumentEdit', gostuff: getText(node)
      }
    } else if (ts.isTupleTypeNode(node)) {
      // string | [number, number]. TODO(pjw): check it really is
      return {
        goType: 'string', gostuff: getText(node)
      }
    } else if (ts.isFunctionTypeNode(node)) {
      // we don't want these members; mark them
      return {
        goType: 'bad', gostuff: getText(node)
      }
    }
    throw new Error(`computeType unknown ${strKind(node)} at ${loc(node)}`)
  }

  function fromIndexSignature(node: ts.IndexSignatureDeclaration): Field {
    let parm: ts.ParameterDeclaration
    let at: ts.Node
    node.forEachChild((n: ts.Node) => {
      if (ts.isParameter(n)) {
        parm = n
      } else if (
          ts.isArrayTypeNode(n) || n.kind == ts.SyntaxKind.AnyKeyword ||
          ts.isUnionTypeNode(n)) {
        at = n
      } else
        throw new Error(`fromIndexSig ${strKind(n)} ${loc(n)}`)
    })
    let goType = computeType(at).goType
    let id: ts.Identifier
    parm.forEachChild((n: ts.Node) => {
      if (ts.isIdentifier(n)) {
        id = n
      } else if (n.kind != ts.SyntaxKind.StringKeyword) {
        throw new Error(`fromIndexSig expected string, ${strKind(n)} ${loc(n)}`)
      }
    })
    goType = `map[string]${goType}`
    return {
      me: node, goName: toGoName(id.text), id: null, goType: goType,
          optional: false, json: `\`json:"${id.text}"\``,
          gostuff: `${getText(node)}`
    }
  }

  function toGoName(s: string): string {
    let ans = s
    if (s.charAt(0) == '_') {
      ans = 'Inner' + s.substring(1)
    }
    else {ans = s.substring(0, 1).toUpperCase() + s.substring(1)};
    ans = ans.replace(/Uri$/, 'URI')
    ans = ans.replace(/Id$/, 'ID')
    return ans
  }

  // find the text of a node
  function getText(node: ts.Node): string {
    let sf = node.getSourceFile();
    let start = node.getStart(sf)
    let end = node.getEnd()
    return sf.text.substring(start, end)
  }
  // return a string of the kinds of the immediate descendants
  function kinds(n: ts.Node): string {
    let res = 'Seen ' + strKind(n);
    function f(n: ts.Node): void{res += ' ' + strKind(n)};
    ts.forEachChild(n, f)
    return res
  }

  function strKind(n: ts.Node): string {
    const x = ts.SyntaxKind[n.kind];
    // some of these have two names
    switch (x) {
      default:
        return x;
      case 'FirstAssignment':
        return 'EqualsToken';
      case 'FirstBinaryOperator':
        return 'LessThanToken';
      case 'FirstCompoundAssignment':
        return 'PlusEqualsToken';
      case 'FirstContextualKeyword':
        return 'AbstractKeyword';
      case 'FirstLiteralToken':
        return 'NumericLiteral';
      case 'FirstNode':
        return 'QualifiedName';
      case 'FirstTemplateToken':
        return 'NoSubstitutionTemplateLiteral';
      case 'LastTemplateToken':
        return 'TemplateTail';
      case 'FirstTypeNode':
        return 'TypePredicate';
    }
  }

  function describe(node: ts.Node) {
    if (node === undefined) {
      return
    }
    let indent = '';

    function f(n: ts.Node) {
      seenAdd(kinds(n))
      if (ts.isIdentifier(n)) {
        pra(`${indent} ${loc(n)} ${strKind(n)} ${n.text}\n`)
      }
      else if (ts.isPropertySignature(n) || ts.isEnumMember(n)) {
        pra(`${indent} ${loc(n)} ${strKind(n)}\n`)
      }
      else if (ts.isTypeLiteralNode(n)) {
        let m = n.members
        pra(`${indent} ${loc(n)} ${strKind(n)} ${m.length}\n`)
      }
      else {pra(`${indent} ${loc(n)} ${strKind(n)}\n`)};
      indent += '  '
      ts.forEachChild(n, f)
      indent = indent.slice(0, indent.length - 2)
    }
    f(node)
  }
}

function getComments(node: ts.Node): string {
  const sf = node.getSourceFile();
  const start = node.getStart(sf, false)
  const starta = node.getStart(sf, true)
  const x = sf.text.substring(starta, start)
  return x
}

function loc(node: ts.Node): string{const sf = node.getSourceFile()
const start = node.getStart()
const x = sf.getLineAndCharacterOfPosition(start)
const full = node.getFullStart()
const y = sf.getLineAndCharacterOfPosition(full)
let fn = sf.fileName
const n = fn.search(/-node./)
fn = fn.substring(n + 6)
  return `${fn} ${x.line + 1}:${x.character + 1} (${y.line + 1}:${
    y.character + 1})`
}

function emitTypes() {
  seenConstTypes.set('MessageQueue', true);  // skip
  for (const t of Types) {
    if (seenConstTypes.get(t.goName)) continue;
    if (t.goName == 'CodeActionKind') continue;  // consts better choice
    if (t.goType === undefined) continue;
    let stuff = (t.stuff == undefined) ? '' : t.stuff;
    prgo(`// ${t.goName} is a type\n`)
    prgo(`${getComments(t.me)}`)
    prgo(`type ${t.goName} ${t.goType}${stuff}\n`)
    seenConstTypes.set(t.goName, true);
  }
}

let byName = new Map<string, Struct>();
  function emitStructs() {
    dontEmit.set('Thenable', true);
    dontEmit.set('EmitterOptions', true);
    dontEmit.set('MessageReader', true);
    dontEmit.set('MessageWriter', true);
    dontEmit.set('CancellationToken', true);
    dontEmit.set('PipeTransport', true);
    dontEmit.set('SocketTransport', true);
    dontEmit.set('Item', true);
    dontEmit.set('Event', true);
    dontEmit.set('Logger', true);
    dontEmit.set('Disposable', true);
    dontEmit.set('PartialMessageInfo', true);
    dontEmit.set('MessageConnection', true);
    dontEmit.set('ResponsePromise', true);
    dontEmit.set('ResponseMessage', true);
    dontEmit.set('ErrorMessage', true);
    dontEmit.set('NotificationMessage', true);
    dontEmit.set('RequestHandlerElement', true);
    dontEmit.set('RequestMessage', true);
    dontEmit.set('NotificationHandlerElement', true);
    dontEmit.set('Message', true);  // duplicate of jsonrpc2:wire.go
    dontEmit.set('LSPLogMessage', true);
    dontEmit.set('InnerEM', true);
    dontEmit.set('ResponseErrorLiteral', true);
    dontEmit.set('TraceOptions', true);
    dontEmit.set('MessageType', true);  // want the enum
    // backwards compatibility, done in requests.ts:
    dontEmit.set('CancelParams', true);

    for (const str of Structs) {
      byName.set(str.name, str)
    }
    let seenName = new Map<string, boolean>()
    for (const str of Structs) {
      if (str.name == 'InitializeError') {
        // only want its consts, not the struct
        continue
      }
      if (seenName.get(str.name) || dontEmit.get(str.name)) {
        continue
      }
      let noopt = false;
      seenName.set(str.name, true)
      prgo(genComments(str.name, getComments(str.me)))
      prgo(`type ${str.name} struct {\n`)
      // if it has fields, generate them
      if (str.fields != undefined) {
        for (const f of str.fields) {
          prgo(strField(f, noopt))
        }
      }
      if (str.extends) {
        // ResourceOperation just repeats the Kind field
        for (const s of str.extends) {
          if (s != 'ResourceOperation')
            prgo(`\t${s}\n`)  // what this type extends.
        }
      } else if (str.embeds) {
        prb(`embeds: ${str.name}\n`);
        noopt = (str.name == 'ClientCapabilities');
        // embedded struct. the hard case is from intersection types,
        // where fields with the same name have to be combined into
        // a single struct
        let fields = new Map<string, Field[]>();
        for (const e of str.embeds) {
          const nm = byName.get(e);
          if (nm.embeds) throw new Error(`${nm.name} is an embedded embed`);
          // each of these fields might be a something that needs amalgamating
          for (const f of nm.fields) {
            let x = fields.get(f.goName);
            if (x === undefined) x = [];
            x.push(f);
            fields.set(f.goName, x);
          }
        }
        fields.forEach((val) => {
          if (val.length > 1) {
            // merge the fields with the same name
            prgo(strField(val[0], noopt, val));
          } else {
            prgo(strField(val[0], noopt));
          }
        });
      }
      prgo(`}\n`);
    }
  }

  function genComments(name: string, maybe: string): string {
    if (maybe == '') return `\n\t// ${name} is\n`;
    if (maybe.indexOf('/**') == 0) {
      return maybe.replace('/**', `\n/*${name} defined:`)
    }
    throw new Error(`weird comment ${maybe.indexOf('/**')}`)
  }

  // Turn a Field into an output string
  function strField(f: Field, noopt?: boolean, flds?: Field[]): string {
    let ans: string[] = [];
    let opt = (!noopt && f.optional) ? '*' : ''
    switch (f.goType.charAt(0)) {
      case 's':  // string
      case 'b':  // bool
      case 'f':  // float64
      case 'i':  // interface{}
      case '[':  // []foo
        opt = ''
    }
    let stuff = (f.gostuff == undefined) ? '' : ` // ${f.gostuff}`
    ans.push(genComments(f.goName, getComments(f.me)))
    if (flds === undefined && f.substruct == undefined) {
      ans.push(`\t${f.goName} ${opt}${f.goType} ${f.json}${stuff}\n`)
    }
    else if (flds !== undefined) {
      ans.push(`\t${f.goName} ${opt}struct{\n`);
      for (const ff of flds) {
        if (ff.substruct !== undefined) {
          for (const x of ff.substruct) {
            ans.push(strField(x, noopt))
          }
        } else if (byName.get(ff.goType) !== undefined) {
          const st = byName.get(ff.goType);
          for (let i = 0; i < st.fields.length; i++) {
            ans.push(strField(st.fields[i], noopt))
          }
        } else {
          ans.push(strField(ff, noopt));
        }
      }
      ans.push(`\t} ${f.json}${stuff}\n`);
    }
    else {
      ans.push(`\t${f.goName} ${opt}struct {\n`)
      for (const x of f.substruct) {
        ans.push(strField(x, noopt))
      }
      ans.push(`\t} ${f.json}${stuff}\n`)
    }
    return (''.concat(...ans))
  }

  function emitConsts() {
    // need the consts too! Generate modifying prefixes and suffixes to ensure
    // consts are unique. (Go consts are package-level, but Typescript's are
    // not.) Use suffixes to minimize changes to gopls.
    let pref = new Map<string, string>(
        [['DiagnosticSeverity', 'Severity']])  // typeName->prefix
    let suff = new Map<string, string>([
      ['CompletionItemKind', 'Completion'], ['InsertTextFormat', 'TextFormat']
    ])
    for (const c of Consts) {
      if (seenConstTypes.get(c.typeName)) {
        continue
      }
      seenConstTypes.set(c.typeName, true);
      if (pref.get(c.typeName) == undefined) {
        pref.set(c.typeName, '')  // initialize to empty value
      }
      if (suff.get(c.typeName) == undefined) {
        suff.set(c.typeName, '')
      }
      prgo(`// ${c.typeName} defines constants\n`)
      prgo(`type ${c.typeName} ${c.goType}\n`)
    }
    prgo('const (\n')
    let seenConsts = new Map<string, boolean>()  // to avoid duplicates
    for (const c of Consts) {
      const x = `${pref.get(c.typeName)}${c.name}${suff.get(c.typeName)}`
      if (seenConsts.get(x)) {
        continue
      }
      seenConsts.set(x, true)
      if (c.value === undefined) continue;      // didn't figure it out
      if (x.startsWith('undefined')) continue;  // what's going on here?
      prgo(genComments(x, getComments(c.me)))
      prgo(`\t${x} ${c.typeName} = ${c.value}\n`)
    }
    prgo(')\n')
  }

  function emitHeader(files: string[]) {
    let lastMod = 0
    let lastDate: Date
    for (const f of files) {
      const st = fs.statSync(f)
      if (st.mtimeMs > lastMod) {
        lastMod = st.mtimeMs
        lastDate = st.mtime
      }
    }
    let a = fs.readFileSync(`${dir}${srcDir}/.git/refs/heads/master`);
    prgo(`// Package protocol contains data types and code for LSP jsonrpcs\n`)
    prgo(`// generated automatically from vscode-languageserver-node\n`)
    prgo(`// commit: ${a.toString()}`)
    prgo(`// last fetched ${lastDate}\n`)
    prgo('package protocol\n\n')
    prgo(`// Code generated (see typescript/README.md) DO NOT EDIT.\n`);
  };

  // ad hoc argument parsing: [-d dir] [-o outputfile], and order matters
  function main() {
    let args = process.argv.slice(2)  // effective command line
    if (args.length > 0) {
      let j = 0;
      if (args[j] == '-d') {
        dir = args[j + 1]
        j += 2
      }
      if (args[j] == '-o') {
        outFname = args[j + 1]
        j += 2
      }
      if (j != args.length) throw new Error(`incomprehensible args ${args}`)
    }
    let files: string[] = [];
    for (let i = 0; i < fnames.length; i++) {
      files.push(`${dir}${fnames[i]}`)
    }
    createOutputFiles()
    generate(
        files, {target: ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS});
    emitHeader(files)
    emitStructs()
    emitConsts()
    emitTypes()
  }

  main()
