diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts
index b141ce607f2..64a2515e774 100644
--- a/src/compiler/diagnosticInformationMap.generated.ts
+++ b/src/compiler/diagnosticInformationMap.generated.ts
@@ -506,6 +506,22 @@ module ts {
Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions: { code: 7024, category: DiagnosticCategory.Error, key: "Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions." },
You_cannot_rename_this_element: { code: 8000, category: DiagnosticCategory.Error, key: "You cannot rename this element." },
You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library: { code: 8001, category: DiagnosticCategory.Error, key: "You cannot rename elements that are defined in the standard TypeScript library." },
+ import_can_only_be_used_in_a_ts_file: { code: 8002, category: DiagnosticCategory.Error, key: "'import ... =' can only be used in a .ts file." },
+ export_can_only_be_used_in_a_ts_file: { code: 8003, category: DiagnosticCategory.Error, key: "'export=' can only be used in a .ts file." },
+ type_parameter_declarations_can_only_be_used_in_a_ts_file: { code: 8004, category: DiagnosticCategory.Error, key: "'type parameter declarations' can only be used in a .ts file." },
+ implements_clauses_can_only_be_used_in_a_ts_file: { code: 8005, category: DiagnosticCategory.Error, key: "'implements clauses' can only be used in a .ts file." },
+ interface_declarations_can_only_be_used_in_a_ts_file: { code: 8006, category: DiagnosticCategory.Error, key: "'interface declarations' can only be used in a .ts file." },
+ module_declarations_can_only_be_used_in_a_ts_file: { code: 8007, category: DiagnosticCategory.Error, key: "'module declarations' can only be used in a .ts file." },
+ type_aliases_can_only_be_used_in_a_ts_file: { code: 8008, category: DiagnosticCategory.Error, key: "'type aliases' can only be used in a .ts file." },
+ _0_can_only_be_used_in_a_ts_file: { code: 8009, category: DiagnosticCategory.Error, key: "'{0}' can only be used in a .ts file." },
+ types_can_only_be_used_in_a_ts_file: { code: 8010, category: DiagnosticCategory.Error, key: "'types' can only be used in a .ts file." },
+ type_arguments_can_only_be_used_in_a_ts_file: { code: 8011, category: DiagnosticCategory.Error, key: "'type arguments' can only be used in a .ts file." },
+ parameter_modifiers_can_only_be_used_in_a_ts_file: { code: 8012, category: DiagnosticCategory.Error, key: "'parameter modifiers' can only be used in a .ts file." },
+ can_only_be_used_in_a_ts_file: { code: 8013, category: DiagnosticCategory.Error, key: "'?' can only be used in a .ts file." },
+ property_declarations_can_only_be_used_in_a_ts_file: { code: 8014, category: DiagnosticCategory.Error, key: "'property declarations' can only be used in a .ts file." },
+ enum_declarations_can_only_be_used_in_a_ts_file: { code: 8015, category: DiagnosticCategory.Error, key: "'enum declarations' can only be used in a .ts file." },
+ type_assertion_expressions_can_only_be_used_in_a_ts_file: { code: 8016, category: DiagnosticCategory.Error, key: "'type assertion expressions' can only be used in a .ts file." },
+ decorators_can_only_be_used_in_a_ts_file: { code: 8017, category: DiagnosticCategory.Error, key: "'decorators' can only be used in a .ts file." },
yield_expressions_are_not_currently_supported: { code: 9000, category: DiagnosticCategory.Error, key: "'yield' expressions are not currently supported." },
Generators_are_not_currently_supported: { code: 9001, category: DiagnosticCategory.Error, key: "Generators are not currently supported." },
Only_identifiers_Slashqualified_names_with_optional_type_arguments_are_currently_supported_in_a_class_extends_clauses: { code: 9002, category: DiagnosticCategory.Error, key: "Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clauses." },
diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json
index cafc1f5efa9..79b652619b5 100644
--- a/src/compiler/diagnosticMessages.json
+++ b/src/compiler/diagnosticMessages.json
@@ -2017,6 +2017,71 @@
"category": "Error",
"code": 8001
},
+ "'import ... =' can only be used in a .ts file.": {
+ "category": "Error",
+ "code": 8002
+ },
+ "'export=' can only be used in a .ts file.": {
+ "category": "Error",
+ "code": 8003
+ },
+ "'type parameter declarations' can only be used in a .ts file.": {
+ "category": "Error",
+ "code": 8004
+ },
+ "'implements clauses' can only be used in a .ts file.": {
+ "category": "Error",
+ "code": 8005
+ },
+ "'interface declarations' can only be used in a .ts file.": {
+ "category": "Error",
+ "code": 8006
+ },
+ "'module declarations' can only be used in a .ts file.": {
+ "category": "Error",
+ "code": 8007
+ },
+ "'type aliases' can only be used in a .ts file.": {
+ "category": "Error",
+ "code": 8008
+ },
+ "'{0}' can only be used in a .ts file.": {
+ "category": "Error",
+ "code": 8009
+ },
+ "'types' can only be used in a .ts file.": {
+ "category": "Error",
+ "code": 8010
+ },
+ "'type arguments' can only be used in a .ts file.": {
+ "category": "Error",
+ "code": 8011
+ },
+ "'parameter modifiers' can only be used in a .ts file.": {
+ "category": "Error",
+ "code": 8012
+ },
+ "'?' can only be used in a .ts file.": {
+ "category": "Error",
+ "code": 8013
+ },
+ "'property declarations' can only be used in a .ts file.": {
+ "category": "Error",
+ "code": 8014
+ },
+ "'enum declarations' can only be used in a .ts file.": {
+ "category": "Error",
+ "code": 8015
+ },
+ "'type assertion expressions' can only be used in a .ts file.": {
+ "category": "Error",
+ "code": 8016
+ },
+ "'decorators' can only be used in a .ts file.": {
+ "category": "Error",
+ "code": 8017
+ },
+
"'yield' expressions are not currently supported.": {
"category": "Error",
"code": 9000
diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts
index 5d488259a36..7269b2db75d 100644
--- a/src/harness/fourslash.ts
+++ b/src/harness/fourslash.ts
@@ -14,6 +14,7 @@
//
///
+///
///
///
///
@@ -115,7 +116,7 @@ module FourSlash {
// Name of testcase metadata including ts.CompilerOptions properties that will be used by globalOptions
// To add additional option, add property into the testOptMetadataNames, refer the property in either globalMetadataNames or fileMetadataNames
// Add cases into convertGlobalOptionsToCompilationsSettings function for the compiler to acknowledge such option from meta data
- var testOptMetadataNames = {
+ var metadataOptionNames = {
baselineFile: 'BaselineFile',
declaration: 'declaration',
emitThisFile: 'emitThisFile', // This flag is used for testing getEmitOutput feature. It allows test-cases to indicate what file to be output in multiple files project
@@ -126,14 +127,15 @@ 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,
- testOptMetadataNames.mapRoot, testOptMetadataNames.module, testOptMetadataNames.out,
- testOptMetadataNames.outDir, testOptMetadataNames.sourceMap, testOptMetadataNames.sourceRoot]
+ var fileMetadataNames = [metadataOptionNames.fileName, metadataOptionNames.emitThisFile, metadataOptionNames.resolveReference];
+ var globalMetadataNames = [metadataOptionNames.allowNonTsExtensions, metadataOptionNames.baselineFile, metadataOptionNames.declaration,
+ metadataOptionNames.mapRoot, metadataOptionNames.module, metadataOptionNames.out,
+ metadataOptionNames.outDir, metadataOptionNames.sourceMap, metadataOptionNames.sourceRoot]
function convertGlobalOptionsToCompilerOptions(globalOptions: { [idx: string]: string }): ts.CompilerOptions {
var settings: ts.CompilerOptions = { target: ts.ScriptTarget.ES5 };
@@ -141,13 +143,16 @@ module FourSlash {
for (var prop in globalOptions) {
if (globalOptions.hasOwnProperty(prop)) {
switch (prop) {
- case testOptMetadataNames.declaration:
+ case metadataOptionNames.allowNonTsExtensions:
+ settings.allowNonTsExtensions = true;
+ break;
+ case metadataOptionNames.declaration:
settings.declaration = true;
break;
- case testOptMetadataNames.mapRoot:
+ case metadataOptionNames.mapRoot:
settings.mapRoot = globalOptions[prop];
break;
- case testOptMetadataNames.module:
+ case metadataOptionNames.module:
// create appropriate external module target for CompilationSettings
switch (globalOptions[prop]) {
case "AMD":
@@ -162,16 +167,16 @@ module FourSlash {
break;
}
break;
- case testOptMetadataNames.out:
+ case metadataOptionNames.out:
settings.out = globalOptions[prop];
break;
- case testOptMetadataNames.outDir:
+ case metadataOptionNames.outDir:
settings.outDir = globalOptions[prop];
break;
- case testOptMetadataNames.sourceMap:
+ case metadataOptionNames.sourceMap:
settings.sourceMap = true;
break;
- case testOptMetadataNames.sourceRoot:
+ case metadataOptionNames.sourceRoot:
settings.sourceRoot = globalOptions[prop];
break;
}
@@ -303,7 +308,7 @@ module FourSlash {
ts.forEach(testData.files, file => {
// Create map between fileName and its content for easily looking up when resolveReference flag is specified
this.inputFiles[file.fileName] = file.content;
- if (!startResolveFileRef && file.fileOptions[testOptMetadataNames.resolveReference]) {
+ if (!startResolveFileRef && file.fileOptions[metadataOptionNames.resolveReference]) {
startResolveFileRef = file;
} else if (startResolveFileRef) {
// If entry point for resolving file references is already specified, report duplication error
@@ -793,6 +798,13 @@ 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, " ");
+ assert.equal(actual, expected);
+ }
+
public verifyQuickInfoString(negative: boolean, expectedText?: string, expectedDocumentation?: string) {
[expectedText, expectedDocumentation].forEach(str => {
if (str) {
@@ -1131,7 +1143,7 @@ module FourSlash {
Harness.Baseline.runBaseline(
"Breakpoint Locations for " + this.activeFile.fileName,
- this.testData.globalOptions[testOptMetadataNames.baselineFile],
+ this.testData.globalOptions[metadataOptionNames.baselineFile],
() => {
return this.baselineCurrentFileLocations(pos => this.getBreakpointStatementLocation(pos));
},
@@ -1146,7 +1158,7 @@ module FourSlash {
var allFourSlashFiles = this.testData.files;
for (var idx = 0; idx < allFourSlashFiles.length; ++idx) {
var file = allFourSlashFiles[idx];
- if (file.fileOptions[testOptMetadataNames.emitThisFile]) {
+ if (file.fileOptions[metadataOptionNames.emitThisFile]) {
// Find a file with the flag emitThisFile turned on
emitFiles.push(file);
}
@@ -1159,7 +1171,7 @@ module FourSlash {
Harness.Baseline.runBaseline(
"Generate getEmitOutput baseline : " + emitFiles.join(" "),
- this.testData.globalOptions[testOptMetadataNames.baselineFile],
+ this.testData.globalOptions[metadataOptionNames.baselineFile],
() => {
var resultString = "";
// Loop through all the emittedFiles and emit them one by one
@@ -1704,7 +1716,7 @@ module FourSlash {
Harness.Baseline.runBaseline(
"Name OrDottedNameSpans for " + this.activeFile.fileName,
- this.testData.globalOptions[testOptMetadataNames.baselineFile],
+ this.testData.globalOptions[metadataOptionNames.baselineFile],
() => {
return this.baselineCurrentFileLocations(pos =>
this.getNameOrDottedNameSpan(pos));
@@ -2280,7 +2292,7 @@ module FourSlash {
if (globalMetadataNamesIndex === -1) {
if (fileMetadataNamesIndex === -1) {
throw new Error('Unrecognized metadata name "' + match[1] + '". Available global metadata names are: ' + globalMetadataNames.join(', ') + '; file metadata names are: ' + fileMetadataNames.join(', '));
- } else if (fileMetadataNamesIndex === fileMetadataNames.indexOf(testOptMetadataNames.fileName)) {
+ } else if (fileMetadataNamesIndex === fileMetadataNames.indexOf(metadataOptionNames.fileName)) {
// Found an @FileName directive, if this is not the first then create a new subfile
if (currentFileContent) {
var file = parseFileContent(currentFileContent, currentFileName, markerPositions, markers, ranges);
diff --git a/src/server/protocol.d.ts b/src/server/protocol.d.ts
index 382ce8494af..3a03c22d49e 100644
--- a/src/server/protocol.d.ts
+++ b/src/server/protocol.d.ts
@@ -617,12 +617,29 @@ declare module ts.server.protocol {
* Optional modifiers for the kind (such as 'public').
*/
kindModifiers: string;
+ /**
+ * A string that is used for comparing completion items so that they can be ordered. This
+ * is often the same as the name but may be different in certain circumstances.
+ */
+ sortText: string;
}
/**
* Additional completion entry details, available on demand
*/
- export interface CompletionEntryDetails extends CompletionEntry {
+ export interface CompletionEntryDetails {
+ /**
+ * The symbol's name.
+ */
+ name: string;
+ /**
+ * The symbol's kind (such as 'className' or 'parameterName').
+ */
+ kind: string;
+ /**
+ * Optional modifiers for the kind (such as 'public').
+ */
+ kindModifiers: string;
/**
* Display parts of the symbol (similar to quick info).
*/
diff --git a/src/services/services.ts b/src/services/services.ts
index 339dcc3a145..12ea84eafc1 100644
--- a/src/services/services.ts
+++ b/src/services/services.ts
@@ -1148,6 +1148,7 @@ module ts {
name: string;
kind: string; // see ScriptElementKind
kindModifiers: string; // see ScriptElementKindModifier, comma separated
+ sortText: string;
}
export interface CompletionEntryDetails {
@@ -1316,6 +1317,7 @@ module ts {
// TODO: move these to enums
export class ScriptElementKind {
static unknown = "";
+ static warning = "warning";
// predefined type (void) or keyword (class)
static keyword = "keyword";
@@ -2166,7 +2168,8 @@ module ts {
keywordCompletions.push({
name: tokenToString(i),
kind: ScriptElementKind.keyword,
- kindModifiers: ScriptElementKindModifier.none
+ kindModifiers: ScriptElementKindModifier.none,
+ sortText: "0"
});
}
@@ -2430,15 +2433,26 @@ module ts {
return program.getSyntacticDiagnostics(getValidSourceFile(fileName));
}
+ function isJavaScript(fileName: string) {
+ return fileExtensionIs(fileName, ".js");
+ }
+
/**
* getSemanticDiagnostiscs return array of Diagnostics. If '-d' is not enabled, only report semantic errors
* If '-d' enabled, report both semantic and emitter errors
*/
- function getSemanticDiagnostics(fileName: string) {
+ function getSemanticDiagnostics(fileName: string): Diagnostic[] {
synchronizeHostData();
let targetSourceFile = getValidSourceFile(fileName);
+ // For JavaScript files, we don't want to report the normal typescript semantic errors.
+ // Instead, we just report errors for using TypeScript-only constructs from within a
+ // JavaScript file.
+ if (isJavaScript(fileName)) {
+ return getJavaScriptSemanticDiagnostics(targetSourceFile);
+ }
+
// Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file.
// Therefore only get diagnostics for given file.
@@ -2452,35 +2466,199 @@ module ts {
return concatenate(semanticDiagnostics, declarationDiagnostics);
}
+ function getJavaScriptSemanticDiagnostics(sourceFile: SourceFile): Diagnostic[] {
+ let diagnostics: Diagnostic[] = [];
+ walk(sourceFile);
+
+ return diagnostics;
+
+ function walk(node: Node): boolean {
+ if (!node) {
+ return false;
+ }
+
+ switch (node.kind) {
+ case SyntaxKind.ImportEqualsDeclaration:
+ diagnostics.push(createDiagnosticForNode(node, Diagnostics.import_can_only_be_used_in_a_ts_file));
+ return true;
+ case SyntaxKind.ExportAssignment:
+ diagnostics.push(createDiagnosticForNode(node, Diagnostics.export_can_only_be_used_in_a_ts_file));
+ return true;
+ case SyntaxKind.ClassDeclaration:
+ let classDeclaration = node;
+ if (checkModifiers(classDeclaration.modifiers) ||
+ checkTypeParameters(classDeclaration.typeParameters)) {
+ return true;
+ }
+ break;
+ case SyntaxKind.HeritageClause:
+ let heritageClause = node;
+ if (heritageClause.token === SyntaxKind.ImplementsKeyword) {
+ diagnostics.push(createDiagnosticForNode(node, Diagnostics.implements_clauses_can_only_be_used_in_a_ts_file));
+ return true;
+ }
+ break;
+ case SyntaxKind.InterfaceDeclaration:
+ diagnostics.push(createDiagnosticForNode(node, Diagnostics.interface_declarations_can_only_be_used_in_a_ts_file));
+ return true;
+ case SyntaxKind.ModuleDeclaration:
+ diagnostics.push(createDiagnosticForNode(node, Diagnostics.module_declarations_can_only_be_used_in_a_ts_file));
+ return true;
+ case SyntaxKind.TypeAliasDeclaration:
+ diagnostics.push(createDiagnosticForNode(node, Diagnostics.type_aliases_can_only_be_used_in_a_ts_file));
+ return true;
+ case SyntaxKind.MethodDeclaration:
+ case SyntaxKind.MethodSignature:
+ case SyntaxKind.Constructor:
+ case SyntaxKind.GetAccessor:
+ case SyntaxKind.SetAccessor:
+ case SyntaxKind.FunctionExpression:
+ case SyntaxKind.FunctionDeclaration:
+ case SyntaxKind.ArrowFunction:
+ case SyntaxKind.FunctionDeclaration:
+ let functionDeclaration = node;
+ if (checkModifiers(functionDeclaration.modifiers) ||
+ checkTypeParameters(functionDeclaration.typeParameters) ||
+ checkTypeAnnotation(functionDeclaration.type)) {
+ return true;
+ }
+ break;
+ case SyntaxKind.VariableStatement:
+ let variableStatement = node;
+ if (checkModifiers(variableStatement.modifiers)) {
+ return true;
+ }
+ break;
+ case SyntaxKind.VariableDeclaration:
+ let variableDeclaration = node;
+ if (checkTypeAnnotation(variableDeclaration.type)) {
+ return true;
+ }
+ break;
+ case SyntaxKind.CallExpression:
+ case SyntaxKind.NewExpression:
+ let expression = node;
+ if (expression.typeArguments && expression.typeArguments.length > 0) {
+ let start = expression.typeArguments.pos;
+ diagnostics.push(createFileDiagnostic(sourceFile, start, expression.typeArguments.end - start,
+ Diagnostics.type_arguments_can_only_be_used_in_a_ts_file));
+ return true;
+ }
+ break;
+ case SyntaxKind.Parameter:
+ let parameter = node;
+ if (parameter.modifiers) {
+ let start = parameter.modifiers.pos;
+ diagnostics.push(createFileDiagnostic(sourceFile, start, parameter.modifiers.end - start,
+ Diagnostics.parameter_modifiers_can_only_be_used_in_a_ts_file));
+ return true;
+ }
+ if (parameter.questionToken) {
+ diagnostics.push(createDiagnosticForNode(parameter.questionToken, Diagnostics.can_only_be_used_in_a_ts_file));
+ return true;
+ }
+ if (parameter.type) {
+ diagnostics.push(createDiagnosticForNode(parameter.type, Diagnostics.types_can_only_be_used_in_a_ts_file));
+ return true;
+ }
+ break;
+ case SyntaxKind.PropertyDeclaration:
+ diagnostics.push(createDiagnosticForNode(node, Diagnostics.property_declarations_can_only_be_used_in_a_ts_file));
+ return true;
+ case SyntaxKind.EnumDeclaration:
+ diagnostics.push(createDiagnosticForNode(node, Diagnostics.enum_declarations_can_only_be_used_in_a_ts_file));
+ return true;
+ case SyntaxKind.TypeAssertionExpression:
+ let typeAssertionExpression = node;
+ diagnostics.push(createDiagnosticForNode(typeAssertionExpression.type, Diagnostics.type_assertion_expressions_can_only_be_used_in_a_ts_file));
+ return true;
+ case SyntaxKind.Decorator:
+ diagnostics.push(createDiagnosticForNode(node, Diagnostics.decorators_can_only_be_used_in_a_ts_file));
+ return true;
+ }
+
+ return 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_a_ts_file));
+ return true;
+ }
+ return false;
+ }
+
+ function checkTypeAnnotation(type: TypeNode): boolean {
+ if (type) {
+ diagnostics.push(createDiagnosticForNode(type, Diagnostics.types_can_only_be_used_in_a_ts_file));
+ return true;
+ }
+
+ return false;
+ }
+
+ function checkModifiers(modifiers: ModifiersArray): boolean {
+ if (modifiers) {
+ for (let modifier of modifiers) {
+ switch (modifier.kind) {
+ case SyntaxKind.PublicKeyword:
+ case SyntaxKind.PrivateKeyword:
+ case SyntaxKind.ProtectedKeyword:
+ case SyntaxKind.DeclareKeyword:
+ diagnostics.push(createDiagnosticForNode(modifier, Diagnostics._0_can_only_be_used_in_a_ts_file, tokenToString(modifier.kind)));
+ return true;
+
+ // These are all legal modifiers.
+ case SyntaxKind.StaticKeyword:
+ case SyntaxKind.ExportKeyword:
+ case SyntaxKind.ConstKeyword:
+ case SyntaxKind.DefaultKeyword:
+ }
+ }
+ }
+
+ return false;
+ }
+ }
+
function getCompilerOptionsDiagnostics() {
synchronizeHostData();
return program.getGlobalDiagnostics();
}
/// Completion
- function getCompletionEntryDisplayName(symbol: Symbol, target: ScriptTarget, performCharacterChecks: boolean): string {
+ function getCompletionEntryDisplayNameForSymbol(symbol: Symbol, target: ScriptTarget, performCharacterChecks: boolean): string {
let displayName = symbol.getName();
+ if (displayName) {
+ // If this is the default export, get the name of the declaration if it exists
+ if (displayName === "default") {
+ let localSymbol = getLocalSymbolForExportDefault(symbol);
+ if (localSymbol && localSymbol.name) {
+ displayName = symbol.valueDeclaration.localSymbol.name;
+ }
+ }
+
+ let firstCharCode = displayName.charCodeAt(0);
+ // First check of the displayName is not external module; if it is an external module, it is not valid entry
+ if ((symbol.flags & SymbolFlags.Namespace) && (firstCharCode === CharacterCodes.singleQuote || firstCharCode === CharacterCodes.doubleQuote)) {
+ // If the symbol is external module, don't show it in the completion list
+ // (i.e declare module "http" { let x; } | // <= request completion here, "http" should not be there)
+ return undefined;
+ }
+ }
+
+ return getCompletionEntryDisplayName(displayName, target, performCharacterChecks);
+ }
+
+ function getCompletionEntryDisplayName(displayName: string, target: ScriptTarget, performCharacterChecks: boolean): string {
if (!displayName) {
return undefined;
}
- // If this is the default export, get the name of the declaration if it exists
- if (displayName === "default") {
- let localSymbol = getLocalSymbolForExportDefault(symbol);
- if (localSymbol && localSymbol.name) {
- displayName = symbol.valueDeclaration.localSymbol.name;
- }
- }
-
let firstCharCode = displayName.charCodeAt(0);
- // First check of the displayName is not external module; if it is an external module, it is not valid entry
- if ((symbol.flags & SymbolFlags.Namespace) && (firstCharCode === CharacterCodes.singleQuote || firstCharCode === CharacterCodes.doubleQuote)) {
- // If the symbol is external module, don't show it in the completion list
- // (i.e declare module "http" { let x; } | // <= request completion here, "http" should not be there)
- return undefined;
- }
-
- if (displayName && displayName.length >= 2 && firstCharCode === displayName.charCodeAt(displayName.length - 1) &&
+ if (displayName.length >= 2 &&
+ firstCharCode === displayName.charCodeAt(displayName.length - 1) &&
(firstCharCode === CharacterCodes.singleQuote || firstCharCode === CharacterCodes.doubleQuote)) {
// If the user entered name for the symbol was quoted, removing the quotes is not enough, as the name could be an
// invalid identifier name. We need to check if whatever was inside the quotes is actually a valid identifier name.
@@ -2510,19 +2688,24 @@ module ts {
// Try to get a valid display name for this symbol, if we could not find one, then ignore it.
// We would like to only show things that can be added after a dot, so for instance numeric properties can
// not be accessed with a dot (a.1 <- invalid)
- let displayName = getCompletionEntryDisplayName(symbol, program.getCompilerOptions().target, /*performCharacterChecks:*/ true);
+ let displayName = getCompletionEntryDisplayNameForSymbol(symbol, program.getCompilerOptions().target, /*performCharacterChecks:*/ true);
if (!displayName) {
return undefined;
}
- // TODO(drosen): Right now we just permit *all* semantic meanings when calling 'getSymbolKind'
- // which is permissible given that it is backwards compatible; but really we should consider
- // passing the meaning for the node so that we don't report that a suggestion for a value is an interface.
- // We COULD also just do what 'getSymbolModifiers' does, which is to use the first declaration.
+ // TODO(drosen): Right now we just permit *all* semantic meanings when calling
+ // 'getSymbolKind' which is permissible given that it is backwards compatible; but
+ // really we should consider passing the meaning for the node so that we don't report
+ // that a suggestion for a value is an interface. We COULD also just do what
+ // 'getSymbolModifiers' does, which is to use the first declaration.
+
+ // Use a 'sortText' of 0' so that all symbol completion entries come before any other
+ // entries (like JavaScript identifier entries).
return {
name: displayName,
kind: getSymbolKind(symbol, typeChecker, location),
- kindModifiers: getSymbolModifiers(symbol)
+ kindModifiers: getSymbolModifiers(symbol),
+ sortText: "0",
};
}
@@ -2566,8 +2749,9 @@ module ts {
return undefined;
}
- // Find the node where completion is requested on, in the case of a completion after a dot, it is the member access expression
- // otherwise, it is a request for all visible symbols in the scope, and the node is the current location
+ // Find the node where completion is requested on, in the case of a completion after
+ // a dot, it is the member access expression other wise, it is a request for all
+ // visible symbols in the scope, and the node is the current location.
let node = currentToken;
let isRightOfDot = false;
if (contextToken && contextToken.kind === SyntaxKind.DotToken && contextToken.parent.kind === SyntaxKind.PropertyAccessExpression) {
@@ -2585,11 +2769,26 @@ module ts {
let semanticStart = new Date().getTime();
let isMemberCompletion: boolean;
let isNewIdentifierLocation: boolean;
- let symbols: Symbol[];
+ let symbols: Symbol[] = [];
if (isRightOfDot) {
+ getTypeScriptMemberSymbols();
+ }
+ else {
+ // For JavaScript or TypeScript, if we're not after a dot, then just try to get the
+ // global symbols in scope. These results should be valid for either language as
+ // the set of symbols that can be referenced from this location.
+ if (!tryGetGlobalSymbols()) {
+ return undefined;
+ }
+ }
+
+ log("getCompletionData: Semantic work: " + (new Date().getTime() - semanticStart));
+
+ return { symbols, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot };
+
+ function getTypeScriptMemberSymbols(): void {
// Right of dot member completion list
- symbols = [];
isMemberCompletion = true;
isNewIdentifierLocation = false;
@@ -2622,7 +2821,8 @@ module ts {
});
}
}
- else {
+
+ function tryGetGlobalSymbols(): boolean {
let containingObjectLiteral = getContainingObjectLiteralApplicableForCompletion(contextToken);
if (containingObjectLiteral) {
// Object literal expression, look up possible property names from contextual type
@@ -2631,7 +2831,7 @@ module ts {
let contextualType = typeInfoResolver.getContextualType(containingObjectLiteral);
if (!contextualType) {
- return undefined;
+ return false;
}
let contextualTypeMembers = typeInfoResolver.getPropertiesOfType(contextualType);
@@ -2704,12 +2904,10 @@ module ts {
let symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias;
symbols = typeInfoResolver.getSymbolsInScope(scopeNode, symbolMeanings);
}
+
+ return true;
}
- log("getCompletionData: Semantic work: " + (new Date().getTime() - semanticStart));
-
- return { symbols, isMemberCompletion, isNewIdentifierLocation, location };
-
/**
* Finds the first node that "embraces" the position, so that one may
* accurately aggregate locals from the closest containing scope.
@@ -3016,12 +3214,20 @@ module ts {
return undefined;
}
- let { symbols, isMemberCompletion, isNewIdentifierLocation, location } = completionData;
- if (!symbols || symbols.length === 0) {
- return undefined;
- }
+ let { symbols, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot } = completionData;
- var entries = getCompletionEntriesFromSymbols(symbols);
+ let entries: CompletionEntry[];
+ if (isRightOfDot && isJavaScript(fileName)) {
+ entries = getCompletionEntriesFromSymbols(symbols);
+ addRange(entries, getJavaScriptCompletionEntries());
+ }
+ else {
+ if (!symbols || symbols.length === 0) {
+ return undefined;
+ }
+
+ entries = getCompletionEntriesFromSymbols(symbols);
+ }
// Add keywords if this is not a member completion list
if (!isMemberCompletion) {
@@ -3030,21 +3236,51 @@ module ts {
return { isMemberCompletion, isNewIdentifierLocation, entries };
- function getCompletionEntriesFromSymbols(symbols: Symbol[]): CompletionEntry[] {
- let start = new Date().getTime();
- var entries: CompletionEntry[] = [];
- var nameToSymbol: Map = {};
+ function getJavaScriptCompletionEntries(): CompletionEntry[] {
+ let entries: CompletionEntry[] = [];
+ let allNames: Map = {};
+ let target = program.getCompilerOptions().target;
- for (let symbol of symbols) {
- let entry = createCompletionEntry(symbol, typeInfoResolver, location);
- if (entry) {
- let id = escapeIdentifier(entry.name);
- if (!lookUp(nameToSymbol, id)) {
- entries.push(entry);
- nameToSymbol[id] = symbol;
+ for (let sourceFile of program.getSourceFiles()) {
+ let nameTable = getNameTable(sourceFile);
+ for (let name in nameTable) {
+ if (!allNames[name]) {
+ allNames[name] = name;
+ let displayName = getCompletionEntryDisplayName(name, target, /*performCharacterChecks:*/ true);
+ if (displayName) {
+ let entry = {
+ name: displayName,
+ kind: ScriptElementKind.warning,
+ kindModifiers: "",
+ sortText: "1"
+ };
+ entries.push(entry);
+ }
}
}
}
+
+ return entries;
+ }
+
+ function getCompletionEntriesFromSymbols(symbols: Symbol[]): CompletionEntry[] {
+ let start = new Date().getTime();
+ var entries: CompletionEntry[] = [];
+
+ if (symbols) {
+ var nameToSymbol: Map = {};
+ for (let symbol of symbols) {
+ let entry = createCompletionEntry(symbol, typeInfoResolver, location);
+ if (entry) {
+ let id = escapeIdentifier(entry.name);
+ if (!lookUp(nameToSymbol, id)) {
+ entries.push(entry);
+ nameToSymbol[id] = symbol;
+ }
+ }
+ }
+ }
+
log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (new Date().getTime() - start));
return entries;
}
@@ -3063,7 +3299,7 @@ module ts {
// We don't need to perform character checks here because we're only comparing the
// name against 'entryName' (which is known to be good), not building a new
// completion entry.
- let symbol = forEach(symbols, s => getCompletionEntryDisplayName(s, target, /*performCharacterChecks:*/ false) === entryName ? s : undefined);
+ let symbol = forEach(symbols, s => getCompletionEntryDisplayNameForSymbol(s, target, /*performCharacterChecks:*/ false) === entryName ? s : undefined);
if (symbol) {
let displayPartsDocumentationsAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getValidSourceFile(fileName), location, typeInfoResolver, location, SemanticMeaning.All);
diff --git a/src/services/shims.ts b/src/services/shims.ts
index adcec5ada2b..7b5eeaf94d2 100644
--- a/src/services/shims.ts
+++ b/src/services/shims.ts
@@ -331,6 +331,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;
@@ -391,18 +407,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/baselines/reference/APISample_compile.js b/tests/baselines/reference/APISample_compile.js
index 9f729564fa6..6c28c96a6d8 100644
--- a/tests/baselines/reference/APISample_compile.js
+++ b/tests/baselines/reference/APISample_compile.js
@@ -1802,6 +1802,7 @@ declare module "typescript" {
name: string;
kind: string;
kindModifiers: string;
+ sortText: string;
}
interface CompletionEntryDetails {
name: string;
@@ -1944,6 +1945,7 @@ declare module "typescript" {
}
class ScriptElementKind {
static unknown: string;
+ static warning: string;
static keyword: string;
static scriptElement: string;
static moduleElement: string;
diff --git a/tests/baselines/reference/APISample_compile.types b/tests/baselines/reference/APISample_compile.types
index d0ff06ce765..635aff75628 100644
--- a/tests/baselines/reference/APISample_compile.types
+++ b/tests/baselines/reference/APISample_compile.types
@@ -5757,6 +5757,9 @@ declare module "typescript" {
kindModifiers: string;
>kindModifiers : string
+
+ sortText: string;
+>sortText : string
}
interface CompletionEntryDetails {
>CompletionEntryDetails : CompletionEntryDetails
@@ -6026,6 +6029,9 @@ declare module "typescript" {
static unknown: string;
>unknown : string
+ static warning: string;
+>warning : string
+
static keyword: string;
>keyword : string
diff --git a/tests/baselines/reference/APISample_linter.js b/tests/baselines/reference/APISample_linter.js
index 1945ded072d..f59fa91da14 100644
--- a/tests/baselines/reference/APISample_linter.js
+++ b/tests/baselines/reference/APISample_linter.js
@@ -1833,6 +1833,7 @@ declare module "typescript" {
name: string;
kind: string;
kindModifiers: string;
+ sortText: string;
}
interface CompletionEntryDetails {
name: string;
@@ -1975,6 +1976,7 @@ declare module "typescript" {
}
class ScriptElementKind {
static unknown: string;
+ static warning: string;
static keyword: string;
static scriptElement: string;
static moduleElement: string;
diff --git a/tests/baselines/reference/APISample_linter.types b/tests/baselines/reference/APISample_linter.types
index c3acb15dd9d..12f4ac12fdc 100644
--- a/tests/baselines/reference/APISample_linter.types
+++ b/tests/baselines/reference/APISample_linter.types
@@ -5903,6 +5903,9 @@ declare module "typescript" {
kindModifiers: string;
>kindModifiers : string
+
+ sortText: string;
+>sortText : string
}
interface CompletionEntryDetails {
>CompletionEntryDetails : CompletionEntryDetails
@@ -6172,6 +6175,9 @@ declare module "typescript" {
static unknown: string;
>unknown : string
+ static warning: string;
+>warning : string
+
static keyword: string;
>keyword : string
diff --git a/tests/baselines/reference/APISample_linter.types.pull b/tests/baselines/reference/APISample_linter.types.pull
index 68ff796104b..0a2a7ea948a 100644
--- a/tests/baselines/reference/APISample_linter.types.pull
+++ b/tests/baselines/reference/APISample_linter.types.pull
@@ -5903,6 +5903,9 @@ declare module "typescript" {
kindModifiers: string;
>kindModifiers : string
+
+ sortText: string;
+>sortText : string
}
interface CompletionEntryDetails {
>CompletionEntryDetails : CompletionEntryDetails
@@ -6172,6 +6175,9 @@ declare module "typescript" {
static unknown: string;
>unknown : string
+ static warning: string;
+>warning : string
+
static keyword: string;
>keyword : string
diff --git a/tests/baselines/reference/APISample_transform.js b/tests/baselines/reference/APISample_transform.js
index c7ab72c95a9..6bdf755ae12 100644
--- a/tests/baselines/reference/APISample_transform.js
+++ b/tests/baselines/reference/APISample_transform.js
@@ -1834,6 +1834,7 @@ declare module "typescript" {
name: string;
kind: string;
kindModifiers: string;
+ sortText: string;
}
interface CompletionEntryDetails {
name: string;
@@ -1976,6 +1977,7 @@ declare module "typescript" {
}
class ScriptElementKind {
static unknown: string;
+ static warning: string;
static keyword: string;
static scriptElement: string;
static moduleElement: string;
diff --git a/tests/baselines/reference/APISample_transform.types b/tests/baselines/reference/APISample_transform.types
index 6b80e4ccde6..4bd248d70c7 100644
--- a/tests/baselines/reference/APISample_transform.types
+++ b/tests/baselines/reference/APISample_transform.types
@@ -5853,6 +5853,9 @@ declare module "typescript" {
kindModifiers: string;
>kindModifiers : string
+
+ sortText: string;
+>sortText : string
}
interface CompletionEntryDetails {
>CompletionEntryDetails : CompletionEntryDetails
@@ -6122,6 +6125,9 @@ declare module "typescript" {
static unknown: string;
>unknown : string
+ static warning: string;
+>warning : string
+
static keyword: string;
>keyword : string
diff --git a/tests/baselines/reference/APISample_watcher.js b/tests/baselines/reference/APISample_watcher.js
index 9d6aa24ec62..3c11e27f0e1 100644
--- a/tests/baselines/reference/APISample_watcher.js
+++ b/tests/baselines/reference/APISample_watcher.js
@@ -1871,6 +1871,7 @@ declare module "typescript" {
name: string;
kind: string;
kindModifiers: string;
+ sortText: string;
}
interface CompletionEntryDetails {
name: string;
@@ -2013,6 +2014,7 @@ declare module "typescript" {
}
class ScriptElementKind {
static unknown: string;
+ static warning: string;
static keyword: string;
static scriptElement: string;
static moduleElement: string;
diff --git a/tests/baselines/reference/APISample_watcher.types b/tests/baselines/reference/APISample_watcher.types
index 8462f3e7ce9..f38cdc9b1af 100644
--- a/tests/baselines/reference/APISample_watcher.types
+++ b/tests/baselines/reference/APISample_watcher.types
@@ -6026,6 +6026,9 @@ declare module "typescript" {
kindModifiers: string;
>kindModifiers : string
+
+ sortText: string;
+>sortText : string
}
interface CompletionEntryDetails {
>CompletionEntryDetails : CompletionEntryDetails
@@ -6295,6 +6298,9 @@ declare module "typescript" {
static unknown: string;
>unknown : string
+ static warning: string;
+>warning : string
+
static keyword: string;
>keyword : string
diff --git a/tests/cases/fourslash/commentsMultiModuleMultiFile.ts b/tests/cases/fourslash/commentsMultiModuleMultiFile.ts
index 87c8abe93a2..9cbe47dd560 100644
--- a/tests/cases/fourslash/commentsMultiModuleMultiFile.ts
+++ b/tests/cases/fourslash/commentsMultiModuleMultiFile.ts
@@ -28,7 +28,7 @@
// this line triggers a semantic/syntactic error check, remove line when 788570 is fixed
edit.insert('');
-
+debugger;
goTo.marker('1');
verify.completionListContains("multiM", "module multiM", "this is multi declare module\nthi is multi module 2\nthis is multi module 3 comment");
diff --git a/tests/cases/fourslash/completionListWithAmbientDeclaration.ts b/tests/cases/fourslash/completionListWithAmbientDeclaration.ts
index 7cfac28fb24..9fb4ffef90e 100644
--- a/tests/cases/fourslash/completionListWithAmbientDeclaration.ts
+++ b/tests/cases/fourslash/completionListWithAmbientDeclaration.ts
@@ -7,7 +7,7 @@
//// declare module 'https' {
//// }
//// /*2*/
-
+debugger;
goTo.marker("1");
verify.not.completionListContains("http");
goTo.marker("2");
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..05bc6727710
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics1.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.js
+//// import a = b;
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'import ... =' can only be used in a .ts file.",
+ "start": 0,
+ "length": 13,
+ "category": "error",
+ "code": 8002
+ }
+]`);
\ No newline at end of file
diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics10.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics10.ts
new file mode 100644
index 00000000000..84c6c45f870
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics10.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.js
+//// function F() { }
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'type parameter declarations' can only be used in a .ts file.",
+ "start": 11,
+ "length": 1,
+ "category": "error",
+ "code": 8004
+ }
+]`);
\ No newline at end of file
diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics11.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics11.ts
new file mode 100644
index 00000000000..7dfd3c4965b
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics11.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.js
+//// function F(): number { }
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'types' can only be used in a .ts file.",
+ "start": 14,
+ "length": 6,
+ "category": "error",
+ "code": 8010
+ }
+]`);
\ No newline at end of file
diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics12.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics12.ts
new file mode 100644
index 00000000000..88a1331ef23
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics12.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.js
+//// declare var v;
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'declare' can only be used in a .ts file.",
+ "start": 0,
+ "length": 7,
+ "category": "error",
+ "code": 8009
+ }
+]`);
\ No newline at end of file
diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics13.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics13.ts
new file mode 100644
index 00000000000..21a5e9cdcaa
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics13.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.js
+//// var v: () => number;
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'types' can only be used in a .ts file.",
+ "start": 7,
+ "length": 12,
+ "category": "error",
+ "code": 8010
+ }
+]`);
\ No newline at end of file
diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics14.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics14.ts
new file mode 100644
index 00000000000..8cd178ffec1
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics14.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.js
+//// Foo();
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'type arguments' can only be used in a .ts file.",
+ "start": 4,
+ "length": 6,
+ "category": "error",
+ "code": 8011
+ }
+]`);
\ No newline at end of file
diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics15.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics15.ts
new file mode 100644
index 00000000000..d1c3a8c6e63
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics15.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.js
+//// function F(public p) { }
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'parameter modifiers' can only be used in a .ts file.",
+ "start": 11,
+ "length": 6,
+ "category": "error",
+ "code": 8012
+ }
+]`);
\ No newline at end of file
diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics16.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics16.ts
new file mode 100644
index 00000000000..2ccac13dbf9
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics16.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.js
+//// function F(p?) { }
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'?' can only be used in a .ts file.",
+ "start": 12,
+ "length": 1,
+ "category": "error",
+ "code": 8013
+ }
+]`);
\ No newline at end of file
diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics17.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics17.ts
new file mode 100644
index 00000000000..5e94c806c60
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics17.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.js
+//// function F(a: number) { }
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'types' can only be used in a .ts file.",
+ "start": 14,
+ "length": 6,
+ "category": "error",
+ "code": 8010
+ }
+]`);
\ No newline at end of file
diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics18.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics18.ts
new file mode 100644
index 00000000000..a2859060cde
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics18.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.js
+//// class C { v }
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'property declarations' can only be used in a .ts file.",
+ "start": 10,
+ "length": 1,
+ "category": "error",
+ "code": 8014
+ }
+]`);
\ No newline at end of file
diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics19.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics19.ts
new file mode 100644
index 00000000000..34dbbc0271d
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics19.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.js
+//// enum E { }
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'enum declarations' can only be used in a .ts file.",
+ "start": 5,
+ "length": 1,
+ "category": "error",
+ "code": 8015
+ }
+]`);
\ 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..b26d16f9017
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics2.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.js
+//// export = b;
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'export=' can only be used in a .ts file.",
+ "start": 0,
+ "length": 11,
+ "category": "error",
+ "code": 8003
+ }
+]`);
\ No newline at end of file
diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics20.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics20.ts
new file mode 100644
index 00000000000..790f02bac92
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics20.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.js
+//// var v = undefined;
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'type assertion expressions' can only be used in a .ts file.",
+ "start": 9,
+ "length": 6,
+ "category": "error",
+ "code": 8016
+ }
+]`);
\ No newline at end of file
diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics21.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics21.ts
new file mode 100644
index 00000000000..23e3274261c
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics21.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.js
+//// @internal class C {}
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'decorators' can only be used in a .ts file.",
+ "start": 0,
+ "length": 9,
+ "category": "error",
+ "code": 8017
+ }
+]`);
\ 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..c7b6c6a80cf
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics3.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.js
+//// class C { }
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'type parameter declarations' can only be used in a .ts file.",
+ "start": 8,
+ "length": 1,
+ "category": "error",
+ "code": 8004
+ }
+]`);
\ No newline at end of file
diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics4.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics4.ts
new file mode 100644
index 00000000000..f32ee5c4b68
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics4.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.js
+//// public class C { }
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'public' can only be used in a .ts file.",
+ "start": 0,
+ "length": 6,
+ "category": "error",
+ "code": 8009
+ }
+]`);
\ No newline at end of file
diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics5.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics5.ts
new file mode 100644
index 00000000000..e405624c9b0
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics5.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.js
+//// class C implements D { }
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'implements clauses' can only be used in a .ts file.",
+ "start": 8,
+ "length": 12,
+ "category": "error",
+ "code": 8005
+ }
+]`);
\ No newline at end of file
diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics6.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics6.ts
new file mode 100644
index 00000000000..918eb035a8b
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics6.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.js
+//// interface I { }
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'interface declarations' can only be used in a .ts file.",
+ "start": 10,
+ "length": 1,
+ "category": "error",
+ "code": 8006
+ }
+]`);
\ No newline at end of file
diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics7.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics7.ts
new file mode 100644
index 00000000000..cdec262f699
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics7.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.js
+//// module M { }
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'module declarations' can only be used in a .ts file.",
+ "start": 7,
+ "length": 1,
+ "category": "error",
+ "code": 8007
+ }
+]`);
\ No newline at end of file
diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics8.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics8.ts
new file mode 100644
index 00000000000..a71a2cf2bc7
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics8.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.js
+//// type a = b;
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'type aliases' can only be used in a .ts file.",
+ "start": 0,
+ "length": 11,
+ "category": "error",
+ "code": 8008
+ }
+]`);
\ No newline at end of file
diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics9.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics9.ts
new file mode 100644
index 00000000000..4bd4ce706b9
--- /dev/null
+++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics9.ts
@@ -0,0 +1,15 @@
+///
+
+// @allowNonTsExtensions: true
+// @Filename: a.js
+//// public function F() { }
+
+verify.getSemanticDiagnostics(`[
+ {
+ "message": "'public' can only be used in a .ts file.",
+ "start": 0,
+ "length": 6,
+ "category": "error",
+ "code": 8009
+ }
+]`);
\ No newline at end of file