
Common AST formats such as TS and Babel do not use a separate node for comments, but instead attach comments to other AST nodes. Previously this was worked around in TS by creating a `NotEmittedStatement` AST node to attach the comment to. But Babel does not have this facility, so it will not be a viable approach for the linker. This commit refactors the output AST, to remove the `CommentStmt` and `JSDocCommentStmt` nodes. Instead statements have a collection of `leadingComments` that are rendered/attached to the final AST nodes when being translated or printed. PR Close #38811
106 lines
3.0 KiB
TypeScript
106 lines
3.0 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright Google LLC All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
* found in the LICENSE file at https://angular.io/license
|
|
*/
|
|
|
|
import {syntaxError} from '@angular/compiler';
|
|
import * as path from 'path';
|
|
import * as ts from 'typescript';
|
|
|
|
import {CompilerOptions, DEFAULT_ERROR_CODE, Diagnostic, SOURCE} from './api';
|
|
|
|
export const GENERATED_FILES = /(.*?)\.(ngfactory|shim\.ngstyle|ngstyle|ngsummary)\.(js|d\.ts|ts)$/;
|
|
export const DTS = /\.d\.ts$/;
|
|
export const TS = /^(?!.*\.d\.ts$).*\.ts$/;
|
|
|
|
export const enum StructureIsReused {
|
|
Not = 0,
|
|
SafeModules = 1,
|
|
Completely = 2
|
|
}
|
|
|
|
// Note: This is an internal property in TypeScript. Use it only for assertions and tests.
|
|
export function tsStructureIsReused(program: ts.Program): StructureIsReused {
|
|
return (program as any).structureIsReused;
|
|
}
|
|
|
|
export function error(msg: string): never {
|
|
throw new Error(`Internal error: ${msg}`);
|
|
}
|
|
|
|
export function userError(msg: string): never {
|
|
throw syntaxError(msg);
|
|
}
|
|
|
|
export function createMessageDiagnostic(messageText: string): ts.Diagnostic&Diagnostic {
|
|
return {
|
|
file: undefined,
|
|
start: undefined,
|
|
length: undefined,
|
|
category: ts.DiagnosticCategory.Message,
|
|
messageText,
|
|
code: DEFAULT_ERROR_CODE,
|
|
source: SOURCE,
|
|
};
|
|
}
|
|
|
|
export function isInRootDir(fileName: string, options: CompilerOptions) {
|
|
return !options.rootDir || pathStartsWithPrefix(options.rootDir, fileName);
|
|
}
|
|
|
|
export function relativeToRootDirs(filePath: string, rootDirs: string[]): string {
|
|
if (!filePath) return filePath;
|
|
for (const dir of rootDirs || []) {
|
|
const rel = pathStartsWithPrefix(dir, filePath);
|
|
if (rel) {
|
|
return rel;
|
|
}
|
|
}
|
|
return filePath;
|
|
}
|
|
|
|
function pathStartsWithPrefix(prefix: string, fullPath: string): string|null {
|
|
const rel = path.relative(prefix, fullPath);
|
|
return rel.startsWith('..') ? null : rel;
|
|
}
|
|
|
|
/**
|
|
* Converts a ng.Diagnostic into a ts.Diagnostic.
|
|
* This looses some information, and also uses an incomplete object as `file`.
|
|
*
|
|
* I.e. only use this where the API allows only a ts.Diagnostic.
|
|
*/
|
|
export function ngToTsDiagnostic(ng: Diagnostic): ts.Diagnostic {
|
|
let file: ts.SourceFile|undefined;
|
|
let start: number|undefined;
|
|
let length: number|undefined;
|
|
if (ng.span) {
|
|
// Note: We can't use a real ts.SourceFile,
|
|
// but we can at least mirror the properties `fileName` and `text`, which
|
|
// are mostly used for error reporting.
|
|
file = {fileName: ng.span.start.file.url, text: ng.span.start.file.content} as ts.SourceFile;
|
|
start = ng.span.start.offset;
|
|
length = ng.span.end.offset - start;
|
|
}
|
|
return {
|
|
file,
|
|
messageText: ng.messageText,
|
|
category: ng.category,
|
|
code: ng.code,
|
|
start,
|
|
length,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Strip multiline comment start and end markers from the `commentText` string.
|
|
*
|
|
* This will also strip the JSDOC comment start marker (`/**`).
|
|
*/
|
|
export function stripComment(commentText: string): string {
|
|
return commentText.replace(/^\/\*\*?/, '').replace(/\*\/$/, '').trim();
|
|
}
|