mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-20 05:17:43 -05:00
Refactoring preProcessFile to use new scanner
This commit is contained in:
@@ -1,44 +0,0 @@
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
module TypeScript {
|
||||
export interface ILineAndCharacter {
|
||||
line: number;
|
||||
character: number;
|
||||
}
|
||||
|
||||
// Note: This is being using by the host (VS) and is marshaled back and forth. When changing this make sure the changes
|
||||
// are reflected in the managed side as well
|
||||
export interface IFileReference extends ILineAndCharacter {
|
||||
path: string;
|
||||
isResident: boolean;
|
||||
position: number;
|
||||
length: number;
|
||||
}
|
||||
|
||||
export interface IPreProcessedFileInfo {
|
||||
referencedFiles: IFileReference[];
|
||||
importedFiles: IFileReference[];
|
||||
diagnostics: TypeScript.Diagnostic[];
|
||||
isLibFile: boolean
|
||||
}
|
||||
|
||||
interface ITripleSlashDirectiveProperties {
|
||||
noDefaultLib: boolean;
|
||||
diagnostics: TypeScript.Diagnostic[];
|
||||
referencedFiles: IFileReference[];
|
||||
}
|
||||
|
||||
} // Tools
|
||||
@@ -1,6 +1,11 @@
|
||||
///<reference path='references.ts' />
|
||||
|
||||
module TypeScript {
|
||||
export interface ILineAndCharacter {
|
||||
line: number;
|
||||
character: number;
|
||||
}
|
||||
|
||||
export class LineMap {
|
||||
public static empty = new LineMap(() => [0], 0);
|
||||
private _lineStarts: number[] = null;
|
||||
|
||||
@@ -80,10 +80,20 @@ module ts {
|
||||
///
|
||||
/// Pre-processing
|
||||
///
|
||||
interface ITripleSlashDirectiveProperties {
|
||||
noDefaultLib: boolean;
|
||||
// Note: This is being using by the host (VS) and is marshaled back and forth. When changing this make sure the changes
|
||||
// are reflected in the managed side as well
|
||||
// TODO (yuisu) : Consider merge with FileReference in types.ts
|
||||
export interface IFileReference {
|
||||
path: string;
|
||||
position: number;
|
||||
length: number;
|
||||
}
|
||||
|
||||
export interface PreProcessedFileInfo {
|
||||
referencedFiles: IFileReference[];
|
||||
importedFiles: IFileReference[];
|
||||
diagnostics: TypeScript.Diagnostic[];
|
||||
referencedFiles: TypeScript.IFileReference[];
|
||||
isLibFile: boolean
|
||||
}
|
||||
|
||||
var scanner: Scanner = createScanner(ScriptTarget.ES5, /*skipTrivia*/ true);
|
||||
@@ -1905,159 +1915,94 @@ module ts {
|
||||
}
|
||||
|
||||
export var tripleSlashReferenceRegExp = /^(\/\/\/\s*<reference\s+path=)('|")(.+?)\2\s*(static=('|")(.+?)\5\s*)*\/>/;
|
||||
export function preProcessFile(fileName: string, sourceText: TypeScript.IScriptSnapshot, readImportFiles = true): TypeScript.IPreProcessedFileInfo {
|
||||
export function preProcessFile(fileName: string, sourceText: TypeScript.IScriptSnapshot, readImportFiles = true): PreProcessedFileInfo {
|
||||
|
||||
var reportDiagnostic = () => { }
|
||||
var text = sourceText.getText(0, sourceText.getLength());
|
||||
var referencedFiles: IFileReference[] = [];
|
||||
var importedFiles: IFileReference[] = [];
|
||||
|
||||
function isNoDefaultLibMatch(comment: string): RegExpExecArray {
|
||||
var isNoDefaultLibRegex = /^(\/\/\/\s*<reference\s+no-default-lib=)('|")(.+?)\2\s*\/>/gim;
|
||||
return isNoDefaultLibRegex.exec(comment);
|
||||
}
|
||||
|
||||
function getFileReferenceFromReferencePath(fileName: string, text: TypeScript.ISimpleText, position: number, comment: string, diagnostics: TypeScript.Diagnostic[]): TypeScript.IFileReference {
|
||||
// First, just see if they've written: /// <reference\s+
|
||||
// If so, then we'll consider this a reference directive and we'll report errors if it's
|
||||
// malformed. Otherwise, we'll completely ignore this.
|
||||
var lineMap = text.lineMap();
|
||||
|
||||
function getFileReferenceFromReferencePath(comment: string): IFileReference {
|
||||
var simpleReferenceRegEx = /^\/\/\/\s*<reference\s+/gim;
|
||||
|
||||
if (simpleReferenceRegEx.exec(comment)) {
|
||||
var isNoDefaultLib = isNoDefaultLibMatch(comment);
|
||||
|
||||
if (!isNoDefaultLib) {
|
||||
var fullReferenceRegEx = tripleSlashReferenceRegExp;
|
||||
var fullReference = fullReferenceRegEx.exec(comment);
|
||||
var path: string = TypeScript.normalizePath(fullReference[3]);
|
||||
if (fullReference) {
|
||||
var path: string = TypeScript.normalizePath(fullReference[3]);
|
||||
var adjustedPath = TypeScript.normalizePath(path);
|
||||
|
||||
if (!fullReference) {
|
||||
// It matched the start of a reference directive, but wasn't well formed. Report
|
||||
// an appropriate error to the user.
|
||||
diagnostics.push(new TypeScript.Diagnostic(fileName, lineMap, position, comment.length, TypeScript.DiagnosticCode.Invalid_reference_directive_syntax));
|
||||
}
|
||||
else {
|
||||
var path: string = normalizePath(fullReference[3]);
|
||||
var adjustedPath = normalizePath(path);
|
||||
|
||||
var isResident = fullReference.length >= 7 && fullReference[6] === "true";
|
||||
return {
|
||||
line: 0,
|
||||
character: 0,
|
||||
// TODO (yuisu) : Move the function to util
|
||||
path: TypeScript.switchToForwardSlashes(adjustedPath),
|
||||
position: 0,
|
||||
length: 0,
|
||||
path: TypeScript.switchToForwardSlashes(adjustedPath),
|
||||
isResident: isResident
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function processImports(text: TypeScript.ISimpleText, scanner: TypeScript.Scanner.IScanner, token: TypeScript.ISyntaxToken, importedFiles: TypeScript.IFileReference[]): void {
|
||||
var lineChar = { line: -1, character: -1 };
|
||||
function processTripleSlashDirectives(): void {
|
||||
var commentRanges = getLeadingCommentRanges(text, 0);
|
||||
forEach(commentRanges, commentRange => {
|
||||
var comment = text.substring(commentRange.pos, commentRange.end);
|
||||
var referencedFile = getFileReferenceFromReferencePath(comment);
|
||||
if (referencedFile) {
|
||||
referencedFile.position = commentRange.pos;
|
||||
referencedFile.length = commentRange.end - commentRange.pos;
|
||||
referencedFiles.push(referencedFile);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var lineMap = text.lineMap();
|
||||
var start = new Date().getTime();
|
||||
function processImport(): void {
|
||||
var scanner = createScanner(getDefaultCompilerOptions().target, /*skipTrivia*/true, text);
|
||||
|
||||
var token = scanner.scan();
|
||||
// Look for:
|
||||
// import foo = module("foo")
|
||||
while (token.kind() !== TypeScript.SyntaxKind.EndOfFileToken) {
|
||||
if (token.kind() === TypeScript.SyntaxKind.ImportKeyword) {
|
||||
var importToken = token;
|
||||
token = scanner.scan(/*allowRegularExpression:*/ false);
|
||||
|
||||
if (TypeScript.SyntaxFacts.isIdentifierNameOrAnyKeyword(token)) {
|
||||
token = scanner.scan(/*allowRegularExpression:*/ false);
|
||||
|
||||
if (token.kind() === TypeScript.SyntaxKind.EqualsToken) {
|
||||
token = scanner.scan(/*allowRegularExpression:*/ false);
|
||||
|
||||
if (token.kind() === TypeScript.SyntaxKind.ModuleKeyword || token.kind() === TypeScript.SyntaxKind.RequireKeyword) {
|
||||
token = scanner.scan(/*allowRegularExpression:*/ false);
|
||||
|
||||
if (token.kind() === TypeScript.SyntaxKind.OpenParenToken) {
|
||||
token = scanner.scan(/*allowRegularExpression:*/ false);
|
||||
|
||||
lineMap.fillLineAndCharacterFromPosition(TypeScript.start(importToken, text), lineChar);
|
||||
|
||||
if (token.kind() === TypeScript.SyntaxKind.StringLiteral) {
|
||||
var ref = {
|
||||
line: lineChar.line,
|
||||
character: lineChar.character,
|
||||
position: TypeScript.start(token, text),
|
||||
length: TypeScript.width(token),
|
||||
path: TypeScript.stripStartAndEndQuotes(TypeScript.switchToForwardSlashes(token.text())),
|
||||
isResident: false
|
||||
// import foo = module("foo");
|
||||
while (token !== SyntaxKind.EndOfFileToken) {
|
||||
if (token === SyntaxKind.ImportKeyword) {
|
||||
var startPosition = scanner.getTokenPos();
|
||||
token = scanner.scan();
|
||||
if (token === SyntaxKind.Identifier) {
|
||||
token = scanner.scan();
|
||||
if (token === SyntaxKind.EqualsToken) {
|
||||
token = scanner.scan();
|
||||
if (token === SyntaxKind.RequireKeyword) {
|
||||
token = scanner.scan();
|
||||
if (token === SyntaxKind.OpenParenToken) {
|
||||
token = scanner.scan();
|
||||
if (token === SyntaxKind.StringLiteral) {
|
||||
var importPath = scanner.getTokenValue();
|
||||
var referencedFile = {
|
||||
// TODO (yuisu) : Move the function to util
|
||||
path: TypeScript.switchToForwardSlashes(importPath),
|
||||
position: startPosition,
|
||||
length: importPath.length
|
||||
};
|
||||
importedFiles.push(ref);
|
||||
importedFiles.push(referencedFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
token = scanner.scan(/*allowRegularExpression:*/ false);
|
||||
token = scanner.scan();
|
||||
}
|
||||
|
||||
var totalTime = new Date().getTime() - start;
|
||||
//TypeScript.fileResolutionScanImportsTime += totalTime
|
||||
}
|
||||
|
||||
function processTripleSlashDirectives(fileName: string, text: TypeScript.ISimpleText, firstToken: TypeScript.ISyntaxToken): ITripleSlashDirectiveProperties {
|
||||
var leadingTrivia = firstToken.leadingTrivia(text);
|
||||
|
||||
var position = 0;
|
||||
var lineChar = { line: -1, character: -1 };
|
||||
var noDefaultLib = false;
|
||||
var diagnostics: TypeScript.Diagnostic[] = [];
|
||||
var referencedFiles: TypeScript.IFileReference[] = [];
|
||||
var lineMap = text.lineMap();
|
||||
|
||||
for (var i = 0, n = leadingTrivia.count(); i < n; i++) {
|
||||
var trivia = leadingTrivia.syntaxTriviaAt(i);
|
||||
|
||||
if (trivia.kind() === TypeScript.SyntaxKind.SingleLineCommentTrivia) {
|
||||
var triviaText = trivia.fullText();
|
||||
var referencedCode = getFileReferenceFromReferencePath(fileName, text, position, triviaText, diagnostics);
|
||||
|
||||
if (referencedCode) {
|
||||
lineMap.fillLineAndCharacterFromPosition(position, lineChar);
|
||||
referencedCode.position = position;
|
||||
referencedCode.length = trivia.fullWidth();
|
||||
referencedCode.line = lineChar.line;
|
||||
referencedCode.character = lineChar.character;
|
||||
|
||||
referencedFiles.push(referencedCode);
|
||||
}
|
||||
|
||||
// is it a lib file?
|
||||
var isNoDefaultLib = isNoDefaultLibMatch(triviaText);
|
||||
if (isNoDefaultLib) {
|
||||
noDefaultLib = isNoDefaultLib[3] === "true";
|
||||
}
|
||||
}
|
||||
|
||||
position += trivia.fullWidth();
|
||||
}
|
||||
|
||||
return { noDefaultLib: noDefaultLib, diagnostics: diagnostics, referencedFiles: referencedFiles };
|
||||
}
|
||||
|
||||
var text = TypeScript.SimpleText.fromScriptSnapshot(sourceText);
|
||||
var scanner = TypeScript.Scanner.createScanner(ts.ScriptTarget.ES5, text, reportDiagnostic);
|
||||
|
||||
var firstToken = scanner.scan(/*allowRegularExpression:*/ false);
|
||||
|
||||
// only search out dynamic mods
|
||||
// if you find a dynamic mod, ignore every other mod inside, until you balance rcurlies
|
||||
// var position
|
||||
|
||||
var importedFiles: TypeScript.IFileReference[] = [];
|
||||
if (readImportFiles) {
|
||||
processImports(text, scanner, firstToken, importedFiles);
|
||||
}
|
||||
|
||||
var properties = processTripleSlashDirectives(fileName, text, firstToken);
|
||||
|
||||
return { referencedFiles: properties.referencedFiles, importedFiles: importedFiles, isLibFile: properties.noDefaultLib, diagnostics: properties.diagnostics };
|
||||
processImport();
|
||||
processTripleSlashDirectives();
|
||||
return { referencedFiles: referencedFiles, importedFiles: importedFiles, isLibFile: false, diagnostics: [] };
|
||||
}
|
||||
|
||||
/// Helpers
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
/// <reference path='services.ts' />
|
||||
|
||||
/// <reference path='compiler\pathUtils.ts' />
|
||||
/// <reference path='compiler\precompile.ts' />
|
||||
|
||||
var debugObjectHost = (<any>this);
|
||||
|
||||
@@ -847,7 +846,7 @@ module ts {
|
||||
return this.forwardJSONCall(
|
||||
"getPreProcessedFileInfo('" + fileName + "')",
|
||||
() => {
|
||||
var result = ts.preProcessFile(fileName, sourceText); //TypeScript.preProcessFile(fileName, sourceText);
|
||||
var result = preProcessFile(fileName, sourceText); //TypeScript.preProcessFile(fileName, sourceText);
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user