mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-14 19:16:17 -06:00
reorganize definitions
This commit is contained in:
parent
bfdf2ac69a
commit
792f9c9ac8
@ -303,160 +303,6 @@ module ts {
|
||||
initializeServices();
|
||||
}
|
||||
|
||||
module TypeScript.Services {
|
||||
export interface IncrementalParse {
|
||||
(oldSyntaxTree: SyntaxTree, textChangeRange: TextChangeRange, newText: ISimpleText): SyntaxTree
|
||||
}
|
||||
|
||||
|
||||
export class Document {
|
||||
private _bloomFilter: BloomFilter = null;
|
||||
|
||||
// By default, our Document class doesn't support incremental update of its contents.
|
||||
// However, we enable other layers (like teh services layer) to inject the capability
|
||||
// into us by setting this function.
|
||||
public static incrementalParse: IncrementalParse = null;
|
||||
|
||||
constructor(private compilationSettings: ts.CompilerOptions,
|
||||
public filename: string,
|
||||
public referencedFiles: string[],
|
||||
private _scriptSnapshot: IScriptSnapshot,
|
||||
public byteOrderMark: ts.ByteOrderMark,
|
||||
public version: number,
|
||||
public isOpen: boolean,
|
||||
private _syntaxTree: SyntaxTree,
|
||||
private _soruceFile: ts.SourceFile) {
|
||||
}
|
||||
|
||||
public isDeclareFile(): boolean {
|
||||
return isDTSFile(this.filename);
|
||||
}
|
||||
|
||||
public sourceUnit(): SourceUnitSyntax {
|
||||
// If we don't have a script, create one from our parse tree.
|
||||
return this.syntaxTree().sourceUnit();
|
||||
}
|
||||
|
||||
public diagnostics(): Diagnostic[] {
|
||||
return this.syntaxTree().diagnostics();
|
||||
}
|
||||
|
||||
public lineMap(): LineMap {
|
||||
return this.syntaxTree().lineMap();
|
||||
}
|
||||
|
||||
public syntaxTree(): SyntaxTree {
|
||||
if (!this._syntaxTree) {
|
||||
var start = new Date().getTime();
|
||||
|
||||
this._syntaxTree = Parser.parse(
|
||||
this.filename, SimpleText.fromScriptSnapshot(this._scriptSnapshot), this.compilationSettings.target, this.isDeclareFile());
|
||||
|
||||
var time = new Date().getTime() - start;
|
||||
|
||||
//TypeScript.syntaxTreeParseTime += time;
|
||||
}
|
||||
|
||||
return this._syntaxTree;
|
||||
}
|
||||
|
||||
public sourceFile(): ts.SourceFile {
|
||||
if (!this._soruceFile) {
|
||||
var start = new Date().getTime();
|
||||
|
||||
this._soruceFile = ts.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 bloomFilter(): BloomFilter {
|
||||
if (!this._bloomFilter) {
|
||||
var identifiers = createIntrinsicsObject<boolean>();
|
||||
var pre = function (cur: TypeScript.ISyntaxElement) {
|
||||
if (ASTHelpers.isValidAstNode(cur)) {
|
||||
if (cur.kind() === SyntaxKind.IdentifierName) {
|
||||
var nodeText = tokenValueText((<TypeScript.ISyntaxToken>cur));
|
||||
|
||||
identifiers[nodeText] = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TypeScript.getAstWalkerFactory().simpleWalk(this.sourceUnit(), pre, null, identifiers);
|
||||
|
||||
var identifierCount = 0;
|
||||
for (var name in identifiers) {
|
||||
if (identifiers[name]) {
|
||||
identifierCount++;
|
||||
}
|
||||
}
|
||||
|
||||
this._bloomFilter = new 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.syntaxTree().isExternalModule();
|
||||
}
|
||||
|
||||
public update(scriptSnapshot: IScriptSnapshot, version: number, isOpen: boolean, textChangeRange: 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 = 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 || Document.incrementalParse === null
|
||||
? TypeScript.Parser.parse(this.filename, text, this.compilationSettings.target, TypeScript.isDTSFile(this.filename))
|
||||
: Document.incrementalParse(oldSyntaxTree, textChangeRange, text);
|
||||
|
||||
return new Document(this.compilationSettings, this.filename, this.referencedFiles, scriptSnapshot, this.byteOrderMark, version, isOpen, newSyntaxTree, /*soruceFile*/ null);
|
||||
}
|
||||
|
||||
public static create(compilationSettings: ts.CompilerOptions, fileName: string, scriptSnapshot: IScriptSnapshot, byteOrderMark: ts.ByteOrderMark, version: number, isOpen: boolean, referencedFiles: string[]): Document {
|
||||
return new Document(compilationSettings, fileName, referencedFiles, scriptSnapshot, byteOrderMark, version, isOpen, /*syntaxTree:*/ null, /*soruceFile*/ null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module TypeScript.Services {
|
||||
// Inject support for incremental parsing to the core compiler Document class.
|
||||
Document.incrementalParse = IncrementalParser.parse;
|
||||
}
|
||||
|
||||
module TypeScript.Services {
|
||||
|
||||
@ -708,6 +554,62 @@ module TypeScript.Services {
|
||||
sourceMapOutput: any;
|
||||
}
|
||||
|
||||
export enum EndOfLineState {
|
||||
Start,
|
||||
InMultiLineCommentTrivia,
|
||||
InSingleQuoteStringLiteral,
|
||||
InDoubleQuoteStringLiteral,
|
||||
}
|
||||
|
||||
export enum TokenClass {
|
||||
Punctuation,
|
||||
Keyword,
|
||||
Operator,
|
||||
Comment,
|
||||
Whitespace,
|
||||
Identifier,
|
||||
NumberLiteral,
|
||||
StringLiteral,
|
||||
RegExpLiteral,
|
||||
}
|
||||
|
||||
export interface ClassificationResult {
|
||||
finalLexState: EndOfLineState;
|
||||
entries: ClassificationInfo[];
|
||||
}
|
||||
|
||||
export interface ClassificationInfo {
|
||||
length: number;
|
||||
classification: TokenClass;
|
||||
}
|
||||
|
||||
export interface Classifier {
|
||||
getClassificationsForLine(text: string, lexState: EndOfLineState): ClassificationResult;
|
||||
}
|
||||
|
||||
export interface IDocumentRegistry {
|
||||
acquireDocument(
|
||||
filename: string,
|
||||
compilationSettings: ts.CompilerOptions,
|
||||
scriptSnapshot: IScriptSnapshot,
|
||||
byteOrderMark: ts.ByteOrderMark,
|
||||
version: number,
|
||||
isOpen: boolean,
|
||||
referencedFiles: string[]): Document;
|
||||
|
||||
updateDocument(
|
||||
document: Document,
|
||||
filename: string,
|
||||
compilationSettings: ts.CompilerOptions,
|
||||
scriptSnapshot: IScriptSnapshot,
|
||||
version: number,
|
||||
isOpen: boolean,
|
||||
textChangeRange: TextChangeRange
|
||||
): Document;
|
||||
|
||||
releaseDocument(filename: string, compilationSettings: ts.CompilerOptions): void
|
||||
}
|
||||
|
||||
// TODO: move these to enums
|
||||
export class ScriptElementKind {
|
||||
static unknown = "";
|
||||
@ -797,192 +699,156 @@ module TypeScript.Services {
|
||||
static warning = "warning";
|
||||
static message = "message";
|
||||
}
|
||||
}
|
||||
|
||||
module TypeScript.Services {
|
||||
export enum EndOfLineState {
|
||||
Start,
|
||||
InMultiLineCommentTrivia,
|
||||
InSingleQuoteStringLiteral,
|
||||
InDoubleQuoteStringLiteral,
|
||||
interface IncrementalParse {
|
||||
(oldSyntaxTree: SyntaxTree, textChangeRange: TextChangeRange, newText: ISimpleText): SyntaxTree
|
||||
}
|
||||
|
||||
export enum TokenClass {
|
||||
Punctuation,
|
||||
Keyword,
|
||||
Operator,
|
||||
Comment,
|
||||
Whitespace,
|
||||
Identifier,
|
||||
NumberLiteral,
|
||||
StringLiteral,
|
||||
RegExpLiteral,
|
||||
}
|
||||
export class Document {
|
||||
private _bloomFilter: BloomFilter = null;
|
||||
|
||||
export interface ClassificationResult {
|
||||
finalLexState: EndOfLineState;
|
||||
entries: ClassificationInfo[];
|
||||
}
|
||||
// By default, our Document class doesn't support incremental update of its contents.
|
||||
// However, we enable other layers (like teh services layer) to inject the capability
|
||||
// into us by setting this function.
|
||||
public static incrementalParse: IncrementalParse = IncrementalParser.parse;
|
||||
|
||||
export interface ClassificationInfo {
|
||||
length: number;
|
||||
classification: TokenClass;
|
||||
}
|
||||
|
||||
export interface Classifier {
|
||||
getClassificationsForLine(text: string, lexState: EndOfLineState): ClassificationResult;
|
||||
}
|
||||
|
||||
export function createClassifier(host: Logger): Classifier {
|
||||
var scanner: TypeScript.Scanner.IScanner;
|
||||
var lastDiagnosticKey: string = null;
|
||||
var noRegexTable: boolean[];
|
||||
var reportDiagnostic = (position: number, fullWidth: number, key: string, args: any[]) => {
|
||||
lastDiagnosticKey = key;
|
||||
};
|
||||
|
||||
if (!noRegexTable) {
|
||||
noRegexTable = [];
|
||||
noRegexTable[TypeScript.SyntaxKind.IdentifierName] = true;
|
||||
noRegexTable[TypeScript.SyntaxKind.StringLiteral] = true;
|
||||
noRegexTable[TypeScript.SyntaxKind.NumericLiteral] = true;
|
||||
noRegexTable[TypeScript.SyntaxKind.RegularExpressionLiteral] = true;
|
||||
noRegexTable[TypeScript.SyntaxKind.ThisKeyword] = true;
|
||||
noRegexTable[TypeScript.SyntaxKind.PlusPlusToken] = true;
|
||||
noRegexTable[TypeScript.SyntaxKind.MinusMinusToken] = true;
|
||||
noRegexTable[TypeScript.SyntaxKind.CloseParenToken] = true;
|
||||
noRegexTable[TypeScript.SyntaxKind.CloseBracketToken] = true;
|
||||
noRegexTable[TypeScript.SyntaxKind.CloseBraceToken] = true;
|
||||
noRegexTable[TypeScript.SyntaxKind.TrueKeyword] = true;
|
||||
noRegexTable[TypeScript.SyntaxKind.FalseKeyword] = true;
|
||||
constructor(private compilationSettings: ts.CompilerOptions,
|
||||
public filename: string,
|
||||
public referencedFiles: string[],
|
||||
private _scriptSnapshot: IScriptSnapshot,
|
||||
public byteOrderMark: ts.ByteOrderMark,
|
||||
public version: number,
|
||||
public isOpen: boolean,
|
||||
private _syntaxTree: SyntaxTree,
|
||||
private _soruceFile: ts.SourceFile) {
|
||||
}
|
||||
|
||||
function getClassificationsForLine(text: string, lexState: EndOfLineState): ClassificationResult {
|
||||
var offset = 0;
|
||||
if (lexState !== EndOfLineState.Start) {
|
||||
// If we're in a string literal, then prepend: "\
|
||||
// (and a newline). That way when we lex we'll think we're still in a string literal.
|
||||
//
|
||||
// If we're in a multiline comment, then prepend: /*
|
||||
// (and a newline). That way when we lex we'll think we're still in a multiline comment.
|
||||
if (lexState === EndOfLineState.InDoubleQuoteStringLiteral) {
|
||||
text = '"\\\n' + text;
|
||||
}
|
||||
else if (lexState === EndOfLineState.InSingleQuoteStringLiteral) {
|
||||
text = "'\\\n" + text;
|
||||
}
|
||||
else if (lexState === EndOfLineState.InMultiLineCommentTrivia) {
|
||||
text = "/*\n" + text;
|
||||
}
|
||||
|
||||
offset = 3;
|
||||
}
|
||||
|
||||
var result = {
|
||||
finalLexState: EndOfLineState.Start,
|
||||
entries: []
|
||||
};
|
||||
|
||||
var simpleText = TypeScript.SimpleText.fromString(text);
|
||||
scanner = Scanner.createScanner(ts.ScriptTarget.ES5, simpleText, reportDiagnostic);
|
||||
|
||||
var lastTokenKind = TypeScript.SyntaxKind.None;
|
||||
var token: ISyntaxToken = null;
|
||||
do {
|
||||
lastDiagnosticKey = null;
|
||||
|
||||
token = scanner.scan(!noRegexTable[lastTokenKind]);
|
||||
lastTokenKind = token.kind();
|
||||
|
||||
processToken(text, simpleText, offset, token, result);
|
||||
}
|
||||
while (token.kind() !== SyntaxKind.EndOfFileToken);
|
||||
|
||||
lastDiagnosticKey = null;
|
||||
return result;
|
||||
public isDeclareFile(): boolean {
|
||||
return isDTSFile(this.filename);
|
||||
}
|
||||
|
||||
function processToken(text: string, simpleText: ISimpleText, offset: number, token: TypeScript.ISyntaxToken, result: ClassificationResult): void {
|
||||
processTriviaList(text, offset, token.leadingTrivia(simpleText), result);
|
||||
addResult(text, offset, result, width(token), token.kind());
|
||||
processTriviaList(text, offset, token.trailingTrivia(simpleText), result);
|
||||
public sourceUnit(): SourceUnitSyntax {
|
||||
// If we don't have a script, create one from our parse tree.
|
||||
return this.syntaxTree().sourceUnit();
|
||||
}
|
||||
|
||||
if (fullEnd(token) >= text.length) {
|
||||
// We're at the end.
|
||||
if (lastDiagnosticKey === TypeScript.DiagnosticCode.AsteriskSlash_expected) {
|
||||
result.finalLexState = EndOfLineState.InMultiLineCommentTrivia;
|
||||
return;
|
||||
}
|
||||
public diagnostics(): Diagnostic[] {
|
||||
return this.syntaxTree().diagnostics();
|
||||
}
|
||||
|
||||
if (token.kind() === TypeScript.SyntaxKind.StringLiteral) {
|
||||
var tokenText = token.text();
|
||||
if (tokenText.length > 0 && tokenText.charCodeAt(tokenText.length - 1) === TypeScript.CharacterCodes.backslash) {
|
||||
var quoteChar = tokenText.charCodeAt(0);
|
||||
result.finalLexState = quoteChar === TypeScript.CharacterCodes.doubleQuote
|
||||
? EndOfLineState.InDoubleQuoteStringLiteral
|
||||
: EndOfLineState.InSingleQuoteStringLiteral;
|
||||
return;
|
||||
public lineMap(): LineMap {
|
||||
return this.syntaxTree().lineMap();
|
||||
}
|
||||
|
||||
public syntaxTree(): SyntaxTree {
|
||||
if (!this._syntaxTree) {
|
||||
var start = new Date().getTime();
|
||||
|
||||
this._syntaxTree = Parser.parse(
|
||||
this.filename, SimpleText.fromScriptSnapshot(this._scriptSnapshot), this.compilationSettings.target, this.isDeclareFile());
|
||||
|
||||
var time = new Date().getTime() - start;
|
||||
|
||||
//TypeScript.syntaxTreeParseTime += time;
|
||||
}
|
||||
|
||||
return this._syntaxTree;
|
||||
}
|
||||
|
||||
public sourceFile(): ts.SourceFile {
|
||||
if (!this._soruceFile) {
|
||||
var start = new Date().getTime();
|
||||
|
||||
this._soruceFile = ts.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 bloomFilter(): BloomFilter {
|
||||
if (!this._bloomFilter) {
|
||||
var identifiers = createIntrinsicsObject<boolean>();
|
||||
var pre = function (cur: TypeScript.ISyntaxElement) {
|
||||
if (ASTHelpers.isValidAstNode(cur)) {
|
||||
if (cur.kind() === SyntaxKind.IdentifierName) {
|
||||
var nodeText = tokenValueText((<TypeScript.ISyntaxToken>cur));
|
||||
|
||||
identifiers[nodeText] = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TypeScript.getAstWalkerFactory().simpleWalk(this.sourceUnit(), pre, null, identifiers);
|
||||
|
||||
var identifierCount = 0;
|
||||
for (var name in identifiers) {
|
||||
if (identifiers[name]) {
|
||||
identifierCount++;
|
||||
}
|
||||
}
|
||||
|
||||
this._bloomFilter = new BloomFilter(identifierCount);
|
||||
this._bloomFilter.addKeys(identifiers);
|
||||
}
|
||||
return this._bloomFilter;
|
||||
}
|
||||
|
||||
function processTriviaList(text: string, offset: number, triviaList: TypeScript.ISyntaxTriviaList, result: ClassificationResult): void {
|
||||
for (var i = 0, n = triviaList.count(); i < n; i++) {
|
||||
var trivia = triviaList.syntaxTriviaAt(i);
|
||||
addResult(text, offset, result, trivia.fullWidth(), trivia.kind());
|
||||
}
|
||||
// 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.syntaxTree().isExternalModule();
|
||||
}
|
||||
|
||||
function addResult(text: string, offset: number, result: ClassificationResult, length: number, kind: TypeScript.SyntaxKind): void {
|
||||
if (length > 0) {
|
||||
// If this is the first classification we're adding to the list, then remove any
|
||||
// offset we have if we were continuing a construct from the previous line.
|
||||
if (result.entries.length === 0) {
|
||||
length -= offset;
|
||||
public update(scriptSnapshot: IScriptSnapshot, version: number, isOpen: boolean, textChangeRange: 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);
|
||||
}
|
||||
|
||||
result.entries.push({ length: length, classification: classFromKind(kind) });
|
||||
}
|
||||
|
||||
var text = 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 || Document.incrementalParse === null
|
||||
? TypeScript.Parser.parse(this.filename, text, this.compilationSettings.target, TypeScript.isDTSFile(this.filename))
|
||||
: Document.incrementalParse(oldSyntaxTree, textChangeRange, text);
|
||||
|
||||
return new Document(this.compilationSettings, this.filename, this.referencedFiles, scriptSnapshot, this.byteOrderMark, version, isOpen, newSyntaxTree, /*soruceFile*/ null);
|
||||
}
|
||||
|
||||
function classFromKind(kind: TypeScript.SyntaxKind) {
|
||||
if (TypeScript.SyntaxFacts.isAnyKeyword(kind)) {
|
||||
return TokenClass.Keyword;
|
||||
}
|
||||
else if (TypeScript.SyntaxFacts.isBinaryExpressionOperatorToken(kind) ||
|
||||
TypeScript.SyntaxFacts.isPrefixUnaryExpressionOperatorToken(kind)) {
|
||||
return TokenClass.Operator;
|
||||
}
|
||||
else if (TypeScript.SyntaxFacts.isAnyPunctuation(kind)) {
|
||||
return TokenClass.Punctuation;
|
||||
}
|
||||
|
||||
switch (kind) {
|
||||
case TypeScript.SyntaxKind.WhitespaceTrivia:
|
||||
return TokenClass.Whitespace;
|
||||
case TypeScript.SyntaxKind.MultiLineCommentTrivia:
|
||||
case TypeScript.SyntaxKind.SingleLineCommentTrivia:
|
||||
return TokenClass.Comment;
|
||||
case TypeScript.SyntaxKind.NumericLiteral:
|
||||
return TokenClass.NumberLiteral;
|
||||
case TypeScript.SyntaxKind.StringLiteral:
|
||||
return TokenClass.StringLiteral;
|
||||
case TypeScript.SyntaxKind.RegularExpressionLiteral:
|
||||
return TokenClass.RegExpLiteral;
|
||||
case TypeScript.SyntaxKind.IdentifierName:
|
||||
default:
|
||||
return TokenClass.Identifier;
|
||||
}
|
||||
public static create(compilationSettings: ts.CompilerOptions, fileName: string, scriptSnapshot: IScriptSnapshot, byteOrderMark: ts.ByteOrderMark, version: number, isOpen: boolean, referencedFiles: string[]): Document {
|
||||
return new Document(compilationSettings, fileName, referencedFiles, scriptSnapshot, byteOrderMark, version, isOpen, /*syntaxTree:*/ null, /*soruceFile*/ null);
|
||||
}
|
||||
|
||||
return {
|
||||
getClassificationsForLine: getClassificationsForLine
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module TypeScript.Services {
|
||||
/// Language Service
|
||||
|
||||
interface CompletionSession {
|
||||
filename: string; // the file where the completion was requested
|
||||
position: number; // position in the file where the completion was requested
|
||||
@ -992,6 +858,13 @@ module TypeScript.Services {
|
||||
typeChecker: ts.TypeChecker;// the typeChecker used to generate this completion
|
||||
}
|
||||
|
||||
interface FormattingOptions {
|
||||
useTabs: boolean;
|
||||
spacesPerTab: number;
|
||||
indentSpaces: number;
|
||||
newLineCharacter: string;
|
||||
}
|
||||
|
||||
// Information about a specific host file.
|
||||
interface HostFileInformation {
|
||||
filename: string;
|
||||
@ -1261,13 +1134,6 @@ module TypeScript.Services {
|
||||
}
|
||||
}
|
||||
|
||||
interface FormattingOptions {
|
||||
useTabs: boolean;
|
||||
spacesPerTab: number;
|
||||
indentSpaces: number;
|
||||
newLineCharacter: string;
|
||||
}
|
||||
|
||||
class DocumentRegistryEntry {
|
||||
public refCount: number = 0;
|
||||
public owners: string[] = [];
|
||||
@ -1275,29 +1141,6 @@ module TypeScript.Services {
|
||||
}
|
||||
}
|
||||
|
||||
export interface IDocumentRegistry {
|
||||
acquireDocument(
|
||||
filename: string,
|
||||
compilationSettings: ts.CompilerOptions,
|
||||
scriptSnapshot: IScriptSnapshot,
|
||||
byteOrderMark: ts.ByteOrderMark,
|
||||
version: number,
|
||||
isOpen: boolean,
|
||||
referencedFiles: string[]): Document;
|
||||
|
||||
updateDocument(
|
||||
document: Document,
|
||||
filename: string,
|
||||
compilationSettings: ts.CompilerOptions,
|
||||
scriptSnapshot: IScriptSnapshot,
|
||||
version: number,
|
||||
isOpen: boolean,
|
||||
textChangeRange: TextChangeRange
|
||||
): Document;
|
||||
|
||||
releaseDocument(filename: string, compilationSettings: ts.CompilerOptions): void
|
||||
}
|
||||
|
||||
export class DocumentRegistry implements IDocumentRegistry {
|
||||
private buckets: ts.Map<ts.Map<DocumentRegistryEntry>> = {};
|
||||
|
||||
@ -2063,4 +1906,154 @@ module TypeScript.Services {
|
||||
getEmitOutput: (filename) => undefined,
|
||||
};
|
||||
}
|
||||
|
||||
/// Classifier
|
||||
|
||||
export function createClassifier(host: Logger): Classifier {
|
||||
var scanner: TypeScript.Scanner.IScanner;
|
||||
var lastDiagnosticKey: string = null;
|
||||
var noRegexTable: boolean[];
|
||||
var reportDiagnostic = (position: number, fullWidth: number, key: string, args: any[]) => {
|
||||
lastDiagnosticKey = key;
|
||||
};
|
||||
|
||||
if (!noRegexTable) {
|
||||
noRegexTable = [];
|
||||
noRegexTable[TypeScript.SyntaxKind.IdentifierName] = true;
|
||||
noRegexTable[TypeScript.SyntaxKind.StringLiteral] = true;
|
||||
noRegexTable[TypeScript.SyntaxKind.NumericLiteral] = true;
|
||||
noRegexTable[TypeScript.SyntaxKind.RegularExpressionLiteral] = true;
|
||||
noRegexTable[TypeScript.SyntaxKind.ThisKeyword] = true;
|
||||
noRegexTable[TypeScript.SyntaxKind.PlusPlusToken] = true;
|
||||
noRegexTable[TypeScript.SyntaxKind.MinusMinusToken] = true;
|
||||
noRegexTable[TypeScript.SyntaxKind.CloseParenToken] = true;
|
||||
noRegexTable[TypeScript.SyntaxKind.CloseBracketToken] = true;
|
||||
noRegexTable[TypeScript.SyntaxKind.CloseBraceToken] = true;
|
||||
noRegexTable[TypeScript.SyntaxKind.TrueKeyword] = true;
|
||||
noRegexTable[TypeScript.SyntaxKind.FalseKeyword] = true;
|
||||
}
|
||||
|
||||
function getClassificationsForLine(text: string, lexState: EndOfLineState): ClassificationResult {
|
||||
var offset = 0;
|
||||
if (lexState !== EndOfLineState.Start) {
|
||||
// If we're in a string literal, then prepend: "\
|
||||
// (and a newline). That way when we lex we'll think we're still in a string literal.
|
||||
//
|
||||
// If we're in a multiline comment, then prepend: /*
|
||||
// (and a newline). That way when we lex we'll think we're still in a multiline comment.
|
||||
if (lexState === EndOfLineState.InDoubleQuoteStringLiteral) {
|
||||
text = '"\\\n' + text;
|
||||
}
|
||||
else if (lexState === EndOfLineState.InSingleQuoteStringLiteral) {
|
||||
text = "'\\\n" + text;
|
||||
}
|
||||
else if (lexState === EndOfLineState.InMultiLineCommentTrivia) {
|
||||
text = "/*\n" + text;
|
||||
}
|
||||
|
||||
offset = 3;
|
||||
}
|
||||
|
||||
var result = {
|
||||
finalLexState: EndOfLineState.Start,
|
||||
entries: []
|
||||
};
|
||||
|
||||
var simpleText = TypeScript.SimpleText.fromString(text);
|
||||
scanner = Scanner.createScanner(ts.ScriptTarget.ES5, simpleText, reportDiagnostic);
|
||||
|
||||
var lastTokenKind = TypeScript.SyntaxKind.None;
|
||||
var token: ISyntaxToken = null;
|
||||
do {
|
||||
lastDiagnosticKey = null;
|
||||
|
||||
token = scanner.scan(!noRegexTable[lastTokenKind]);
|
||||
lastTokenKind = token.kind();
|
||||
|
||||
processToken(text, simpleText, offset, token, result);
|
||||
}
|
||||
while (token.kind() !== SyntaxKind.EndOfFileToken);
|
||||
|
||||
lastDiagnosticKey = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
function processToken(text: string, simpleText: ISimpleText, offset: number, token: TypeScript.ISyntaxToken, result: ClassificationResult): void {
|
||||
processTriviaList(text, offset, token.leadingTrivia(simpleText), result);
|
||||
addResult(text, offset, result, width(token), token.kind());
|
||||
processTriviaList(text, offset, token.trailingTrivia(simpleText), result);
|
||||
|
||||
if (fullEnd(token) >= text.length) {
|
||||
// We're at the end.
|
||||
if (lastDiagnosticKey === TypeScript.DiagnosticCode.AsteriskSlash_expected) {
|
||||
result.finalLexState = EndOfLineState.InMultiLineCommentTrivia;
|
||||
return;
|
||||
}
|
||||
|
||||
if (token.kind() === TypeScript.SyntaxKind.StringLiteral) {
|
||||
var tokenText = token.text();
|
||||
if (tokenText.length > 0 && tokenText.charCodeAt(tokenText.length - 1) === TypeScript.CharacterCodes.backslash) {
|
||||
var quoteChar = tokenText.charCodeAt(0);
|
||||
result.finalLexState = quoteChar === TypeScript.CharacterCodes.doubleQuote
|
||||
? EndOfLineState.InDoubleQuoteStringLiteral
|
||||
: EndOfLineState.InSingleQuoteStringLiteral;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function processTriviaList(text: string, offset: number, triviaList: TypeScript.ISyntaxTriviaList, result: ClassificationResult): void {
|
||||
for (var i = 0, n = triviaList.count(); i < n; i++) {
|
||||
var trivia = triviaList.syntaxTriviaAt(i);
|
||||
addResult(text, offset, result, trivia.fullWidth(), trivia.kind());
|
||||
}
|
||||
}
|
||||
|
||||
function addResult(text: string, offset: number, result: ClassificationResult, length: number, kind: TypeScript.SyntaxKind): void {
|
||||
if (length > 0) {
|
||||
// If this is the first classification we're adding to the list, then remove any
|
||||
// offset we have if we were continuing a construct from the previous line.
|
||||
if (result.entries.length === 0) {
|
||||
length -= offset;
|
||||
}
|
||||
|
||||
result.entries.push({ length: length, classification: classFromKind(kind) });
|
||||
}
|
||||
}
|
||||
|
||||
function classFromKind(kind: TypeScript.SyntaxKind) {
|
||||
if (TypeScript.SyntaxFacts.isAnyKeyword(kind)) {
|
||||
return TokenClass.Keyword;
|
||||
}
|
||||
else if (TypeScript.SyntaxFacts.isBinaryExpressionOperatorToken(kind) ||
|
||||
TypeScript.SyntaxFacts.isPrefixUnaryExpressionOperatorToken(kind)) {
|
||||
return TokenClass.Operator;
|
||||
}
|
||||
else if (TypeScript.SyntaxFacts.isAnyPunctuation(kind)) {
|
||||
return TokenClass.Punctuation;
|
||||
}
|
||||
|
||||
switch (kind) {
|
||||
case TypeScript.SyntaxKind.WhitespaceTrivia:
|
||||
return TokenClass.Whitespace;
|
||||
case TypeScript.SyntaxKind.MultiLineCommentTrivia:
|
||||
case TypeScript.SyntaxKind.SingleLineCommentTrivia:
|
||||
return TokenClass.Comment;
|
||||
case TypeScript.SyntaxKind.NumericLiteral:
|
||||
return TokenClass.NumberLiteral;
|
||||
case TypeScript.SyntaxKind.StringLiteral:
|
||||
return TokenClass.StringLiteral;
|
||||
case TypeScript.SyntaxKind.RegularExpressionLiteral:
|
||||
return TokenClass.RegExpLiteral;
|
||||
case TypeScript.SyntaxKind.IdentifierName:
|
||||
default:
|
||||
return TokenClass.Identifier;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
getClassificationsForLine: getClassificationsForLine
|
||||
};
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user