mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-30 01:04:49 -05:00
Consolidate Document and SoruceFile
This commit is contained in:
@@ -67,6 +67,13 @@ module ts {
|
||||
getReturnType(): Type;
|
||||
}
|
||||
|
||||
export interface SourceFile {
|
||||
getSourceUnit(): TypeScript.SourceUnitSyntax;
|
||||
getSyntaxTree(): TypeScript.SyntaxTree;
|
||||
getBloomFilter(): TypeScript.BloomFilter;
|
||||
update(scriptSnapshot: TypeScript.IScriptSnapshot, version: number, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange): SourceFile;
|
||||
}
|
||||
|
||||
var scanner: Scanner = createScanner(ScriptTarget.ES5);
|
||||
|
||||
var emptyArray: any [] = [];
|
||||
@@ -81,7 +88,6 @@ module ts {
|
||||
}
|
||||
|
||||
class NodeObject implements Node {
|
||||
|
||||
public kind: SyntaxKind;
|
||||
public pos: number;
|
||||
public end: number;
|
||||
@@ -294,6 +300,130 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
var incrementalParse: IncrementalParse = TypeScript.IncrementalParser.parse;
|
||||
|
||||
class SourceFileObject extends NodeObject implements SourceFile {
|
||||
public filename: string;
|
||||
public text: string;
|
||||
public getLineAndCharacterFromPosition(position: number): { line: number; character: number } { return null; }
|
||||
public amdDependencies: string[];
|
||||
public referencedFiles: FileReference[];
|
||||
public syntacticErrors: Diagnostic[];
|
||||
public semanticErrors: Diagnostic[];
|
||||
public hasNoDefaultLib: boolean;
|
||||
public externalModuleIndicator: Node; // The first node that causes this file to be an external module
|
||||
public nodeCount: number;
|
||||
public identifierCount: number;
|
||||
public symbolCount: number;
|
||||
public statements: NodeArray<Statement>;
|
||||
public byteOrderMark: ByteOrderMark;
|
||||
public version: number;
|
||||
public isOpen: boolean;
|
||||
public languageVersion: ScriptTarget;
|
||||
|
||||
private bloomFilter: TypeScript.BloomFilter;
|
||||
private syntaxTree: TypeScript.SyntaxTree;
|
||||
private scriptSnapshot: TypeScript.IScriptSnapshot;
|
||||
|
||||
public getSourceUnit(): TypeScript.SourceUnitSyntax {
|
||||
// If we don't have a script, create one from our parse tree.
|
||||
return this.getSyntaxTree().sourceUnit();
|
||||
}
|
||||
|
||||
public getLineMap(): TypeScript.LineMap {
|
||||
return this.getSyntaxTree().lineMap();
|
||||
}
|
||||
|
||||
public getSyntaxTree(): TypeScript.SyntaxTree {
|
||||
if (!this.syntaxTree) {
|
||||
var start = new Date().getTime();
|
||||
|
||||
this.syntaxTree = TypeScript.Parser.parse(
|
||||
this.filename, TypeScript.SimpleText.fromScriptSnapshot(this.scriptSnapshot), this.languageVersion, this.isDeclareFile());
|
||||
|
||||
var time = new Date().getTime() - start;
|
||||
|
||||
//TypeScript.syntaxTreeParseTime += time;
|
||||
}
|
||||
|
||||
return this.syntaxTree;
|
||||
}
|
||||
|
||||
private isDeclareFile(): boolean {
|
||||
return TypeScript.isDTSFile(this.filename);
|
||||
}
|
||||
|
||||
public getBloomFilter(): TypeScript.BloomFilter {
|
||||
if (!this.bloomFilter) {
|
||||
var identifiers = TypeScript.createIntrinsicsObject<boolean>();
|
||||
var pre = function (cur: TypeScript.ISyntaxElement) {
|
||||
if (TypeScript.ASTHelpers.isValidAstNode(cur)) {
|
||||
if (cur.kind() === TypeScript.SyntaxKind.IdentifierName) {
|
||||
var nodeText = TypeScript.tokenValueText((<TypeScript.ISyntaxToken>cur));
|
||||
|
||||
identifiers[nodeText] = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TypeScript.getAstWalkerFactory().simpleWalk(this.getSourceUnit(), pre, null, identifiers);
|
||||
|
||||
var identifierCount = 0;
|
||||
for (var name in identifiers) {
|
||||
if (identifiers[name]) {
|
||||
identifierCount++;
|
||||
}
|
||||
}
|
||||
|
||||
this.bloomFilter = new TypeScript.BloomFilter(identifierCount);
|
||||
this.bloomFilter.addKeys(identifiers);
|
||||
}
|
||||
return this.bloomFilter;
|
||||
}
|
||||
|
||||
public update(scriptSnapshot: TypeScript.IScriptSnapshot, version: number, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange): SourceFile {
|
||||
// See if we are currently holding onto a syntax tree. We may not be because we're
|
||||
// either a closed file, or we've just been lazy and haven't had to create the syntax
|
||||
// tree yet. Access the field instead of the method so we don't accidently realize
|
||||
// the old syntax tree.
|
||||
var oldSyntaxTree = this.syntaxTree;
|
||||
|
||||
if (textChangeRange !== null && Debug.shouldAssert(AssertionLevel.Normal)) {
|
||||
var oldText = this.scriptSnapshot;
|
||||
var newText = scriptSnapshot;
|
||||
|
||||
TypeScript.Debug.assert((oldText.getLength() - textChangeRange.span().length() + textChangeRange.newLength()) === newText.getLength());
|
||||
|
||||
if (Debug.shouldAssert(AssertionLevel.VeryAggressive)) {
|
||||
var oldTextPrefix = oldText.getText(0, textChangeRange.span().start());
|
||||
var newTextPrefix = newText.getText(0, textChangeRange.span().start());
|
||||
TypeScript.Debug.assert(oldTextPrefix === newTextPrefix);
|
||||
|
||||
var oldTextSuffix = oldText.getText(textChangeRange.span().end(), oldText.getLength());
|
||||
var newTextSuffix = newText.getText(textChangeRange.newSpan().end(), newText.getLength());
|
||||
TypeScript.Debug.assert(oldTextSuffix === newTextSuffix);
|
||||
}
|
||||
}
|
||||
|
||||
var text = TypeScript.SimpleText.fromScriptSnapshot(scriptSnapshot);
|
||||
|
||||
// If we don't have a text change, or we don't have an old syntax tree, then do a full
|
||||
// parse. Otherwise, do an incremental parse.
|
||||
var newSyntaxTree = textChangeRange === null || oldSyntaxTree === null
|
||||
? TypeScript.Parser.parse(this.filename, text, this.languageVersion, TypeScript.isDTSFile(this.filename))
|
||||
: TypeScript.IncrementalParser.parse(oldSyntaxTree, textChangeRange, text);
|
||||
|
||||
return SourceFileObject.createSourceFileObject(this.languageVersion, this.filename, scriptSnapshot, this.byteOrderMark, version, isOpen, newSyntaxTree);
|
||||
}
|
||||
|
||||
public static createSourceFileObject(languageVersion: ScriptTarget, filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, byteOrderMark: ByteOrderMark, version: number, isOpen: boolean, syntaxTree: TypeScript.SyntaxTree) {
|
||||
var newSoruceFile = <SourceFileObject><any>createSourceFile(filename, scriptSnapshot.getText(0, scriptSnapshot.getLength()), languageVersion, byteOrderMark, version, isOpen);
|
||||
newSoruceFile.scriptSnapshot = scriptSnapshot;
|
||||
newSoruceFile.syntaxTree = syntaxTree;
|
||||
return newSoruceFile;
|
||||
}
|
||||
}
|
||||
|
||||
export interface Logger {
|
||||
information(): boolean;
|
||||
debug(): boolean;
|
||||
@@ -563,17 +693,17 @@ module ts {
|
||||
byteOrderMark: ByteOrderMark,
|
||||
version: number,
|
||||
isOpen: boolean,
|
||||
referencedFiles: string[]): Document;
|
||||
referencedFiles: string[]): SourceFile;
|
||||
|
||||
updateDocument(
|
||||
document: Document,
|
||||
document: SourceFile,
|
||||
filename: string,
|
||||
compilationSettings: CompilerOptions,
|
||||
scriptSnapshot: TypeScript.IScriptSnapshot,
|
||||
version: number,
|
||||
isOpen: boolean,
|
||||
textChangeRange: TypeScript.TextChangeRange
|
||||
): Document;
|
||||
): SourceFile;
|
||||
|
||||
releaseDocument(filename: string, compilationSettings: CompilerOptions): void
|
||||
}
|
||||
@@ -665,172 +795,6 @@ module ts {
|
||||
(oldSyntaxTree: TypeScript.SyntaxTree, textChangeRange: TypeScript.TextChangeRange, newText: TypeScript.ISimpleText): TypeScript.SyntaxTree
|
||||
}
|
||||
|
||||
export interface Document {
|
||||
getFilename(): string;
|
||||
getByteOrderMark(): ByteOrderMark;
|
||||
getVersion(): number;
|
||||
isOpen(): boolean;
|
||||
getSourceUnit(): TypeScript.SourceUnitSyntax;
|
||||
getSyntaxTree(): TypeScript.SyntaxTree;
|
||||
getSourceFile(): SourceFile;
|
||||
getBloomFilter(): TypeScript.BloomFilter;
|
||||
update(scriptSnapshot: TypeScript.IScriptSnapshot, version: number, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange): Document;
|
||||
}
|
||||
|
||||
class DocumentObject implements Document {
|
||||
private bloomFilter: TypeScript.BloomFilter = null;
|
||||
|
||||
// By default, our Document class doesn't support incremental update of its conten
|
||||
// However, we enable other layers (like teh services layer) to inject the capability
|
||||
// into us by setting this function.
|
||||
public static incrementalParse: IncrementalParse = TypeScript.IncrementalParser.parse;
|
||||
|
||||
constructor(private compilationSettings: CompilerOptions,
|
||||
public filename: string,
|
||||
public referencedFiles: string[],
|
||||
private scriptSnapshot: TypeScript.IScriptSnapshot,
|
||||
public byteOrderMark: ByteOrderMark,
|
||||
public version: number,
|
||||
public _isOpen: boolean,
|
||||
private syntaxTree: TypeScript.SyntaxTree,
|
||||
private soruceFile: SourceFile) {
|
||||
}
|
||||
|
||||
public getFilename(): string {
|
||||
return this.filename;
|
||||
}
|
||||
|
||||
public getVersion(): number {
|
||||
return this.version;
|
||||
}
|
||||
|
||||
public isOpen(): boolean {
|
||||
return this._isOpen;
|
||||
}
|
||||
|
||||
public getByteOrderMark(): ByteOrderMark {
|
||||
return this.byteOrderMark;
|
||||
}
|
||||
public isDeclareFile(): boolean {
|
||||
return TypeScript.isDTSFile(this.filename);
|
||||
}
|
||||
|
||||
public getSourceUnit(): TypeScript.SourceUnitSyntax {
|
||||
// If we don't have a script, create one from our parse tree.
|
||||
return this.getSyntaxTree().sourceUnit();
|
||||
}
|
||||
|
||||
public getLineMap(): TypeScript.LineMap {
|
||||
return this.getSyntaxTree().lineMap();
|
||||
}
|
||||
|
||||
public getSyntaxTree(): TypeScript.SyntaxTree {
|
||||
if (!this.syntaxTree) {
|
||||
var start = new Date().getTime();
|
||||
|
||||
this.syntaxTree = TypeScript.Parser.parse(
|
||||
this.filename, TypeScript.SimpleText.fromScriptSnapshot(this.scriptSnapshot), this.compilationSettings.target, this.isDeclareFile());
|
||||
|
||||
var time = new Date().getTime() - start;
|
||||
|
||||
//TypeScript.syntaxTreeParseTime += time;
|
||||
}
|
||||
|
||||
return this.syntaxTree;
|
||||
}
|
||||
|
||||
public getSourceFile(): SourceFile {
|
||||
if (!this.soruceFile) {
|
||||
var start = new Date().getTime();
|
||||
|
||||
this.soruceFile = createSourceFile(this.filename, this.scriptSnapshot.getText(0, this.scriptSnapshot.getLength()), this.compilationSettings.target);
|
||||
|
||||
var time = new Date().getTime() - start;
|
||||
|
||||
//TypeScript.astParseTime += time;
|
||||
}
|
||||
|
||||
return this.soruceFile;
|
||||
}
|
||||
|
||||
public getBloomFilter(): TypeScript.BloomFilter {
|
||||
if (!this.bloomFilter) {
|
||||
var identifiers = TypeScript.createIntrinsicsObject<boolean>();
|
||||
var pre = function (cur: TypeScript.ISyntaxElement) {
|
||||
if (TypeScript.ASTHelpers.isValidAstNode(cur)) {
|
||||
if (cur.kind() === TypeScript.SyntaxKind.IdentifierName) {
|
||||
var nodeText = TypeScript.tokenValueText((<TypeScript.ISyntaxToken>cur));
|
||||
|
||||
identifiers[nodeText] = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TypeScript.getAstWalkerFactory().simpleWalk(this.getSourceUnit(), pre, null, identifiers);
|
||||
|
||||
var identifierCount = 0;
|
||||
for (var name in identifiers) {
|
||||
if (identifiers[name]) {
|
||||
identifierCount++;
|
||||
}
|
||||
}
|
||||
|
||||
this.bloomFilter = new TypeScript.BloomFilter(identifierCount);
|
||||
this.bloomFilter.addKeys(identifiers);
|
||||
}
|
||||
return this.bloomFilter;
|
||||
}
|
||||
|
||||
// Returns true if this file should get emitted into its own unique output file.
|
||||
// Otherwise, it should be written into a single output file along with the rest of hte
|
||||
// documents in the compilation.
|
||||
public emitToOwnOutputFile(): boolean {
|
||||
// If we haven't specified an output file in our settings, then we're definitely
|
||||
// emitting to our own file. Also, if we're an external module, then we're
|
||||
// definitely emitting to our own file.
|
||||
return !this.compilationSettings.out || this.getSyntaxTree().isExternalModule();
|
||||
}
|
||||
|
||||
public update(scriptSnapshot: TypeScript.IScriptSnapshot, version: number, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange): Document {
|
||||
// See if we are currently holding onto a syntax tree. We may not be because we're
|
||||
// either a closed file, or we've just been lazy and haven't had to create the syntax
|
||||
// tree yet. Access the field instead of the method so we don't accidently realize
|
||||
// the old syntax tree.
|
||||
var oldSyntaxTree = this.syntaxTree;
|
||||
|
||||
if (textChangeRange !== null && Debug.shouldAssert(AssertionLevel.Normal)) {
|
||||
var oldText = this.scriptSnapshot;
|
||||
var newText = scriptSnapshot;
|
||||
|
||||
TypeScript.Debug.assert((oldText.getLength() - textChangeRange.span().length() + textChangeRange.newLength()) === newText.getLength());
|
||||
|
||||
if (Debug.shouldAssert(AssertionLevel.VeryAggressive)) {
|
||||
var oldTextPrefix = oldText.getText(0, textChangeRange.span().start());
|
||||
var newTextPrefix = newText.getText(0, textChangeRange.span().start());
|
||||
TypeScript.Debug.assert(oldTextPrefix === newTextPrefix);
|
||||
|
||||
var oldTextSuffix = oldText.getText(textChangeRange.span().end(), oldText.getLength());
|
||||
var newTextSuffix = newText.getText(textChangeRange.newSpan().end(), newText.getLength());
|
||||
TypeScript.Debug.assert(oldTextSuffix === newTextSuffix);
|
||||
}
|
||||
}
|
||||
|
||||
var text = TypeScript.SimpleText.fromScriptSnapshot(scriptSnapshot);
|
||||
|
||||
// If we don't have a text change, or we don't have an old syntax tree, then do a full
|
||||
// parse. Otherwise, do an incremental parse.
|
||||
var newSyntaxTree = textChangeRange === null || oldSyntaxTree === null || DocumentObject.incrementalParse === null
|
||||
? TypeScript.Parser.parse(this.filename, text, this.compilationSettings.target, TypeScript.isDTSFile(this.filename))
|
||||
: DocumentObject.incrementalParse(oldSyntaxTree, textChangeRange, text);
|
||||
|
||||
return new DocumentObject(this.compilationSettings, this.filename, this.referencedFiles, scriptSnapshot, this.byteOrderMark, version, isOpen, newSyntaxTree, /*soruceFile*/ null);
|
||||
}
|
||||
}
|
||||
|
||||
export function createDocument(compilationSettings: CompilerOptions, fileName: string, scriptSnapshot: TypeScript.IScriptSnapshot, byteOrderMark: ByteOrderMark, version: number, isOpen: boolean, referencedFiles: string[]): Document {
|
||||
return new DocumentObject(compilationSettings, fileName, referencedFiles, scriptSnapshot, byteOrderMark, version, isOpen, /*syntaxTree:*/ null, /*soruceFile*/ null);
|
||||
}
|
||||
|
||||
/// Language Service
|
||||
|
||||
interface CompletionSession {
|
||||
@@ -859,7 +823,7 @@ module ts {
|
||||
}
|
||||
|
||||
interface DocumentRegistryEntry {
|
||||
document: Document;
|
||||
document: SourceFile;
|
||||
refCount: number;
|
||||
owners: string[];
|
||||
}
|
||||
@@ -1172,13 +1136,12 @@ module ts {
|
||||
scriptSnapshot: TypeScript.IScriptSnapshot,
|
||||
byteOrderMark: ByteOrderMark,
|
||||
version: number,
|
||||
isOpen: boolean,
|
||||
referencedFiles: string[]= []): Document {
|
||||
isOpen: boolean): SourceFile {
|
||||
|
||||
var bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true);
|
||||
var entry = lookUp(bucket, filename);
|
||||
if (!entry) {
|
||||
var document = createDocument(compilationSettings, filename, scriptSnapshot, byteOrderMark, version, isOpen, referencedFiles);
|
||||
var document = createSourceFile(filename, scriptSnapshot.getText(0, scriptSnapshot.getLength()), compilationSettings.target, byteOrderMark, version, isOpen);
|
||||
|
||||
bucket[filename] = entry = {
|
||||
document: document,
|
||||
@@ -1192,21 +1155,21 @@ module ts {
|
||||
}
|
||||
|
||||
function updateDocument(
|
||||
document: Document,
|
||||
document: SourceFile,
|
||||
filename: string,
|
||||
compilationSettings: CompilerOptions,
|
||||
scriptSnapshot: TypeScript.IScriptSnapshot,
|
||||
version: number,
|
||||
isOpen: boolean,
|
||||
textChangeRange: TypeScript.TextChangeRange
|
||||
): Document {
|
||||
): SourceFile {
|
||||
|
||||
var bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ false);
|
||||
Debug.assert(bucket);
|
||||
var entry = lookUp(bucket, filename);
|
||||
Debug.assert(entry);
|
||||
|
||||
if (entry.document.isOpen() === isOpen && entry.document.getVersion() === version) {
|
||||
if (entry.document.isOpen === isOpen && entry.document.version === version) {
|
||||
return entry.document;
|
||||
}
|
||||
|
||||
@@ -1252,7 +1215,7 @@ module ts {
|
||||
var program: Program;
|
||||
var typeChecker: TypeChecker;
|
||||
var useCaseSensitivefilenames = false;
|
||||
var documentsByName: Map<Document> = {};
|
||||
var documentsByName: Map<SourceFile> = {};
|
||||
var documentRegistry = documentRegistry;
|
||||
var cancellationToken = new CancellationTokenObject(host.getCancellationToken());
|
||||
var activeCompletionSession: CompletionSession; // The current active completion session, used to get the completion entry details
|
||||
@@ -1262,7 +1225,7 @@ module ts {
|
||||
TypeScript.LocalizedDiagnosticMessages = host.getLocalizedDiagnosticMessages();
|
||||
}
|
||||
|
||||
function getDocument(filename: string): Document {
|
||||
function getDocument(filename: string): SourceFile {
|
||||
return lookUp(documentsByName, filename);
|
||||
}
|
||||
|
||||
@@ -1339,12 +1302,12 @@ module ts {
|
||||
var isOpen = hostCache.isOpen(filename);
|
||||
var scriptSnapshot = hostCache.getScriptSnapshot(filename);
|
||||
|
||||
var document: Document = getDocument(filename);
|
||||
var document: SourceFile = getDocument(filename);
|
||||
if (document) {
|
||||
//
|
||||
// If the document is the same, assume no update
|
||||
//
|
||||
if (document.getVersion() === version && document.isOpen() === isOpen) {
|
||||
if (document.version === version && document.isOpen === isOpen) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1356,7 +1319,7 @@ module ts {
|
||||
// new text buffer).
|
||||
var textChangeRange: TypeScript.TextChangeRange = null;
|
||||
if (document.isOpen && isOpen) {
|
||||
textChangeRange = hostCache.getScriptTextChangeRangeSinceVersion(filename, document.getVersion());
|
||||
textChangeRange = hostCache.getScriptTextChangeRangeSinceVersion(filename, document.version);
|
||||
}
|
||||
|
||||
document = documentRegistry.updateDocument(document, filename, compilationSettings, scriptSnapshot, version, isOpen, textChangeRange);
|
||||
@@ -2217,7 +2180,7 @@ module ts {
|
||||
getNodeConstructor: kind => {
|
||||
function Node() {
|
||||
}
|
||||
var proto = new NodeObject();
|
||||
var proto = kind === SyntaxKind.SourceFile ? new SourceFileObject() : new NodeObject();
|
||||
proto.kind = kind;
|
||||
proto.pos = 0;
|
||||
proto.end = 0;
|
||||
|
||||
Reference in New Issue
Block a user