Repository: sandersn/downlevel-dts (js)

Issue:
Reference types directives appear to be duplicated
If an input d.ts has a reference directive like
```ts
/// <reference types="node" />
```

then that line will appear twice in the output d.ts:

```ts
/// <reference types="node" />
/// <reference types="node" />
```

Pull request description:
Work around triple slash duplication from Typescript
Fixes #12
Won't be needed after Microsoft/Typescript#36242 is fixed or has a better workaround.

Note that this PR may cause reordering of triple-slash references.

Patch:
diff --git a/index.js b/index.js
index a357383..0d6f314 100644
--- a/index.js
+++ b/index.js
@@ -6,6 +6,43 @@ const path = require("path");
 const assert = require("assert");
 
 /** @typedef {import("typescript").Node} Node */
+/**
+ * @param {string} src
+ * @param {string} target
+ */
+function main(src, target) {
+  if (!src || !target) {
+    console.log("Usage: node index.js test test/ts3.4");
+    process.exit(1);
+  }
+
+  // TODO: target path is probably wrong for absolute src (or target?)
+  // TODO: Probably will want to alter package.json if discovered in the right place.
+  const program = ts.createProgram(
+    sh
+      .find(path.join(src))
+      .filter(f => f.endsWith(".d.ts") && !/node_modules/.test(f)),
+    {}
+  );
+  const checker = program.getTypeChecker(); // just used for setting parent pointers right now
+  const files = mapDefined(program.getRootFileNames(), program.getSourceFile);
+  const printer = ts.createPrinter({
+    newLine: ts.NewLineKind.CarriageReturnLineFeed
+  });
+  for (const t of ts.transform(files, [doTransform]).transformed) {
+    const f = /** @type {import("typescript").SourceFile} */ (t);
+    const targetPath = path.join(target, f.fileName.slice(src.length));
+    sh.mkdir("-p", path.dirname(targetPath));
+    fs.writeFileSync(targetPath, dedupeTripleSlash(printer.printFile(f)));
+  }
+}
+module.exports.main = main;
+
+if (!(/** @type {*} */ (module.parent))) {
+  const src = process.argv[2];
+  const target = process.argv[3];
+  main(src, target);
+}
 
 /** @param {import("typescript").TransformationContext} k */
 function doTransform(k) {
@@ -109,42 +146,12 @@ function getMatchingAccessor(n, getset) {
     m => isOther(m) && m.name.getText() === n.name.getText()
   );
 }
-/**
- * @param {string} src
- * @param {string} target
- */
-function main(src, target) {
-  if (!src || !target) {
-    console.log("Usage: node index.js test test/ts3.4");
-    process.exit(1);
-  }
 
-  // TODO: target path is probably wrong for absolute src (or target?)
-  // TODO: Probably will want to alter package.json if discovered in the right place.
-  const program = ts.createProgram(
-    sh
-      .find(path.join(src))
-      .filter(f => f.endsWith(".d.ts") && !/node_modules/.test(f)),
-    {}
-  );
-  const checker = program.getTypeChecker(); // just used for setting parent pointers right now
-  const files = mapDefined(program.getRootFileNames(), program.getSourceFile);
-  const printer = ts.createPrinter({
-    newLine: ts.NewLineKind.CarriageReturnLineFeed
-  });
-  for (const t of ts.transform(files, [doTransform]).transformed) {
-    const f = /** @type {import("typescript").SourceFile} */ (t);
-    const targetPath = path.join(target, f.fileName.slice(src.length));
-    sh.mkdir("-p", path.dirname(targetPath));
-    fs.writeFileSync(targetPath, printer.printFile(f));
-  }
-}
-module.exports.main = main;
-
-if (!(/** @type {*} */ (module.parent))) {
-  const src = process.argv[2];
-  const target = process.argv[3];
-  main(src, target);
+/** @param {string} s */
+function dedupeTripleSlash(s) {
+  const lines = s.split("\n");
+  const i = lines.findIndex(line => !line.startsWith("/// <reference "));
+  return [...new Set(lines.slice(0, i)), ...lines.slice(i)].join("\n");
 }
 
 /**


Test patch:
diff --git a/baselines/ts3.4/test.d.ts b/baselines/ts3.4/test.d.ts
index 5d03581..7e1711c 100644
--- a/baselines/ts3.4/test.d.ts
+++ b/baselines/ts3.4/test.d.ts
@@ -1,10 +1,11 @@
-/// <reference types="node" />
+/// <reference path="./src/test.d.ts" />
 /// <reference types="node" />
 export class C {
     protected p: number;
     public readonly q: string;
     private r: boolean;
 }
+// hi, this should still be there
 export namespace N {
     abstract class D {
         p: number;
diff --git a/test/test.d.ts b/test/test.d.ts
index dfda6a3..17a6fbb 100644
--- a/test/test.d.ts
+++ b/test/test.d.ts
@@ -1,10 +1,12 @@
 /// <reference types="node" />
+/// <reference path="./src/test.d.ts" />
 export class C {
   protected get p(): number;
   protected set p(value: number);
   public get q(): string;
   private set r(value: boolean);
 }
+// hi, this should still be there
 export namespace N {
   abstract class D {
     get p(): number;