Introduce an object to store and manage diagnostics for different compiler components.
This commit is contained in:
parent
de13648c9f
commit
35a6d0e68a
5 changed files with 118 additions and 34 deletions
|
@ -104,8 +104,7 @@ module ts {
|
|||
var nodeLinks: NodeLinks[] = [];
|
||||
var potentialThisCollisions: Node[] = [];
|
||||
|
||||
var diagnostics: Diagnostic[] = [];
|
||||
var diagnosticsModified: boolean = false;
|
||||
var diagnostics = createDiagnosticCollection();
|
||||
|
||||
var primitiveTypeInfo: Map<{ type: Type; flags: TypeFlags }> = {
|
||||
"string": {
|
||||
|
@ -122,16 +121,11 @@ module ts {
|
|||
}
|
||||
};
|
||||
|
||||
function addDiagnostic(diagnostic: Diagnostic) {
|
||||
diagnostics.push(diagnostic);
|
||||
diagnosticsModified = true;
|
||||
}
|
||||
|
||||
function error(location: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): void {
|
||||
var diagnostic = location
|
||||
? createDiagnosticForNode(location, message, arg0, arg1, arg2)
|
||||
: createCompilerDiagnostic(message, arg0, arg1, arg2);
|
||||
addDiagnostic(diagnostic);
|
||||
diagnostics.add(diagnostic);
|
||||
}
|
||||
|
||||
function createSymbol(flags: SymbolFlags, name: string): Symbol {
|
||||
|
@ -3479,7 +3473,8 @@ module ts {
|
|||
if (containingMessageChain) {
|
||||
errorInfo = concatenateDiagnosticMessageChains(containingMessageChain, errorInfo);
|
||||
}
|
||||
addDiagnostic(createDiagnosticForNodeFromMessageChain(errorNode, errorInfo, host.getCompilerHost().getNewLine()));
|
||||
|
||||
diagnostics.add(createDiagnosticForNodeFromMessageChain(errorNode, errorInfo, host.getCompilerHost().getNewLine()));
|
||||
}
|
||||
return result !== Ternary.False;
|
||||
|
||||
|
@ -5705,9 +5700,9 @@ module ts {
|
|||
return false;
|
||||
}
|
||||
else {
|
||||
var diagnosticsCount = diagnostics.length;
|
||||
var modificationCount = diagnostics.getModificationCount();
|
||||
checkClassPropertyAccess(node, left, type, prop);
|
||||
return diagnostics.length === diagnosticsCount
|
||||
return diagnostics.getModificationCount() === modificationCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8927,7 +8922,7 @@ module ts {
|
|||
|
||||
var errorInfo = chainDiagnosticMessages(undefined, Diagnostics.Named_properties_0_of_types_1_and_2_are_not_identical, prop.name, typeName1, typeName2);
|
||||
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Interface_0_cannot_simultaneously_extend_types_1_and_2, typeToString(type), typeName1, typeName2);
|
||||
addDiagnostic(createDiagnosticForNodeFromMessageChain(typeNode, errorInfo, host.getCompilerHost().getNewLine()));
|
||||
diagnostics.add(createDiagnosticForNodeFromMessageChain(typeNode, errorInfo, host.getCompilerHost().getNewLine()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9578,30 +9573,19 @@ module ts {
|
|||
}
|
||||
}
|
||||
|
||||
function getSortedDiagnostics(): Diagnostic[]{
|
||||
Debug.assert(produceDiagnostics, "diagnostics are available only in the full typecheck mode");
|
||||
|
||||
if (diagnosticsModified) {
|
||||
diagnostics.sort(compareDiagnostics);
|
||||
diagnostics = deduplicateSortedDiagnostics(diagnostics);
|
||||
diagnosticsModified = false;
|
||||
}
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
function getDiagnostics(sourceFile?: SourceFile): Diagnostic[] {
|
||||
throwIfNonDiagnosticsProducing();
|
||||
if (sourceFile) {
|
||||
checkSourceFile(sourceFile);
|
||||
return filter(getSortedDiagnostics(), d => d.file === sourceFile);
|
||||
return diagnostics.getDiagnostics(sourceFile.fileName);
|
||||
}
|
||||
forEach(host.getSourceFiles(), checkSourceFile);
|
||||
return getSortedDiagnostics();
|
||||
return diagnostics.getDiagnostics();
|
||||
}
|
||||
|
||||
function getGlobalDiagnostics(): Diagnostic[]{
|
||||
throwIfNonDiagnosticsProducing();
|
||||
return filter(getSortedDiagnostics(), d => !d.file);
|
||||
return diagnostics.getGlobalDiagnostics();
|
||||
}
|
||||
|
||||
function throwIfNonDiagnosticsProducing() {
|
||||
|
@ -10234,7 +10218,7 @@ module ts {
|
|||
// Bind all source files and propagate errors
|
||||
forEach(host.getSourceFiles(), file => {
|
||||
bindSourceFile(file);
|
||||
forEach(file.semanticDiagnostics, addDiagnostic);
|
||||
forEach(file.semanticDiagnostics, d => diagnostics.add(d));
|
||||
});
|
||||
// Initialize global symbol table
|
||||
forEach(host.getSourceFiles(), file => {
|
||||
|
@ -11035,14 +11019,14 @@ module ts {
|
|||
if (!hasParseDiagnostics(sourceFile)) {
|
||||
var scanner = createScanner(languageVersion, /*skipTrivia*/ true, sourceFile.text);
|
||||
var start = scanToken(scanner, node.pos);
|
||||
diagnostics.push(createFileDiagnostic(sourceFile, start, scanner.getTextPos() - start, message, arg0, arg1, arg2));
|
||||
diagnostics.add(createFileDiagnostic(sourceFile, start, scanner.getTextPos() - start, message, arg0, arg1, arg2));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function grammarErrorAtPos(sourceFile: SourceFile, start: number, length: number, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean {
|
||||
if (!hasParseDiagnostics(sourceFile)) {
|
||||
diagnostics.push(createFileDiagnostic(sourceFile, start, length, message, arg0, arg1, arg2));
|
||||
diagnostics.add(createFileDiagnostic(sourceFile, start, length, message, arg0, arg1, arg2));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -11052,7 +11036,7 @@ module ts {
|
|||
if (!hasParseDiagnostics(sourceFile)) {
|
||||
var span = getErrorSpanForNode(node);
|
||||
var start = span.end > span.pos ? skipTrivia(sourceFile.text, span.pos) : span.pos;
|
||||
diagnostics.push(createFileDiagnostic(sourceFile, start, span.end - start, message, arg0, arg1, arg2));
|
||||
diagnostics.add(createFileDiagnostic(sourceFile, start, span.end - start, message, arg0, arg1, arg2));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -11186,7 +11170,7 @@ module ts {
|
|||
if (!hasParseDiagnostics(sourceFile)) {
|
||||
var scanner = createScanner(languageVersion, /*skipTrivia*/ true, sourceFile.text);
|
||||
scanToken(scanner, node.pos);
|
||||
diagnostics.push(createFileDiagnostic(sourceFile, scanner.getTextPos(), 0, message, arg0, arg1, arg2));
|
||||
diagnostics.add(createFileDiagnostic(sourceFile, scanner.getTextPos(), 0, message, arg0, arg1, arg2));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -358,10 +358,9 @@ module ts {
|
|||
|
||||
export function getSyntacticDiagnostics(sourceFile: SourceFile) {
|
||||
if (!sourceFile.syntacticDiagnostics) {
|
||||
// Don't bother doing any grammar checks if there are already parser errors.
|
||||
// Otherwise we may end up with too many cascading errors.
|
||||
sourceFile.syntacticDiagnostics = sourceFile.referenceDiagnostics.concat(sourceFile.parseDiagnostics);
|
||||
}
|
||||
|
||||
return sourceFile.syntacticDiagnostics;
|
||||
}
|
||||
|
||||
|
|
|
@ -1678,4 +1678,24 @@ module ts {
|
|||
span: TextSpan;
|
||||
newLength: number;
|
||||
}
|
||||
|
||||
// @internal
|
||||
export interface DiagnosticCollection {
|
||||
// Adds a diagnostic to this diagnostic collection.
|
||||
add(diagnostic?: Diagnostic): void;
|
||||
|
||||
// Gets all the diagnostics that aren't associated with a file.
|
||||
getGlobalDiagnostics(): Diagnostic[];
|
||||
|
||||
// If fileName is provided, gets all the diagnostics associated with that file name.
|
||||
// Otherwise, returns all the diagnostics (global and file associated) in this colletion.
|
||||
getDiagnostics(fileName?: string): Diagnostic[];
|
||||
|
||||
// Gets a count of how many times this collectoin has been modified. This value changes
|
||||
// each time 'add' is called (regardless of whether or not an equivalent diagnostic was
|
||||
// already in the collection). As such, it can be used as a simple way to tell if any
|
||||
// operation caused diagnostics to be returned by storing and comparing the return value
|
||||
// of this method before/after the operation is performed.
|
||||
getModificationCount(): number;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1068,4 +1068,84 @@ module ts {
|
|||
|
||||
return createTextChangeRange(createTextSpanFromBounds(oldStartN, oldEndN), /*newLength: */newEndN - oldStartN);
|
||||
}
|
||||
|
||||
// @internal
|
||||
export function createDiagnosticCollection(): DiagnosticCollection {
|
||||
var nonFileDiagnostics: Diagnostic[] = [];
|
||||
var fileDiagnostics: Map<Diagnostic[]> = {};
|
||||
|
||||
var diagnosticsModified = false;
|
||||
var modificationCount = 0;
|
||||
|
||||
return {
|
||||
add,
|
||||
getGlobalDiagnostics,
|
||||
getDiagnostics,
|
||||
getModificationCount
|
||||
};
|
||||
|
||||
function getModificationCount() {
|
||||
return modificationCount;
|
||||
}
|
||||
|
||||
function add(diagnostic: Diagnostic): void {
|
||||
var diagnostics: Diagnostic[];
|
||||
if (diagnostic.file) {
|
||||
diagnostics = fileDiagnostics[diagnostic.file.fileName];
|
||||
if (!diagnostics) {
|
||||
diagnostics = [];
|
||||
fileDiagnostics[diagnostic.file.fileName] = diagnostics;
|
||||
}
|
||||
}
|
||||
else {
|
||||
diagnostics = nonFileDiagnostics;
|
||||
}
|
||||
|
||||
diagnostics.push(diagnostic);
|
||||
diagnosticsModified = true;
|
||||
modificationCount++;
|
||||
}
|
||||
|
||||
function getGlobalDiagnostics(): Diagnostic[] {
|
||||
sortAndDeduplicate();
|
||||
return nonFileDiagnostics;
|
||||
}
|
||||
|
||||
function getDiagnostics(fileName?: string): Diagnostic[] {
|
||||
sortAndDeduplicate();
|
||||
if (fileName) {
|
||||
return fileDiagnostics[fileName] || [];
|
||||
}
|
||||
|
||||
var allDiagnostics: Diagnostic[] = [];
|
||||
forEach(nonFileDiagnostics, d => { allDiagnostics.push(d) });
|
||||
|
||||
for (var key in fileDiagnostics) {
|
||||
if (hasProperty(fileDiagnostics, key)) {
|
||||
forEach(fileDiagnostics[key], d => { allDiagnostics.push(d) });
|
||||
}
|
||||
}
|
||||
|
||||
return sortAndDeplicateList(allDiagnostics);
|
||||
}
|
||||
|
||||
function sortAndDeduplicate() {
|
||||
if (!diagnosticsModified) {
|
||||
return;
|
||||
}
|
||||
|
||||
diagnosticsModified = false;
|
||||
nonFileDiagnostics = sortAndDeplicateList(nonFileDiagnostics);
|
||||
|
||||
for (var key in fileDiagnostics) {
|
||||
if (hasProperty(fileDiagnostics, key)) {
|
||||
fileDiagnostics[key] = sortAndDeplicateList(fileDiagnostics[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sortAndDeplicateList(diagnostics: Diagnostic[]): Diagnostic[] {
|
||||
return deduplicateSortedDiagnostics(diagnostics.sort(compareDiagnostics))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -921,6 +921,7 @@ module Harness {
|
|||
// Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file
|
||||
currentDirectory?: string) {
|
||||
|
||||
debugger;
|
||||
options = options || { noResolve: false };
|
||||
options.target = options.target || ts.ScriptTarget.ES3;
|
||||
options.module = options.module || ts.ModuleKind.None;
|
||||
|
@ -1074,7 +1075,7 @@ module Harness {
|
|||
otherFiles.forEach(register);
|
||||
|
||||
var fileOutputs: GeneratedFile[] = [];
|
||||
|
||||
|
||||
var programFiles = inputFiles.map(file => file.unitName);
|
||||
var program = ts.createProgram(programFiles, options, createCompilerHost(inputFiles.concat(otherFiles),
|
||||
(fn, contents, writeByteOrderMark) => fileOutputs.push({ fileName: fn, code: contents, writeByteOrderMark: writeByteOrderMark }),
|
||||
|
|
Loading…
Reference in a new issue