Merge branch 'master' into out-module-concat

This commit is contained in:
Wesley Wigham 2015-10-30 15:47:35 -07:00
commit 70fba0b820
18 changed files with 805 additions and 697 deletions

View file

@ -96,7 +96,7 @@ var servicesSources = [
return path.join(servicesDirectory, f);
}));
var serverSources = [
var serverCoreSources = [
"node.d.ts",
"editorServices.ts",
"protocol.d.ts",
@ -104,7 +104,9 @@ var serverSources = [
"server.ts"
].map(function (f) {
return path.join(serverDirectory, f);
}).concat(servicesSources);
});
var serverSources = serverCoreSources.concat(servicesSources);
var languageServiceLibrarySources = [
"editorServices.ts",
@ -903,7 +905,9 @@ function lintFileAsync(options, path, cb) {
});
}
var lintTargets = compilerSources.concat(harnessCoreSources);
var lintTargets = compilerSources
.concat(harnessCoreSources)
.concat(serverCoreSources);
desc("Runs tslint on the compiler sources");
task("lint", ["build-rules"], function() {

View file

@ -12647,7 +12647,7 @@ namespace ts {
error(node.expression, Diagnostics.Setters_cannot_return_a_value);
}
else if (func.kind === SyntaxKind.Constructor) {
if (!isTypeAssignableTo(exprType, returnType)) {
if (!checkTypeAssignableTo(exprType, returnType, node.expression)) {
error(node.expression, Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class);
}
}

View file

@ -17,45 +17,55 @@ namespace ts {
True = -1
}
export function createFileMap<T>(getCanonicalFileName: (fileName: string) => string): FileMap<T> {
export function createFileMap<T>(keyMapper?: (key: string) => string): FileMap<T> {
let files: Map<T> = {};
return {
get,
set,
contains,
remove,
clear,
forEachValue: forEachValueInMap
forEachValue: forEachValueInMap,
clear
};
function set(fileName: string, value: T) {
files[normalizeKey(fileName)] = value;
function forEachValueInMap(f: (key: Path, value: T) => void) {
for (let key in files) {
f(<Path>key, files[key]);
}
}
function get(fileName: string) {
return files[normalizeKey(fileName)];
// path should already be well-formed so it does not need to be normalized
function get(path: Path): T {
return files[toKey(path)];
}
function contains(fileName: string) {
return hasProperty(files, normalizeKey(fileName));
function set(path: Path, value: T) {
files[toKey(path)] = value;
}
function remove (fileName: string) {
let key = normalizeKey(fileName);
function contains(path: Path) {
return hasProperty(files, toKey(path));
}
function remove(path: Path) {
const key = toKey(path);
delete files[key];
}
function forEachValueInMap(f: (value: T) => void) {
forEachValue(files, f);
}
function normalizeKey(key: string) {
return getCanonicalFileName(normalizeSlashes(key));
}
function clear() {
files = {};
}
function toKey(path: Path): string {
return keyMapper ? keyMapper(path) : path;
}
}
export function toPath(fileName: string, basePath: string, getCanonicalFileName: (path: string) => string): Path {
const nonCanonicalizedPath = isRootedDiskPath(fileName)
? normalizePath(fileName)
: getNormalizedAbsolutePath(fileName, basePath);
return <Path>getCanonicalFileName(nonCanonicalizedPath);
}
export const enum Comparison {

View file

@ -346,7 +346,7 @@ namespace ts {
? ((moduleNames: string[], containingFile: string) => host.resolveModuleNames(moduleNames, containingFile))
: ((moduleNames: string[], containingFile: string) => map(moduleNames, moduleName => resolveModuleName(moduleName, containingFile, options, host).resolvedModule));
let filesByName = createFileMap<SourceFile>(getCanonicalFileName);
let filesByName = createFileMap<SourceFile>();
// stores 'filename -> file association' ignoring case
// used to track cases when two file names differ only in casing
let filesByNameIgnoreCase = host.useCaseSensitiveFileNames() ? createFileMap<SourceFile>(fileName => fileName.toLowerCase()) : undefined;
@ -384,7 +384,7 @@ namespace ts {
program = {
getRootFileNames: () => rootNames,
getSourceFile: getSourceFile,
getSourceFile,
getSourceFiles: () => files,
getCompilerOptions: () => options,
getSyntacticDiagnostics,
@ -435,7 +435,7 @@ namespace ts {
// check if program source files has changed in the way that can affect structure of the program
let newSourceFiles: SourceFile[] = [];
let normalizedAbsoluteFileNames: string[] = [];
let filePaths: Path[] = [];
let modifiedSourceFiles: SourceFile[] = [];
for (let oldSourceFile of oldProgram.getSourceFiles()) {
@ -444,8 +444,8 @@ namespace ts {
return false;
}
const normalizedAbsolutePath = getNormalizedAbsolutePath(newSourceFile.fileName, currentDirectory);
normalizedAbsoluteFileNames.push(normalizedAbsolutePath);
newSourceFile.path = oldSourceFile.path;
filePaths.push(newSourceFile.path);
if (oldSourceFile !== newSourceFile) {
if (oldSourceFile.hasNoDefaultLib !== newSourceFile.hasNoDefaultLib) {
@ -469,7 +469,7 @@ namespace ts {
if (resolveModuleNamesWorker) {
let moduleNames = map(newSourceFile.imports, name => name.text);
let resolutions = resolveModuleNamesWorker(moduleNames, normalizedAbsolutePath);
let resolutions = resolveModuleNamesWorker(moduleNames, getNormalizedAbsolutePath(newSourceFile.fileName, currentDirectory));
// ensure that module resolution results are still correct
for (let i = 0; i < moduleNames.length; ++i) {
let newResolution = resolutions[i];
@ -500,7 +500,7 @@ namespace ts {
// update fileName -> file mapping
for (let i = 0, len = newSourceFiles.length; i < len; ++i) {
filesByName.set(normalizedAbsoluteFileNames[i], newSourceFiles[i]);
filesByName.set(filePaths[i], newSourceFiles[i]);
}
files = newSourceFiles;
@ -570,7 +570,7 @@ namespace ts {
}
function getSourceFile(fileName: string): SourceFile {
return filesByName.get(getNormalizedAbsolutePath(fileName, currentDirectory));
return filesByName.get(toPath(fileName, currentDirectory, getCanonicalFileName));
}
function getDiagnosticsHelper(
@ -741,7 +741,7 @@ namespace ts {
diagnostic = Diagnostics.File_0_has_unsupported_extension_The_only_supported_extensions_are_1;
diagnosticArgument = [fileName, "'" + supportedExtensions.join("', '") + "'"];
}
else if (!findSourceFile(fileName, getNormalizedAbsolutePath(fileName, currentDirectory), isDefaultLib, refFile, refPos, refEnd)) {
else if (!findSourceFile(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, refFile, refPos, refEnd)) {
diagnostic = Diagnostics.File_0_not_found;
diagnosticArgument = [fileName];
}
@ -751,13 +751,13 @@ namespace ts {
}
}
else {
let nonTsFile: SourceFile = options.allowNonTsExtensions && findSourceFile(fileName, getNormalizedAbsolutePath(fileName, currentDirectory), isDefaultLib, refFile, refPos, refEnd);
let nonTsFile: SourceFile = options.allowNonTsExtensions && findSourceFile(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, refFile, refPos, refEnd);
if (!nonTsFile) {
if (options.allowNonTsExtensions) {
diagnostic = Diagnostics.File_0_not_found;
diagnosticArgument = [fileName];
}
else if (!forEach(supportedExtensions, extension => findSourceFile(fileName + extension, getNormalizedAbsolutePath(fileName + extension, currentDirectory), isDefaultLib, refFile, refPos, refEnd))) {
else if (!forEach(supportedExtensions, extension => findSourceFile(fileName + extension, toPath(fileName + extension, currentDirectory, getCanonicalFileName), isDefaultLib, refFile, refPos, refEnd))) {
diagnostic = Diagnostics.File_0_not_found;
fileName += ".ts";
diagnosticArgument = [fileName];
@ -786,7 +786,7 @@ namespace ts {
}
// Get source file from normalized fileName
function findSourceFile(fileName: string, normalizedAbsolutePath: string, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number): SourceFile {
function findSourceFile(fileName: string, normalizedAbsolutePath: Path, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number): SourceFile {
if (filesByName.contains(normalizedAbsolutePath)) {
const file = filesByName.get(normalizedAbsolutePath);
// try to check if we've already seen this file but with a different casing in path
@ -811,6 +811,8 @@ namespace ts {
filesByName.set(normalizedAbsolutePath, file);
if (file) {
file.path = normalizedAbsolutePath;
if (host.useCaseSensitiveFileNames()) {
// for case-sensitive file systems check if we've already seen some file with similar filename ignoring case
const existingFile = filesByNameIgnoreCase.get(normalizedAbsolutePath);
@ -865,14 +867,7 @@ namespace ts {
let resolution = resolutions[i];
setResolvedModule(file, moduleNames[i], resolution);
if (resolution && !options.noResolve) {
const absoluteImportPath = isRootedDiskPath(resolution.resolvedFileName)
? resolution.resolvedFileName
: getNormalizedAbsolutePath(resolution.resolvedFileName, currentDirectory);
// convert an absolute import path to path that is relative to current directory
// this was host still can locate it but files names in user output will be shorter (and thus look nicer).
const relativePath = getRelativePathToDirectoryOrUrl(currentDirectory, absoluteImportPath, currentDirectory, getCanonicalFileName, false);
const importedFile = findSourceFile(relativePath, absoluteImportPath, /* isDefaultLib */ false, file, skipTrivia(file.text, file.imports[i].pos), file.imports[i].end);
const importedFile = findSourceFile(resolution.resolvedFileName, toPath(resolution.resolvedFileName, currentDirectory, getCanonicalFileName), /* isDefaultLib */ false, file, skipTrivia(file.text, file.imports[i].pos), file.imports[i].end);
if (importedFile && resolution.isExternalLibraryImport) {
if (!isExternalModule(importedFile)) {

View file

@ -81,12 +81,16 @@ namespace ts {
return <string>diagnostic.messageText;
}
function reportDiagnostic(diagnostic: Diagnostic) {
function reportDiagnostic(diagnostic: Diagnostic, host: CompilerHost) {
let output = "";
if (diagnostic.file) {
let loc = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
output += `${ diagnostic.file.fileName }(${ loc.line + 1 },${ loc.character + 1 }): `;
const relativeFileName = host
? convertToRelativePath(diagnostic.file.fileName, host.getCurrentDirectory(), fileName => host.getCanonicalFileName(fileName))
: diagnostic.file.fileName;
output += `${ relativeFileName }(${ loc.line + 1 },${ loc.character + 1 }): `;
}
let category = DiagnosticCategory[diagnostic.category].toLowerCase();
@ -95,9 +99,9 @@ namespace ts {
sys.write(output);
}
function reportDiagnostics(diagnostics: Diagnostic[]) {
function reportDiagnostics(diagnostics: Diagnostic[], host: CompilerHost) {
for (let i = 0; i < diagnostics.length; i++) {
reportDiagnostic(diagnostics[i]);
reportDiagnostic(diagnostics[i], host);
}
}
@ -166,7 +170,7 @@ namespace ts {
if (commandLine.options.locale) {
if (!isJSONSupported()) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--locale"));
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--locale"), /* compilerHost */ undefined);
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
validateLocaleAndSetLanguage(commandLine.options.locale, commandLine.errors);
@ -175,7 +179,7 @@ namespace ts {
// If there are any errors due to command line parsing and/or
// setting up localization, report them and quit.
if (commandLine.errors.length > 0) {
reportDiagnostics(commandLine.errors);
reportDiagnostics(commandLine.errors, compilerHost);
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
@ -185,7 +189,7 @@ namespace ts {
}
if (commandLine.options.version) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Version_0, ts.version));
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Version_0, ts.version), /* compilerHost */ undefined);
return sys.exit(ExitStatus.Success);
}
@ -197,12 +201,12 @@ namespace ts {
if (commandLine.options.project) {
if (!isJSONSupported()) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--project"));
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--project"), /* compilerHost */ undefined);
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
configFileName = normalizePath(combinePaths(commandLine.options.project, "tsconfig.json"));
if (commandLine.fileNames.length !== 0) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line));
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line), /* compilerHost */ undefined);
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
}
@ -220,7 +224,7 @@ namespace ts {
// Firefox has Object.prototype.watch
if (commandLine.options.watch && commandLine.options.hasOwnProperty("watch")) {
if (!sys.watchFile) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"));
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /* compilerHost */ undefined);
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
if (configFileName) {
@ -256,7 +260,7 @@ namespace ts {
let configObject = result.config;
let configParseResult = parseJsonConfigFileContent(configObject, sys, getDirectoryPath(configFileName));
if (configParseResult.errors.length > 0) {
reportDiagnostics(configParseResult.errors);
reportDiagnostics(configParseResult.errors, /* compilerHost */ undefined);
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
return;
}
@ -463,7 +467,7 @@ namespace ts {
}
}
reportDiagnostics(diagnostics);
reportDiagnostics(diagnostics, compilerHost);
// If the user doesn't want us to emit, then we're done at this point.
if (compilerOptions.noEmit) {
@ -474,7 +478,7 @@ namespace ts {
// Otherwise, emit and report any errors we ran into.
let emitOutput = program.emit();
reportDiagnostics(emitOutput.diagnostics);
reportDiagnostics(emitOutput.diagnostics, compilerHost);
// If the emitter didn't emit anything, then pass that value along.
if (emitOutput.emitSkipped) {
@ -587,7 +591,7 @@ namespace ts {
let currentDirectory = sys.getCurrentDirectory();
let file = normalizePath(combinePaths(currentDirectory, "tsconfig.json"));
if (sys.fileExists(file)) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file));
reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file), /* compilerHost */ undefined);
}
else {
let compilerOptions = extend(options, defaultInitCompilerOptions);
@ -602,7 +606,7 @@ namespace ts {
}
sys.writeFile(file, JSON.stringify(configurations, undefined, 4));
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Successfully_created_a_tsconfig_json_file));
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Successfully_created_a_tsconfig_json_file), /* compilerHost */ undefined);
}
return;

View file

@ -3,12 +3,17 @@ namespace ts {
[index: string]: T;
}
// branded string type used to store absolute, normalized and canonicalized paths
// arbitrary file name can be converted to Path via toPath function
export type Path = string & { __pathBrand: any };
export interface FileMap<T> {
get(fileName: string): T;
set(fileName: string, value: T): void;
contains(fileName: string): boolean;
remove(fileName: string): void;
forEachValue(f: (v: T) => void): void;
get(fileName: Path): T;
set(fileName: Path, value: T): void;
contains(fileName: Path): boolean;
remove(fileName: Path): void;
forEachValue(f: (key: Path, v: T) => void): void;
clear(): void;
}
@ -1250,6 +1255,7 @@ namespace ts {
endOfFileToken: Node;
fileName: string;
/* internal */ path: Path;
text: string;
amdDependencies: {path: string; name: string}[];

View file

@ -1357,7 +1357,6 @@ namespace ts {
export function tryResolveScriptReference(host: ScriptReferenceHost, sourceFile: SourceFile, reference: FileReference) {
if (!host.getCompilerOptions().noResolve) {
let referenceFileName = isRootedDiskPath(reference.fileName) ? reference.fileName : combinePaths(getDirectoryPath(sourceFile.fileName), reference.fileName);
referenceFileName = getNormalizedAbsolutePath(referenceFileName, host.getCurrentDirectory());
return host.getSourceFile(referenceFileName);
}
}
@ -2193,6 +2192,12 @@ namespace ts {
return result;
}
export function convertToRelativePath(absoluteOrRelativePath: string, basePath: string, getCanonicalFileName: (path: string) => string): string {
return !isRootedDiskPath(absoluteOrRelativePath)
? absoluteOrRelativePath
: getRelativePathToDirectoryOrUrl(basePath, absoluteOrRelativePath, basePath, getCanonicalFileName, /* isAbsolutePathAnUrl */ false);
}
const carriageReturnLineFeed = "\r\n";
const lineFeed = "\n";
export function getNewLineCharacter(options: CompilerOptions): string {

View file

@ -234,12 +234,15 @@ class ProjectRunner extends RunnerBase {
}
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean) {
// convert file name to rooted name
// if filename is not rooted - concat it with project root and then expand project root relative to current directory
let diskFileName = ts.isRootedDiskPath(fileName)
? fileName
: ts.normalizeSlashes(testCase.projectRoot) + "/" + ts.normalizeSlashes(fileName);
: Harness.IO.resolvePath(ts.normalizeSlashes(testCase.projectRoot) + "/" + ts.normalizeSlashes(fileName));
let diskRelativeName = ts.getRelativePathToDirectoryOrUrl(testCase.projectRoot, diskFileName,
getCurrentDirectory(), Harness.Compiler.getCanonicalFileName, /*isAbsolutePathAnUrl*/ false);
let currentDirectory = getCurrentDirectory();
// compute file name relative to current directory (expanded project root)
let diskRelativeName = ts.getRelativePathToDirectoryOrUrl(currentDirectory, diskFileName, currentDirectory, Harness.Compiler.getCanonicalFileName, /*isAbsolutePathAnUrl*/ false);
if (ts.isRootedDiskPath(diskRelativeName) || diskRelativeName.substr(0, 3) === "../") {
// If the generated output file resides in the parent folder or is rooted path,
// we need to instead create files that can live in the project reference folder
@ -376,8 +379,12 @@ class ProjectRunner extends RunnerBase {
runTest: testCase.runTest,
bug: testCase.bug,
rootDir: testCase.rootDir,
resolvedInputFiles: ts.map(compilerResult.program.getSourceFiles(), inputFile => inputFile.fileName),
emittedFiles: ts.map(compilerResult.outputFiles, outputFile => outputFile.emittedFileName)
resolvedInputFiles: ts.map(compilerResult.program.getSourceFiles(), inputFile => {
return ts.convertToRelativePath(inputFile.fileName, getCurrentDirectory(), path => Harness.Compiler.getCanonicalFileName(path));
}),
emittedFiles: ts.map(compilerResult.outputFiles, outputFile => {
return ts.convertToRelativePath(outputFile.emittedFileName, getCurrentDirectory(), path => Harness.Compiler.getCanonicalFileName(path));
})
};
return resolutionInfo;

File diff suppressed because it is too large Load diff

32
src/server/node.d.ts vendored
View file

@ -62,14 +62,14 @@ declare var SlowBuffer: {
// Buffer class
interface Buffer extends NodeBuffer { }
interface BufferConstructor {
new (str: string, encoding ?: string): Buffer;
new (str: string, encoding?: string): Buffer;
new (size: number): Buffer;
new (size: Uint8Array): Buffer;
new (array: any[]): Buffer;
prototype: Buffer;
isBuffer(obj: any): boolean;
byteLength(string: string, encoding ?: string): number;
concat(list: Buffer[], totalLength ?: number): Buffer;
byteLength(string: string, encoding?: string): number;
concat(list: Buffer[], totalLength?: number): Buffer;
}
declare var Buffer: BufferConstructor;
@ -78,7 +78,7 @@ declare var Buffer: BufferConstructor;
* GLOBAL INTERFACES *
* *
************************************************/
declare module NodeJS {
declare namespace NodeJS {
export interface ErrnoException extends Error {
errno?: any;
code?: string;
@ -245,7 +245,7 @@ interface NodeBuffer {
fill(value: any, offset?: number, end?: number): void;
}
declare module NodeJS {
declare namespace NodeJS {
export interface Path {
normalize(p: string): string;
join(...paths: any[]): string;
@ -258,7 +258,7 @@ declare module NodeJS {
}
}
declare module NodeJS {
declare namespace NodeJS {
export interface ReadLineInstance extends EventEmitter {
setPrompt(prompt: string, length: number): void;
prompt(preserveCursor?: boolean): void;
@ -280,8 +280,8 @@ declare module NodeJS {
}
}
declare module NodeJS {
module events {
declare namespace NodeJS {
namespace events {
export class EventEmitter implements NodeJS.EventEmitter {
static listenerCount(emitter: EventEmitter, event: string): number;
@ -297,8 +297,8 @@ declare module NodeJS {
}
}
declare module NodeJS {
module stream {
declare namespace NodeJS {
namespace stream {
export interface Stream extends events.EventEmitter {
pipe<T extends NodeJS.WritableStream>(destination: T, options?: { end?: boolean; }): T;
@ -397,8 +397,8 @@ declare module NodeJS {
}
}
declare module NodeJS {
module fs {
declare namespace NodeJS {
namespace fs {
interface Stats {
isFile(): boolean;
isDirectory(): boolean;
@ -547,8 +547,8 @@ declare module NodeJS {
}
}
declare module NodeJS {
module path {
declare namespace NodeJS {
namespace path {
export function normalize(p: string): string;
export function join(...paths: any[]): string;
export function resolve(...pathSegments: any[]): string;
@ -560,8 +560,8 @@ declare module NodeJS {
}
}
declare module NodeJS {
module _debugger {
declare namespace NodeJS {
namespace _debugger {
export interface Packet {
raw: string;
headers: string[];

View file

@ -16,7 +16,7 @@ declare namespace ts.server.protocol {
*/
type: string;
}
/**
* Client-initiated request message
*/
@ -31,7 +31,7 @@ declare namespace ts.server.protocol {
*/
arguments?: any;
}
/**
* Request to reload the project structure for all the opened files
*/
@ -107,7 +107,7 @@ declare namespace ts.server.protocol {
* A request to get the project information of the current file
*/
export interface ProjectInfoRequest extends Request {
arguments: ProjectInfoRequestArgs
arguments: ProjectInfoRequestArgs;
}
/**
@ -200,7 +200,7 @@ declare namespace ts.server.protocol {
/**
* Object found in response messages defining a span of text in source code.
*/
export interface TextSpan {
export interface TextSpan {
/**
* First character of the definition.
*/
@ -261,18 +261,18 @@ declare namespace ts.server.protocol {
* in the file at a given line and column.
*/
export interface DocumentHighlightsRequest extends FileLocationRequest {
arguments: DocumentHighlightsRequestArgs
arguments: DocumentHighlightsRequestArgs;
}
export interface HighlightSpan extends TextSpan {
kind: string
kind: string;
}
export interface DocumentHighlightsItem {
/**
* File containing highlight spans.
*/
file: string,
file: string;
/**
* Spans to highlight in file.
@ -422,76 +422,76 @@ declare namespace ts.server.protocol {
* Editor options
*/
export interface EditorOptions {
/** Number of spaces for each tab. Default value is 4. */
tabSize?: number;
/** Number of spaces to indent during formatting. Default value is 4. */
indentSize?: number;
/** The new line character to be used. Default value is the OS line delimiter. */
newLineCharacter?: string;
/** Whether tabs should be converted to spaces. Default value is true. */
convertTabsToSpaces?: boolean;
convertTabsToSpaces?: boolean;
}
/**
* Format options
*/
export interface FormatOptions extends EditorOptions {
/** Defines space handling after a comma delimiter. Default value is true. */
insertSpaceAfterCommaDelimiter?: boolean;
/** Defines space handling after a semicolon in a for statemen. Default value is true */
insertSpaceAfterSemicolonInForStatements?: boolean;
/** Defines space handling after a binary operator. Default value is true. */
insertSpaceBeforeAndAfterBinaryOperators?: boolean;
/** Defines space handling after keywords in control flow statement. Default value is true. */
insertSpaceAfterKeywordsInControlFlowStatements?: boolean;
/** Defines space handling after function keyword for anonymous functions. Default value is false. */
insertSpaceAfterFunctionKeywordForAnonymousFunctions?: boolean;
/** Defines space handling after opening and before closing non empty parenthesis. Default value is false. */
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis?: boolean;
/** Defines space handling after opening and before closing non empty brackets. Default value is false. */
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets?: boolean;
/** Defines whether an open brace is put onto a new line for functions or not. Default value is false. */
placeOpenBraceOnNewLineForFunctions?: boolean;
/** Defines whether an open brace is put onto a new line for control blocks or not. Default value is false. */
placeOpenBraceOnNewLineForControlBlocks?: boolean;
/** Index operator */
[key:string] : string | number | boolean;
[key: string] : string | number | boolean;
}
/**
* Information found in a configure request.
*/
export interface ConfigureRequestArguments {
/**
* Information about the host, for example 'Emacs 24.4' or
* 'Sublime Text version 3075'
*/
hostInfo?: string;
/**
* If present, tab settings apply only to this file.
*/
file?: string;
/**
* The format options to use during formatting and other code editing features.
*/
formatOptions?: FormatOptions;
formatOptions?: FormatOptions;
}
/**
@ -561,27 +561,27 @@ declare namespace ts.server.protocol {
* The symbol's kind (such as 'className' or 'parameterName' or plain 'text').
*/
kind: string;
/**
* Optional modifiers for the kind (such as 'public').
*/
kindModifiers: string;
/**
* Starting file location of symbol.
*/
start: Location;
/**
* One past last character of symbol.
*/
end: Location;
/**
* Type and kind of symbol.
*/
displayString: string;
/**
* Documentation associated with symbol.
*/
@ -603,7 +603,7 @@ declare namespace ts.server.protocol {
* Last line of range for which to format text in file.
*/
endLine: number;
/**
* Character offset on last line of range for which to format text in file.
*/
@ -619,7 +619,7 @@ declare namespace ts.server.protocol {
*/
export interface FormatRequest extends FileLocationRequest {
arguments: FormatRequestArgs;
}
}
/**
* Object found in response messages defining an editing
@ -638,7 +638,7 @@ declare namespace ts.server.protocol {
* One character past last character of the text span to edit.
*/
end: Location;
/**
* Replace the span defined above with this string (may be
* the empty string).
@ -723,7 +723,7 @@ declare namespace ts.server.protocol {
* Text of an item describing the symbol.
*/
text: string;
/**
* The symbol's kind (such as 'className' or 'parameterName' or plain 'text').
*/
@ -773,7 +773,7 @@ declare namespace ts.server.protocol {
* Display parts of the symbol (similar to quick info).
*/
displayParts: SymbolDisplayPart[];
/**
* Documentation strings for the symbol.
*/
@ -790,94 +790,94 @@ declare namespace ts.server.protocol {
/**
* Signature help information for a single parameter
*/
*/
export interface SignatureHelpParameter {
/**
* The parameter's name
*/
*/
name: string;
/**
* Documentation of the parameter.
*/
documentation: SymbolDisplayPart[];
/**
* Display parts of the parameter.
*/
displayParts: SymbolDisplayPart[];
/**
* Whether the parameter is optional or not.
*/
*/
isOptional: boolean;
}
/**
* Represents a single signature to show in signature help.
*/
*/
export interface SignatureHelpItem {
/**
* Whether the signature accepts a variable number of arguments.
*/
*/
isVariadic: boolean;
/**
* The prefix display parts.
*/
*/
prefixDisplayParts: SymbolDisplayPart[];
/**
* The suffix disaply parts.
*/
*/
suffixDisplayParts: SymbolDisplayPart[];
/**
* The separator display parts.
*/
*/
separatorDisplayParts: SymbolDisplayPart[];
/**
* The signature helps items for the parameters.
*/
*/
parameters: SignatureHelpParameter[];
/**
* The signature's documentation
*/
documentation: SymbolDisplayPart[];
}
/**
* Signature help items found in the response of a signature help request.
*/
export interface SignatureHelpItems {
/**
* The signature help items.
*/
*/
items: SignatureHelpItem[];
/**
* The span for which signature help should appear on a signature
*/
*/
applicableSpan: TextSpan;
/**
* The item selected in the set of available help items.
*/
*/
selectedItemIndex: number;
/**
* The argument selected in the set of parameters.
*/
*/
argumentIndex: number;
/**
* The argument count
*/
*/
argumentCount: number;
}
@ -885,9 +885,9 @@ declare namespace ts.server.protocol {
* Arguments of a signature help request.
*/
export interface SignatureHelpRequestArgs extends FileLocationRequestArgs {
}
/**
* Signature help request; value of command field is "signatureHelp".
* Given a file location (file, line, col), return the signature
@ -899,7 +899,7 @@ declare namespace ts.server.protocol {
/**
* Repsonse object for a SignatureHelpRequest.
*/
*/
export interface SignatureHelpResponse extends Response {
body?: SignatureHelpItems;
}
@ -926,9 +926,9 @@ declare namespace ts.server.protocol {
* it request for every file in this project.
*/
export interface GeterrForProjectRequest extends Request {
arguments: GeterrForProjectRequestArgs
arguments: GeterrForProjectRequestArgs;
}
/**
* Arguments for geterr messages.
*/
@ -968,12 +968,12 @@ declare namespace ts.server.protocol {
* Starting file location at which text appies.
*/
start: Location;
/**
* The last file location at which the text applies.
*/
end: Location;
/**
* Text of diagnostic message.
*/
@ -985,7 +985,7 @@ declare namespace ts.server.protocol {
* The file for which diagnostic information is reported.
*/
file: string;
/**
* An array of diagnostic information items.
*/
@ -999,7 +999,7 @@ declare namespace ts.server.protocol {
export interface DiagnosticEvent extends Event {
body?: DiagnosticEventBody;
}
/**
* Arguments for reload request.
*/
@ -1083,12 +1083,12 @@ declare namespace ts.server.protocol {
* The symbol's name.
*/
name: string;
/**
* The symbol's kind (such as 'className' or 'parameterName').
*/
kind: string;
/**
* exact, substring, or prefix.
*/
@ -1098,39 +1098,39 @@ declare namespace ts.server.protocol {
* If this was a case sensitive or insensitive match.
*/
isCaseSensitive?: boolean;
/**
* Optional modifiers for the kind (such as 'public').
*/
kindModifiers?: string;
/**
* The file in which the symbol is found.
*/
file: string;
/**
* The location within file at which the symbol is found.
*/
start: Location;
/**
* One past the last character of the symbol.
*/
end: Location;
/**
* Name of symbol's container symbol (if any); for example,
* the class name if symbol is a class member.
*/
containerName?: string;
/**
* Kind of symbol's container symbol (if any).
*/
containerKind?: string;
}
/**
* Navto response message. Body is an array of navto items. Each
* item gives a symbol that matched the search term.
@ -1208,7 +1208,7 @@ declare namespace ts.server.protocol {
childItems?: NavigationBarItem[];
}
export interface NavBarResponse extends Response {
export interface NavBarResponse extends Response {
body?: NavigationBarItem[];
}
}

View file

@ -1,13 +1,15 @@
/// <reference path="node.d.ts" />
/// <reference path="session.ts" />
// used in fs.writeSync
/* tslint:disable:no-null */
namespace ts.server {
var nodeproto: typeof NodeJS._debugger = require('_debugger');
var readline: NodeJS.ReadLine = require('readline');
var path: NodeJS.Path = require('path');
var fs: typeof NodeJS.fs = require('fs');
const nodeproto: typeof NodeJS._debugger = require("_debugger");
const readline: NodeJS.ReadLine = require("readline");
const path: NodeJS.Path = require("path");
const fs: typeof NodeJS.fs = require("fs");
var rl = readline.createInterface({
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false,
@ -68,7 +70,7 @@ namespace ts.server {
}
if (this.fd >= 0) {
s = s + "\n";
var prefix = Logger.padStringRight(type + " " + this.seq.toString(), " ");
const prefix = Logger.padStringRight(type + " " + this.seq.toString(), " ");
if (this.firstInGroup) {
s = prefix + s;
this.firstInGroup = false;
@ -77,7 +79,7 @@ namespace ts.server {
this.seq++;
this.firstInGroup = true;
}
var buf = new Buffer(s);
const buf = new Buffer(s);
fs.writeSync(this.fd, buf, 0, buf.length, null);
}
}
@ -95,12 +97,12 @@ namespace ts.server {
}
listen() {
rl.on('line', (input: string) => {
var message = input.trim();
rl.on("line", (input: string) => {
const message = input.trim();
this.onMessage(message);
});
rl.on('close', () => {
rl.on("close", () => {
this.exit();
});
}
@ -112,11 +114,11 @@ namespace ts.server {
}
function parseLoggingEnvironmentString(logEnvStr: string): LogOptions {
var logEnv: LogOptions = {};
var args = logEnvStr.split(' ');
for (var i = 0, len = args.length; i < (len - 1); i += 2) {
var option = args[i];
var value = args[i + 1];
const logEnv: LogOptions = {};
const args = logEnvStr.split(" ");
for (let i = 0, len = args.length; i < (len - 1); i += 2) {
const option = args[i];
const value = args[i + 1];
if (option && value) {
switch (option) {
case "-file":
@ -133,11 +135,11 @@ namespace ts.server {
// TSS_LOG "{ level: "normal | verbose | terse", file?: string}"
function createLoggerFromEnv() {
var fileName: string = undefined;
var detailLevel = "normal";
var logEnvStr = process.env["TSS_LOG"];
let fileName: string = undefined;
let detailLevel = "normal";
const logEnvStr = process.env["TSS_LOG"];
if (logEnvStr) {
var logEnv = parseLoggingEnvironmentString(logEnvStr);
const logEnv = parseLoggingEnvironmentString(logEnvStr);
if (logEnv.file) {
fileName = logEnv.file;
}
@ -153,7 +155,7 @@ namespace ts.server {
// This places log file in the directory containing editorServices.js
// TODO: check that this location is writable
var logger = createLoggerFromEnv();
const logger = createLoggerFromEnv();
let pending: string[] = [];
let canWrite = true;
@ -177,8 +179,8 @@ namespace ts.server {
// Override sys.write because fs.writeSync is not reliable on Node 4
ts.sys.write = (s: string) => writeMessage(s);
var ioSession = new IOSession(ts.sys, logger);
process.on('uncaughtException', function(err: Error) {
const ioSession = new IOSession(ts.sys, logger);
process.on("uncaughtException", function(err: Error) {
ioSession.logError(err, "unknown");
});
// Start listening

View file

@ -4,7 +4,7 @@
/// <reference path="editorServices.ts" />
namespace ts.server {
var spaceCache:string[] = [];
const spaceCache: string[] = [];
interface StackTraceError extends Error {
stack?: string;
@ -12,30 +12,31 @@ namespace ts.server {
export function generateSpaces(n: number): string {
if (!spaceCache[n]) {
var strBuilder = "";
for (var i = 0; i < n; i++) {
let strBuilder = "";
for (let i = 0; i < n; i++) {
strBuilder += " ";
}
spaceCache[n] = strBuilder;
}
}
return spaceCache[n];
}
export function generateIndentString(n: number, editorOptions: EditorOptions): string {
if (editorOptions.ConvertTabsToSpaces) {
return generateSpaces(n);
} else {
var result = "";
for (var i = 0; i < Math.floor(n / editorOptions.TabSize); i++) {
}
else {
let result = "";
for (let i = 0; i < Math.floor(n / editorOptions.TabSize); i++) {
result += "\t";
}
for (var i = 0; i < n % editorOptions.TabSize; i++) {
for (let i = 0; i < n % editorOptions.TabSize; i++) {
result += " ";
}
return result;
}
}
interface FileStart {
file: string;
start: ILineInfo;
@ -56,7 +57,7 @@ namespace ts.server {
return -1;
}
else if (a.file == b.file) {
var n = compareNumber(a.start.line, b.start.line);
const n = compareNumber(a.start.line, b.start.line);
if (n === 0) {
return compareNumber(a.start.offset, b.start.offset);
}
@ -66,7 +67,7 @@ namespace ts.server {
return 1;
}
}
function formatDiag(fileName: string, project: Project, diag: ts.Diagnostic) {
return {
start: project.compilerService.host.positionToLineOffset(fileName, diag.start),
@ -81,7 +82,7 @@ namespace ts.server {
}
function allEditsBeforePos(edits: ts.TextChange[], pos: number) {
for (var i = 0, len = edits.length; i < len; i++) {
for (let i = 0, len = edits.length; i < len; i++) {
if (ts.textSpanEnd(edits[i].span) >= pos) {
return false;
}
@ -89,7 +90,7 @@ namespace ts.server {
return true;
}
export module CommandNames {
export namespace CommandNames {
export const Brace = "brace";
export const Change = "change";
export const Close = "close";
@ -119,8 +120,8 @@ namespace ts.server {
export const Unknown = "unknown";
}
module Errors {
export var NoProject = new Error("No Project.");
namespace Errors {
export const NoProject = new Error("No Project.");
}
export interface ServerHost extends ts.System {
@ -136,13 +137,13 @@ namespace ts.server {
private changeSeq = 0;
constructor(
private host: ServerHost,
private byteLength: (buf: string, encoding?: string) => number,
private hrtime: (start?: number[]) => number[],
private host: ServerHost,
private byteLength: (buf: string, encoding?: string) => number,
private hrtime: (start?: number[]) => number[],
private logger: Logger
) {
this.projectService =
new ProjectService(host, logger, (eventName,project,fileName) => {
new ProjectService(host, logger, (eventName, project, fileName) => {
this.handleEvent(eventName, project, fileName);
});
}
@ -156,8 +157,8 @@ namespace ts.server {
}
public logError(err: Error, cmd: string) {
var typedErr = <StackTraceError>err;
var msg = "Exception on executing command " + cmd;
const typedErr = <StackTraceError>err;
let msg = "Exception on executing command " + cmd;
if (typedErr.message) {
msg += ":\n" + typedErr.message;
if (typedErr.stack) {
@ -172,16 +173,16 @@ namespace ts.server {
}
public send(msg: protocol.Message) {
var json = JSON.stringify(msg);
const json = JSON.stringify(msg);
if (this.logger.isVerbose()) {
this.logger.info(msg.type + ": " + json);
}
this.sendLineToClient('Content-Length: ' + (1 + this.byteLength(json, 'utf8')) +
'\r\n\r\n' + json);
this.sendLineToClient("Content-Length: " + (1 + this.byteLength(json, "utf8")) +
"\r\n\r\n" + json);
}
public event(info: any, eventName: string) {
var ev: protocol.Event = {
const ev: protocol.Event = {
seq: 0,
type: "event",
event: eventName,
@ -191,13 +192,13 @@ namespace ts.server {
}
private response(info: any, cmdName: string, reqSeq = 0, errorMsg?: string) {
var res: protocol.Response = {
const res: protocol.Response = {
seq: 0,
type: "response",
command: cmdName,
request_seq: reqSeq,
success: !errorMsg,
}
};
if (!errorMsg) {
res.body = info;
}
@ -213,10 +214,10 @@ namespace ts.server {
private semanticCheck(file: string, project: Project) {
try {
var diags = project.compilerService.languageService.getSemanticDiagnostics(file);
const diags = project.compilerService.languageService.getSemanticDiagnostics(file);
if (diags) {
var bakedDiags = diags.map((diag) => formatDiag(file, project, diag));
const bakedDiags = diags.map((diag) => formatDiag(file, project, diag));
this.event({ file: file, diagnostics: bakedDiags }, "semanticDiag");
}
}
@ -227,9 +228,9 @@ namespace ts.server {
private syntacticCheck(file: string, project: Project) {
try {
var diags = project.compilerService.languageService.getSyntacticDiagnostics(file);
const diags = project.compilerService.languageService.getSyntacticDiagnostics(file);
if (diags) {
var bakedDiags = diags.map((diag) => formatDiag(file, project, diag));
const bakedDiags = diags.map((diag) => formatDiag(file, project, diag));
this.event({ file: file, diagnostics: bakedDiags }, "syntaxDiag");
}
}
@ -242,7 +243,7 @@ namespace ts.server {
this.syntacticCheck(file, project);
this.semanticCheck(file, project);
}
private reloadProjects() {
this.projectService.reloadProjects();
}
@ -267,10 +268,10 @@ namespace ts.server {
clearImmediate(this.immediateId);
this.immediateId = undefined;
}
var index = 0;
var checkOne = () => {
let index = 0;
const checkOne = () => {
if (matchSeq(seq)) {
var checkSpec = checkList[index++];
const checkSpec = checkList[index++];
if (checkSpec.project.getSourceFileFromName(checkSpec.fileName, requireOpen)) {
this.syntacticCheck(checkSpec.fileName, checkSpec.project);
this.immediateId = setImmediate(() => {
@ -285,23 +286,23 @@ namespace ts.server {
});
}
}
}
};
if ((checkList.length > index) && (matchSeq(seq))) {
this.errorTimer = setTimeout(checkOne, ms);
}
}
private getDefinition(line: number, offset: number, fileName: string): protocol.FileSpan[] {
var file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
const file = ts.normalizePath(fileName);
const project = this.projectService.getProjectForFile(file);
if (!project) {
throw Errors.NoProject;
}
var compilerService = project.compilerService;
var position = compilerService.host.lineOffsetToPosition(file, line, offset);
const compilerService = project.compilerService;
const position = compilerService.host.lineOffsetToPosition(file, line, offset);
var definitions = compilerService.languageService.getDefinitionAtPosition(file, position);
const definitions = compilerService.languageService.getDefinitionAtPosition(file, position);
if (!definitions) {
return undefined;
}
@ -314,16 +315,16 @@ namespace ts.server {
}
private getTypeDefinition(line: number, offset: number, fileName: string): protocol.FileSpan[] {
var file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
const file = ts.normalizePath(fileName);
const project = this.projectService.getProjectForFile(file);
if (!project) {
throw Errors.NoProject;
}
var compilerService = project.compilerService;
var position = compilerService.host.lineOffsetToPosition(file, line, offset);
const compilerService = project.compilerService;
const position = compilerService.host.lineOffsetToPosition(file, line, offset);
var definitions = compilerService.languageService.getTypeDefinitionAtPosition(file, position);
const definitions = compilerService.languageService.getTypeDefinitionAtPosition(file, position);
if (!definitions) {
return undefined;
}
@ -361,7 +362,7 @@ namespace ts.server {
end,
file: fileName,
isWriteAccess
}
};
});
}
@ -375,9 +376,9 @@ namespace ts.server {
let { compilerService } = project;
let position = compilerService.host.lineOffsetToPosition(fileName, line, offset);
let documentHighlights = compilerService.languageService.getDocumentHighlights(fileName, position, filesToSearch);
if (!documentHighlights) {
return undefined;
}
@ -402,12 +403,12 @@ namespace ts.server {
}
private getProjectInfo(fileName: string, needFileNameList: boolean): protocol.ProjectInfo {
fileName = ts.normalizePath(fileName)
let project = this.projectService.getProjectForFile(fileName)
fileName = ts.normalizePath(fileName);
let project = this.projectService.getProjectForFile(fileName);
let projectInfo: protocol.ProjectInfo = {
configFileName: project.projectFilename
}
};
if (needFileNameList) {
projectInfo.fileNames = project.getFileNames();
@ -416,16 +417,16 @@ namespace ts.server {
return projectInfo;
}
private getRenameLocations(line: number, offset: number, fileName: string,findInComments: boolean, findInStrings: boolean): protocol.RenameResponseBody {
var file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
private getRenameLocations(line: number, offset: number, fileName: string, findInComments: boolean, findInStrings: boolean): protocol.RenameResponseBody {
const file = ts.normalizePath(fileName);
const project = this.projectService.getProjectForFile(file);
if (!project) {
throw Errors.NoProject;
}
var compilerService = project.compilerService;
var position = compilerService.host.lineOffsetToPosition(file, line, offset);
var renameInfo = compilerService.languageService.getRenameInfo(file, position);
const compilerService = project.compilerService;
const position = compilerService.host.lineOffsetToPosition(file, line, offset);
const renameInfo = compilerService.languageService.getRenameInfo(file, position);
if (!renameInfo) {
return undefined;
}
@ -437,12 +438,12 @@ namespace ts.server {
};
}
var renameLocations = compilerService.languageService.findRenameLocations(file, position, findInStrings, findInComments);
const renameLocations = compilerService.languageService.findRenameLocations(file, position, findInStrings, findInComments);
if (!renameLocations) {
return undefined;
}
var bakedRenameLocs = renameLocations.map(location => (<protocol.FileSpan>{
const bakedRenameLocs = renameLocations.map(location => (<protocol.FileSpan>{
file: location.fileName,
start: compilerService.host.positionToLineOffset(location.fileName, location.textSpan.start),
end: compilerService.host.positionToLineOffset(location.fileName, ts.textSpanEnd(location.textSpan)),
@ -466,7 +467,7 @@ namespace ts.server {
}
}
}).reduce<protocol.SpanGroup[]>((accum: protocol.SpanGroup[], cur: protocol.FileSpan) => {
var curFileAccum: protocol.SpanGroup;
let curFileAccum: protocol.SpanGroup;
if (accum.length > 0) {
curFileAccum = accum[accum.length - 1];
if (curFileAccum.file != cur.file) {
@ -487,34 +488,34 @@ namespace ts.server {
private getReferences(line: number, offset: number, fileName: string): protocol.ReferencesResponseBody {
// TODO: get all projects for this file; report refs for all projects deleting duplicates
// can avoid duplicates by eliminating same ref file from subsequent projects
var file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
const file = ts.normalizePath(fileName);
const project = this.projectService.getProjectForFile(file);
if (!project) {
throw Errors.NoProject;
}
var compilerService = project.compilerService;
var position = compilerService.host.lineOffsetToPosition(file, line, offset);
const compilerService = project.compilerService;
const position = compilerService.host.lineOffsetToPosition(file, line, offset);
var references = compilerService.languageService.getReferencesAtPosition(file, position);
const references = compilerService.languageService.getReferencesAtPosition(file, position);
if (!references) {
return undefined;
}
var nameInfo = compilerService.languageService.getQuickInfoAtPosition(file, position);
const nameInfo = compilerService.languageService.getQuickInfoAtPosition(file, position);
if (!nameInfo) {
return undefined;
}
var displayString = ts.displayPartsToString(nameInfo.displayParts);
var nameSpan = nameInfo.textSpan;
var nameColStart = compilerService.host.positionToLineOffset(file, nameSpan.start).offset;
var nameText = compilerService.host.getScriptSnapshot(file).getText(nameSpan.start, ts.textSpanEnd(nameSpan));
var bakedRefs: protocol.ReferencesResponseItem[] = references.map(ref => {
var start = compilerService.host.positionToLineOffset(ref.fileName, ref.textSpan.start);
var refLineSpan = compilerService.host.lineToTextSpan(ref.fileName, start.line - 1);
var snap = compilerService.host.getScriptSnapshot(ref.fileName);
var lineText = snap.getText(refLineSpan.start, ts.textSpanEnd(refLineSpan)).replace(/\r|\n/g, "");
const displayString = ts.displayPartsToString(nameInfo.displayParts);
const nameSpan = nameInfo.textSpan;
const nameColStart = compilerService.host.positionToLineOffset(file, nameSpan.start).offset;
const nameText = compilerService.host.getScriptSnapshot(file).getText(nameSpan.start, ts.textSpanEnd(nameSpan));
const bakedRefs: protocol.ReferencesResponseItem[] = references.map(ref => {
const start = compilerService.host.positionToLineOffset(ref.fileName, ref.textSpan.start);
const refLineSpan = compilerService.host.lineToTextSpan(ref.fileName, start.line - 1);
const snap = compilerService.host.getScriptSnapshot(ref.fileName);
const lineText = snap.getText(refLineSpan.start, ts.textSpanEnd(refLineSpan)).replace(/\r|\n/g, "");
return {
file: ref.fileName,
start: start,
@ -532,26 +533,26 @@ namespace ts.server {
}
private openClientFile(fileName: string) {
var file = ts.normalizePath(fileName);
const file = ts.normalizePath(fileName);
this.projectService.openClientFile(file);
}
private getQuickInfo(line: number, offset: number, fileName: string): protocol.QuickInfoResponseBody {
var file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
const file = ts.normalizePath(fileName);
const project = this.projectService.getProjectForFile(file);
if (!project) {
throw Errors.NoProject;
}
var compilerService = project.compilerService;
var position = compilerService.host.lineOffsetToPosition(file, line, offset);
var quickInfo = compilerService.languageService.getQuickInfoAtPosition(file, position);
const compilerService = project.compilerService;
const position = compilerService.host.lineOffsetToPosition(file, line, offset);
const quickInfo = compilerService.languageService.getQuickInfoAtPosition(file, position);
if (!quickInfo) {
return undefined;
}
var displayString = ts.displayPartsToString(quickInfo.displayParts);
var docString = ts.displayPartsToString(quickInfo.documentation);
const displayString = ts.displayPartsToString(quickInfo.displayParts);
const docString = ts.displayPartsToString(quickInfo.documentation);
return {
kind: quickInfo.kind,
kindModifiers: quickInfo.kindModifiers,
@ -563,18 +564,18 @@ namespace ts.server {
}
private getFormattingEditsForRange(line: number, offset: number, endLine: number, endOffset: number, fileName: string): protocol.CodeEdit[] {
var file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
const file = ts.normalizePath(fileName);
const project = this.projectService.getProjectForFile(file);
if (!project) {
throw Errors.NoProject;
}
var compilerService = project.compilerService;
var startPosition = compilerService.host.lineOffsetToPosition(file, line, offset);
var endPosition = compilerService.host.lineOffsetToPosition(file, endLine, endOffset);
const compilerService = project.compilerService;
const startPosition = compilerService.host.lineOffsetToPosition(file, line, offset);
const endPosition = compilerService.host.lineOffsetToPosition(file, endLine, endOffset);
// TODO: avoid duplicate code (with formatonkey)
var edits = compilerService.languageService.getFormattingEditsForRange(file, startPosition, endPosition,
const edits = compilerService.languageService.getFormattingEditsForRange(file, startPosition, endPosition,
this.projectService.getFormatCodeOptions(file));
if (!edits) {
return undefined;
@ -590,17 +591,17 @@ namespace ts.server {
}
private getFormattingEditsAfterKeystroke(line: number, offset: number, key: string, fileName: string): protocol.CodeEdit[] {
var file = ts.normalizePath(fileName);
const file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
const project = this.projectService.getProjectForFile(file);
if (!project) {
throw Errors.NoProject;
}
var compilerService = project.compilerService;
var position = compilerService.host.lineOffsetToPosition(file, line, offset);
var formatOptions = this.projectService.getFormatCodeOptions(file);
var edits = compilerService.languageService.getFormattingEditsAfterKeystroke(file, position, key,
const compilerService = project.compilerService;
const position = compilerService.host.lineOffsetToPosition(file, line, offset);
const formatOptions = this.projectService.getFormatCodeOptions(file);
const edits = compilerService.languageService.getFormattingEditsAfterKeystroke(file, position, key,
formatOptions);
// Check whether we should auto-indent. This will be when
// the position is on a line containing only whitespace.
@ -609,23 +610,24 @@ namespace ts.server {
// only to the previous line. If all this is true, then
// add edits necessary to properly indent the current line.
if ((key == "\n") && ((!edits) || (edits.length === 0) || allEditsBeforePos(edits, position))) {
var scriptInfo = compilerService.host.getScriptInfo(file);
const scriptInfo = compilerService.host.getScriptInfo(file);
if (scriptInfo) {
var lineInfo = scriptInfo.getLineInfo(line);
const lineInfo = scriptInfo.getLineInfo(line);
if (lineInfo && (lineInfo.leaf) && (lineInfo.leaf.text)) {
var lineText = lineInfo.leaf.text;
const lineText = lineInfo.leaf.text;
if (lineText.search("\\S") < 0) {
// TODO: get these options from host
var editorOptions: ts.EditorOptions = {
const editorOptions: ts.EditorOptions = {
IndentSize: formatOptions.IndentSize,
TabSize: formatOptions.TabSize,
NewLineCharacter: "\n",
ConvertTabsToSpaces: formatOptions.ConvertTabsToSpaces,
IndentStyle: ts.IndentStyle.Smart,
};
var preferredIndent = compilerService.languageService.getIndentationAtPosition(file, position, editorOptions);
var hasIndent = 0;
for (var i = 0, len = lineText.length; i < len; i++) {
const preferredIndent = compilerService.languageService.getIndentationAtPosition(file, position, editorOptions);
let hasIndent = 0;
let i: number, len: number;
for (i = 0, len = lineText.length; i < len; i++) {
if (lineText.charAt(i) == " ") {
hasIndent++;
}
@ -638,7 +640,7 @@ namespace ts.server {
}
// i points to the first non whitespace character
if (preferredIndent !== hasIndent) {
var firstNoWhiteSpacePosition = lineInfo.offset + i;
let firstNoWhiteSpacePosition = lineInfo.offset + i;
edits.push({
span: ts.createTextSpanFromBounds(lineInfo.offset, firstNoWhiteSpacePosition),
newText: generateIndentString(preferredIndent, editorOptions)
@ -668,16 +670,16 @@ namespace ts.server {
if (!prefix) {
prefix = "";
}
var file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
const file = ts.normalizePath(fileName);
const project = this.projectService.getProjectForFile(file);
if (!project) {
throw Errors.NoProject;
}
var compilerService = project.compilerService;
var position = compilerService.host.lineOffsetToPosition(file, line, offset);
const compilerService = project.compilerService;
const position = compilerService.host.lineOffsetToPosition(file, line, offset);
var completions = compilerService.languageService.getCompletionsAtPosition(file, position);
const completions = compilerService.languageService.getCompletionsAtPosition(file, position);
if (!completions) {
return undefined;
}
@ -692,17 +694,17 @@ namespace ts.server {
private getCompletionEntryDetails(line: number, offset: number,
entryNames: string[], fileName: string): protocol.CompletionEntryDetails[] {
var file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
const file = ts.normalizePath(fileName);
const project = this.projectService.getProjectForFile(file);
if (!project) {
throw Errors.NoProject;
}
var compilerService = project.compilerService;
var position = compilerService.host.lineOffsetToPosition(file, line, offset);
const compilerService = project.compilerService;
const position = compilerService.host.lineOffsetToPosition(file, line, offset);
return entryNames.reduce((accum: protocol.CompletionEntryDetails[], entryName: string) => {
var details = compilerService.languageService.getCompletionEntryDetails(file, position, entryName);
const details = compilerService.languageService.getCompletionEntryDetails(file, position, entryName);
if (details) {
accum.push(details);
}
@ -711,21 +713,21 @@ namespace ts.server {
}
private getSignatureHelpItems(line: number, offset: number, fileName: string): protocol.SignatureHelpItems {
var file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
const file = ts.normalizePath(fileName);
const project = this.projectService.getProjectForFile(file);
if (!project) {
throw Errors.NoProject;
}
var compilerService = project.compilerService;
var position = compilerService.host.lineOffsetToPosition(file, line, offset);
var helpItems = compilerService.languageService.getSignatureHelpItems(file, position);
const compilerService = project.compilerService;
const position = compilerService.host.lineOffsetToPosition(file, line, offset);
const helpItems = compilerService.languageService.getSignatureHelpItems(file, position);
if (!helpItems) {
return undefined;
}
var span = helpItems.applicableSpan;
var result: protocol.SignatureHelpItems = {
const span = helpItems.applicableSpan;
const result: protocol.SignatureHelpItems = {
items: helpItems.items,
applicableSpan: {
start: compilerService.host.positionToLineOffset(file, span.start),
@ -734,15 +736,15 @@ namespace ts.server {
selectedItemIndex: helpItems.selectedItemIndex,
argumentIndex: helpItems.argumentIndex,
argumentCount: helpItems.argumentCount,
}
};
return result;
}
private getDiagnostics(delay: number, fileNames: string[]) {
var checkList = fileNames.reduce((accum: PendingErrorCheck[], fileName: string) => {
const checkList = fileNames.reduce((accum: PendingErrorCheck[], fileName: string) => {
fileName = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(fileName);
const project = this.projectService.getProjectForFile(fileName);
if (project) {
accum.push({ fileName, project });
}
@ -750,17 +752,17 @@ namespace ts.server {
}, []);
if (checkList.length > 0) {
this.updateErrorCheck(checkList, this.changeSeq,(n) => n === this.changeSeq, delay)
this.updateErrorCheck(checkList, this.changeSeq, (n) => n === this.changeSeq, delay);
}
}
private change(line: number, offset: number, endLine: number, endOffset: number, insertString: string, fileName: string) {
var file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
const file = ts.normalizePath(fileName);
const project = this.projectService.getProjectForFile(file);
if (project) {
var compilerService = project.compilerService;
var start = compilerService.host.lineOffsetToPosition(file, line, offset);
var end = compilerService.host.lineOffsetToPosition(file, endLine, endOffset);
const compilerService = project.compilerService;
const start = compilerService.host.lineOffsetToPosition(file, line, offset);
const end = compilerService.host.lineOffsetToPosition(file, endLine, endOffset);
if (start >= 0) {
compilerService.host.editScript(file, start, end, insertString);
this.changeSeq++;
@ -770,9 +772,9 @@ namespace ts.server {
}
private reload(fileName: string, tempFileName: string, reqSeq = 0) {
var file = ts.normalizePath(fileName);
var tmpfile = ts.normalizePath(tempFileName);
var project = this.projectService.getProjectForFile(file);
const file = ts.normalizePath(fileName);
const tmpfile = ts.normalizePath(tempFileName);
const project = this.projectService.getProjectForFile(file);
if (project) {
this.changeSeq++;
// make sure no changes happen before this one is finished
@ -783,10 +785,10 @@ namespace ts.server {
}
private saveToTmp(fileName: string, tempFileName: string) {
var file = ts.normalizePath(fileName);
var tmpfile = ts.normalizePath(tempFileName);
const file = ts.normalizePath(fileName);
const tmpfile = ts.normalizePath(tempFileName);
var project = this.projectService.getProjectForFile(file);
const project = this.projectService.getProjectForFile(file);
if (project) {
project.compilerService.host.saveTo(file, tmpfile);
}
@ -794,7 +796,7 @@ namespace ts.server {
private closeClientFile(fileName: string) {
if (!fileName) { return; }
var file = ts.normalizePath(fileName);
const file = ts.normalizePath(fileName);
this.projectService.closeClientFile(file);
}
@ -803,7 +805,7 @@ namespace ts.server {
return undefined;
}
var compilerService = project.compilerService;
const compilerService = project.compilerService;
return items.map(item => ({
text: item.text,
@ -818,14 +820,14 @@ namespace ts.server {
}
private getNavigationBarItems(fileName: string): protocol.NavigationBarItem[] {
var file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
const file = ts.normalizePath(fileName);
const project = this.projectService.getProjectForFile(file);
if (!project) {
throw Errors.NoProject;
}
var compilerService = project.compilerService;
var items = compilerService.languageService.getNavigationBarItems(file);
const compilerService = project.compilerService;
const items = compilerService.languageService.getNavigationBarItems(file);
if (!items) {
return undefined;
}
@ -834,22 +836,22 @@ namespace ts.server {
}
private getNavigateToItems(searchValue: string, fileName: string, maxResultCount?: number): protocol.NavtoItem[] {
var file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
const file = ts.normalizePath(fileName);
const project = this.projectService.getProjectForFile(file);
if (!project) {
throw Errors.NoProject;
}
var compilerService = project.compilerService;
var navItems = compilerService.languageService.getNavigateToItems(searchValue, maxResultCount);
const compilerService = project.compilerService;
const navItems = compilerService.languageService.getNavigateToItems(searchValue, maxResultCount);
if (!navItems) {
return undefined;
}
return navItems.map((navItem) => {
var start = compilerService.host.positionToLineOffset(navItem.fileName, navItem.textSpan.start);
var end = compilerService.host.positionToLineOffset(navItem.fileName, ts.textSpanEnd(navItem.textSpan));
var bakedItem: protocol.NavtoItem = {
const start = compilerService.host.positionToLineOffset(navItem.fileName, navItem.textSpan.start);
const end = compilerService.host.positionToLineOffset(navItem.fileName, ts.textSpanEnd(navItem.textSpan));
const bakedItem: protocol.NavtoItem = {
name: navItem.name,
kind: navItem.kind,
file: navItem.fileName,
@ -859,7 +861,7 @@ namespace ts.server {
if (navItem.kindModifiers && (navItem.kindModifiers != "")) {
bakedItem.kindModifiers = navItem.kindModifiers;
}
if (navItem.matchKind != 'none') {
if (navItem.matchKind !== "none") {
bakedItem.matchKind = navItem.matchKind;
}
if (navItem.containerName && (navItem.containerName.length > 0)) {
@ -873,21 +875,21 @@ namespace ts.server {
}
private getBraceMatching(line: number, offset: number, fileName: string): protocol.TextSpan[] {
var file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
const file = ts.normalizePath(fileName);
const project = this.projectService.getProjectForFile(file);
if (!project) {
throw Errors.NoProject;
}
var compilerService = project.compilerService;
var position = compilerService.host.lineOffsetToPosition(file, line, offset);
var spans = compilerService.languageService.getBraceMatchingAtPosition(file, position);
const compilerService = project.compilerService;
const position = compilerService.host.lineOffsetToPosition(file, line, offset);
const spans = compilerService.languageService.getBraceMatchingAtPosition(file, position);
if (!spans) {
return undefined;
}
return spans.map(span => ({
start: compilerService.host.positionToLineOffset(file, span.start),
end: compilerService.host.positionToLineOffset(file, span.start + span.length)
@ -943,59 +945,59 @@ namespace ts.server {
exit() {
}
private handlers : Map<(request: protocol.Request) => {response?: any, responseRequired?: boolean}> = {
private handlers: Map<(request: protocol.Request) => {response?: any, responseRequired?: boolean}> = {
[CommandNames.Exit]: () => {
this.exit();
return { responseRequired: false};
},
[CommandNames.Definition]: (request: protocol.Request) => {
var defArgs = <protocol.FileLocationRequestArgs>request.arguments;
const defArgs = <protocol.FileLocationRequestArgs>request.arguments;
return {response: this.getDefinition(defArgs.line, defArgs.offset, defArgs.file), responseRequired: true};
},
[CommandNames.TypeDefinition]: (request: protocol.Request) => {
var defArgs = <protocol.FileLocationRequestArgs>request.arguments;
const defArgs = <protocol.FileLocationRequestArgs>request.arguments;
return {response: this.getTypeDefinition(defArgs.line, defArgs.offset, defArgs.file), responseRequired: true};
},
[CommandNames.References]: (request: protocol.Request) => {
var defArgs = <protocol.FileLocationRequestArgs>request.arguments;
const defArgs = <protocol.FileLocationRequestArgs>request.arguments;
return {response: this.getReferences(defArgs.line, defArgs.offset, defArgs.file), responseRequired: true};
},
[CommandNames.Rename]: (request: protocol.Request) => {
var renameArgs = <protocol.RenameRequestArgs>request.arguments;
return {response: this.getRenameLocations(renameArgs.line, renameArgs.offset, renameArgs.file, renameArgs.findInComments, renameArgs.findInStrings), responseRequired: true}
const renameArgs = <protocol.RenameRequestArgs>request.arguments;
return {response: this.getRenameLocations(renameArgs.line, renameArgs.offset, renameArgs.file, renameArgs.findInComments, renameArgs.findInStrings), responseRequired: true};
},
[CommandNames.Open]: (request: protocol.Request) => {
var openArgs = <protocol.OpenRequestArgs>request.arguments;
const openArgs = <protocol.OpenRequestArgs>request.arguments;
this.openClientFile(openArgs.file);
return {responseRequired: false}
return {responseRequired: false};
},
[CommandNames.Quickinfo]: (request: protocol.Request) => {
var quickinfoArgs = <protocol.FileLocationRequestArgs>request.arguments;
const quickinfoArgs = <protocol.FileLocationRequestArgs>request.arguments;
return {response: this.getQuickInfo(quickinfoArgs.line, quickinfoArgs.offset, quickinfoArgs.file), responseRequired: true};
},
[CommandNames.Format]: (request: protocol.Request) => {
var formatArgs = <protocol.FormatRequestArgs>request.arguments;
const formatArgs = <protocol.FormatRequestArgs>request.arguments;
return {response: this.getFormattingEditsForRange(formatArgs.line, formatArgs.offset, formatArgs.endLine, formatArgs.endOffset, formatArgs.file), responseRequired: true};
},
[CommandNames.Formatonkey]: (request: protocol.Request) => {
var formatOnKeyArgs = <protocol.FormatOnKeyRequestArgs>request.arguments;
const formatOnKeyArgs = <protocol.FormatOnKeyRequestArgs>request.arguments;
return {response: this.getFormattingEditsAfterKeystroke(formatOnKeyArgs.line, formatOnKeyArgs.offset, formatOnKeyArgs.key, formatOnKeyArgs.file), responseRequired: true};
},
[CommandNames.Completions]: (request: protocol.Request) => {
var completionsArgs = <protocol.CompletionsRequestArgs>request.arguments;
return {response: this.getCompletions(completionsArgs.line, completionsArgs.offset, completionsArgs.prefix, completionsArgs.file), responseRequired: true}
const completionsArgs = <protocol.CompletionsRequestArgs>request.arguments;
return {response: this.getCompletions(completionsArgs.line, completionsArgs.offset, completionsArgs.prefix, completionsArgs.file), responseRequired: true};
},
[CommandNames.CompletionDetails]: (request: protocol.Request) => {
var completionDetailsArgs = <protocol.CompletionDetailsRequestArgs>request.arguments;
return {response: this.getCompletionEntryDetails(completionDetailsArgs.line,completionDetailsArgs.offset,
completionDetailsArgs.entryNames,completionDetailsArgs.file), responseRequired: true}
const completionDetailsArgs = <protocol.CompletionDetailsRequestArgs>request.arguments;
return {response: this.getCompletionEntryDetails(completionDetailsArgs.line, completionDetailsArgs.offset,
completionDetailsArgs.entryNames, completionDetailsArgs.file), responseRequired: true};
},
[CommandNames.SignatureHelp]: (request: protocol.Request) => {
var signatureHelpArgs = <protocol.SignatureHelpRequestArgs>request.arguments;
return {response: this.getSignatureHelpItems(signatureHelpArgs.line, signatureHelpArgs.offset, signatureHelpArgs.file), responseRequired: true}
const signatureHelpArgs = <protocol.SignatureHelpRequestArgs>request.arguments;
return {response: this.getSignatureHelpItems(signatureHelpArgs.line, signatureHelpArgs.offset, signatureHelpArgs.file), responseRequired: true};
},
[CommandNames.Geterr]: (request: protocol.Request) => {
var geterrArgs = <protocol.GeterrRequestArgs>request.arguments;
const geterrArgs = <protocol.GeterrRequestArgs>request.arguments;
return {response: this.getDiagnostics(geterrArgs.delay, geterrArgs.files), responseRequired: false};
},
[CommandNames.GeterrForProject]: (request: protocol.Request) => {
@ -1003,54 +1005,54 @@ namespace ts.server {
return {response: this.getDiagnosticsForProject(delay, file), responseRequired: false};
},
[CommandNames.Change]: (request: protocol.Request) => {
var changeArgs = <protocol.ChangeRequestArgs>request.arguments;
const changeArgs = <protocol.ChangeRequestArgs>request.arguments;
this.change(changeArgs.line, changeArgs.offset, changeArgs.endLine, changeArgs.endOffset,
changeArgs.insertString, changeArgs.file);
return {responseRequired: false}
return {responseRequired: false};
},
[CommandNames.Configure]: (request: protocol.Request) => {
var configureArgs = <protocol.ConfigureRequestArguments>request.arguments;
const configureArgs = <protocol.ConfigureRequestArguments>request.arguments;
this.projectService.setHostConfiguration(configureArgs);
this.output(undefined, CommandNames.Configure, request.seq);
return {responseRequired: false}
return {responseRequired: false};
},
[CommandNames.Reload]: (request: protocol.Request) => {
var reloadArgs = <protocol.ReloadRequestArgs>request.arguments;
const reloadArgs = <protocol.ReloadRequestArgs>request.arguments;
this.reload(reloadArgs.file, reloadArgs.tmpfile, request.seq);
return {responseRequired: false}
return {responseRequired: false};
},
[CommandNames.Saveto]: (request: protocol.Request) => {
var savetoArgs = <protocol.SavetoRequestArgs>request.arguments;
const savetoArgs = <protocol.SavetoRequestArgs>request.arguments;
this.saveToTmp(savetoArgs.file, savetoArgs.tmpfile);
return {responseRequired: false}
return {responseRequired: false};
},
[CommandNames.Close]: (request: protocol.Request) => {
var closeArgs = <protocol.FileRequestArgs>request.arguments;
const closeArgs = <protocol.FileRequestArgs>request.arguments;
this.closeClientFile(closeArgs.file);
return {responseRequired: false};
},
[CommandNames.Navto]: (request: protocol.Request) => {
var navtoArgs = <protocol.NavtoRequestArgs>request.arguments;
const navtoArgs = <protocol.NavtoRequestArgs>request.arguments;
return {response: this.getNavigateToItems(navtoArgs.searchValue, navtoArgs.file, navtoArgs.maxResultCount), responseRequired: true};
},
[CommandNames.Brace]: (request: protocol.Request) => {
var braceArguments = <protocol.FileLocationRequestArgs>request.arguments;
const braceArguments = <protocol.FileLocationRequestArgs>request.arguments;
return {response: this.getBraceMatching(braceArguments.line, braceArguments.offset, braceArguments.file), responseRequired: true};
},
[CommandNames.NavBar]: (request: protocol.Request) => {
var navBarArgs = <protocol.FileRequestArgs>request.arguments;
const navBarArgs = <protocol.FileRequestArgs>request.arguments;
return {response: this.getNavigationBarItems(navBarArgs.file), responseRequired: true};
},
[CommandNames.Occurrences]: (request: protocol.Request) => {
var { line, offset, file: fileName } = <protocol.FileLocationRequestArgs>request.arguments;
const { line, offset, file: fileName } = <protocol.FileLocationRequestArgs>request.arguments;
return {response: this.getOccurrences(line, offset, fileName), responseRequired: true};
},
[CommandNames.DocumentHighlights]: (request: protocol.Request) => {
var { line, offset, file: fileName, filesToSearch } = <protocol.DocumentHighlightsRequestArgs>request.arguments;
const { line, offset, file: fileName, filesToSearch } = <protocol.DocumentHighlightsRequestArgs>request.arguments;
return {response: this.getDocumentHighlights(line, offset, fileName, filesToSearch), responseRequired: true};
},
[CommandNames.ProjectInfo]: (request: protocol.Request) => {
var { file, needFileNameList } = <protocol.ProjectInfoRequestArgs>request.arguments;
const { file, needFileNameList } = <protocol.ProjectInfoRequestArgs>request.arguments;
return {response: this.getProjectInfo(file, needFileNameList), responseRequired: true};
},
[CommandNames.ReloadProjects]: (request: protocol.ReloadProjectsRequest) => {
@ -1065,11 +1067,12 @@ namespace ts.server {
this.handlers[command] = handler;
}
public executeCommand(request: protocol.Request) : {response?: any, responseRequired?: boolean} {
var handler = this.handlers[request.command];
public executeCommand(request: protocol.Request): {response?: any, responseRequired?: boolean} {
const handler = this.handlers[request.command];
if (handler) {
return handler(request);
} else {
}
else {
this.projectService.log("Unrecognized JSON command: " + JSON.stringify(request));
this.output(undefined, CommandNames.Unknown, request.seq, "Unrecognized JSON command: " + request.command);
return {responseRequired: false};
@ -1077,20 +1080,22 @@ namespace ts.server {
}
public onMessage(message: string) {
let start: number[];
if (this.logger.isVerbose()) {
this.logger.info("request: " + message);
var start = this.hrtime();
start = this.hrtime();
}
let request: protocol.Request;
try {
var request = <protocol.Request>JSON.parse(message);
var {response, responseRequired} = this.executeCommand(request);
request = <protocol.Request>JSON.parse(message);
const {response, responseRequired} = this.executeCommand(request);
if (this.logger.isVerbose()) {
var elapsed = this.hrtime(start);
var seconds = elapsed[0]
var nanoseconds = elapsed[1];
var elapsedMs = ((1e9 * seconds) + nanoseconds)/1000000.0;
var leader = "Elapsed time (in milliseconds)";
const elapsed = this.hrtime(start);
const seconds = elapsed[0];
const nanoseconds = elapsed[1];
const elapsedMs = ((1e9 * seconds) + nanoseconds) / 1000000.0;
let leader = "Elapsed time (in milliseconds)";
if (!responseRequired) {
leader = "Async elapsed time (in milliseconds)";
}
@ -1102,7 +1107,8 @@ namespace ts.server {
else if (responseRequired) {
this.output(undefined, request.command, request.seq, "No content available.");
}
} catch (err) {
}
catch (err) {
if (err instanceof OperationCanceledException) {
// Handle cancellation exceptions
}

View file

@ -773,6 +773,7 @@ namespace ts {
class SourceFileObject extends NodeObject implements SourceFile {
public _declarationBrand: any;
public fileName: string;
public path: Path;
public text: string;
public scriptSnapshot: IScriptSnapshot;
public lineMap: number[];
@ -1695,15 +1696,17 @@ namespace ts {
class HostCache {
private fileNameToEntry: FileMap<HostFileInformation>;
private _compilationSettings: CompilerOptions;
private currentDirectory: string;
constructor(private host: LanguageServiceHost, getCanonicalFileName: (fileName: string) => string) {
constructor(private host: LanguageServiceHost, private getCanonicalFileName: (fileName: string) => string) {
// script id => script index
this.fileNameToEntry = createFileMap<HostFileInformation>(getCanonicalFileName);
this.currentDirectory = host.getCurrentDirectory();
this.fileNameToEntry = createFileMap<HostFileInformation>();
// Initialize the list with the root file names
let rootFileNames = host.getScriptFileNames();
for (let fileName of rootFileNames) {
this.createEntry(fileName);
this.createEntry(fileName, toPath(fileName, this.currentDirectory, getCanonicalFileName));
}
// store the compilation settings
@ -1714,7 +1717,7 @@ namespace ts {
return this._compilationSettings;
}
private createEntry(fileName: string) {
private createEntry(fileName: string, path: Path) {
let entry: HostFileInformation;
let scriptSnapshot = this.host.getScriptSnapshot(fileName);
if (scriptSnapshot) {
@ -1725,30 +1728,31 @@ namespace ts {
};
}
this.fileNameToEntry.set(fileName, entry);
this.fileNameToEntry.set(path, entry);
return entry;
}
private getEntry(fileName: string): HostFileInformation {
return this.fileNameToEntry.get(fileName);
private getEntry(path: Path): HostFileInformation {
return this.fileNameToEntry.get(path);
}
private contains(fileName: string): boolean {
return this.fileNameToEntry.contains(fileName);
private contains(path: Path): boolean {
return this.fileNameToEntry.contains(path);
}
public getOrCreateEntry(fileName: string): HostFileInformation {
if (this.contains(fileName)) {
return this.getEntry(fileName);
let path = toPath(fileName, this.currentDirectory, this.getCanonicalFileName)
if (this.contains(path)) {
return this.getEntry(path);
}
return this.createEntry(fileName);
return this.createEntry(fileName, path);
}
public getRootFileNames(): string[] {
let fileNames: string[] = [];
this.fileNameToEntry.forEachValue(value => {
this.fileNameToEntry.forEachValue((path, value) => {
if (value) {
fileNames.push(value.hostFileName);
}
@ -1757,13 +1761,13 @@ namespace ts {
return fileNames;
}
public getVersion(fileName: string): string {
let file = this.getEntry(fileName);
public getVersion(path: Path): string {
let file = this.getEntry(path);
return file && file.version;
}
public getScriptSnapshot(fileName: string): IScriptSnapshot {
let file = this.getEntry(fileName);
public getScriptSnapshot(path: Path): IScriptSnapshot {
let file = this.getEntry(path);
return file && file.scriptSnapshot;
}
}
@ -1993,7 +1997,7 @@ namespace ts {
}
export function createDocumentRegistry(useCaseSensitiveFileNames?: boolean): DocumentRegistry {
export function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory = ""): DocumentRegistry {
// Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have
// for those settings.
let buckets: Map<FileMap<DocumentRegistryEntry>> = {};
@ -2007,7 +2011,7 @@ namespace ts {
let key = getKeyFromCompilationSettings(settings);
let bucket = lookUp(buckets, key);
if (!bucket && createIfMissing) {
buckets[key] = bucket = createFileMap<DocumentRegistryEntry>(getCanonicalFileName);
buckets[key] = bucket = createFileMap<DocumentRegistryEntry>();
}
return bucket;
}
@ -2016,14 +2020,13 @@ namespace ts {
let bucketInfoArray = Object.keys(buckets).filter(name => name && name.charAt(0) === '_').map(name => {
let entries = lookUp(buckets, name);
let sourceFiles: { name: string; refCount: number; references: string[]; }[] = [];
for (let i in entries) {
let entry = entries.get(i);
entries.forEachValue((key, entry) => {
sourceFiles.push({
name: i,
name: key,
refCount: entry.languageServiceRefCount,
references: entry.owners.slice(0)
});
}
});
sourceFiles.sort((x, y) => y.refCount - x.refCount);
return {
bucket: name,
@ -2049,7 +2052,8 @@ namespace ts {
acquiring: boolean): SourceFile {
let bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true);
let entry = bucket.get(fileName);
let path = toPath(fileName, currentDirectory, getCanonicalFileName);
let entry = bucket.get(path);
if (!entry) {
Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?");
@ -2061,7 +2065,7 @@ namespace ts {
languageServiceRefCount: 0,
owners: []
};
bucket.set(fileName, entry);
bucket.set(path, entry);
}
else {
// We have an entry for this file. However, it may be for a different version of
@ -2089,12 +2093,14 @@ namespace ts {
let bucket = getBucketForCompilationSettings(compilationSettings, false);
Debug.assert(bucket !== undefined);
let entry = bucket.get(fileName);
let path = toPath(fileName, currentDirectory, getCanonicalFileName);
let entry = bucket.get(path);
entry.languageServiceRefCount--;
Debug.assert(entry.languageServiceRefCount >= 0);
if (entry.languageServiceRefCount === 0) {
bucket.remove(fileName);
bucket.remove(path);
}
}
@ -2556,7 +2562,9 @@ namespace ts {
}
}
export function createLanguageService(host: LanguageServiceHost, documentRegistry: DocumentRegistry = createDocumentRegistry()): LanguageService {
export function createLanguageService(host: LanguageServiceHost,
documentRegistry: DocumentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory())): LanguageService {
let syntaxTreeCache: SyntaxTreeCache = new SyntaxTreeCache(host);
let ruleProvider: formatting.RulesProvider;
let program: Program;
@ -2565,6 +2573,7 @@ namespace ts {
let useCaseSensitivefileNames = false;
let cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken());
let currentDirectory = host.getCurrentDirectory();
// Check if the localized messages json is set, otherwise query the host for it
if (!localizedDiagnosticMessages && host.getLocalizedDiagnosticMessages) {
localizedDiagnosticMessages = host.getLocalizedDiagnosticMessages();
@ -2579,8 +2588,7 @@ namespace ts {
let getCanonicalFileName = createGetCanonicalFileName(useCaseSensitivefileNames);
function getValidSourceFile(fileName: string): SourceFile {
fileName = normalizeSlashes(fileName);
let sourceFile = program.getSourceFile(getCanonicalFileName(fileName));
let sourceFile = program.getSourceFile(fileName);
if (!sourceFile) {
throw new Error("Could not find file: '" + fileName + "'.");
}
@ -2641,7 +2649,7 @@ namespace ts {
getNewLine: () => getNewLineOrDefaultFromHost(host),
getDefaultLibFileName: (options) => host.getDefaultLibFileName(options),
writeFile: (fileName, data, writeByteOrderMark) => { },
getCurrentDirectory: () => host.getCurrentDirectory(),
getCurrentDirectory: () => currentDirectory,
fileExists: (fileName): boolean => {
// stub missing host functionality
Debug.assert(!host.resolveModuleNames);
@ -2665,9 +2673,8 @@ namespace ts {
if (program) {
let oldSourceFiles = program.getSourceFiles();
for (let oldSourceFile of oldSourceFiles) {
let fileName = oldSourceFile.fileName;
if (!newProgram.getSourceFile(fileName) || changesInCompilationSettingsAffectSyntax) {
documentRegistry.releaseDocument(fileName, oldSettings);
if (!newProgram.getSourceFile(oldSourceFile.fileName) || changesInCompilationSettingsAffectSyntax) {
documentRegistry.releaseDocument(oldSourceFile.fileName, oldSettings);
}
}
}
@ -2732,7 +2739,8 @@ namespace ts {
}
function sourceFileUpToDate(sourceFile: SourceFile): boolean {
return sourceFile && sourceFile.version === hostCache.getVersion(sourceFile.fileName);
let path = sourceFile.path || toPath(sourceFile.fileName, currentDirectory, getCanonicalFileName);
return sourceFile && sourceFile.version === hostCache.getVersion(path);
}
function programUpToDate(): boolean {

View file

@ -1,11 +1,16 @@
tests/cases/compiler/constructorReturnsInvalidType.ts(3,16): error TS2322: Type 'number' is not assignable to type 'X'.
Property 'foo' is missing in type 'Number'.
tests/cases/compiler/constructorReturnsInvalidType.ts(3,16): error TS2409: Return type of constructor signature must be assignable to the instance type of the class
==== tests/cases/compiler/constructorReturnsInvalidType.ts (1 errors) ====
==== tests/cases/compiler/constructorReturnsInvalidType.ts (2 errors) ====
class X {
constructor() {
return 1;
~
!!! error TS2322: Type 'number' is not assignable to type 'X'.
!!! error TS2322: Property 'foo' is missing in type 'Number'.
~
!!! error TS2409: Return type of constructor signature must be assignable to the instance type of the class
}
foo() { }

View file

@ -1,8 +1,13 @@
tests/cases/conformance/classes/constructorDeclarations/constructorWithAssignableReturnExpression.ts(12,16): error TS2322: Type 'number' is not assignable to type 'D'.
Property 'x' is missing in type 'Number'.
tests/cases/conformance/classes/constructorDeclarations/constructorWithAssignableReturnExpression.ts(12,16): error TS2409: Return type of constructor signature must be assignable to the instance type of the class
tests/cases/conformance/classes/constructorDeclarations/constructorWithAssignableReturnExpression.ts(26,16): error TS2322: Type '{ x: number; }' is not assignable to type 'F<T>'.
Types of property 'x' are incompatible.
Type 'number' is not assignable to type 'T'.
tests/cases/conformance/classes/constructorDeclarations/constructorWithAssignableReturnExpression.ts(26,16): error TS2409: Return type of constructor signature must be assignable to the instance type of the class
==== tests/cases/conformance/classes/constructorDeclarations/constructorWithAssignableReturnExpression.ts (2 errors) ====
==== tests/cases/conformance/classes/constructorDeclarations/constructorWithAssignableReturnExpression.ts (4 errors) ====
// a class constructor may return an expression, it must be assignable to the class instance type to be valid
class C {
@ -16,6 +21,9 @@ tests/cases/conformance/classes/constructorDeclarations/constructorWithAssignabl
constructor() {
return 1; // error
~
!!! error TS2322: Type 'number' is not assignable to type 'D'.
!!! error TS2322: Property 'x' is missing in type 'Number'.
~
!!! error TS2409: Return type of constructor signature must be assignable to the instance type of the class
}
}
@ -32,6 +40,10 @@ tests/cases/conformance/classes/constructorDeclarations/constructorWithAssignabl
constructor() {
return { x: 1 }; // error
~~~~~~~~
!!! error TS2322: Type '{ x: number; }' is not assignable to type 'F<T>'.
!!! error TS2322: Types of property 'x' are incompatible.
!!! error TS2322: Type 'number' is not assignable to type 'T'.
~~~~~~~~
!!! error TS2409: Return type of constructor signature must be assignable to the instance type of the class
}
}

View file

@ -1,10 +1,20 @@
tests/cases/compiler/returnInConstructor1.ts(11,16): error TS2322: Type 'number' is not assignable to type 'B'.
Property 'foo' is missing in type 'Number'.
tests/cases/compiler/returnInConstructor1.ts(11,16): error TS2409: Return type of constructor signature must be assignable to the instance type of the class
tests/cases/compiler/returnInConstructor1.ts(25,16): error TS2322: Type 'string' is not assignable to type 'D'.
Property 'foo' is missing in type 'String'.
tests/cases/compiler/returnInConstructor1.ts(25,16): error TS2409: Return type of constructor signature must be assignable to the instance type of the class
tests/cases/compiler/returnInConstructor1.ts(39,16): error TS2322: Type '{ foo: number; }' is not assignable to type 'F'.
Types of property 'foo' are incompatible.
Type 'number' is not assignable to type 'string'.
tests/cases/compiler/returnInConstructor1.ts(39,16): error TS2409: Return type of constructor signature must be assignable to the instance type of the class
tests/cases/compiler/returnInConstructor1.ts(55,16): error TS2322: Type 'G' is not assignable to type 'H'.
Types of property 'foo' are incompatible.
Type '() => void' is not assignable to type 'string'.
tests/cases/compiler/returnInConstructor1.ts(55,16): error TS2409: Return type of constructor signature must be assignable to the instance type of the class
==== tests/cases/compiler/returnInConstructor1.ts (4 errors) ====
==== tests/cases/compiler/returnInConstructor1.ts (8 errors) ====
class A {
foo() { }
constructor() {
@ -17,6 +27,9 @@ tests/cases/compiler/returnInConstructor1.ts(55,16): error TS2409: Return type o
constructor() {
return 1; // error
~
!!! error TS2322: Type 'number' is not assignable to type 'B'.
!!! error TS2322: Property 'foo' is missing in type 'Number'.
~
!!! error TS2409: Return type of constructor signature must be assignable to the instance type of the class
}
}
@ -33,6 +46,9 @@ tests/cases/compiler/returnInConstructor1.ts(55,16): error TS2409: Return type o
constructor() {
return "test"; // error
~~~~~~
!!! error TS2322: Type 'string' is not assignable to type 'D'.
!!! error TS2322: Property 'foo' is missing in type 'String'.
~~~~~~
!!! error TS2409: Return type of constructor signature must be assignable to the instance type of the class
}
}
@ -49,6 +65,10 @@ tests/cases/compiler/returnInConstructor1.ts(55,16): error TS2409: Return type o
constructor() {
return { foo: 1 }; //error
~~~~~~~~~~
!!! error TS2322: Type '{ foo: number; }' is not assignable to type 'F'.
!!! error TS2322: Types of property 'foo' are incompatible.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
~~~~~~~~~~
!!! error TS2409: Return type of constructor signature must be assignable to the instance type of the class
}
}
@ -67,6 +87,10 @@ tests/cases/compiler/returnInConstructor1.ts(55,16): error TS2409: Return type o
super();
return new G(); //error
~~~~~~~
!!! error TS2322: Type 'G' is not assignable to type 'H'.
!!! error TS2322: Types of property 'foo' are incompatible.
!!! error TS2322: Type '() => void' is not assignable to type 'string'.
~~~~~~~
!!! error TS2409: Return type of constructor signature must be assignable to the instance type of the class
}
}

View file

@ -25,6 +25,8 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(96,9):
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(97,16): error TS1228: A type predicate is only allowed in return type position for functions and methods.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(98,20): error TS1228: A type predicate is only allowed in return type position for functions and methods.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(104,25): error TS1228: A type predicate is only allowed in return type position for functions and methods.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(105,16): error TS2322: Type 'boolean' is not assignable to type 'D'.
Property 'm1' is missing in type 'Boolean'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(105,16): error TS2409: Return type of constructor signature must be assignable to the instance type of the class
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(107,20): error TS1228: A type predicate is only allowed in return type position for functions and methods.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(110,20): error TS1228: A type predicate is only allowed in return type position for functions and methods.
@ -37,7 +39,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(133,34
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(137,39): error TS1230: A type predicate cannot reference element 'p1' in a binding pattern.
==== tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts (31 errors) ====
==== tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts (32 errors) ====
class A {
propA: number;
@ -192,6 +194,9 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(137,39
!!! error TS1228: A type predicate is only allowed in return type position for functions and methods.
return true;
~~~~
!!! error TS2322: Type 'boolean' is not assignable to type 'D'.
!!! error TS2322: Property 'm1' is missing in type 'Boolean'.
~~~~
!!! error TS2409: Return type of constructor signature must be assignable to the instance type of the class
}
get m1(p1: A): p1 is C {