diff --git a/Jakefile.js b/Jakefile.js
index b3e18e8cb1a..ad853238111 100644
--- a/Jakefile.js
+++ b/Jakefile.js
@@ -143,6 +143,7 @@ var harnessSources = harnessCoreSources.concat([
"customTransforms.ts",
"programMissingFiles.ts",
"symbolWalker.ts",
+ "languageService.ts",
].map(function (f) {
return path.join(unittestsDirectory, f);
})).concat([
diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts
index 2a07d2b6560..725070c02bf 100644
--- a/src/compiler/utilities.ts
+++ b/src/compiler/utilities.ts
@@ -32,7 +32,6 @@ namespace ts {
}
const stringWriter = createSingleLineStringWriter();
- let stringWriterAcquired = false;
function createSingleLineStringWriter(): StringSymbolWriter {
let str = "";
@@ -62,15 +61,14 @@ namespace ts {
}
export function usingSingleLineStringWriter(action: (writer: StringSymbolWriter) => void): string {
+ const oldString = stringWriter.string();
try {
- Debug.assert(!stringWriterAcquired);
- stringWriterAcquired = true;
action(stringWriter);
return stringWriter.string();
}
finally {
stringWriter.clear();
- stringWriterAcquired = false;
+ stringWriter.writeKeyword(oldString);
}
}
diff --git a/src/harness/tsconfig.json b/src/harness/tsconfig.json
index 1469079bcaa..bd7c9bc2ffa 100644
--- a/src/harness/tsconfig.json
+++ b/src/harness/tsconfig.json
@@ -128,6 +128,7 @@
"./unittests/extractMethods.ts",
"./unittests/textChanges.ts",
"./unittests/telemetry.ts",
+ "./unittests/languageService.ts",
"./unittests/programMissingFiles.ts"
]
}
diff --git a/src/harness/unittests/languageService.ts b/src/harness/unittests/languageService.ts
new file mode 100644
index 00000000000..9c838845c20
--- /dev/null
+++ b/src/harness/unittests/languageService.ts
@@ -0,0 +1,49 @@
+///
+
+namespace ts {
+ describe("languageService", () => {
+ const files: {[index: string]: string} = {
+ "foo.ts": `import Vue from "./vue";
+import Component from "./vue-class-component";
+import { vueTemplateHtml } from "./variables";
+
+@Component({
+ template: vueTemplateHtml,
+})
+class Carousel extends Vue {
+}`,
+ "variables.ts": `export const vueTemplateHtml = \`\`;`,
+ "vue.d.ts": `export namespace Vue { export type Config = { template: string }; }`,
+ "vue-class-component.d.ts": `import Vue from "./vue";
+export function Component(x: Config): any;`
+};
+ it("should be able to create a language service which can respond to deinition requests without throwing", () => {
+ const languageService = ts.createLanguageService({
+ getCompilationSettings() {
+ return {};
+ },
+ getScriptFileNames() {
+ return ["foo.ts", "variables.ts", "vue.d.ts", "vue-class-component.d.ts"];
+ },
+ getScriptVersion(_fileName) {
+ return "";
+ },
+ getScriptSnapshot(fileName) {
+ if (fileName === ".ts") {
+ return ts.ScriptSnapshot.fromString("");
+ }
+ return ts.ScriptSnapshot.fromString(files[fileName] || "");
+ },
+ getCurrentDirectory: () => ".",
+ getDefaultLibFileName(options) {
+ return ts.getDefaultLibFilePath(options);
+ },
+ fileExists: noop as any,
+ readFile: noop as any,
+ readDirectory: noop as any,
+ });
+ const definitions = languageService.getDefinitionAtPosition("foo.ts", 160); // 160 is the latter `vueTemplateHtml` position
+ expect(definitions).to.exist;
+ });
+ });
+}
\ No newline at end of file