diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts
index 95a320ac052..44927a7a49a 100644
--- a/src/harness/fourslash.ts
+++ b/src/harness/fourslash.ts
@@ -14,6 +14,7 @@
//
///
+///
///
///
///
@@ -126,12 +127,13 @@ module FourSlash {
outDir: 'outDir',
sourceMap: 'sourceMap',
sourceRoot: 'sourceRoot',
+ allowNonTsExtensions: 'allowNonTsExtensions',
resolveReference: 'ResolveReference', // This flag is used to specify entry file for resolve file references. The flag is only allow once per test file
};
// List of allowed metadata names
var fileMetadataNames = [testOptMetadataNames.fileName, testOptMetadataNames.emitThisFile, testOptMetadataNames.resolveReference];
- var globalMetadataNames = [testOptMetadataNames.baselineFile, testOptMetadataNames.declaration,
+ var globalMetadataNames = [testOptMetadataNames.allowNonTsExtensions, testOptMetadataNames.baselineFile, testOptMetadataNames.declaration,
testOptMetadataNames.mapRoot, testOptMetadataNames.module, testOptMetadataNames.out,
testOptMetadataNames.outDir, testOptMetadataNames.sourceMap, testOptMetadataNames.sourceRoot]
@@ -141,6 +143,9 @@ module FourSlash {
for (var prop in globalOptions) {
if (globalOptions.hasOwnProperty(prop)) {
switch (prop) {
+ case testOptMetadataNames.allowNonTsExtensions:
+ settings.allowNonTsExtensions = true;
+ break;
case testOptMetadataNames.declaration:
settings.declaration = true;
break;
@@ -788,6 +793,16 @@ module FourSlash {
return "\nActual " + name + ":\n\t" + actualValue + "\nExpected value:\n\t" + expectedValue;
}
+ public getSemanticDiagnostics(expected: string) {
+ var diagnostics = this.languageService.getSemanticDiagnostics(this.activeFile.fileName);
+ var realized = ts.realizeDiagnostics(diagnostics, "\r\n");
+ var actual = JSON.stringify(realized, null, " ");
+ if (actual !== expected) {
+ ts.sys.writeFile("c:\\temp\\out.txt", actual);
+ }
+ assert.equal(actual, expected);
+ }
+
public verifyQuickInfoString(negative: boolean, expectedText?: string, expectedDocumentation?: string) {
[expectedText, expectedDocumentation].forEach(str => {
if (str) {
diff --git a/src/services/services.ts b/src/services/services.ts
index 88a56a850cb..8715a171c8b 100644
--- a/src/services/services.ts
+++ b/src/services/services.ts
@@ -2420,12 +2420,10 @@ module ts {
case SyntaxKind.ExportAssignment:
diagnostics.push(createDiagnosticForNode(node, Diagnostics.export_can_only_be_used_in_TypeScript));
return;
- case SyntaxKind.TypeParameter:
- diagnostics.push(createDiagnosticForNode(node, Diagnostics.type_parameter_declarations_can_only_be_used_in_TypeScript));
- return;
case SyntaxKind.ClassDeclaration:
let classDeclaration = node;
- if (checkModifiers(classDeclaration.modifiers)) {
+ if (checkModifiers(classDeclaration.modifiers) ||
+ checkTypeParameters(classDeclaration.typeParameters)) {
return;
}
break;
@@ -2456,6 +2454,7 @@ module ts {
case SyntaxKind.FunctionDeclaration:
let functionDeclaration = node;
if (checkModifiers(functionDeclaration.modifiers) ||
+ checkTypeParameters(functionDeclaration.typeParameters) ||
checkTypeAnnotation(functionDeclaration.type)) {
return;
}
@@ -2476,7 +2475,8 @@ module ts {
case SyntaxKind.NewExpression:
let expression = node;
if (expression.typeArguments && expression.typeArguments.length > 0) {
- diagnostics.push(createFileDiagnostic(sourceFile, expression.typeArguments.pos, expression.typeArguments.end,
+ let start = expression.typeArguments.pos;
+ diagnostics.push(createFileDiagnostic(sourceFile, start, expression.typeArguments.end - start,
Diagnostics.type_arguments_can_only_be_used_in_TypeScript));
return;
}
@@ -2484,7 +2484,8 @@ module ts {
case SyntaxKind.Parameter:
let parameter = node;
if (parameter.modifiers) {
- diagnostics.push(createFileDiagnostic(sourceFile, parameter.modifiers.pos, parameter.modifiers.end,
+ let start = parameter.modifiers.pos;
+ diagnostics.push(createFileDiagnostic(sourceFile, start, parameter.modifiers.end - start,
Diagnostics.parameter_modifiers_can_only_be_used_in_TypeScript));
return;
}
@@ -2511,6 +2512,15 @@ module ts {
forEachChild(node, walk);
}
+ function checkTypeParameters(typeParameters: NodeArray): boolean {
+ if (typeParameters) {
+ let start = typeParameters.pos;
+ diagnostics.push(createFileDiagnostic(sourceFile, start, typeParameters.end - start, Diagnostics.type_parameter_declarations_can_only_be_used_in_TypeScript));
+ return true;
+ }
+ return false;
+ }
+
function checkTypeAnnotation(type: TypeNode): boolean {
if (type) {
diagnostics.push(createDiagnosticForNode(type, Diagnostics.types_can_only_be_used_in_TypeScript));
diff --git a/src/services/shims.ts b/src/services/shims.ts
index fc47ff95280..f2082ee39cb 100644
--- a/src/services/shims.ts
+++ b/src/services/shims.ts
@@ -325,6 +325,22 @@ module ts {
}
}
+ /* @internal */
+ export function realizeDiagnostics(diagnostics: Diagnostic[], newLine: string): { message: string; start: number; length: number; category: string; } []{
+ return diagnostics.map(d => realizeDiagnostic(d, newLine));
+ }
+
+ function realizeDiagnostic(diagnostic: Diagnostic, newLine: string): { message: string; start: number; length: number; category: string; } {
+ return {
+ message: flattenDiagnosticMessageText(diagnostic.messageText, newLine),
+ start: diagnostic.start,
+ length: diagnostic.length,
+ /// TODO: no need for the tolowerCase call
+ category: DiagnosticCategory[diagnostic.category].toLowerCase(),
+ code: diagnostic.code
+ };
+ }
+
class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim {
private logger: Logger;
@@ -385,18 +401,7 @@ module ts {
private realizeDiagnostics(diagnostics: Diagnostic[]): { message: string; start: number; length: number; category: string; }[]{
var newLine = this.getNewLine();
- return diagnostics.map(d => this.realizeDiagnostic(d, newLine));
- }
-
- private realizeDiagnostic(diagnostic: Diagnostic, newLine: string): { message: string; start: number; length: number; category: string; } {
- return {
- message: flattenDiagnosticMessageText(diagnostic.messageText, newLine),
- start: diagnostic.start,
- length: diagnostic.length,
- /// TODO: no need for the tolowerCase call
- category: DiagnosticCategory[diagnostic.category].toLowerCase(),
- code: diagnostic.code
- };
+ return ts.realizeDiagnostics(diagnostics, newLine);
}
public getSyntacticClassifications(fileName: string, start: number, length: number): string {
diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts
index 087c43786f0..8ade18fc200 100644
--- a/tests/cases/fourslash/fourslash.ts
+++ b/tests/cases/fourslash/fourslash.ts
@@ -439,6 +439,10 @@ module FourSlashInterface {
displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[]) {
FourSlash.currentTestState.verifyQuickInfoDisplayParts(kind, kindModifiers, textSpan, displayParts, documentation);
}
+
+ public getSemanticDiagnostics(expected: string) {
+ FourSlash.currentTestState.getSemanticDiagnostics(expected);
+ }
}
export class edit {
diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics1.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics1.ts
new file mode 100644
index 00000000000..e73b487347a
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics1.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.tsjs
+//// import a = b;
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'import ... =' can only be used in TypeScript.",
+ "start": 0,
+ "length": 13,
+ "category": "error",
+ "code": 8002
+ }
+]`);
\ No newline at end of file
diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics2.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics2.ts
new file mode 100644
index 00000000000..e239577e5e4
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics2.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.tsjs
+//// export = b;
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'export=' can only be used in TypeScript.",
+ "start": 0,
+ "length": 11,
+ "category": "error",
+ "code": 8003
+ }
+]`);
\ No newline at end of file
diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics3.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics3.ts
new file mode 100644
index 00000000000..d74e97b36cc
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics3.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.tsjs
+//// class C;
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'type parameter declarations' can only be used in TypeScript.",
+ "start": 8,
+ "length": 1,
+ "category": "error",
+ "code": 8004
+ }
+]`);
\ No newline at end of file