mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-20 13:45:34 -05:00
Resolve diagnostics conflict
This commit is contained in:
@@ -877,7 +877,8 @@ namespace ts {
|
||||
if (nameNotFoundMessage) {
|
||||
if (!errorLocation ||
|
||||
!checkAndReportErrorForMissingPrefix(errorLocation, name, nameArg) &&
|
||||
!checkAndReportErrorForExtendingInterface(errorLocation)) {
|
||||
!checkAndReportErrorForExtendingInterface(errorLocation) &&
|
||||
!checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning)) {
|
||||
error(errorLocation, nameNotFoundMessage, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg));
|
||||
}
|
||||
}
|
||||
@@ -987,6 +988,16 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function checkAndReportErrorForUsingTypeAsValue(errorLocation: Node, name: string, meaning: SymbolFlags): boolean {
|
||||
if (meaning & (SymbolFlags.Value & ~SymbolFlags.NamespaceModule)) {
|
||||
const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined));
|
||||
if (symbol && !(symbol.flags & SymbolFlags.NamespaceModule)) {
|
||||
error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkResolvedBlockScopedVariable(result: Symbol, errorLocation: Node): void {
|
||||
Debug.assert((result.flags & SymbolFlags.BlockScopedVariable) !== 0);
|
||||
@@ -10869,7 +10880,7 @@ namespace ts {
|
||||
const prop = getPropertyOfType(apparentType, right.text);
|
||||
if (!prop) {
|
||||
if (right.text && !checkAndReportErrorForExtendingInterface(node)) {
|
||||
error(right, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(right), typeToString(type.flags & TypeFlags.ThisType ? apparentType : type));
|
||||
reportNonexistentProperty(right, type.flags & TypeFlags.ThisType ? apparentType : type);
|
||||
}
|
||||
return unknownType;
|
||||
}
|
||||
@@ -10903,6 +10914,20 @@ namespace ts {
|
||||
return propType;
|
||||
}
|
||||
return getFlowTypeOfReference(node, propType, /*assumeInitialized*/ true, /*flowContainer*/ undefined);
|
||||
|
||||
function reportNonexistentProperty(propNode: Identifier, containingType: Type) {
|
||||
let errorInfo: DiagnosticMessageChain;
|
||||
if (containingType.flags & TypeFlags.Union && !(containingType.flags & TypeFlags.Primitive)) {
|
||||
for (const subtype of (containingType as UnionType).types) {
|
||||
if (!getPropertyOfType(subtype, propNode.text)) {
|
||||
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(subtype));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(containingType));
|
||||
diagnostics.add(createDiagnosticForNodeFromMessageChain(propNode, errorInfo));
|
||||
}
|
||||
}
|
||||
|
||||
function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean {
|
||||
|
||||
@@ -806,12 +806,45 @@ namespace ts {
|
||||
* @param basePath A root directory to resolve relative path entries in the config
|
||||
* file to. e.g. outDir
|
||||
*/
|
||||
export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions: CompilerOptions = {}, configFileName?: string): ParsedCommandLine {
|
||||
export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions: CompilerOptions = {}, configFileName?: string, resolutionStack: Path[] = []): ParsedCommandLine {
|
||||
const errors: Diagnostic[] = [];
|
||||
const compilerOptions: CompilerOptions = convertCompilerOptionsFromJsonWorker(json["compilerOptions"], basePath, errors, configFileName);
|
||||
const options = extend(existingOptions, compilerOptions);
|
||||
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames);
|
||||
const resolvedPath = toPath(configFileName || "", basePath, getCanonicalFileName);
|
||||
if (resolutionStack.indexOf(resolvedPath) >= 0) {
|
||||
return {
|
||||
options: {},
|
||||
fileNames: [],
|
||||
typingOptions: {},
|
||||
raw: json,
|
||||
errors: [createCompilerDiagnostic(Diagnostics.Circularity_detected_while_resolving_configuration_Colon_0, [...resolutionStack, resolvedPath].join(" -> "))],
|
||||
wildcardDirectories: {}
|
||||
};
|
||||
}
|
||||
|
||||
let options: CompilerOptions = convertCompilerOptionsFromJsonWorker(json["compilerOptions"], basePath, errors, configFileName);
|
||||
const typingOptions: TypingOptions = convertTypingOptionsFromJsonWorker(json["typingOptions"], basePath, errors, configFileName);
|
||||
|
||||
if (json["extends"]) {
|
||||
let [include, exclude, files, baseOptions]: [string[], string[], string[], CompilerOptions] = [undefined, undefined, undefined, {}];
|
||||
if (typeof json["extends"] === "string") {
|
||||
[include, exclude, files, baseOptions] = (tryExtendsName(json["extends"]) || [include, exclude, files, baseOptions]);
|
||||
}
|
||||
else {
|
||||
errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "extends", "string"));
|
||||
}
|
||||
if (include && !json["include"]) {
|
||||
json["include"] = include;
|
||||
}
|
||||
if (exclude && !json["exclude"]) {
|
||||
json["exclude"] = exclude;
|
||||
}
|
||||
if (files && !json["files"]) {
|
||||
json["files"] = files;
|
||||
}
|
||||
options = assign({}, baseOptions, options);
|
||||
}
|
||||
|
||||
options = extend(existingOptions, options);
|
||||
options.configFilePath = configFileName;
|
||||
|
||||
const { fileNames, wildcardDirectories } = getFileNames(errors);
|
||||
@@ -825,6 +858,39 @@ namespace ts {
|
||||
wildcardDirectories
|
||||
};
|
||||
|
||||
function tryExtendsName(extendedConfig: string): [string[], string[], string[], CompilerOptions] {
|
||||
// If the path isn't a rooted or relative path, don't try to resolve it (we reserve the right to special case module-id like paths in the future)
|
||||
if (!(isRootedDiskPath(extendedConfig) || startsWith(normalizeSlashes(extendedConfig), "./") || startsWith(normalizeSlashes(extendedConfig), "../"))) {
|
||||
errors.push(createCompilerDiagnostic(Diagnostics.The_path_in_an_extends_options_must_be_relative_or_rooted));
|
||||
return;
|
||||
}
|
||||
let extendedConfigPath = toPath(extendedConfig, basePath, getCanonicalFileName);
|
||||
if (!host.fileExists(extendedConfigPath) && !endsWith(extendedConfigPath, ".json")) {
|
||||
extendedConfigPath = `${extendedConfigPath}.json` as Path;
|
||||
if (!host.fileExists(extendedConfigPath)) {
|
||||
errors.push(createCompilerDiagnostic(Diagnostics.File_0_does_not_exist, extendedConfig));
|
||||
return;
|
||||
}
|
||||
}
|
||||
const extendedResult = readConfigFile(extendedConfigPath, path => host.readFile(path));
|
||||
if (extendedResult.error) {
|
||||
errors.push(extendedResult.error);
|
||||
return;
|
||||
}
|
||||
const extendedDirname = getDirectoryPath(extendedConfigPath);
|
||||
const relativeDifference = convertToRelativePath(extendedDirname, basePath, getCanonicalFileName);
|
||||
const updatePath: (path: string) => string = path => isRootedDiskPath(path) ? path : combinePaths(relativeDifference, path);
|
||||
// Merge configs (copy the resolution stack so it is never reused between branches in potential diamond-problem scenarios)
|
||||
const result = parseJsonConfigFileContent(extendedResult.config, host, extendedDirname, /*existingOptions*/undefined, getBaseFileName(extendedConfigPath), resolutionStack.concat([resolvedPath]));
|
||||
errors.push(...result.errors);
|
||||
const [include, exclude, files] = map(["include", "exclude", "files"], key => {
|
||||
if (!json[key] && extendedResult.config[key]) {
|
||||
return map(extendedResult.config[key], updatePath);
|
||||
}
|
||||
});
|
||||
return [include, exclude, files, result.options];
|
||||
}
|
||||
|
||||
function getFileNames(errors: Diagnostic[]): ExpandResult {
|
||||
let fileNames: string[];
|
||||
if (hasProperty(json, "files")) {
|
||||
|
||||
@@ -377,6 +377,20 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
export function mapObject<T, U>(object: MapLike<T>, f: (key: string, x: T) => [string, U]): MapLike<U> {
|
||||
let result: MapLike<U>;
|
||||
if (object) {
|
||||
result = {};
|
||||
for (const v of getOwnKeys(object)) {
|
||||
const [key, value]: [string, U] = f(v, object[v]) || [undefined, undefined];
|
||||
if (key !== undefined) {
|
||||
result[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function concatenate<T>(array1: T[], array2: T[]): T[] {
|
||||
if (!array2 || !array2.length) return array1;
|
||||
if (!array1 || !array1.length) return array2;
|
||||
@@ -639,6 +653,18 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function assign<T1 extends MapLike<{}>, T2, T3>(t: T1, arg1: T2, arg2: T3): T1 & T2 & T3;
|
||||
export function assign<T1 extends MapLike<{}>, T2>(t: T1, arg1: T2): T1 & T2;
|
||||
export function assign<T1 extends MapLike<{}>>(t: T1, ...args: any[]): any;
|
||||
export function assign<T1 extends MapLike<{}>>(t: T1, ...args: any[]) {
|
||||
for (const arg of args) {
|
||||
for (const p of getOwnKeys(arg)) {
|
||||
t[p] = arg[p];
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce the properties of a map.
|
||||
*
|
||||
|
||||
@@ -1947,10 +1947,14 @@
|
||||
"category": "Error",
|
||||
"code": 2692
|
||||
},
|
||||
"Left side of comma operator is unused and has no side effects.": {
|
||||
"'{0}' only refers to a type, but is being used as a value here.": {
|
||||
"category": "Error",
|
||||
"code": 2693
|
||||
},
|
||||
"Left side of comma operator is unused and has no side effects.": {
|
||||
"category": "Error",
|
||||
"code": 2694
|
||||
},
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 4000
|
||||
@@ -3047,5 +3051,14 @@
|
||||
"Unknown typing option '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 17010
|
||||
},
|
||||
|
||||
"Circularity detected while resolving configuration: {0}": {
|
||||
"category": "Error",
|
||||
"code": 18000
|
||||
},
|
||||
"The path in an 'extends' options must be relative or rooted.": {
|
||||
"category": "Error",
|
||||
"code": 18001
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,43 +71,92 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
});
|
||||
};`;
|
||||
|
||||
// The __generator helper is used by down-level transformations to emulate the runtime
|
||||
// semantics of an ES2015 generator function. When called, this helper returns an
|
||||
// object that implements the Iterator protocol, in that it has `next`, `return`, and
|
||||
// `throw` methods that step through the generator when invoked.
|
||||
//
|
||||
// parameters:
|
||||
// thisArg The value to use as the `this` binding for the transformed generator body.
|
||||
// body A function that acts as the transformed generator body.
|
||||
//
|
||||
// variables:
|
||||
// _ Persistent state for the generator that is shared between the helper and the
|
||||
// generator body. The state object has the following members:
|
||||
// sent() - A method that returns or throws the current completion value.
|
||||
// label - The next point at which to resume evaluation of the generator body.
|
||||
// trys - A stack of protected regions (try/catch/finally blocks).
|
||||
// ops - A stack of pending instructions when inside of a finally block.
|
||||
// f A value indicating whether the generator is executing.
|
||||
// y An iterator to delegate for a yield*.
|
||||
// t A temporary variable that holds one of the following values (note that these
|
||||
// cases do not overlap):
|
||||
// - The completion value when resuming from a `yield` or `yield*`.
|
||||
// - The error value for a catch block.
|
||||
// - The current protected region (array of try/catch/finally/end labels).
|
||||
// - The verb (`next`, `throw`, or `return` method) to delegate to the expression
|
||||
// of a `yield*`.
|
||||
// - The result of evaluating the verb delegated to the expression of a `yield*`.
|
||||
//
|
||||
// functions:
|
||||
// verb(n) Creates a bound callback to the `step` function for opcode `n`.
|
||||
// step(op) Evaluates opcodes in a generator body until execution is suspended or
|
||||
// completed.
|
||||
//
|
||||
// The __generator helper understands a limited set of instructions:
|
||||
// 0: next(value?) - Start or resume the generator with the specified value.
|
||||
// 1: throw(error) - Resume the generator with an exception. If the generator is
|
||||
// suspended inside of one or more protected regions, evaluates
|
||||
// any intervening finally blocks between the current label and
|
||||
// the nearest catch block or function boundary. If uncaught, the
|
||||
// exception is thrown to the caller.
|
||||
// 2: return(value?) - Resume the generator as if with a return. If the generator is
|
||||
// suspended inside of one or more protected regions, evaluates any
|
||||
// intervening finally blocks.
|
||||
// 3: break(label) - Jump to the specified label. If the label is outside of the
|
||||
// current protected region, evaluates any intervening finally
|
||||
// blocks.
|
||||
// 4: yield(value?) - Yield execution to the caller with an optional value. When
|
||||
// resumed, the generator will continue at the next label.
|
||||
// 5: yield*(value) - Delegates evaluation to the supplied iterator. When
|
||||
// delegation completes, the generator will continue at the next
|
||||
// label.
|
||||
// 6: catch(error) - Handles an exception thrown from within the generator body. If
|
||||
// the current label is inside of one or more protected regions,
|
||||
// evaluates any intervening finally blocks between the current
|
||||
// label and the nearest catch block or function boundary. If
|
||||
// uncaught, the exception is thrown to the caller.
|
||||
// 7: endfinally - Ends a finally block, resuming the last instruction prior to
|
||||
// entering a finally block.
|
||||
//
|
||||
// For examples of how these are used, see the comments in ./transformers/generators.ts
|
||||
const generatorHelper = `
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f;
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t;
|
||||
return { next: verb(0), "throw": verb(1), "return": verb(2) };
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (1) {
|
||||
if (_.done) switch (op[0]) {
|
||||
case 0: return { value: void 0, done: true };
|
||||
case 1: case 6: throw op[1];
|
||||
case 2: return { value: op[1], done: true };
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [0, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
try {
|
||||
switch (f = 1, op[0]) {
|
||||
case 0: case 1: sent = op; break;
|
||||
case 4: return _.label++, { value: op[1], done: false };
|
||||
case 7: op = _.stack.pop(), _.trys.pop(); continue;
|
||||
default:
|
||||
var r = _.trys.length > 0 && _.trys[_.trys.length - 1];
|
||||
if (!r && (op[0] === 6 || op[0] === 2)) { _.done = 1; continue; }
|
||||
if (op[0] === 3 && (!r || (op[1] > r[0] && op[1] < r[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < r[1]) { _.label = r[1], sent = op; break; }
|
||||
if (r && _.label < r[2]) { _.label = r[2], _.stack.push(op); break; }
|
||||
if (r[2]) { _.stack.pop(); }
|
||||
_.trys.pop();
|
||||
continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
}
|
||||
catch (e) { op = [6, e]; }
|
||||
finally { f = 0, sent = void 0; }
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
return {
|
||||
next: function (v) { return step([0, v]); },
|
||||
"throw": function (v) { return step([1, v]); },
|
||||
"return": function (v) { return step([2, v]); }
|
||||
};
|
||||
};`;
|
||||
|
||||
// emit output for the __export helper function
|
||||
|
||||
@@ -2055,9 +2055,24 @@ namespace ts {
|
||||
if (!isBlock(loopBody)) {
|
||||
loopBody = createBlock([loopBody], /*location*/ undefined, /*multiline*/ true);
|
||||
}
|
||||
|
||||
const isAsyncBlockContainingAwait =
|
||||
containingNonArrowFunction
|
||||
&& (containingNonArrowFunction.emitFlags & NodeEmitFlags.AsyncFunctionBody) !== 0
|
||||
&& (node.statement.transformFlags & TransformFlags.ContainsYield) !== 0;
|
||||
|
||||
let loopBodyFlags: NodeEmitFlags = 0;
|
||||
if (currentState.containsLexicalThis) {
|
||||
loopBodyFlags |= NodeEmitFlags.CapturesThis;
|
||||
}
|
||||
|
||||
if (isAsyncBlockContainingAwait) {
|
||||
loopBodyFlags |= NodeEmitFlags.AsyncFunctionBody;
|
||||
}
|
||||
|
||||
const convertedLoopVariable =
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList(
|
||||
[
|
||||
createVariableDeclaration(
|
||||
@@ -2065,16 +2080,14 @@ namespace ts {
|
||||
/*type*/ undefined,
|
||||
setNodeEmitFlags(
|
||||
createFunctionExpression(
|
||||
/*asteriskToken*/ undefined,
|
||||
isAsyncBlockContainingAwait ? createToken(SyntaxKind.AsteriskToken) : undefined,
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
loopParameters,
|
||||
/*type*/ undefined,
|
||||
<Block>loopBody
|
||||
),
|
||||
currentState.containsLexicalThis
|
||||
? NodeEmitFlags.CapturesThis
|
||||
: 0
|
||||
loopBodyFlags
|
||||
)
|
||||
)
|
||||
]
|
||||
@@ -2160,7 +2173,7 @@ namespace ts {
|
||||
));
|
||||
}
|
||||
|
||||
const convertedLoopBodyStatements = generateCallToConvertedLoop(functionName, loopParameters, currentState);
|
||||
const convertedLoopBodyStatements = generateCallToConvertedLoop(functionName, loopParameters, currentState, isAsyncBlockContainingAwait);
|
||||
let loop: IterationStatement;
|
||||
if (convert) {
|
||||
loop = convert(node, convertedLoopBodyStatements);
|
||||
@@ -2173,12 +2186,17 @@ namespace ts {
|
||||
loop = visitEachChild(loop, visitor, context);
|
||||
// set loop statement
|
||||
loop.statement = createBlock(
|
||||
generateCallToConvertedLoop(functionName, loopParameters, currentState),
|
||||
convertedLoopBodyStatements,
|
||||
/*location*/ undefined,
|
||||
/*multiline*/ true
|
||||
);
|
||||
|
||||
// reset and re-aggregate the transform flags
|
||||
loop.transformFlags = 0;
|
||||
aggregateTransformFlags(loop);
|
||||
}
|
||||
|
||||
|
||||
statements.push(
|
||||
currentParent.kind === SyntaxKind.LabeledStatement
|
||||
? createLabel((<LabeledStatement>currentParent).label, loop)
|
||||
@@ -2199,7 +2217,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function generateCallToConvertedLoop(loopFunctionExpressionName: Identifier, parameters: ParameterDeclaration[], state: ConvertedLoopState): Statement[] {
|
||||
function generateCallToConvertedLoop(loopFunctionExpressionName: Identifier, parameters: ParameterDeclaration[], state: ConvertedLoopState, isAsyncBlockContainingAwait: boolean): Statement[] {
|
||||
const outerConvertedLoopState = convertedLoopState;
|
||||
|
||||
const statements: Statement[] = [];
|
||||
@@ -2212,8 +2230,9 @@ namespace ts {
|
||||
!state.labeledNonLocalContinues;
|
||||
|
||||
const call = createCall(loopFunctionExpressionName, /*typeArguments*/ undefined, map(parameters, p => <Identifier>p.name));
|
||||
const callResult = isAsyncBlockContainingAwait ? createYield(createToken(SyntaxKind.AsteriskToken), call) : call;
|
||||
if (isSimpleLoop) {
|
||||
statements.push(createStatement(call));
|
||||
statements.push(createStatement(callResult));
|
||||
copyOutParameters(state.loopOutParameters, CopyDirection.ToOriginal, statements);
|
||||
}
|
||||
else {
|
||||
@@ -2221,7 +2240,7 @@ namespace ts {
|
||||
const stateVariable = createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList(
|
||||
[createVariableDeclaration(loopResultName, /*type*/ undefined, call)]
|
||||
[createVariableDeclaration(loopResultName, /*type*/ undefined, callResult)]
|
||||
)
|
||||
);
|
||||
statements.push(stateVariable);
|
||||
|
||||
@@ -21,10 +21,11 @@
|
||||
// .brfalse LABEL, (x) - Jump to a label IIF the expression `x` is falsey.
|
||||
// If jumping out of a protected region, all .finally
|
||||
// blocks are executed.
|
||||
// .yield RESUME, (x) - Yield the value of the optional expression `x`.
|
||||
// Resume at the label RESUME.
|
||||
// .yieldstar RESUME, (x) - Delegate yield to the value of the optional
|
||||
// expression `x`. Resume at the label RESUME.
|
||||
// .yield (x) - Yield the value of the optional expression `x`.
|
||||
// Resume at the next label.
|
||||
// .yieldstar (x) - Delegate yield to the value of the optional
|
||||
// expression `x`. Resume at the next label.
|
||||
// NOTE: `x` must be an Iterator, not an Iterable.
|
||||
// .loop CONTINUE, BREAK - Marks the beginning of a loop. Any "continue" or
|
||||
// "break" abrupt completions jump to the CONTINUE or
|
||||
// BREAK labels, respectively.
|
||||
@@ -80,13 +81,13 @@
|
||||
// -------------------------------|----------------------------------------------
|
||||
// .brfalse LABEL, (x) | if (!(x)) return [3, /*break*/, LABEL];
|
||||
// -------------------------------|----------------------------------------------
|
||||
// .yield RESUME, (x) | return [4 /*yield*/, x];
|
||||
// .yield (x) | return [4 /*yield*/, x];
|
||||
// .mark RESUME | case RESUME:
|
||||
// a = %sent%; | a = state.sent();
|
||||
// a = %sent%; | a = state.sent();
|
||||
// -------------------------------|----------------------------------------------
|
||||
// .yieldstar RESUME, (X) | return [5 /*yield**/, x];
|
||||
// .yieldstar (x) | return [5 /*yield**/, x];
|
||||
// .mark RESUME | case RESUME:
|
||||
// a = %sent%; | a = state.sent();
|
||||
// a = %sent%; | a = state.sent();
|
||||
// -------------------------------|----------------------------------------------
|
||||
// .with (_a) | with (_a) {
|
||||
// a(); | a();
|
||||
@@ -109,7 +110,7 @@
|
||||
// .br END | return [3 /*break*/, END];
|
||||
// .catch (e) |
|
||||
// .mark CATCH | case CATCH:
|
||||
// | e = state.error;
|
||||
// | e = state.sent();
|
||||
// b(); | b();
|
||||
// .br END | return [3 /*break*/, END];
|
||||
// .finally |
|
||||
@@ -906,7 +907,7 @@ namespace ts {
|
||||
*
|
||||
* @param node The node to visit.
|
||||
*/
|
||||
function visitYieldExpression(node: YieldExpression) {
|
||||
function visitYieldExpression(node: YieldExpression): LeftHandSideExpression {
|
||||
// [source]
|
||||
// x = yield a();
|
||||
//
|
||||
@@ -917,7 +918,14 @@ namespace ts {
|
||||
|
||||
// NOTE: we are explicitly not handling YieldStar at this time.
|
||||
const resumeLabel = defineLabel();
|
||||
emitYield(visitNode(node.expression, visitor, isExpression), /*location*/ node);
|
||||
const expression = visitNode(node.expression, visitor, isExpression);
|
||||
if (node.asteriskToken) {
|
||||
emitYieldStar(expression, /*location*/ node);
|
||||
}
|
||||
else {
|
||||
emitYield(expression, /*location*/ node);
|
||||
}
|
||||
|
||||
markLabel(resumeLabel);
|
||||
return createGeneratorResume();
|
||||
}
|
||||
@@ -2480,6 +2488,16 @@ namespace ts {
|
||||
emitWorker(OpCode.BreakWhenFalse, [label, condition], location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a YieldStar operation for the provided expression.
|
||||
*
|
||||
* @param expression An optional value for the yield operation.
|
||||
* @param location An optional source map location for the assignment.
|
||||
*/
|
||||
function emitYieldStar(expression?: Expression, location?: TextRange): void {
|
||||
emitWorker(OpCode.YieldStar, [expression], location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a Yield operation for the provided expression.
|
||||
*
|
||||
|
||||
@@ -1807,6 +1807,8 @@ namespace ts {
|
||||
* @param path The path to test.
|
||||
*/
|
||||
fileExists(path: string): boolean;
|
||||
|
||||
readFile(path: string): string;
|
||||
}
|
||||
|
||||
export interface WriteFileCallback {
|
||||
|
||||
@@ -1844,7 +1844,8 @@ namespace Harness {
|
||||
const parseConfigHost: ts.ParseConfigHost = {
|
||||
useCaseSensitiveFileNames: false,
|
||||
readDirectory: (name) => [],
|
||||
fileExists: (name) => true
|
||||
fileExists: (name) => true,
|
||||
readFile: (name) => ts.forEach(testUnitData, data => data.name.toLowerCase() === name.toLowerCase() ? data.content : undefined)
|
||||
};
|
||||
|
||||
// check if project has tsconfig.json in the list of files
|
||||
|
||||
@@ -222,6 +222,7 @@ class ProjectRunner extends RunnerBase {
|
||||
useCaseSensitiveFileNames: Harness.IO.useCaseSensitiveFileNames(),
|
||||
fileExists,
|
||||
readDirectory,
|
||||
readFile
|
||||
};
|
||||
const configParseResult = ts.parseJsonConfigFileContent(configObject, configParseHost, ts.getDirectoryPath(configFileName), compilerOptions);
|
||||
if (configParseResult.errors.length > 0) {
|
||||
@@ -292,6 +293,10 @@ class ProjectRunner extends RunnerBase {
|
||||
return Harness.IO.fileExists(getFileNameInTheProjectTest(fileName));
|
||||
}
|
||||
|
||||
function readFile(fileName: string): string {
|
||||
return Harness.IO.readFile(getFileNameInTheProjectTest(fileName));
|
||||
}
|
||||
|
||||
function getSourceFileText(fileName: string): string {
|
||||
let text: string = undefined;
|
||||
try {
|
||||
|
||||
@@ -79,6 +79,7 @@ namespace RWC {
|
||||
useCaseSensitiveFileNames: Harness.IO.useCaseSensitiveFileNames(),
|
||||
fileExists: Harness.IO.fileExists,
|
||||
readDirectory: Harness.IO.readDirectory,
|
||||
readFile: Harness.IO.readFile
|
||||
};
|
||||
const configParseResult = ts.parseJsonConfigFileContent(parsedTsconfigFileContents.config, configParseHost, ts.getDirectoryPath(tsconfigFile.path));
|
||||
fileNames = configParseResult.fileNames;
|
||||
|
||||
@@ -86,6 +86,7 @@
|
||||
"./unittests/moduleResolution.ts",
|
||||
"./unittests/tsconfigParsing.ts",
|
||||
"./unittests/commandLineParsing.ts",
|
||||
"./unittests/configurationExtension.ts",
|
||||
"./unittests/convertCompilerOptionsFromJson.ts",
|
||||
"./unittests/convertTypingOptionsFromJson.ts",
|
||||
"./unittests/tsserverProjectSystem.ts",
|
||||
|
||||
187
src/harness/unittests/configurationExtension.ts
Normal file
187
src/harness/unittests/configurationExtension.ts
Normal file
@@ -0,0 +1,187 @@
|
||||
/// <reference path="..\harness.ts" />
|
||||
/// <reference path="..\virtualFileSystem.ts" />
|
||||
|
||||
namespace ts {
|
||||
const testContents = {
|
||||
"/dev/tsconfig.json": `{
|
||||
"extends": "./configs/base",
|
||||
"files": [
|
||||
"main.ts",
|
||||
"supplemental.ts"
|
||||
]
|
||||
}`,
|
||||
"/dev/tsconfig.nostrictnull.json": `{
|
||||
"extends": "./tsconfig",
|
||||
"compilerOptions": {
|
||||
"strictNullChecks": false
|
||||
}
|
||||
}`,
|
||||
"/dev/configs/base.json": `{
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true
|
||||
}
|
||||
}`,
|
||||
"/dev/configs/tests.json": `{
|
||||
"compilerOptions": {
|
||||
"preserveConstEnums": true,
|
||||
"removeComments": false,
|
||||
"sourceMap": true
|
||||
},
|
||||
"exclude": [
|
||||
"../tests/baselines",
|
||||
"../tests/scenarios"
|
||||
],
|
||||
"include": [
|
||||
"../tests/**/*.ts"
|
||||
]
|
||||
}`,
|
||||
"/dev/circular.json": `{
|
||||
"extends": "./circular2",
|
||||
"compilerOptions": {
|
||||
"module": "amd"
|
||||
}
|
||||
}`,
|
||||
"/dev/circular2.json": `{
|
||||
"extends": "./circular",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs"
|
||||
}
|
||||
}`,
|
||||
"/dev/missing.json": `{
|
||||
"extends": "./missing2",
|
||||
"compilerOptions": {
|
||||
"types": []
|
||||
}
|
||||
}`,
|
||||
"/dev/failure.json": `{
|
||||
"extends": "./failure2.json",
|
||||
"compilerOptions": {
|
||||
"typeRoots": []
|
||||
}
|
||||
}`,
|
||||
"/dev/failure2.json": `{
|
||||
"excludes": ["*.js"]
|
||||
}`,
|
||||
"/dev/configs/first.json": `{
|
||||
"extends": "./base",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs"
|
||||
},
|
||||
"files": ["../main.ts"]
|
||||
}`,
|
||||
"/dev/configs/second.json": `{
|
||||
"extends": "./base",
|
||||
"compilerOptions": {
|
||||
"module": "amd"
|
||||
},
|
||||
"include": ["../supplemental.*"]
|
||||
}`,
|
||||
"/dev/extends.json": `{ "extends": 42 }`,
|
||||
"/dev/extends2.json": `{ "extends": "configs/base" }`,
|
||||
"/dev/main.ts": "",
|
||||
"/dev/supplemental.ts": "",
|
||||
"/dev/tests/unit/spec.ts": "",
|
||||
"/dev/tests/utils.ts": "",
|
||||
"/dev/tests/scenarios/first.json": "",
|
||||
"/dev/tests/baselines/first/output.ts": ""
|
||||
};
|
||||
|
||||
const caseInsensitiveBasePath = "c:/dev/";
|
||||
const caseInsensitiveHost = new Utils.MockParseConfigHost(caseInsensitiveBasePath, /*useCaseSensitiveFileNames*/ false, mapObject(testContents, (key, content) => [`c:${key}`, content]));
|
||||
|
||||
const caseSensitiveBasePath = "/dev/";
|
||||
const caseSensitiveHost = new Utils.MockParseConfigHost(caseSensitiveBasePath, /*useCaseSensitiveFileNames*/ true, testContents);
|
||||
|
||||
function verifyDiagnostics(actual: Diagnostic[], expected: {code: number, category: DiagnosticCategory, messageText: string}[]) {
|
||||
assert.isTrue(expected.length === actual.length, `Expected error: ${JSON.stringify(expected)}. Actual error: ${JSON.stringify(actual)}.`);
|
||||
for (let i = 0; i < actual.length; i++) {
|
||||
const actualError = actual[i];
|
||||
const expectedError = expected[i];
|
||||
assert.equal(actualError.code, expectedError.code, "Error code mismatch");
|
||||
assert.equal(actualError.category, expectedError.category, "Category mismatch");
|
||||
assert.equal(flattenDiagnosticMessageText(actualError.messageText, "\n"), expectedError.messageText);
|
||||
}
|
||||
}
|
||||
|
||||
describe("Configuration Extension", () => {
|
||||
forEach<[string, string, Utils.MockParseConfigHost], void>([
|
||||
["under a case insensitive host", caseInsensitiveBasePath, caseInsensitiveHost],
|
||||
["under a case sensitive host", caseSensitiveBasePath, caseSensitiveHost]
|
||||
], ([testName, basePath, host]) => {
|
||||
function testSuccess(name: string, entry: string, expected: CompilerOptions, expectedFiles: string[]) {
|
||||
it(name, () => {
|
||||
const {config, error} = ts.readConfigFile(entry, name => host.readFile(name));
|
||||
assert(config && !error, flattenDiagnosticMessageText(error && error.messageText, "\n"));
|
||||
const parsed = ts.parseJsonConfigFileContent(config, host, basePath, {}, entry);
|
||||
assert(!parsed.errors.length, flattenDiagnosticMessageText(parsed.errors[0] && parsed.errors[0].messageText, "\n"));
|
||||
expected.configFilePath = entry;
|
||||
assert.deepEqual(parsed.options, expected);
|
||||
assert.deepEqual(parsed.fileNames, expectedFiles);
|
||||
});
|
||||
}
|
||||
|
||||
function testFailure(name: string, entry: string, expectedDiagnostics: {code: number, category: DiagnosticCategory, messageText: string}[]) {
|
||||
it(name, () => {
|
||||
const {config, error} = ts.readConfigFile(entry, name => host.readFile(name));
|
||||
assert(config && !error, flattenDiagnosticMessageText(error && error.messageText, "\n"));
|
||||
const parsed = ts.parseJsonConfigFileContent(config, host, basePath, {}, entry);
|
||||
verifyDiagnostics(parsed.errors, expectedDiagnostics);
|
||||
});
|
||||
}
|
||||
|
||||
describe(testName, () => {
|
||||
testSuccess("can resolve an extension with a base extension", "tsconfig.json", {
|
||||
allowJs: true,
|
||||
noImplicitAny: true,
|
||||
strictNullChecks: true,
|
||||
}, [
|
||||
combinePaths(basePath, "main.ts"),
|
||||
combinePaths(basePath, "supplemental.ts"),
|
||||
]);
|
||||
|
||||
testSuccess("can resolve an extension with a base extension that overrides options", "tsconfig.nostrictnull.json", {
|
||||
allowJs: true,
|
||||
noImplicitAny: true,
|
||||
strictNullChecks: false,
|
||||
}, [
|
||||
combinePaths(basePath, "main.ts"),
|
||||
combinePaths(basePath, "supplemental.ts"),
|
||||
]);
|
||||
|
||||
testFailure("can report errors on circular imports", "circular.json", [
|
||||
{
|
||||
code: 18000,
|
||||
category: DiagnosticCategory.Error,
|
||||
messageText: `Circularity detected while resolving configuration: ${[combinePaths(basePath, "circular.json"), combinePaths(basePath, "circular2.json"), combinePaths(basePath, "circular.json")].join(" -> ")}`
|
||||
}
|
||||
]);
|
||||
|
||||
testFailure("can report missing configurations", "missing.json", [{
|
||||
code: 6096,
|
||||
category: DiagnosticCategory.Message,
|
||||
messageText: `File './missing2' does not exist.`
|
||||
}]);
|
||||
|
||||
testFailure("can report errors in extended configs", "failure.json", [{
|
||||
code: 6114,
|
||||
category: DiagnosticCategory.Error,
|
||||
messageText: `Unknown option 'excludes'. Did you mean 'exclude'?`
|
||||
}]);
|
||||
|
||||
testFailure("can error when 'extends' is not a string", "extends.json", [{
|
||||
code: 5024,
|
||||
category: DiagnosticCategory.Error,
|
||||
messageText: `Compiler option 'extends' requires a value of type string.`
|
||||
}]);
|
||||
|
||||
testFailure("can error when 'extends' is neither relative nor rooted.", "extends2.json", [{
|
||||
code: 18001,
|
||||
category: DiagnosticCategory.Error,
|
||||
messageText: `The path in an 'extends' options must be relative or rooted.`
|
||||
}]);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -10,9 +10,9 @@ namespace Utils {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
isDirectory() { return false; }
|
||||
isFile() { return false; }
|
||||
isFileSystem() { return false; }
|
||||
isDirectory(): this is VirtualDirectory { return false; }
|
||||
isFile(): this is VirtualFile { return false; }
|
||||
isFileSystem(): this is VirtualFileSystem { return false; }
|
||||
}
|
||||
|
||||
export class VirtualFile extends VirtualFileSystemEntry {
|
||||
@@ -82,9 +82,8 @@ namespace Utils {
|
||||
return file;
|
||||
}
|
||||
else if (entry.isFile()) {
|
||||
const file = <VirtualFile>entry;
|
||||
file.content = content;
|
||||
return file;
|
||||
entry.content = content;
|
||||
return entry;
|
||||
}
|
||||
else {
|
||||
return undefined;
|
||||
@@ -196,10 +195,18 @@ namespace Utils {
|
||||
}
|
||||
|
||||
export class MockParseConfigHost extends VirtualFileSystem implements ts.ParseConfigHost {
|
||||
constructor(currentDirectory: string, ignoreCase: boolean, files: string[]) {
|
||||
constructor(currentDirectory: string, ignoreCase: boolean, files: ts.MapLike<string> | string[]) {
|
||||
super(currentDirectory, ignoreCase);
|
||||
for (const file of files) {
|
||||
this.addFile(file);
|
||||
const fileNames = (files instanceof Array) ? files : ts.getOwnKeys(files);
|
||||
for (const file of fileNames) {
|
||||
this.addFile(file, (files as any)[file]);
|
||||
}
|
||||
}
|
||||
|
||||
readFile(path: string): string {
|
||||
const value = this.traversePath(path);
|
||||
if (value && value.isFile()) {
|
||||
return value.content;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
85
src/lib/es5.d.ts
vendored
85
src/lib/es5.d.ts
vendored
@@ -3949,12 +3949,9 @@ declare module Intl {
|
||||
resolvedOptions(): ResolvedCollatorOptions;
|
||||
}
|
||||
var Collator: {
|
||||
new (locales?: string[], options?: CollatorOptions): Collator;
|
||||
new (locale?: string, options?: CollatorOptions): Collator;
|
||||
(locales?: string[], options?: CollatorOptions): Collator;
|
||||
(locale?: string, options?: CollatorOptions): Collator;
|
||||
supportedLocalesOf(locales: string[], options?: CollatorOptions): string[];
|
||||
supportedLocalesOf(locale: string, options?: CollatorOptions): string[];
|
||||
new (locales?: string | string[], options?: CollatorOptions): Collator;
|
||||
(locales?: string | string[], options?: CollatorOptions): Collator;
|
||||
supportedLocalesOf(locales: string | string[], options?: CollatorOptions): string[];
|
||||
}
|
||||
|
||||
interface NumberFormatOptions {
|
||||
@@ -3989,12 +3986,9 @@ declare module Intl {
|
||||
resolvedOptions(): ResolvedNumberFormatOptions;
|
||||
}
|
||||
var NumberFormat: {
|
||||
new (locales?: string[], options?: NumberFormatOptions): NumberFormat;
|
||||
new (locale?: string, options?: NumberFormatOptions): NumberFormat;
|
||||
(locales?: string[], options?: NumberFormatOptions): NumberFormat;
|
||||
(locale?: string, options?: NumberFormatOptions): NumberFormat;
|
||||
supportedLocalesOf(locales: string[], options?: NumberFormatOptions): string[];
|
||||
supportedLocalesOf(locale: string, options?: NumberFormatOptions): string[];
|
||||
new (locales?: string | string[], options?: NumberFormatOptions): NumberFormat;
|
||||
(locales?: string | string[], options?: NumberFormatOptions): NumberFormat;
|
||||
supportedLocalesOf(locales: string | string[], options?: NumberFormatOptions): string[];
|
||||
}
|
||||
|
||||
interface DateTimeFormatOptions {
|
||||
@@ -4035,88 +4029,49 @@ declare module Intl {
|
||||
resolvedOptions(): ResolvedDateTimeFormatOptions;
|
||||
}
|
||||
var DateTimeFormat: {
|
||||
new (locales?: string[], options?: DateTimeFormatOptions): DateTimeFormat;
|
||||
new (locale?: string, options?: DateTimeFormatOptions): DateTimeFormat;
|
||||
(locales?: string[], options?: DateTimeFormatOptions): DateTimeFormat;
|
||||
(locale?: string, options?: DateTimeFormatOptions): DateTimeFormat;
|
||||
supportedLocalesOf(locales: string[], options?: DateTimeFormatOptions): string[];
|
||||
supportedLocalesOf(locale: string, options?: DateTimeFormatOptions): string[];
|
||||
new (locales?: string | string[], options?: DateTimeFormatOptions): DateTimeFormat;
|
||||
(locales?: string | string[], options?: DateTimeFormatOptions): DateTimeFormat;
|
||||
supportedLocalesOf(locales: string | string[], options?: DateTimeFormatOptions): string[];
|
||||
}
|
||||
}
|
||||
|
||||
interface String {
|
||||
/**
|
||||
* Determines whether two strings are equivalent in the current locale.
|
||||
* Determines whether two strings are equivalent in the current or specified locale.
|
||||
* @param that String to compare to target string
|
||||
* @param locales An array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. This parameter must conform to BCP 47 standards; see the Intl.Collator object for details.
|
||||
* @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. This parameter must conform to BCP 47 standards; see the Intl.Collator object for details.
|
||||
* @param options An object that contains one or more properties that specify comparison options. see the Intl.Collator object for details.
|
||||
*/
|
||||
localeCompare(that: string, locales: string[], options?: Intl.CollatorOptions): number;
|
||||
|
||||
/**
|
||||
* Determines whether two strings are equivalent in the current locale.
|
||||
* @param that String to compare to target string
|
||||
* @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. This parameter must conform to BCP 47 standards; see the Intl.Collator object for details.
|
||||
* @param options An object that contains one or more properties that specify comparison options. see the Intl.Collator object for details.
|
||||
*/
|
||||
localeCompare(that: string, locale: string, options?: Intl.CollatorOptions): number;
|
||||
localeCompare(that: string, locales?: string | string[], options?: Intl.CollatorOptions): number;
|
||||
}
|
||||
|
||||
interface Number {
|
||||
/**
|
||||
* Converts a number to a string by using the current or specified locale.
|
||||
* @param locales An array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used.
|
||||
* @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used.
|
||||
* @param options An object that contains one or more properties that specify comparison options.
|
||||
*/
|
||||
toLocaleString(locales?: string[], options?: Intl.NumberFormatOptions): string;
|
||||
|
||||
/**
|
||||
* Converts a number to a string by using the current or specified locale.
|
||||
* @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used.
|
||||
* @param options An object that contains one or more properties that specify comparison options.
|
||||
*/
|
||||
toLocaleString(locale?: string, options?: Intl.NumberFormatOptions): string;
|
||||
toLocaleString(locales?: string | string[], options?: Intl.NumberFormatOptions): string;
|
||||
}
|
||||
|
||||
interface Date {
|
||||
/**
|
||||
* Converts a date and time to a string by using the current or specified locale.
|
||||
* @param locales An array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used.
|
||||
* @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used.
|
||||
* @param options An object that contains one or more properties that specify comparison options.
|
||||
*/
|
||||
toLocaleString(locales?: string[], options?: Intl.DateTimeFormatOptions): string;
|
||||
toLocaleString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string;
|
||||
/**
|
||||
* Converts a date to a string by using the current or specified locale.
|
||||
* @param locales An array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used.
|
||||
* @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used.
|
||||
* @param options An object that contains one or more properties that specify comparison options.
|
||||
*/
|
||||
toLocaleDateString(locales?: string[], options?: Intl.DateTimeFormatOptions): string;
|
||||
toLocaleDateString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string;
|
||||
|
||||
/**
|
||||
* Converts a time to a string by using the current or specified locale.
|
||||
* @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used.
|
||||
* @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used.
|
||||
* @param options An object that contains one or more properties that specify comparison options.
|
||||
*/
|
||||
toLocaleTimeString(locale?: string[], options?: Intl.DateTimeFormatOptions): string;
|
||||
|
||||
/**
|
||||
* Converts a date and time to a string by using the current or specified locale.
|
||||
* @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used.
|
||||
* @param options An object that contains one or more properties that specify comparison options.
|
||||
*/
|
||||
toLocaleString(locale?: string, options?: Intl.DateTimeFormatOptions): string;
|
||||
|
||||
/**
|
||||
* Converts a date to a string by using the current or specified locale.
|
||||
* @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used.
|
||||
* @param options An object that contains one or more properties that specify comparison options.
|
||||
*/
|
||||
toLocaleDateString(locale?: string, options?: Intl.DateTimeFormatOptions): string;
|
||||
|
||||
/**
|
||||
* Converts a time to a string by using the current or specified locale.
|
||||
* @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used.
|
||||
* @param options An object that contains one or more properties that specify comparison options.
|
||||
*/
|
||||
toLocaleTimeString(locale?: string, options?: Intl.DateTimeFormatOptions): string;
|
||||
toLocaleTimeString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string;
|
||||
}
|
||||
|
||||
@@ -91,7 +91,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
public getText(sourceFile?: SourceFile): string {
|
||||
return (sourceFile || this.getSourceFile()).text.substring(this.getStart(), this.getEnd());
|
||||
if (!sourceFile) {
|
||||
sourceFile = this.getSourceFile();
|
||||
}
|
||||
return sourceFile.text.substring(this.getStart(sourceFile), this.getEnd());
|
||||
}
|
||||
|
||||
private addSyntheticNodes(nodes: Node[], pos: number, end: number, useJSDocScanner?: boolean): number {
|
||||
|
||||
Reference in New Issue
Block a user