mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 16:38:05 -06:00
Merge pull request #1735 from Microsoft/LSAPICleanup
Language Service host API cleanup
This commit is contained in:
commit
bbbec22917
@ -644,6 +644,10 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function getDefaultLibFilename(options: CompilerOptions): string {
|
||||
return options.target === ScriptTarget.ES6 ? "lib.es6.d.ts" : "lib.d.ts";
|
||||
}
|
||||
|
||||
export interface ObjectAllocator {
|
||||
getNodeConstructor(kind: SyntaxKind): new () => Node;
|
||||
getSymbolConstructor(): new (flags: SymbolFlags, name: string) => Symbol;
|
||||
|
||||
@ -64,7 +64,7 @@ module ts {
|
||||
|
||||
return {
|
||||
getSourceFile,
|
||||
getDefaultLibFilename: options => combinePaths(getDirectoryPath(normalizePath(sys.getExecutingFilePath())), options.target === ScriptTarget.ES6 ? "lib.es6.d.ts" : "lib.d.ts"),
|
||||
getDefaultLibFilename: options => combinePaths(getDirectoryPath(normalizePath(sys.getExecutingFilePath())), getDefaultLibFilename(options)),
|
||||
writeFile,
|
||||
getCurrentDirectory: () => currentDirectory || (currentDirectory = sys.getCurrentDirectory()),
|
||||
useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames,
|
||||
@ -174,7 +174,7 @@ module ts {
|
||||
}
|
||||
var diagnostic: DiagnosticMessage;
|
||||
if (hasExtension(filename)) {
|
||||
if (!options.allowNonTsExtensions && !fileExtensionIs(filename, ".ts")) {
|
||||
if (!options.allowNonTsExtensions && !fileExtensionIs(host.getCanonicalFileName(filename), ".ts")) {
|
||||
diagnostic = Diagnostics.File_0_must_have_extension_ts_or_d_ts;
|
||||
}
|
||||
else if (!findSourceFile(filename, isDefaultLib, refFile, refPos, refEnd)) {
|
||||
|
||||
@ -237,9 +237,6 @@ module FourSlash {
|
||||
getLength: () => {
|
||||
return sourceText.length;
|
||||
},
|
||||
getLineStartPositions: () => {
|
||||
return <number[]>[];
|
||||
},
|
||||
getChangeRange: (oldSnapshot: ts.IScriptSnapshot) => {
|
||||
return <ts.TextChangeRange>undefined;
|
||||
}
|
||||
@ -1403,7 +1400,7 @@ module FourSlash {
|
||||
var content = snapshot.getText(0, snapshot.getLength());
|
||||
|
||||
var referenceSourceFile = ts.createLanguageServiceSourceFile(
|
||||
this.activeFile.fileName, createScriptSnapShot(content), ts.ScriptTarget.Latest, /*version:*/ "0", /*isOpen:*/ false, /*setNodeParents:*/ false);
|
||||
this.activeFile.fileName, createScriptSnapShot(content), ts.ScriptTarget.Latest, /*version:*/ "0", /*setNodeParents:*/ false);
|
||||
var referenceSyntaxDiagnostics = referenceSourceFile.getSyntacticDiagnostics();
|
||||
|
||||
Utils.assertDiagnosticsEquals(incrementalSyntaxDiagnostics, referenceSyntaxDiagnostics);
|
||||
|
||||
@ -930,6 +930,8 @@ module Harness {
|
||||
settingsCallback(null);
|
||||
}
|
||||
|
||||
var newLine = '\r\n';
|
||||
|
||||
var useCaseSensitiveFileNames = ts.sys.useCaseSensitiveFileNames;
|
||||
this.settings.forEach(setting => {
|
||||
switch (setting.flag.toLowerCase()) {
|
||||
@ -1008,7 +1010,7 @@ module Harness {
|
||||
|
||||
case 'newline':
|
||||
case 'newlines':
|
||||
ts.sys.newLine = setting.value;
|
||||
newLine = setting.value;
|
||||
break;
|
||||
|
||||
case 'comments':
|
||||
@ -1050,7 +1052,7 @@ module Harness {
|
||||
break;
|
||||
|
||||
case 'includebuiltfile':
|
||||
inputFiles.push({ unitName: setting.value, content: IO.readFile(libFolder + setting.value) });
|
||||
inputFiles.push({ unitName: setting.value, content: normalizeLineEndings(IO.readFile(libFolder + setting.value), newLine) });
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1096,7 +1098,7 @@ module Harness {
|
||||
onComplete(result, program);
|
||||
|
||||
// reset what newline means in case the last test changed it
|
||||
ts.sys.newLine = '\r\n';
|
||||
ts.sys.newLine = newLine;
|
||||
return options;
|
||||
}
|
||||
|
||||
@ -1168,6 +1170,14 @@ module Harness {
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeLineEndings(text: string, lineEnding: string): string {
|
||||
var normalized = text.replace(/\r\n?/g, '\n');
|
||||
if (lineEnding !== '\n') {
|
||||
normalized = normalized.replace(/\n/g, lineEnding);
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
export function getMinimalDiagnostic(err: ts.Diagnostic): HarnessDiagnostic {
|
||||
var errorLineInfo = err.file ? err.file.getLineAndCharacterFromPosition(err.start) : { line: 0, character: 0 };
|
||||
return {
|
||||
|
||||
@ -7,7 +7,7 @@ module Harness.LanguageService {
|
||||
public editRanges: { length: number; textChangeRange: ts.TextChangeRange; }[] = [];
|
||||
public lineMap: number[] = null;
|
||||
|
||||
constructor(public fileName: string, public content: string, public isOpen = true) {
|
||||
constructor(public fileName: string, public content: string) {
|
||||
this.setContent(content);
|
||||
}
|
||||
|
||||
@ -72,14 +72,6 @@ module Harness.LanguageService {
|
||||
return this.textSnapshot.length;
|
||||
}
|
||||
|
||||
public getLineStartPositions(): string {
|
||||
if (this.lineMap === null) {
|
||||
this.lineMap = ts.computeLineStarts(this.textSnapshot);
|
||||
}
|
||||
|
||||
return JSON.stringify(this.lineMap);
|
||||
}
|
||||
|
||||
public getChangeRange(oldScript: ts.ScriptSnapshotShim): string {
|
||||
var oldShim = <ScriptSnapshotShim>oldScript;
|
||||
var range = this.scriptInfo.getTextChangeRangeBetweenVersions(oldShim.version, this.version);
|
||||
@ -109,11 +101,9 @@ module Harness.LanguageService {
|
||||
fileName: string,
|
||||
compilationSettings: ts.CompilerOptions,
|
||||
scriptSnapshot: ts.IScriptSnapshot,
|
||||
version: string,
|
||||
isOpen: boolean): ts.SourceFile {
|
||||
version: string): ts.SourceFile {
|
||||
var sourceFile = ts.createSourceFile(fileName, scriptSnapshot.getText(0, scriptSnapshot.getLength()), compilationSettings.target);
|
||||
sourceFile.version = version;
|
||||
sourceFile.isOpen = isOpen;
|
||||
return sourceFile;
|
||||
}
|
||||
|
||||
@ -123,10 +113,9 @@ module Harness.LanguageService {
|
||||
compilationSettings: ts.CompilerOptions,
|
||||
scriptSnapshot: ts.IScriptSnapshot,
|
||||
version: string,
|
||||
isOpen: boolean,
|
||||
textChangeRange: ts.TextChangeRange
|
||||
): ts.SourceFile {
|
||||
return ts.updateLanguageServiceSourceFile(document, scriptSnapshot, version, isOpen, textChangeRange);
|
||||
return ts.updateLanguageServiceSourceFile(document, scriptSnapshot, version, textChangeRange);
|
||||
}
|
||||
|
||||
public releaseDocument(fileName: string, compilationSettings: ts.CompilerOptions): void {
|
||||
@ -159,13 +148,17 @@ module Harness.LanguageService {
|
||||
}
|
||||
|
||||
private getScriptInfo(fileName: string): ScriptInfo {
|
||||
return this.fileNameToScript[fileName];
|
||||
return ts.lookUp(this.fileNameToScript, fileName);
|
||||
}
|
||||
|
||||
public addScript(fileName: string, content: string) {
|
||||
this.fileNameToScript[fileName] = new ScriptInfo(fileName, content);
|
||||
}
|
||||
|
||||
private contains(fileName: string): boolean {
|
||||
return ts.hasProperty(this.fileNameToScript, fileName);
|
||||
}
|
||||
|
||||
public updateScript(fileName: string, content: string) {
|
||||
var script = this.getScriptInfo(fileName);
|
||||
if (script !== null) {
|
||||
@ -223,20 +216,22 @@ module Harness.LanguageService {
|
||||
|
||||
public getScriptFileNames(): string {
|
||||
var fileNames: string[] = [];
|
||||
ts.forEachKey(this.fileNameToScript, (fileName) => { fileNames.push(fileName); });
|
||||
ts.forEachKey(this.fileNameToScript,(fileName) => { fileNames.push(fileName); });
|
||||
return JSON.stringify(fileNames);
|
||||
}
|
||||
|
||||
public getScriptSnapshot(fileName: string): ts.ScriptSnapshotShim {
|
||||
return new ScriptSnapshotShim(this.getScriptInfo(fileName));
|
||||
if (this.contains(fileName)) {
|
||||
return new ScriptSnapshotShim(this.getScriptInfo(fileName));
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public getScriptVersion(fileName: string): string {
|
||||
return this.getScriptInfo(fileName).version.toString();
|
||||
}
|
||||
|
||||
public getScriptIsOpen(fileName: string): boolean {
|
||||
return this.getScriptInfo(fileName).isOpen;
|
||||
if (this.contains(fileName)) {
|
||||
return this.getScriptInfo(fileName).version.toString();
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public getLocalizedDiagnosticMessages(): string {
|
||||
@ -272,7 +267,6 @@ module Harness.LanguageService {
|
||||
public parseSourceText(fileName: string, sourceText: ts.IScriptSnapshot): ts.SourceFile {
|
||||
var result = ts.createSourceFile(fileName, sourceText.getText(0, sourceText.getLength()), ts.ScriptTarget.Latest);
|
||||
result.version = "1";
|
||||
result.isOpen = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ module ts.formatting {
|
||||
private activeRules: Rule[];
|
||||
private rulesMap: RulesMap;
|
||||
|
||||
constructor(private logger: Logger) {
|
||||
constructor() {
|
||||
this.globalRules = new Rules();
|
||||
}
|
||||
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
/// <reference path='formatting\smartIndenter.ts' />
|
||||
|
||||
module ts {
|
||||
|
||||
export var servicesVersion = "0.5"
|
||||
|
||||
export interface Node {
|
||||
@ -56,7 +57,6 @@ module ts {
|
||||
}
|
||||
|
||||
export interface SourceFile {
|
||||
isOpen: boolean;
|
||||
version: string;
|
||||
scriptSnapshot: IScriptSnapshot;
|
||||
nameTable: Map<string>;
|
||||
@ -75,13 +75,6 @@ module ts {
|
||||
/** Gets the length of this script snapshot. */
|
||||
getLength(): number;
|
||||
|
||||
/**
|
||||
* This call returns the array containing the start position of every line.
|
||||
* i.e."[0, 10, 55]". TODO: consider making this optional. The language service could
|
||||
* always determine this (albeit in a more expensive manner).
|
||||
*/
|
||||
getLineStartPositions(): number[];
|
||||
|
||||
/**
|
||||
* Gets the TextChangeRange that describe how the text changed between this text and
|
||||
* an older version. This information is used by the incremental parser to determine
|
||||
@ -107,16 +100,10 @@ module ts {
|
||||
return this.text.length;
|
||||
}
|
||||
|
||||
public getLineStartPositions(): number[] {
|
||||
if (!this._lineStartPositions) {
|
||||
this._lineStartPositions = computeLineStarts(this.text);
|
||||
}
|
||||
|
||||
return this._lineStartPositions;
|
||||
}
|
||||
|
||||
public getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange {
|
||||
throw new Error("not yet implemented");
|
||||
// Text-based snapshots do not support incremental parsing. Return undefined
|
||||
// to signal that to the caller.
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@ -755,7 +742,6 @@ module ts {
|
||||
public identifierCount: number;
|
||||
public symbolCount: number;
|
||||
public version: string;
|
||||
public isOpen: boolean;
|
||||
public languageVersion: ScriptTarget;
|
||||
public identifiers: Map<string>;
|
||||
public nameTable: Map<string>;
|
||||
@ -850,26 +836,22 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
export interface Logger {
|
||||
log(s: string): void;
|
||||
trace(s: string): void;
|
||||
error(s: string): void;
|
||||
}
|
||||
|
||||
//
|
||||
// Public interface of the host of a language service instance.
|
||||
//
|
||||
export interface LanguageServiceHost extends Logger {
|
||||
export interface LanguageServiceHost {
|
||||
getCompilationSettings(): CompilerOptions;
|
||||
getNewLine?(): string;
|
||||
getScriptFileNames(): string[];
|
||||
getScriptVersion(fileName: string): string;
|
||||
getScriptIsOpen(fileName: string): boolean;
|
||||
getScriptSnapshot(fileName: string): IScriptSnapshot;
|
||||
getLocalizedDiagnosticMessages?(): any;
|
||||
getCancellationToken?(): CancellationToken;
|
||||
getCurrentDirectory(): string;
|
||||
getDefaultLibFilename(options: CompilerOptions): string;
|
||||
log? (s: string): void;
|
||||
trace? (s: string): void;
|
||||
error? (s: string): void;
|
||||
}
|
||||
|
||||
//
|
||||
@ -918,6 +900,8 @@ module ts {
|
||||
|
||||
getEmitOutput(fileName: string): EmitOutput;
|
||||
|
||||
getProgram(): Program;
|
||||
|
||||
getSourceFile(filename: string): SourceFile;
|
||||
|
||||
dispose(): void;
|
||||
@ -1172,24 +1156,79 @@ module ts {
|
||||
getClassificationsForLine(text: string, lexState: EndOfLineState, classifyKeywordsInGenerics?: boolean): ClassificationResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* The document registry represents a store of SourceFile objects that can be shared between
|
||||
* multiple LanguageService instances. A LanguageService instance holds on the SourceFile (AST)
|
||||
* of files in the context.
|
||||
* SourceFile objects account for most of the memory usage by the language service. Sharing
|
||||
* the same DocumentRegistry instance between different instances of LanguageService allow
|
||||
* for more efficient memory utilization since all projects will share at least the library
|
||||
* file (lib.d.ts).
|
||||
*
|
||||
* A more advanced use of the document registry is to serialize sourceFile objects to disk
|
||||
* and re-hydrate them when needed.
|
||||
*
|
||||
* To create a default DocumentRegistry, use createDocumentRegistry to create one, and pass it
|
||||
* to all subsequent createLanguageService calls.
|
||||
*/
|
||||
export interface DocumentRegistry {
|
||||
/**
|
||||
* Request a stored SourceFile with a given filename and compilationSettings.
|
||||
* The first call to acquire will call createLanguageServiceSourceFile to generate
|
||||
* the SourceFile if was not found in the registry.
|
||||
*
|
||||
* @param filename The name of the file requested
|
||||
* @param compilationSettings Some compilation settings like target affects the
|
||||
* shape of a the resulting SourceFile. This allows the DocumentRegistry to store
|
||||
* multiple copies of the same file for different compilation settings.
|
||||
* @parm scriptSnapshot Text of the file. Only used if the file was not found
|
||||
* in the registry and a new one was created.
|
||||
* @parm version Current version of the file. Only used if the file was not found
|
||||
* in the registry and a new one was created.
|
||||
*/
|
||||
acquireDocument(
|
||||
filename: string,
|
||||
compilationSettings: CompilerOptions,
|
||||
scriptSnapshot: IScriptSnapshot,
|
||||
version: string,
|
||||
isOpen: boolean): SourceFile;
|
||||
version: string): SourceFile;
|
||||
|
||||
/**
|
||||
* Request an updated version of an already existing SourceFile with a given filename
|
||||
* and compilationSettings. The update will intern call updateLanguageServiceSourceFile
|
||||
* to get an updated SourceFile.
|
||||
*
|
||||
* Note: It is not allowed to call update on a SourceFile that was not acquired from this
|
||||
* registry originally.
|
||||
*
|
||||
* @param sourceFile The original sourceFile object to update
|
||||
* @param filename The name of the file requested
|
||||
* @param compilationSettings Some compilation settings like target affects the
|
||||
* shape of a the resulting SourceFile. This allows the DocumentRegistry to store
|
||||
* multiple copies of the same file for different compilation settings.
|
||||
* @parm scriptSnapshot Text of the file. Only used if the file was not found
|
||||
* in the registry and a new one was created.
|
||||
* @parm version Current version of the file. Only used if the file was not found
|
||||
* in the registry and a new one was created.
|
||||
* @parm textChangeRange Change ranges since the last snapshot. Only used if the file
|
||||
* was not found in the registry and a new one was created.
|
||||
*/
|
||||
updateDocument(
|
||||
sourceFile: SourceFile,
|
||||
filename: string,
|
||||
compilationSettings: CompilerOptions,
|
||||
scriptSnapshot: IScriptSnapshot,
|
||||
version: string,
|
||||
isOpen: boolean,
|
||||
textChangeRange: TextChangeRange
|
||||
): SourceFile;
|
||||
textChangeRange: TextChangeRange): SourceFile;
|
||||
|
||||
/**
|
||||
* Informs the DocumentRegistry that a file is not needed any longer.
|
||||
*
|
||||
* Note: It is not allowed to call release on a SourceFile that was not acquired from
|
||||
* this registry originally.
|
||||
*
|
||||
* @param filename The name of the file to be released
|
||||
* @param compilationSettings The compilation settings used to acquire the file
|
||||
*/
|
||||
releaseDocument(filename: string, compilationSettings: CompilerOptions): void
|
||||
}
|
||||
|
||||
@ -1327,10 +1366,9 @@ module ts {
|
||||
|
||||
// Information about a specific host file.
|
||||
interface HostFileInformation {
|
||||
filename: string;
|
||||
hostFilename: string;
|
||||
version: string;
|
||||
isOpen: boolean;
|
||||
sourceText?: IScriptSnapshot;
|
||||
scriptSnapshot: IScriptSnapshot;
|
||||
}
|
||||
|
||||
interface DocumentRegistryEntry {
|
||||
@ -1418,16 +1456,13 @@ module ts {
|
||||
// script id => script index
|
||||
this.filenameToEntry = {};
|
||||
|
||||
var filenames = host.getScriptFileNames();
|
||||
for (var i = 0, n = filenames.length; i < n; i++) {
|
||||
var filename = filenames[i];
|
||||
this.filenameToEntry[normalizeSlashes(filename)] = {
|
||||
filename: filename,
|
||||
version: host.getScriptVersion(filename),
|
||||
isOpen: host.getScriptIsOpen(filename)
|
||||
};
|
||||
// Initialize the list with the root file names
|
||||
var rootFilenames = host.getScriptFileNames();
|
||||
for (var i = 0, n = rootFilenames.length; i < n; i++) {
|
||||
this.createEntry(rootFilenames[i]);
|
||||
}
|
||||
|
||||
// store the compilation settings
|
||||
this._compilationSettings = host.getCompilationSettings() || getDefaultCompilerOptions();
|
||||
}
|
||||
|
||||
@ -1435,28 +1470,41 @@ module ts {
|
||||
return this._compilationSettings;
|
||||
}
|
||||
|
||||
private createEntry(filename: string) {
|
||||
var entry: HostFileInformation;
|
||||
var scriptSnapshot = this.host.getScriptSnapshot(filename);
|
||||
if (scriptSnapshot) {
|
||||
entry = {
|
||||
hostFilename: filename,
|
||||
version: this.host.getScriptVersion(filename),
|
||||
scriptSnapshot: scriptSnapshot
|
||||
};
|
||||
}
|
||||
|
||||
return this.filenameToEntry[normalizeSlashes(filename)] = entry;
|
||||
}
|
||||
|
||||
public getEntry(filename: string): HostFileInformation {
|
||||
filename = normalizeSlashes(filename);
|
||||
return lookUp(this.filenameToEntry, filename);
|
||||
return lookUp(this.filenameToEntry, normalizeSlashes(filename));
|
||||
}
|
||||
|
||||
public contains(filename: string): boolean {
|
||||
return !!this.getEntry(filename);
|
||||
return hasProperty(this.filenameToEntry, normalizeSlashes(filename));
|
||||
}
|
||||
|
||||
public getHostfilename(filename: string) {
|
||||
var hostCacheEntry = this.getEntry(filename);
|
||||
if (hostCacheEntry) {
|
||||
return hostCacheEntry.filename;
|
||||
public getOrCreateEntry(filename: string): HostFileInformation {
|
||||
if (this.contains(filename)) {
|
||||
return this.getEntry(filename);
|
||||
}
|
||||
return filename;
|
||||
|
||||
return this.createEntry(filename);
|
||||
}
|
||||
|
||||
public getFilenames(): string[] {
|
||||
public getRootFilenames(): string[] {
|
||||
var fileNames: string[] = [];
|
||||
|
||||
forEachKey(this.filenameToEntry, key => {
|
||||
if (hasProperty(this.filenameToEntry, key))
|
||||
if (hasProperty(this.filenameToEntry, key) && this.filenameToEntry[key])
|
||||
fileNames.push(key);
|
||||
});
|
||||
|
||||
@ -1464,19 +1512,13 @@ module ts {
|
||||
}
|
||||
|
||||
public getVersion(filename: string): string {
|
||||
return this.getEntry(filename).version;
|
||||
}
|
||||
|
||||
public isOpen(filename: string): boolean {
|
||||
return this.getEntry(filename).isOpen;
|
||||
var file = this.getEntry(filename);
|
||||
return file && file.version;
|
||||
}
|
||||
|
||||
public getScriptSnapshot(filename: string): IScriptSnapshot {
|
||||
var file = this.getEntry(filename);
|
||||
if (!file.sourceText) {
|
||||
file.sourceText = this.host.getScriptSnapshot(file.filename);
|
||||
}
|
||||
return file.sourceText;
|
||||
return file && file.scriptSnapshot;
|
||||
}
|
||||
|
||||
public getChangeRange(filename: string, lastKnownVersion: string, oldScriptSnapshot: IScriptSnapshot): TextChangeRange {
|
||||
@ -1502,11 +1544,17 @@ module ts {
|
||||
constructor(private host: LanguageServiceHost) {
|
||||
}
|
||||
|
||||
private log(message: string) {
|
||||
if (this.host.log) {
|
||||
this.host.log(message);
|
||||
}
|
||||
}
|
||||
|
||||
private initialize(filename: string) {
|
||||
// ensure that both source file and syntax tree are either initialized or not initialized
|
||||
var start = new Date().getTime();
|
||||
this.hostCache = new HostCache(this.host);
|
||||
this.host.log("SyntaxTreeCache.Initialize: new HostCache: " + (new Date().getTime() - start));
|
||||
this.log("SyntaxTreeCache.Initialize: new HostCache: " + (new Date().getTime() - start));
|
||||
|
||||
var version = this.hostCache.getVersion(filename);
|
||||
var sourceFile: SourceFile;
|
||||
@ -1515,8 +1563,8 @@ module ts {
|
||||
var scriptSnapshot = this.hostCache.getScriptSnapshot(filename);
|
||||
|
||||
var start = new Date().getTime();
|
||||
sourceFile = createLanguageServiceSourceFile(filename, scriptSnapshot, ScriptTarget.Latest, version, /*isOpen*/ true, /*setNodeParents;*/ true);
|
||||
this.host.log("SyntaxTreeCache.Initialize: createSourceFile: " + (new Date().getTime() - start));
|
||||
sourceFile = createLanguageServiceSourceFile(filename, scriptSnapshot, ScriptTarget.Latest, version, /*setNodeParents:*/ true);
|
||||
this.log("SyntaxTreeCache.Initialize: createSourceFile: " + (new Date().getTime() - start));
|
||||
}
|
||||
else if (this.currentFileVersion !== version) {
|
||||
var scriptSnapshot = this.hostCache.getScriptSnapshot(filename);
|
||||
@ -1524,8 +1572,8 @@ module ts {
|
||||
var editRange = this.hostCache.getChangeRange(filename, this.currentFileVersion, this.currentSourceFile.scriptSnapshot);
|
||||
|
||||
var start = new Date().getTime();
|
||||
sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, /*isOpen*/ true, editRange);
|
||||
this.host.log("SyntaxTreeCache.Initialize: updateSourceFile: " + (new Date().getTime() - start));
|
||||
sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange);
|
||||
this.log("SyntaxTreeCache.Initialize: updateSourceFile: " + (new Date().getTime() - start));
|
||||
}
|
||||
|
||||
if (sourceFile) {
|
||||
@ -1546,15 +1594,14 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function setSourceFileFields(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, isOpen: boolean) {
|
||||
function setSourceFileFields(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string) {
|
||||
sourceFile.version = version;
|
||||
sourceFile.isOpen = isOpen;
|
||||
sourceFile.scriptSnapshot = scriptSnapshot;
|
||||
}
|
||||
|
||||
export function createLanguageServiceSourceFile(filename: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, isOpen: boolean, setNodeParents: boolean): SourceFile {
|
||||
export function createLanguageServiceSourceFile(filename: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, setNodeParents: boolean): SourceFile {
|
||||
var sourceFile = createSourceFile(filename, scriptSnapshot.getText(0, scriptSnapshot.getLength()), scriptTarget, setNodeParents);
|
||||
setSourceFileFields(sourceFile, scriptSnapshot, version, isOpen);
|
||||
setSourceFileFields(sourceFile, scriptSnapshot, version);
|
||||
// after full parsing we can use table with interned strings as name table
|
||||
sourceFile.nameTable = sourceFile.identifiers;
|
||||
return sourceFile;
|
||||
@ -1562,7 +1609,7 @@ module ts {
|
||||
|
||||
export var disableIncrementalParsing = false;
|
||||
|
||||
export function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, isOpen: boolean, textChangeRange: TextChangeRange): SourceFile {
|
||||
export function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange): SourceFile {
|
||||
if (textChangeRange && Debug.shouldAssert(AssertionLevel.Normal)) {
|
||||
var oldText = sourceFile.scriptSnapshot;
|
||||
var newText = scriptSnapshot;
|
||||
@ -1583,11 +1630,11 @@ module ts {
|
||||
// If we were given a text change range, and our version or open-ness changed, then
|
||||
// incrementally parse this file.
|
||||
if (textChangeRange) {
|
||||
if (version !== sourceFile.version || isOpen != sourceFile.isOpen) {
|
||||
if (version !== sourceFile.version) {
|
||||
// Once incremental parsing is ready, then just call into this function.
|
||||
if (!disableIncrementalParsing) {
|
||||
var newSourceFile = sourceFile.update(scriptSnapshot.getText(0, scriptSnapshot.getLength()), textChangeRange);
|
||||
setSourceFileFields(newSourceFile, scriptSnapshot, version, isOpen);
|
||||
setSourceFileFields(newSourceFile, scriptSnapshot, version);
|
||||
// after incremental parsing nameTable might not be up-to-date
|
||||
// drop it so it can be lazily recreated later
|
||||
newSourceFile.nameTable = undefined;
|
||||
@ -1597,7 +1644,7 @@ module ts {
|
||||
}
|
||||
|
||||
// Otherwise, just create a new source file.
|
||||
return createLanguageServiceSourceFile(sourceFile.filename, scriptSnapshot, sourceFile.languageVersion, version, isOpen, /*setNodeParents:*/ true);
|
||||
return createLanguageServiceSourceFile(sourceFile.filename, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents:*/ true);
|
||||
}
|
||||
|
||||
export function createDocumentRegistry(): DocumentRegistry {
|
||||
@ -1641,13 +1688,12 @@ module ts {
|
||||
filename: string,
|
||||
compilationSettings: CompilerOptions,
|
||||
scriptSnapshot: IScriptSnapshot,
|
||||
version: string,
|
||||
isOpen: boolean): SourceFile {
|
||||
version: string): SourceFile {
|
||||
|
||||
var bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true);
|
||||
var entry = lookUp(bucket, filename);
|
||||
if (!entry) {
|
||||
var sourceFile = createLanguageServiceSourceFile(filename, scriptSnapshot, compilationSettings.target, version, isOpen, /*setNodeParents:*/ false);
|
||||
var sourceFile = createLanguageServiceSourceFile(filename, scriptSnapshot, compilationSettings.target, version, /*setNodeParents:*/ false);
|
||||
|
||||
bucket[filename] = entry = {
|
||||
sourceFile: sourceFile,
|
||||
@ -1666,7 +1712,6 @@ module ts {
|
||||
compilationSettings: CompilerOptions,
|
||||
scriptSnapshot: IScriptSnapshot,
|
||||
version: string,
|
||||
isOpen: boolean,
|
||||
textChangeRange: TextChangeRange
|
||||
): SourceFile {
|
||||
|
||||
@ -1675,7 +1720,7 @@ module ts {
|
||||
var entry = lookUp(bucket, filename);
|
||||
Debug.assert(entry !== undefined);
|
||||
|
||||
entry.sourceFile = updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version, isOpen, textChangeRange);
|
||||
entry.sourceFile = updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version, textChangeRange);
|
||||
return entry.sourceFile;
|
||||
}
|
||||
|
||||
@ -1926,18 +1971,14 @@ module ts {
|
||||
});
|
||||
}
|
||||
|
||||
export function createLanguageService(host: LanguageServiceHost, documentRegistry: DocumentRegistry): LanguageService {
|
||||
export function createLanguageService(host: LanguageServiceHost, documentRegistry: DocumentRegistry = createDocumentRegistry()): LanguageService {
|
||||
var syntaxTreeCache: SyntaxTreeCache = new SyntaxTreeCache(host);
|
||||
var ruleProvider: formatting.RulesProvider;
|
||||
var hostCache: HostCache; // A cache of all the information about the files on the host side.
|
||||
var program: Program;
|
||||
|
||||
// this checker is used to answer all LS questions except errors
|
||||
var typeInfoResolver: TypeChecker;
|
||||
|
||||
var useCaseSensitivefilenames = false;
|
||||
var sourceFilesByName: Map<SourceFile> = {};
|
||||
var documentRegistry = documentRegistry;
|
||||
var cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken());
|
||||
var activeCompletionSession: CompletionSession; // The current active completion session, used to get the completion entry details
|
||||
|
||||
@ -1946,12 +1987,22 @@ module ts {
|
||||
localizedDiagnosticMessages = host.getLocalizedDiagnosticMessages();
|
||||
}
|
||||
|
||||
function log(message: string) {
|
||||
if (host.log) {
|
||||
host.log(message);
|
||||
}
|
||||
}
|
||||
|
||||
function getCanonicalFileName(filename: string) {
|
||||
return useCaseSensitivefilenames ? filename : filename.toLowerCase();
|
||||
}
|
||||
|
||||
function getSourceFile(filename: string): SourceFile {
|
||||
return lookUp(sourceFilesByName, getCanonicalFileName(filename));
|
||||
function getValidSourceFile(filename: string): SourceFile {
|
||||
var sourceFile = program.getSourceFile(getCanonicalFileName(filename));
|
||||
if (!sourceFile) {
|
||||
throw new Error("Could not find file: '" + filename + "'.");
|
||||
}
|
||||
return sourceFile;
|
||||
}
|
||||
|
||||
function getDiagnosticsProducingTypeChecker() {
|
||||
@ -1961,142 +2012,121 @@ module ts {
|
||||
function getRuleProvider(options: FormatCodeOptions) {
|
||||
// Ensure rules are initialized and up to date wrt to formatting options
|
||||
if (!ruleProvider) {
|
||||
ruleProvider = new formatting.RulesProvider(host);
|
||||
ruleProvider = new formatting.RulesProvider();
|
||||
}
|
||||
|
||||
ruleProvider.ensureUpToDate(options);
|
||||
return ruleProvider;
|
||||
}
|
||||
|
||||
function createCompilerHost(): CompilerHost {
|
||||
return {
|
||||
getSourceFile: (filename, languageVersion) => {
|
||||
var sourceFile = getSourceFile(filename);
|
||||
return sourceFile && sourceFile.getSourceFile();
|
||||
},
|
||||
getCancellationToken: () => cancellationToken,
|
||||
getCanonicalFileName: (filename) => useCaseSensitivefilenames ? filename : filename.toLowerCase(),
|
||||
useCaseSensitiveFileNames: () => useCaseSensitivefilenames,
|
||||
getNewLine: () => {
|
||||
return host.getNewLine ? host.getNewLine() : "\r\n";
|
||||
},
|
||||
getDefaultLibFilename: (options): string => {
|
||||
return host.getDefaultLibFilename(options);
|
||||
},
|
||||
writeFile: (filename, data, writeByteOrderMark) => {
|
||||
},
|
||||
getCurrentDirectory: (): string => {
|
||||
return host.getCurrentDirectory();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function sourceFileUpToDate(sourceFile: SourceFile): boolean {
|
||||
return sourceFile && sourceFile.version === hostCache.getVersion(sourceFile.filename) && sourceFile.isOpen === hostCache.isOpen(sourceFile.filename);
|
||||
}
|
||||
|
||||
function programUpToDate(): boolean {
|
||||
// If we haven't create a program yet, then it is not up-to-date
|
||||
if (!program) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If number of files in the program do not match, it is not up-to-date
|
||||
var hostFilenames = hostCache.getFilenames();
|
||||
if (program.getSourceFiles().length !== hostFilenames.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If any file is not up-to-date, then the whole program is not up-to-date
|
||||
for (var i = 0, n = hostFilenames.length; i < n; i++) {
|
||||
if (!sourceFileUpToDate(program.getSourceFile(hostFilenames[i]))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If the compilation settings do no match, then the program is not up-to-date
|
||||
return compareDataObjects(program.getCompilerOptions(), hostCache.compilationSettings());
|
||||
}
|
||||
|
||||
function synchronizeHostData(): void {
|
||||
// Reset the cache at start of every refresh
|
||||
hostCache = new HostCache(host);
|
||||
// Get a fresh cache of the host information
|
||||
var hostCache = new HostCache(host);
|
||||
|
||||
// If the program is already up-to-date, we can reuse it
|
||||
if (programUpToDate()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var compilationSettings = hostCache.compilationSettings();
|
||||
|
||||
// Now, remove any files from the compiler that are no longer in the host.
|
||||
var oldProgram = program;
|
||||
if (oldProgram) {
|
||||
var oldSettings = program.getCompilerOptions();
|
||||
// If the language version changed, then that affects what types of things we parse. So
|
||||
// we have to dump all syntax trees.
|
||||
// TODO: handle propagateEnumConstants
|
||||
// TODO: is module still needed
|
||||
var settingsChangeAffectsSyntax = oldSettings.target !== compilationSettings.target || oldSettings.module !== compilationSettings.module;
|
||||
|
||||
var changesInCompilationSettingsAffectSyntax =
|
||||
oldSettings && compilationSettings && !compareDataObjects(oldSettings, compilationSettings) && settingsChangeAffectsSyntax;
|
||||
var oldSourceFiles = program.getSourceFiles();
|
||||
|
||||
for (var i = 0, n = oldSourceFiles.length; i < n; i++) {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
var filename = oldSourceFiles[i].filename;
|
||||
if (!hostCache.contains(filename) || changesInCompilationSettingsAffectSyntax) {
|
||||
documentRegistry.releaseDocument(filename, oldSettings);
|
||||
delete sourceFilesByName[getCanonicalFileName(filename)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now, for every file the host knows about, either add the file (if the compiler
|
||||
// doesn't know about it.). Or notify the compiler about any changes (if it does
|
||||
// know about it.)
|
||||
var hostfilenames = hostCache.getFilenames();
|
||||
for (var i = 0, n = hostfilenames.length; i < n; i++) {
|
||||
var filename = hostfilenames[i];
|
||||
|
||||
var version = hostCache.getVersion(filename);
|
||||
var isOpen = hostCache.isOpen(filename);
|
||||
var scriptSnapshot = hostCache.getScriptSnapshot(filename);
|
||||
|
||||
var sourceFile: SourceFile = getSourceFile(filename);
|
||||
if (sourceFile) {
|
||||
//
|
||||
// If the sourceFile is the same, assume no update
|
||||
//
|
||||
if (sourceFileUpToDate(sourceFile)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only perform incremental parsing on open files that are being edited. If a file was
|
||||
// open, but is now closed, we want to re-parse entirely so we don't have any tokens that
|
||||
// are holding onto expensive script snapshot instances on the host. Similarly, if a
|
||||
// file was closed, then we always want to re-parse. This is so our tree doesn't keep
|
||||
// the old buffer alive that represented the file on disk (as the host has moved to a
|
||||
// new text buffer).
|
||||
var textChangeRange: TextChangeRange = null;
|
||||
if (sourceFile.isOpen && isOpen) {
|
||||
textChangeRange = hostCache.getChangeRange(filename, sourceFile.version, sourceFile.scriptSnapshot);
|
||||
}
|
||||
|
||||
sourceFile = documentRegistry.updateDocument(sourceFile, filename, compilationSettings, scriptSnapshot, version, isOpen, textChangeRange);
|
||||
}
|
||||
else {
|
||||
sourceFile = documentRegistry.acquireDocument(filename, compilationSettings, scriptSnapshot, version, isOpen);
|
||||
}
|
||||
|
||||
// Remember the new sourceFile
|
||||
sourceFilesByName[getCanonicalFileName(filename)] = sourceFile;
|
||||
}
|
||||
var oldSettings = program && program.getCompilerOptions();
|
||||
var newSettings = hostCache.compilationSettings();
|
||||
var changesInCompilationSettingsAffectSyntax = oldSettings && oldSettings.target !== newSettings.target;
|
||||
|
||||
// Now create a new compiler
|
||||
program = createProgram(hostfilenames, compilationSettings, createCompilerHost());
|
||||
var newProgram = createProgram(hostCache.getRootFilenames(), newSettings, {
|
||||
getSourceFile: getOrCreateSourceFile,
|
||||
getCancellationToken: () => cancellationToken,
|
||||
getCanonicalFileName: (filename) => useCaseSensitivefilenames ? filename : filename.toLowerCase(),
|
||||
useCaseSensitiveFileNames: () => useCaseSensitivefilenames,
|
||||
getNewLine: () => host.getNewLine ? host.getNewLine() : "\r\n",
|
||||
getDefaultLibFilename: (options) => host.getDefaultLibFilename(options),
|
||||
writeFile: (filename, data, writeByteOrderMark) => { },
|
||||
getCurrentDirectory: () => host.getCurrentDirectory()
|
||||
});
|
||||
|
||||
// Release any files we have acquired in the old program but are
|
||||
// not part of the new program.
|
||||
if (program) {
|
||||
var oldSourceFiles = program.getSourceFiles();
|
||||
for (var i = 0, n = oldSourceFiles.length; i < n; i++) {
|
||||
var filename = oldSourceFiles[i].filename;
|
||||
if (!newProgram.getSourceFile(filename) || changesInCompilationSettingsAffectSyntax) {
|
||||
documentRegistry.releaseDocument(filename, oldSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
program = newProgram;
|
||||
typeInfoResolver = program.getTypeChecker(/*produceDiagnostics*/ false);
|
||||
|
||||
return;
|
||||
|
||||
function getOrCreateSourceFile(filename: string): SourceFile {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
|
||||
// The program is asking for this file, check first if the host can locate it.
|
||||
// If the host can not locate the file, then it does not exist. return undefined
|
||||
// to the program to allow reporting of errors for missing files.
|
||||
var hostFileInformation = hostCache.getOrCreateEntry(filename);
|
||||
if (!hostFileInformation) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Check if the language version has changed since we last created a program; if they are the same,
|
||||
// it is safe to reuse the souceFiles; if not, then the shape of the AST can change, and the oldSourceFile
|
||||
// can not be reused. we have to dump all syntax trees and create new ones.
|
||||
if (!changesInCompilationSettingsAffectSyntax) {
|
||||
|
||||
// Check if the old program had this file already
|
||||
var oldSourceFile = program && program.getSourceFile(filename);
|
||||
if (oldSourceFile) {
|
||||
// This SourceFile is safe to reuse, return it
|
||||
if (sourceFileUpToDate(oldSourceFile)) {
|
||||
return oldSourceFile;
|
||||
}
|
||||
|
||||
// We have an older version of the sourceFile, incrementally parse the changes
|
||||
var textChangeRange = hostCache.getChangeRange(filename, oldSourceFile.version, oldSourceFile.scriptSnapshot);
|
||||
return documentRegistry.updateDocument(oldSourceFile, filename, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version, textChangeRange);
|
||||
}
|
||||
}
|
||||
|
||||
// Could not find this file in the old program, create a new SourceFile for it.
|
||||
return documentRegistry.acquireDocument(filename, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version);
|
||||
}
|
||||
|
||||
function sourceFileUpToDate(sourceFile: SourceFile): boolean {
|
||||
return sourceFile && sourceFile.version === hostCache.getVersion(sourceFile.filename);
|
||||
}
|
||||
|
||||
function programUpToDate(): boolean {
|
||||
// If we haven't create a program yet, then it is not up-to-date
|
||||
if (!program) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If number of files in the program do not match, it is not up-to-date
|
||||
var rootFilenames = hostCache.getRootFilenames();
|
||||
if (program.getSourceFiles().length !== rootFilenames.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If any file is not up-to-date, then the whole program is not up-to-date
|
||||
for (var i = 0, n = rootFilenames.length; i < n; i++) {
|
||||
if (!sourceFileUpToDate(program.getSourceFile(rootFilenames[i]))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If the compilation settings do no match, then the program is not up-to-date
|
||||
return compareDataObjects(program.getCompilerOptions(), hostCache.compilationSettings());
|
||||
}
|
||||
}
|
||||
|
||||
function getProgram(): Program {
|
||||
synchronizeHostData();
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2123,7 +2153,7 @@ module ts {
|
||||
|
||||
filename = normalizeSlashes(filename);
|
||||
|
||||
return program.getDiagnostics(getSourceFile(filename));
|
||||
return program.getDiagnostics(getValidSourceFile(filename));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2136,7 +2166,7 @@ module ts {
|
||||
filename = normalizeSlashes(filename)
|
||||
var compilerOptions = program.getCompilerOptions();
|
||||
var checker = getDiagnosticsProducingTypeChecker();
|
||||
var targetSourceFile = getSourceFile(filename);
|
||||
var targetSourceFile = getValidSourceFile(filename);
|
||||
|
||||
// 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.
|
||||
@ -2213,19 +2243,19 @@ module ts {
|
||||
filename = normalizeSlashes(filename);
|
||||
|
||||
var syntacticStart = new Date().getTime();
|
||||
var sourceFile = getSourceFile(filename);
|
||||
var sourceFile = getValidSourceFile(filename);
|
||||
|
||||
var start = new Date().getTime();
|
||||
var currentToken = getTokenAtPosition(sourceFile, position);
|
||||
host.log("getCompletionsAtPosition: Get current token: " + (new Date().getTime() - start));
|
||||
log("getCompletionsAtPosition: Get current token: " + (new Date().getTime() - start));
|
||||
|
||||
var start = new Date().getTime();
|
||||
// Completion not allowed inside comments, bail out if this is the case
|
||||
var insideComment = isInsideComment(sourceFile, currentToken, position);
|
||||
host.log("getCompletionsAtPosition: Is inside comment: " + (new Date().getTime() - start));
|
||||
log("getCompletionsAtPosition: Is inside comment: " + (new Date().getTime() - start));
|
||||
|
||||
if (insideComment) {
|
||||
host.log("Returning an empty list because completion was inside a comment.");
|
||||
log("Returning an empty list because completion was inside a comment.");
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@ -2233,19 +2263,19 @@ module ts {
|
||||
// Note: previousToken can be undefined if we are the beginning of the file
|
||||
var start = new Date().getTime();
|
||||
var previousToken = findPrecedingToken(position, sourceFile);
|
||||
host.log("getCompletionsAtPosition: Get previous token 1: " + (new Date().getTime() - start));
|
||||
log("getCompletionsAtPosition: Get previous token 1: " + (new Date().getTime() - start));
|
||||
|
||||
// The caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS|
|
||||
// Skip this partial identifier to the previous token
|
||||
if (previousToken && position <= previousToken.end && previousToken.kind === SyntaxKind.Identifier) {
|
||||
var start = new Date().getTime();
|
||||
previousToken = findPrecedingToken(previousToken.pos, sourceFile);
|
||||
host.log("getCompletionsAtPosition: Get previous token 2: " + (new Date().getTime() - start));
|
||||
log("getCompletionsAtPosition: Get previous token 2: " + (new Date().getTime() - start));
|
||||
}
|
||||
|
||||
// Check if this is a valid completion location
|
||||
if (previousToken && isCompletionListBlocker(previousToken)) {
|
||||
host.log("Returning an empty list because completion was requested in an invalid position.");
|
||||
log("Returning an empty list because completion was requested in an invalid position.");
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@ -2274,7 +2304,7 @@ module ts {
|
||||
symbols: {},
|
||||
typeChecker: typeInfoResolver
|
||||
};
|
||||
host.log("getCompletionsAtPosition: Syntactic work: " + (new Date().getTime() - syntacticStart));
|
||||
log("getCompletionsAtPosition: Syntactic work: " + (new Date().getTime() - syntacticStart));
|
||||
|
||||
var location = getTouchingPropertyName(sourceFile, position);
|
||||
// Populate the completion list
|
||||
@ -2348,7 +2378,7 @@ module ts {
|
||||
if (!isMemberCompletion) {
|
||||
Array.prototype.push.apply(activeCompletionSession.entries, keywordCompletions);
|
||||
}
|
||||
host.log("getCompletionsAtPosition: Semantic work: " + (new Date().getTime() - semanticStart));
|
||||
log("getCompletionsAtPosition: Semantic work: " + (new Date().getTime() - semanticStart));
|
||||
|
||||
return {
|
||||
isMemberCompletion,
|
||||
@ -2367,7 +2397,7 @@ module ts {
|
||||
}
|
||||
}
|
||||
});
|
||||
host.log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (new Date().getTime() - start));
|
||||
log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (new Date().getTime() - start));
|
||||
}
|
||||
|
||||
function isCompletionListBlocker(previousToken: Node): boolean {
|
||||
@ -2375,7 +2405,7 @@ module ts {
|
||||
var result = isInStringOrRegularExpressionOrTemplateLiteral(previousToken) ||
|
||||
isIdentifierDefinitionLocation(previousToken) ||
|
||||
isRightOfIllegalDot(previousToken);
|
||||
host.log("getCompletionsAtPosition: isCompletionListBlocker: " + (new Date().getTime() - start));
|
||||
log("getCompletionsAtPosition: isCompletionListBlocker: " + (new Date().getTime() - start));
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -2539,7 +2569,7 @@ module ts {
|
||||
// in the getCompletionsAtPosition earlier
|
||||
filename = normalizeSlashes(filename);
|
||||
|
||||
var sourceFile = getSourceFile(filename);
|
||||
var sourceFile = getValidSourceFile(filename);
|
||||
|
||||
var session = activeCompletionSession;
|
||||
|
||||
@ -2557,7 +2587,7 @@ module ts {
|
||||
// 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.
|
||||
Debug.assert(session.typeChecker.getTypeOfSymbolAtLocation(symbol, location) !== undefined, "Could not find type for symbol");
|
||||
var displayPartsDocumentationsAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getSourceFile(filename), location, session.typeChecker, location, SemanticMeaning.All);
|
||||
var displayPartsDocumentationsAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getValidSourceFile(filename), location, session.typeChecker, location, SemanticMeaning.All);
|
||||
return {
|
||||
name: entryName,
|
||||
kind: displayPartsDocumentationsAndSymbolKind.symbolKind,
|
||||
@ -3058,7 +3088,7 @@ module ts {
|
||||
synchronizeHostData();
|
||||
|
||||
fileName = normalizeSlashes(fileName);
|
||||
var sourceFile = getSourceFile(fileName);
|
||||
var sourceFile = getValidSourceFile(fileName);
|
||||
var node = getTouchingPropertyName(sourceFile, position);
|
||||
if (!node) {
|
||||
return undefined;
|
||||
@ -3104,7 +3134,7 @@ module ts {
|
||||
synchronizeHostData();
|
||||
|
||||
filename = normalizeSlashes(filename);
|
||||
var sourceFile = getSourceFile(filename);
|
||||
var sourceFile = getValidSourceFile(filename);
|
||||
|
||||
var node = getTouchingPropertyName(sourceFile, position);
|
||||
if (!node) {
|
||||
@ -3240,7 +3270,7 @@ module ts {
|
||||
synchronizeHostData();
|
||||
|
||||
filename = normalizeSlashes(filename);
|
||||
var sourceFile = getSourceFile(filename);
|
||||
var sourceFile = getValidSourceFile(filename);
|
||||
|
||||
var node = getTouchingWord(sourceFile, position);
|
||||
if (!node) {
|
||||
@ -3785,7 +3815,7 @@ module ts {
|
||||
synchronizeHostData();
|
||||
|
||||
fileName = normalizeSlashes(fileName);
|
||||
var sourceFile = getSourceFile(fileName);
|
||||
var sourceFile = getValidSourceFile(fileName);
|
||||
|
||||
var node = getTouchingPropertyName(sourceFile, position);
|
||||
if (!node) {
|
||||
@ -4608,7 +4638,7 @@ module ts {
|
||||
synchronizeHostData();
|
||||
|
||||
filename = normalizeSlashes(filename);
|
||||
var sourceFile = getSourceFile(filename);
|
||||
var sourceFile = getValidSourceFile(filename);
|
||||
|
||||
var outputFiles: OutputFile[] = [];
|
||||
|
||||
@ -4757,7 +4787,7 @@ module ts {
|
||||
synchronizeHostData();
|
||||
|
||||
fileName = normalizeSlashes(fileName);
|
||||
var sourceFile = getSourceFile(fileName);
|
||||
var sourceFile = getValidSourceFile(fileName);
|
||||
|
||||
return SignatureHelp.getSignatureHelpItems(sourceFile, position, typeInfoResolver, cancellationToken);
|
||||
}
|
||||
@ -4840,7 +4870,7 @@ module ts {
|
||||
synchronizeHostData();
|
||||
fileName = normalizeSlashes(fileName);
|
||||
|
||||
var sourceFile = getSourceFile(fileName);
|
||||
var sourceFile = getValidSourceFile(fileName);
|
||||
|
||||
var result: ClassifiedSpan[] = [];
|
||||
processNode(sourceFile);
|
||||
@ -5194,12 +5224,12 @@ module ts {
|
||||
|
||||
var start = new Date().getTime();
|
||||
var sourceFile = getCurrentSourceFile(filename);
|
||||
host.log("getIndentationAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start));
|
||||
log("getIndentationAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start));
|
||||
|
||||
var start = new Date().getTime();
|
||||
|
||||
var result = formatting.SmartIndenter.getIndentation(position, sourceFile, editorOptions);
|
||||
host.log("getIndentationAtPosition: computeIndentation : " + (new Date().getTime() - start));
|
||||
log("getIndentationAtPosition: computeIndentation : " + (new Date().getTime() - start));
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -5246,7 +5276,7 @@ module ts {
|
||||
|
||||
filename = normalizeSlashes(filename);
|
||||
|
||||
var sourceFile = getSourceFile(filename);
|
||||
var sourceFile = getValidSourceFile(filename);
|
||||
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
|
||||
@ -5392,7 +5422,7 @@ module ts {
|
||||
synchronizeHostData();
|
||||
|
||||
fileName = normalizeSlashes(fileName);
|
||||
var sourceFile = getSourceFile(fileName);
|
||||
var sourceFile = getValidSourceFile(fileName);
|
||||
|
||||
var node = getTouchingWord(sourceFile, position);
|
||||
|
||||
@ -5468,11 +5498,12 @@ module ts {
|
||||
getFormattingEditsAfterKeystroke,
|
||||
getEmitOutput,
|
||||
getSourceFile: getCurrentSourceFile,
|
||||
getProgram
|
||||
};
|
||||
}
|
||||
|
||||
/// Classifier
|
||||
export function createClassifier(host: Logger): Classifier {
|
||||
export function createClassifier(): Classifier {
|
||||
var scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false);
|
||||
|
||||
/// We do not have a full parser support to know when we should parse a regex or not
|
||||
@ -5775,6 +5806,23 @@ module ts {
|
||||
return { getClassificationsForLine };
|
||||
}
|
||||
|
||||
/// getDefaultLibraryFilePath
|
||||
declare var __dirname: string;
|
||||
|
||||
/**
|
||||
* Get the path of the default library file (lib.d.ts) as distributed with the typescript
|
||||
* node package.
|
||||
* The functionality is not supported if the ts module is consumed outside of a node module.
|
||||
*/
|
||||
export function getDefaultLibFilePath(options: CompilerOptions): string {
|
||||
// Check __dirname is defined and that we are on a node.js system.
|
||||
if (typeof __dirname !== "undefined") {
|
||||
return __dirname + directorySeparator + getDefaultLibFilename(options);
|
||||
}
|
||||
|
||||
throw new Error("getDefaultLibFilePath is only supported when consumed as a node module. ");
|
||||
}
|
||||
|
||||
function initializeServices() {
|
||||
objectAllocator = {
|
||||
getNodeConstructor: kind => {
|
||||
|
||||
@ -25,9 +25,6 @@ module ts {
|
||||
/** Gets the length of this script snapshot. */
|
||||
getLength(): number;
|
||||
|
||||
/** This call returns the JSON-encoded array of the type: number[] */
|
||||
getLineStartPositions(): string;
|
||||
|
||||
/**
|
||||
* Returns a JSON-encoded value of the type:
|
||||
* { span: { start: number; length: number }; newLength: number }
|
||||
@ -37,6 +34,12 @@ module ts {
|
||||
getChangeRange(oldSnapshot: ScriptSnapshotShim): string;
|
||||
}
|
||||
|
||||
export interface Logger {
|
||||
log(s: string): void;
|
||||
trace(s: string): void;
|
||||
error(s: string): void;
|
||||
}
|
||||
|
||||
/** Public interface of the host of a language service shim instance.*/
|
||||
export interface LanguageServiceShimHost extends Logger {
|
||||
getCompilationSettings(): string;
|
||||
@ -44,7 +47,6 @@ module ts {
|
||||
/** Returns a JSON-encoded value of the type: string[] */
|
||||
getScriptFileNames(): string;
|
||||
getScriptVersion(fileName: string): string;
|
||||
getScriptIsOpen(fileName: string): boolean;
|
||||
getScriptSnapshot(fileName: string): ScriptSnapshotShim;
|
||||
getLocalizedDiagnosticMessages(): string;
|
||||
getCancellationToken(): CancellationToken;
|
||||
@ -187,14 +189,6 @@ module ts {
|
||||
return this.scriptSnapshotShim.getLength();
|
||||
}
|
||||
|
||||
public getLineStartPositions(): number[] {
|
||||
if (this.lineStartPositions == null) {
|
||||
this.lineStartPositions = JSON.parse(this.scriptSnapshotShim.getLineStartPositions());
|
||||
}
|
||||
|
||||
return this.lineStartPositions;
|
||||
}
|
||||
|
||||
public getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange {
|
||||
var oldSnapshotShim = <ScriptSnapshotShimAdapter>oldSnapshot;
|
||||
var encoded = this.scriptSnapshotShim.getChangeRange(oldSnapshotShim.scriptSnapshotShim);
|
||||
@ -239,17 +233,14 @@ module ts {
|
||||
}
|
||||
|
||||
public getScriptSnapshot(fileName: string): IScriptSnapshot {
|
||||
return new ScriptSnapshotShimAdapter(this.shimHost.getScriptSnapshot(fileName));
|
||||
var scriptSnapshot = this.shimHost.getScriptSnapshot(fileName);
|
||||
return scriptSnapshot && new ScriptSnapshotShimAdapter(scriptSnapshot);
|
||||
}
|
||||
|
||||
public getScriptVersion(fileName: string): string {
|
||||
return this.shimHost.getScriptVersion(fileName);
|
||||
}
|
||||
|
||||
public getScriptIsOpen(fileName: string): boolean {
|
||||
return this.shimHost.getScriptIsOpen(fileName);
|
||||
}
|
||||
|
||||
public getLocalizedDiagnosticMessages(): any {
|
||||
var diagnosticMessagesJson = this.shimHost.getLocalizedDiagnosticMessages();
|
||||
if (diagnosticMessagesJson == null || diagnosticMessagesJson == "") {
|
||||
@ -269,13 +260,13 @@ module ts {
|
||||
return this.shimHost.getCancellationToken();
|
||||
}
|
||||
|
||||
public getDefaultLibFilename(options: CompilerOptions): string {
|
||||
return this.shimHost.getDefaultLibFilename(JSON.stringify(options));
|
||||
}
|
||||
|
||||
public getCurrentDirectory(): string {
|
||||
return this.shimHost.getCurrentDirectory();
|
||||
}
|
||||
|
||||
public getDefaultLibFilename(options: CompilerOptions): string {
|
||||
return this.shimHost.getDefaultLibFilename(JSON.stringify(options));
|
||||
}
|
||||
}
|
||||
|
||||
function simpleForwardCall(logger: Logger, actionDescription: string, action: () => any): any {
|
||||
@ -669,9 +660,9 @@ module ts {
|
||||
class ClassifierShimObject extends ShimBase implements ClassifierShim {
|
||||
public classifier: Classifier;
|
||||
|
||||
constructor(factory: ShimFactory, public logger: Logger) {
|
||||
constructor(factory: ShimFactory) {
|
||||
super(factory);
|
||||
this.classifier = createClassifier(this.logger);
|
||||
this.classifier = createClassifier();
|
||||
}
|
||||
|
||||
/// COLORIZATION
|
||||
@ -761,7 +752,7 @@ module ts {
|
||||
|
||||
public createClassifierShim(logger: Logger): ClassifierShim {
|
||||
try {
|
||||
return new ClassifierShimObject(this, logger);
|
||||
return new ClassifierShimObject(this);
|
||||
}
|
||||
catch (err) {
|
||||
logInternalError(logger, err);
|
||||
|
||||
1943
tests/baselines/reference/APISample_compile.js
Normal file
1943
tests/baselines/reference/APISample_compile.js
Normal file
File diff suppressed because it is too large
Load Diff
5976
tests/baselines/reference/APISample_compile.types
Normal file
5976
tests/baselines/reference/APISample_compile.types
Normal file
File diff suppressed because it is too large
Load Diff
1995
tests/baselines/reference/APISample_linter.js
Normal file
1995
tests/baselines/reference/APISample_linter.js
Normal file
File diff suppressed because it is too large
Load Diff
6106
tests/baselines/reference/APISample_linter.types
Normal file
6106
tests/baselines/reference/APISample_linter.types
Normal file
File diff suppressed because it is too large
Load Diff
2000
tests/baselines/reference/APISample_transform.js
Normal file
2000
tests/baselines/reference/APISample_transform.js
Normal file
File diff suppressed because it is too large
Load Diff
6054
tests/baselines/reference/APISample_transform.types
Normal file
6054
tests/baselines/reference/APISample_transform.types
Normal file
File diff suppressed because it is too large
Load Diff
2058
tests/baselines/reference/APISample_watcher.js
Normal file
2058
tests/baselines/reference/APISample_watcher.js
Normal file
File diff suppressed because it is too large
Load Diff
6232
tests/baselines/reference/APISample_watcher.types
Normal file
6232
tests/baselines/reference/APISample_watcher.types
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,10 +1,5 @@
|
||||
tests/cases/compiler/contextualTyping.ts(189,18): error TS2384: Overload signatures must all be ambient or non-ambient.
|
||||
tests/cases/compiler/contextualTyping.ts(197,15): error TS2300: Duplicate identifier 'Point'.
|
||||
tests/cases/compiler/contextualTyping.ts(207,10): error TS2300: Duplicate identifier 'Point'.
|
||||
tests/cases/compiler/contextualTyping.ts(230,5): error TS2322: Type '{}' is not assignable to type 'B'.\n Property 'x' is missing in type '{}'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/contextualTyping.ts (4 errors) ====
|
||||
tests/cases/compiler/contextualTyping.ts(189,18): error TS2384: Overload signatures must all be ambient or non-ambient.\ntests/cases/compiler/contextualTyping.ts(197,15): error TS2300: Duplicate identifier 'Point'.\ntests/cases/compiler/contextualTyping.ts(207,10): error TS2300: Duplicate identifier 'Point'.\ntests/cases/compiler/contextualTyping.ts(230,5): error TS2322: Type '{}' is not assignable to type 'B'.
|
||||
Property 'x' is missing in type '{}'.\n\n\n==== tests/cases/compiler/contextualTyping.ts (4 errors) ====
|
||||
// DEFAULT INTERFACES
|
||||
interface IFoo {
|
||||
n: number;
|
||||
@ -242,5 +237,6 @@ tests/cases/compiler/contextualTyping.ts(230,5): error TS2322: Type '{}' is not
|
||||
interface B extends A { }
|
||||
var x: B = { };
|
||||
~
|
||||
!!! error TS2322: Type '{}' is not assignable to type 'B'.\n Property 'x' is missing in type '{}'.
|
||||
!!! error TS2322: Type '{}' is not assignable to type 'B'.
|
||||
!!! error TS2322: Property 'x' is missing in type '{}'.
|
||||
|
||||
@ -232,4 +232,206 @@ var x: B = { };
|
||||
|
||||
|
||||
//// [contextualTyping.js]
|
||||
// CONTEXT: Class property declaration\nvar C1T5 = (function () {\n function C1T5() {\n this.foo = function (i) {\n return i;\n };\n }\n return C1T5;\n})();\n// CONTEXT: Module property declaration\nvar C2T5;\n(function (C2T5) {\n C2T5.foo = function (i) {\n return i;\n };\n})(C2T5 || (C2T5 = {}));\n// CONTEXT: Variable declaration\nvar c3t1 = (function (s) {\n return s;\n});\nvar c3t2 = ({\n n: 1\n});\nvar c3t3 = [];\nvar c3t4 = function () {\n return ({});\n};\nvar c3t5 = function (n) {\n return ({});\n};\nvar c3t6 = function (n, s) {\n return ({});\n};\nvar c3t7 = function (n) {\n return n;\n};\nvar c3t8 = function (n) {\n return n;\n};\nvar c3t9 = [[], []];\nvar c3t10 = [({}), ({})];\nvar c3t11 = [function (n, s) {\n return s;\n}];\nvar c3t12 = {\n foo: ({})\n};\nvar c3t13 = ({\n f: function (i, s) {\n return s;\n }\n});\nvar c3t14 = ({\n a: []\n});\n// CONTEXT: Class property assignment\nvar C4T5 = (function () {\n function C4T5() {\n this.foo = function (i, s) {\n return s;\n };\n }\n return C4T5;\n})();\n// CONTEXT: Module property assignment\nvar C5T5;\n(function (C5T5) {\n C5T5.foo;\n C5T5.foo = function (i, s) {\n return s;\n };\n})(C5T5 || (C5T5 = {}));\n// CONTEXT: Variable assignment\nvar c6t5;\nc6t5 = function (n) {\n return ({});\n};\n// CONTEXT: Array index assignment\nvar c7t2;\nc7t2[0] = ({ n: 1 });\nvar objc8 = ({});\nobjc8.t1 = (function (s) {\n return s;\n});\nobjc8.t2 = ({\n n: 1\n});\nobjc8.t3 = [];\nobjc8.t4 = function () {\n return ({});\n};\nobjc8.t5 = function (n) {\n return ({});\n};\nobjc8.t6 = function (n, s) {\n return ({});\n};\nobjc8.t7 = function (n) {\n return n;\n};\nobjc8.t8 = function (n) {\n return n;\n};\nobjc8.t9 = [[], []];\nobjc8.t10 = [({}), ({})];\nobjc8.t11 = [function (n, s) {\n return s;\n}];\nobjc8.t12 = {\n foo: ({})\n};\nobjc8.t13 = ({\n f: function (i, s) {\n return s;\n }\n});\nobjc8.t14 = ({\n a: []\n});\n// CONTEXT: Function call\nfunction c9t5(f) {\n}\n;\nc9t5(function (n) {\n return ({});\n});\n// CONTEXT: Return statement\nvar c10t5 = function () {\n return function (n) {\n return ({});\n };\n};\n// CONTEXT: Newing a class\nvar C11t5 = (function () {\n function C11t5(f) {\n }\n return C11t5;\n})();\n;\nvar i = new C11t5(function (n) {\n return ({});\n});\n// CONTEXT: Type annotated expression\nvar c12t1 = (function (s) {\n return s;\n});\nvar c12t2 = ({\n n: 1\n});\nvar c12t3 = [];\nvar c12t4 = function () {\n return ({});\n};\nvar c12t5 = function (n) {\n return ({});\n};\nvar c12t6 = function (n, s) {\n return ({});\n};\nvar c12t7 = function (n) {\n return n;\n};\nvar c12t8 = function (n) {\n return n;\n};\nvar c12t9 = [[], []];\nvar c12t10 = [({}), ({})];\nvar c12t11 = [function (n, s) {\n return s;\n}];\nvar c12t12 = {\n foo: ({})\n};\nvar c12t13 = ({\n f: function (i, s) {\n return s;\n }\n});\nvar c12t14 = ({\n a: []\n});\nfunction EF1(a, b) {\n return a + b;\n}\nvar efv = EF1(1, 2);\nfunction Point(x, y) {\n this.x = x;\n this.y = y;\n return this;\n}\nPoint.origin = new Point(0, 0);\nPoint.prototype.add = function (dx, dy) {\n return new Point(this.x + dx, this.y + dy);\n};\nPoint.prototype = {\n x: 0,\n y: 0,\n add: function (dx, dy) {\n return new Point(this.x + dx, this.y + dy);\n }\n};\nvar x = {};\n//# sourceMappingURL=contextualTyping.js.map
|
||||
// CONTEXT: Class property declaration
|
||||
var C1T5 = (function () {
|
||||
function C1T5() {
|
||||
this.foo = function (i) {
|
||||
return i;
|
||||
};
|
||||
}
|
||||
return C1T5;
|
||||
})();
|
||||
// CONTEXT: Module property declaration
|
||||
var C2T5;
|
||||
(function (C2T5) {
|
||||
C2T5.foo = function (i) {
|
||||
return i;
|
||||
};
|
||||
})(C2T5 || (C2T5 = {}));
|
||||
// CONTEXT: Variable declaration
|
||||
var c3t1 = (function (s) {
|
||||
return s;
|
||||
});
|
||||
var c3t2 = ({
|
||||
n: 1
|
||||
});
|
||||
var c3t3 = [];
|
||||
var c3t4 = function () {
|
||||
return ({});
|
||||
};
|
||||
var c3t5 = function (n) {
|
||||
return ({});
|
||||
};
|
||||
var c3t6 = function (n, s) {
|
||||
return ({});
|
||||
};
|
||||
var c3t7 = function (n) {
|
||||
return n;
|
||||
};
|
||||
var c3t8 = function (n) {
|
||||
return n;
|
||||
};
|
||||
var c3t9 = [[], []];
|
||||
var c3t10 = [({}), ({})];
|
||||
var c3t11 = [function (n, s) {
|
||||
return s;
|
||||
}];
|
||||
var c3t12 = {
|
||||
foo: ({})
|
||||
};
|
||||
var c3t13 = ({
|
||||
f: function (i, s) {
|
||||
return s;
|
||||
}
|
||||
});
|
||||
var c3t14 = ({
|
||||
a: []
|
||||
});
|
||||
// CONTEXT: Class property assignment
|
||||
var C4T5 = (function () {
|
||||
function C4T5() {
|
||||
this.foo = function (i, s) {
|
||||
return s;
|
||||
};
|
||||
}
|
||||
return C4T5;
|
||||
})();
|
||||
// CONTEXT: Module property assignment
|
||||
var C5T5;
|
||||
(function (C5T5) {
|
||||
C5T5.foo;
|
||||
C5T5.foo = function (i, s) {
|
||||
return s;
|
||||
};
|
||||
})(C5T5 || (C5T5 = {}));
|
||||
// CONTEXT: Variable assignment
|
||||
var c6t5;
|
||||
c6t5 = function (n) {
|
||||
return ({});
|
||||
};
|
||||
// CONTEXT: Array index assignment
|
||||
var c7t2;
|
||||
c7t2[0] = ({ n: 1 });
|
||||
var objc8 = ({});
|
||||
objc8.t1 = (function (s) {
|
||||
return s;
|
||||
});
|
||||
objc8.t2 = ({
|
||||
n: 1
|
||||
});
|
||||
objc8.t3 = [];
|
||||
objc8.t4 = function () {
|
||||
return ({});
|
||||
};
|
||||
objc8.t5 = function (n) {
|
||||
return ({});
|
||||
};
|
||||
objc8.t6 = function (n, s) {
|
||||
return ({});
|
||||
};
|
||||
objc8.t7 = function (n) {
|
||||
return n;
|
||||
};
|
||||
objc8.t8 = function (n) {
|
||||
return n;
|
||||
};
|
||||
objc8.t9 = [[], []];
|
||||
objc8.t10 = [({}), ({})];
|
||||
objc8.t11 = [function (n, s) {
|
||||
return s;
|
||||
}];
|
||||
objc8.t12 = {
|
||||
foo: ({})
|
||||
};
|
||||
objc8.t13 = ({
|
||||
f: function (i, s) {
|
||||
return s;
|
||||
}
|
||||
});
|
||||
objc8.t14 = ({
|
||||
a: []
|
||||
});
|
||||
// CONTEXT: Function call
|
||||
function c9t5(f) {
|
||||
}
|
||||
;
|
||||
c9t5(function (n) {
|
||||
return ({});
|
||||
});
|
||||
// CONTEXT: Return statement
|
||||
var c10t5 = function () {
|
||||
return function (n) {
|
||||
return ({});
|
||||
};
|
||||
};
|
||||
// CONTEXT: Newing a class
|
||||
var C11t5 = (function () {
|
||||
function C11t5(f) {
|
||||
}
|
||||
return C11t5;
|
||||
})();
|
||||
;
|
||||
var i = new C11t5(function (n) {
|
||||
return ({});
|
||||
});
|
||||
// CONTEXT: Type annotated expression
|
||||
var c12t1 = (function (s) {
|
||||
return s;
|
||||
});
|
||||
var c12t2 = ({
|
||||
n: 1
|
||||
});
|
||||
var c12t3 = [];
|
||||
var c12t4 = function () {
|
||||
return ({});
|
||||
};
|
||||
var c12t5 = function (n) {
|
||||
return ({});
|
||||
};
|
||||
var c12t6 = function (n, s) {
|
||||
return ({});
|
||||
};
|
||||
var c12t7 = function (n) {
|
||||
return n;
|
||||
};
|
||||
var c12t8 = function (n) {
|
||||
return n;
|
||||
};
|
||||
var c12t9 = [[], []];
|
||||
var c12t10 = [({}), ({})];
|
||||
var c12t11 = [function (n, s) {
|
||||
return s;
|
||||
}];
|
||||
var c12t12 = {
|
||||
foo: ({})
|
||||
};
|
||||
var c12t13 = ({
|
||||
f: function (i, s) {
|
||||
return s;
|
||||
}
|
||||
});
|
||||
var c12t14 = ({
|
||||
a: []
|
||||
});
|
||||
function EF1(a, b) {
|
||||
return a + b;
|
||||
}
|
||||
var efv = EF1(1, 2);
|
||||
function Point(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
return this;
|
||||
}
|
||||
Point.origin = new Point(0, 0);
|
||||
Point.prototype.add = function (dx, dy) {
|
||||
return new Point(this.x + dx, this.y + dy);
|
||||
};
|
||||
Point.prototype = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
add: function (dx, dy) {
|
||||
return new Point(this.x + dx, this.y + dy);
|
||||
}
|
||||
};
|
||||
var x = {};
|
||||
//# sourceMappingURL=contextualTyping.js.map
|
||||
File diff suppressed because it is too large
Load Diff
@ -2,4 +2,4 @@
|
||||
var foo: {id:number;} = {id:4};
|
||||
|
||||
//// [contextualTyping1.js]
|
||||
var foo = { id: 4 };
|
||||
var foo = { id: 4 };\n
|
||||
37
tests/cases/compiler/APISample_compile.ts
Normal file
37
tests/cases/compiler/APISample_compile.ts
Normal file
@ -0,0 +1,37 @@
|
||||
// @module: commonjs
|
||||
// @includebuiltfile: typescript.d.ts
|
||||
|
||||
/*
|
||||
* Note: This test is a public API sample. The sample sources can be found
|
||||
at: https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#a-minimal-compiler
|
||||
* Please log a "breaking change" issue for any API breaking change affecting this issue
|
||||
*/
|
||||
|
||||
declare var process: any;
|
||||
declare var console: any;
|
||||
|
||||
import ts = require("typescript");
|
||||
|
||||
export function compile(filenames: string[], options: ts.CompilerOptions): void {
|
||||
var host = ts.createCompilerHost(options);
|
||||
var program = ts.createProgram(filenames, options, host);
|
||||
var checker = ts.createTypeChecker(program, /*produceDiagnostics*/ true);
|
||||
var result = program.emitFiles();
|
||||
|
||||
var allDiagnostics = program.getDiagnostics()
|
||||
.concat(checker.getDiagnostics())
|
||||
.concat(result.diagnostics);
|
||||
|
||||
allDiagnostics.forEach(diagnostic => {
|
||||
var lineChar = diagnostic.file.getLineAndCharacterFromPosition(diagnostic.start);
|
||||
console.log(`${diagnostic.file.filename} (${lineChar.line},${lineChar.character}): ${diagnostic.messageText}`);
|
||||
});
|
||||
|
||||
console.log(`Process exiting with code '${result.emitResultStatus}'.`);
|
||||
process.exit(result.emitResultStatus);
|
||||
}
|
||||
|
||||
compile(process.argv.slice(2), {
|
||||
noEmitOnError: true, noImplicitAny: true,
|
||||
target: ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS
|
||||
});
|
||||
65
tests/cases/compiler/APISample_linter.ts
Normal file
65
tests/cases/compiler/APISample_linter.ts
Normal file
@ -0,0 +1,65 @@
|
||||
// @module: commonjs
|
||||
// @includebuiltfile: typescript.d.ts
|
||||
|
||||
/*
|
||||
* Note: This test is a public API sample. The sample sources can be found
|
||||
at: https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#traversing-the-ast-with-a-little-linter
|
||||
* Please log a "breaking change" issue for any API breaking change affecting this issue
|
||||
*/
|
||||
|
||||
declare var process: any;
|
||||
declare var console: any;
|
||||
declare var fs: any;
|
||||
|
||||
import ts = require("typescript");
|
||||
|
||||
export function delint(sourceFile: ts.SourceFile) {
|
||||
delintNode(sourceFile);
|
||||
|
||||
function delintNode(node: ts.Node) {
|
||||
switch (node.kind) {
|
||||
case ts.SyntaxKind.ForStatement:
|
||||
case ts.SyntaxKind.ForInStatement:
|
||||
case ts.SyntaxKind.WhileStatement:
|
||||
case ts.SyntaxKind.DoStatement:
|
||||
if ((<ts.IterationStatement>node).statement.kind !== ts.SyntaxKind.Block) {
|
||||
report(node, "A looping statement's contents should be wrapped in a block body.");
|
||||
}
|
||||
break;
|
||||
case ts.SyntaxKind.IfStatement:
|
||||
var ifStatement = (<ts.IfStatement>node);
|
||||
if (ifStatement.thenStatement.kind !== ts.SyntaxKind.Block) {
|
||||
report(ifStatement.thenStatement, "An if statement's contents should be wrapped in a block body.");
|
||||
}
|
||||
if (ifStatement.elseStatement &&
|
||||
ifStatement.elseStatement.kind !== ts.SyntaxKind.Block && ifStatement.elseStatement.kind !== ts.SyntaxKind.IfStatement) {
|
||||
report(ifStatement.elseStatement, "An else statement's contents should be wrapped in a block body.");
|
||||
}
|
||||
break;
|
||||
|
||||
case ts.SyntaxKind.BinaryExpression:
|
||||
var op = (<ts.BinaryExpression>node).operator;
|
||||
|
||||
if (op === ts.SyntaxKind.EqualsEqualsToken || op === ts.SyntaxKind.ExclamationEqualsToken) {
|
||||
report(node, "Use '===' and '!=='.")
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ts.forEachChild(node, delintNode);
|
||||
}
|
||||
|
||||
function report(node: ts.Node, message: string) {
|
||||
var lineChar = sourceFile.getLineAndCharacterFromPosition(node.getStart());
|
||||
console.log(`${sourceFile.filename} (${lineChar.line},${lineChar.character}): ${message}`)
|
||||
}
|
||||
}
|
||||
|
||||
var filenames = process.argv.slice(2);
|
||||
filenames.forEach(filename => {
|
||||
// Parse a file
|
||||
var sourceFile = ts.createSourceFile(filename, fs.readFileSync(filename).toString(), ts.ScriptTarget.ES6, /*setParentNodes */ true);
|
||||
|
||||
// delint it
|
||||
delint(sourceFile);
|
||||
});
|
||||
67
tests/cases/compiler/APISample_transform.ts
Normal file
67
tests/cases/compiler/APISample_transform.ts
Normal file
@ -0,0 +1,67 @@
|
||||
// @module: commonjs
|
||||
// @includebuiltfile: typescript.d.ts
|
||||
|
||||
/*
|
||||
* Note: This test is a public API sample. The sample sources can be found
|
||||
at: https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#a-simple-transform-function
|
||||
* Please log a "breaking change" issue for any API breaking change affecting this issue
|
||||
*/
|
||||
|
||||
declare var process: any;
|
||||
declare var console: any;
|
||||
declare var fs: any;
|
||||
declare var path: any;
|
||||
|
||||
import ts = require("typescript");
|
||||
|
||||
function transform(contents: string, compilerOptions: ts.CompilerOptions = {}) {
|
||||
// Sources
|
||||
var files = {
|
||||
"file.ts": contents,
|
||||
"lib.d.ts": fs.readFileSync(ts.getDefaultLibFilePath(compilerOptions)).toString()
|
||||
};
|
||||
|
||||
// Generated outputs
|
||||
var outputs = [];
|
||||
|
||||
// Create a compilerHost object to allow the compiler to read and write files
|
||||
var compilerHost = {
|
||||
getSourceFile: (filename, target) => {
|
||||
return files[filename] !== undefined ?
|
||||
ts.createSourceFile(filename, files[filename], target) : undefined;
|
||||
},
|
||||
writeFile: (name, text, writeByteOrderMark) => {
|
||||
outputs.push({ name: name, text: text, writeByteOrderMark: writeByteOrderMark });
|
||||
},
|
||||
getDefaultLibFilename: () => "lib.d.ts",
|
||||
useCaseSensitiveFileNames: () => false,
|
||||
getCanonicalFileName: (filename) => filename,
|
||||
getCurrentDirectory: () => "",
|
||||
getNewLine: () => "\n"
|
||||
};
|
||||
|
||||
// Create a program from inputs
|
||||
var program = ts.createProgram(["file.ts"], compilerOptions, compilerHost);
|
||||
|
||||
// Query for early errors
|
||||
var errors = program.getDiagnostics();
|
||||
// Do not generate code in the presence of early errors
|
||||
if (!errors.length) {
|
||||
// Type check and get semantic errors
|
||||
var checker = program.getTypeChecker(true);
|
||||
errors = checker.getDiagnostics();
|
||||
// Generate output
|
||||
program.emitFiles();
|
||||
}
|
||||
return {
|
||||
outputs: outputs,
|
||||
errors: errors.map(function (e) { return e.file.filename + "(" + e.file.getLineAndCharacterFromPosition(e.start).line + "): " + e.messageText; })
|
||||
};
|
||||
}
|
||||
|
||||
// Calling our transform function using a simple TypeScript variable declarations,
|
||||
// and loading the default library like:
|
||||
var source = "var x: number = 'string'";
|
||||
var result = transform(source);
|
||||
|
||||
console.log(JSON.stringify(result));
|
||||
104
tests/cases/compiler/APISample_watcher.ts
Normal file
104
tests/cases/compiler/APISample_watcher.ts
Normal file
@ -0,0 +1,104 @@
|
||||
// @module: commonjs
|
||||
// @includebuiltfile: typescript.d.ts
|
||||
|
||||
/*
|
||||
* Note: This test is a public API sample. The sample sources can be found
|
||||
at: https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#incremental-build-support-using-the-language-services
|
||||
* Please log a "breaking change" issue for any API breaking change affecting this issue
|
||||
*/
|
||||
|
||||
declare var process: any;
|
||||
declare var console: any;
|
||||
declare var fs: any;
|
||||
declare var path: any;
|
||||
|
||||
import ts = require("typescript");
|
||||
|
||||
function watch(rootFilenames: string[], options: ts.CompilerOptions) {
|
||||
var files: ts.Map<{ version: number }> = {};
|
||||
|
||||
// initialize the list of files
|
||||
rootFilenames.forEach(filename => {
|
||||
files[filename] = { version: 0 };
|
||||
});
|
||||
|
||||
// Create the language service host to allow the LS to communicate with the host
|
||||
var servicesHost: ts.LanguageServiceHost = {
|
||||
getScriptFileNames: () => rootFilenames,
|
||||
getScriptVersion: (filename) => files[filename] && files[filename].version.toString(),
|
||||
getScriptSnapshot: (filename) => {
|
||||
if (!fs.existsSync(filename)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return ts.ScriptSnapshot.fromString(fs.readFileSync(filename).toString());
|
||||
},
|
||||
getCurrentDirectory: () => process.cwd(),
|
||||
getCompilationSettings: () => options,
|
||||
getDefaultLibFilename: (options) => ts.getDefaultLibFilePath(options),
|
||||
};
|
||||
|
||||
// Create the language service files
|
||||
var services = ts.createLanguageService(servicesHost, ts.createDocumentRegistry())
|
||||
|
||||
// Now let's watch the files
|
||||
rootFilenames.forEach(filename => {
|
||||
// First time around, emit all files
|
||||
emitFile(filename);
|
||||
|
||||
// Add a watch on the file to handle next change
|
||||
fs.watchFile(filename,
|
||||
{ persistent: true, interval: 250 },
|
||||
(curr, prev) => {
|
||||
// Check timestamp
|
||||
if (+curr.mtime <= +prev.mtime) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the version to signal a change in the file
|
||||
files[filename].version++;
|
||||
|
||||
// write the changes to disk
|
||||
emitFile(filename);
|
||||
});
|
||||
});
|
||||
|
||||
function emitFile(filename: string) {
|
||||
var output = services.getEmitOutput(filename);
|
||||
|
||||
if (output.emitOutputStatus === ts.EmitReturnStatus.Succeeded) {
|
||||
console.log(`Emitting ${filename}`);
|
||||
}
|
||||
else {
|
||||
console.log(`Emitting ${filename} failed`);
|
||||
logErrors(filename);
|
||||
}
|
||||
|
||||
output.outputFiles.forEach(o => {
|
||||
fs.writeFileSync(o.name, o.text, "utf8");
|
||||
});
|
||||
}
|
||||
|
||||
function logErrors(filename: string) {
|
||||
var allDiagnostics = services.getCompilerOptionsDiagnostics()
|
||||
.concat(services.getSyntacticDiagnostics(filename))
|
||||
.concat(services.getSemanticDiagnostics(filename));
|
||||
|
||||
allDiagnostics.forEach(diagnostic => {
|
||||
if (diagnostic.file) {
|
||||
var lineChar = diagnostic.file.getLineAndCharacterFromPosition(diagnostic.start);
|
||||
console.log(` Error ${diagnostic.file.filename} (${lineChar.line},${lineChar.character}): ${diagnostic.messageText}`);
|
||||
}
|
||||
else {
|
||||
console.log(` Error: ${diagnostic.messageText}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize files constituting the program as all .ts files in the current directory
|
||||
var currentDirectoryFiles = fs.readdirSync(process.cwd()).
|
||||
filter(filename=> filename.length >= 3 && filename.substr(filename.length - 3, 3) === ".ts");
|
||||
|
||||
// Start the watcher
|
||||
watch(currentDirectoryFiles, { module: ts.ModuleKind.CommonJS });
|
||||
@ -20,7 +20,7 @@ module ts {
|
||||
}
|
||||
|
||||
function createTree(text: IScriptSnapshot, version: string) {
|
||||
return createLanguageServiceSourceFile(/*fileName:*/ "", text, ScriptTarget.Latest, version, /*isOpen:*/ true, /*setNodeParents:*/ true)
|
||||
return createLanguageServiceSourceFile(/*fileName:*/ "", text, ScriptTarget.Latest, version, /*setNodeParents:*/ true)
|
||||
}
|
||||
|
||||
function assertSameDiagnostics(file1: SourceFile, file2: SourceFile) {
|
||||
@ -56,7 +56,7 @@ module ts {
|
||||
Utils.assertInvariants(newTree, /*parent:*/ undefined);
|
||||
|
||||
// Create a tree for the new text, in an incremental fashion.
|
||||
var incrementalNewTree = updateLanguageServiceSourceFile(oldTree, newText, oldTree.version + ".", /*isOpen:*/ true, textChangeRange);
|
||||
var incrementalNewTree = updateLanguageServiceSourceFile(oldTree, newText, oldTree.version + ".", textChangeRange);
|
||||
Utils.assertInvariants(incrementalNewTree, /*parent:*/ undefined);
|
||||
|
||||
// We should get the same tree when doign a full or incremental parse.
|
||||
|
||||
@ -5,8 +5,8 @@ describe("DocumentRegistry", () => {
|
||||
var documentRegistry = ts.createDocumentRegistry();
|
||||
var defaultCompilerOptions = ts.getDefaultCompilerOptions();
|
||||
|
||||
var f1 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), "1", false);
|
||||
var f2 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), "1", false);
|
||||
var f1 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1");
|
||||
var f2 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1");
|
||||
|
||||
assert(f1 === f2, "DocumentRegistry should return the same document for the same name");
|
||||
});
|
||||
@ -17,22 +17,22 @@ describe("DocumentRegistry", () => {
|
||||
|
||||
// change compilation setting that doesn't affect parsing - should have the same document
|
||||
compilerOptions.declaration = true;
|
||||
var f1 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), "1", false);
|
||||
var f1 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1");
|
||||
compilerOptions.declaration = false;
|
||||
var f2 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), "1", false);
|
||||
var f2 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1");
|
||||
|
||||
assert(f1 === f2, "Expected to have the same document instance");
|
||||
|
||||
|
||||
// change value of compilation setting that is used during production of AST - new document is required
|
||||
compilerOptions.target = ts.ScriptTarget.ES3;
|
||||
var f3 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), "1", false);
|
||||
var f3 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1");
|
||||
|
||||
assert(f1 !== f3, "Changed target: Expected to have different instances of document");
|
||||
|
||||
compilerOptions.module = ts.ModuleKind.CommonJS;
|
||||
var f4 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), "1", false);
|
||||
var f4 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1");
|
||||
|
||||
assert(f1 !== f4, "Changed module: Expected to have different instances of document");
|
||||
assert(f3 === f4, "Changed module: Expected to have the same instance of the document");
|
||||
});
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user