[Transforms] Update transforms with recent master (#8960)
* Remove check narrowing only certain types, add test showing issues with this * string literal case test * Reconcile fix with CFA work * Defaultable -> NotNarrowable to align with use * Missed a defaultable in comments * Add test for narrowing to unions of string literals * Actually merge from master * Run fixupParentReferences when parsing isolated jsDocComment * initial revision of unit test support for project system in tsserver * Add non-widening forms of null and undefined * Create separate control flows for property declarations with initializers * Add regression test * Add tests * Remove unused variable * Add null check and CR feedback * Revert "Merge pull request #7235 from weswigham/narrow-all-types" This reverts commitef0f6c8fe4
, reversing changes made to9f087cb62a
. * reuse the fixupParentReferences function * Fix up error from merging with master
This commit is contained in:
parent
e9dadd7707
commit
f619282af1
|
@ -180,7 +180,8 @@ var harnessSources = harnessCoreSources.concat([
|
|||
"tsconfigParsing.ts",
|
||||
"commandLineParsing.ts",
|
||||
"convertCompilerOptionsFromJson.ts",
|
||||
"convertTypingOptionsFromJson.ts"
|
||||
"convertTypingOptionsFromJson.ts",
|
||||
"tsserverProjectSystem.ts"
|
||||
].map(function (f) {
|
||||
return path.join(unittestsDirectory, f);
|
||||
})).concat([
|
||||
|
|
|
@ -1163,6 +1163,8 @@ namespace ts {
|
|||
|
||||
case SyntaxKind.ModuleBlock:
|
||||
return ContainerFlags.IsControlFlowContainer;
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
return (<PropertyDeclaration>node).initializer ? ContainerFlags.IsControlFlowContainer : 0;
|
||||
|
||||
case SyntaxKind.CatchClause:
|
||||
case SyntaxKind.ForStatement:
|
||||
|
|
|
@ -108,16 +108,16 @@ namespace ts {
|
|||
const unknownSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "unknown");
|
||||
const resolvingSymbol = createSymbol(SymbolFlags.Transient, "__resolving__");
|
||||
|
||||
const nullableWideningFlags = strictNullChecks ? 0 : TypeFlags.ContainsUndefinedOrNull;
|
||||
const anyType = createIntrinsicType(TypeFlags.Any, "any");
|
||||
const stringType = createIntrinsicType(TypeFlags.String, "string");
|
||||
const numberType = createIntrinsicType(TypeFlags.Number, "number");
|
||||
const booleanType = createIntrinsicType(TypeFlags.Boolean, "boolean");
|
||||
const esSymbolType = createIntrinsicType(TypeFlags.ESSymbol, "symbol");
|
||||
const voidType = createIntrinsicType(TypeFlags.Void, "void");
|
||||
const undefinedType = createIntrinsicType(TypeFlags.Undefined | nullableWideningFlags, "undefined");
|
||||
const nullType = createIntrinsicType(TypeFlags.Null | nullableWideningFlags, "null");
|
||||
const emptyArrayElementType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefinedOrNull, "undefined");
|
||||
const undefinedType = createIntrinsicType(TypeFlags.Undefined, "undefined");
|
||||
const undefinedWideningType = strictNullChecks ? undefinedType : createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsWideningType, "undefined");
|
||||
const nullType = createIntrinsicType(TypeFlags.Null, "null");
|
||||
const nullWideningType = strictNullChecks ? nullType : createIntrinsicType(TypeFlags.Null | TypeFlags.ContainsWideningType, "null");
|
||||
const unknownType = createIntrinsicType(TypeFlags.Any, "unknown");
|
||||
const neverType = createIntrinsicType(TypeFlags.Never, "never");
|
||||
|
||||
|
@ -3403,7 +3403,7 @@ namespace ts {
|
|||
error(type.symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, symbolToString(type.symbol));
|
||||
return type.resolvedBaseConstructorType = unknownType;
|
||||
}
|
||||
if (baseConstructorType !== unknownType && baseConstructorType !== nullType && !isConstructorType(baseConstructorType)) {
|
||||
if (baseConstructorType !== unknownType && baseConstructorType !== nullWideningType && !isConstructorType(baseConstructorType)) {
|
||||
error(baseTypeNode.expression, Diagnostics.Type_0_is_not_a_constructor_function_type, typeToString(baseConstructorType));
|
||||
return type.resolvedBaseConstructorType = unknownType;
|
||||
}
|
||||
|
@ -5009,6 +5009,7 @@ namespace ts {
|
|||
containsAny?: boolean;
|
||||
containsUndefined?: boolean;
|
||||
containsNull?: boolean;
|
||||
containsNonWideningType?: boolean;
|
||||
}
|
||||
|
||||
function addTypeToSet(typeSet: TypeSet, type: Type, typeSetKind: TypeFlags) {
|
||||
|
@ -5019,6 +5020,7 @@ namespace ts {
|
|||
if (type.flags & TypeFlags.Any) typeSet.containsAny = true;
|
||||
if (type.flags & TypeFlags.Undefined) typeSet.containsUndefined = true;
|
||||
if (type.flags & TypeFlags.Null) typeSet.containsNull = true;
|
||||
if (!(type.flags & TypeFlags.ContainsWideningType)) typeSet.containsNonWideningType = true;
|
||||
}
|
||||
else if (type !== neverType && !contains(typeSet, type)) {
|
||||
typeSet.push(type);
|
||||
|
@ -5079,8 +5081,8 @@ namespace ts {
|
|||
removeSubtypes(typeSet);
|
||||
}
|
||||
if (typeSet.length === 0) {
|
||||
return typeSet.containsNull ? nullType :
|
||||
typeSet.containsUndefined ? undefinedType :
|
||||
return typeSet.containsNull ? typeSet.containsNonWideningType ? nullType : nullWideningType :
|
||||
typeSet.containsUndefined ? typeSet.containsNonWideningType ? undefinedType : undefinedWideningType :
|
||||
neverType;
|
||||
}
|
||||
else if (typeSet.length === 1) {
|
||||
|
@ -5880,7 +5882,7 @@ namespace ts {
|
|||
if (!(target.flags & TypeFlags.Never)) {
|
||||
if (target.flags & TypeFlags.Any || source.flags & TypeFlags.Never) return Ternary.True;
|
||||
if (source.flags & TypeFlags.Undefined) {
|
||||
if (!strictNullChecks || target.flags & (TypeFlags.Undefined | TypeFlags.Void) || source === emptyArrayElementType) return Ternary.True;
|
||||
if (!strictNullChecks || target.flags & (TypeFlags.Undefined | TypeFlags.Void)) return Ternary.True;
|
||||
}
|
||||
if (source.flags & TypeFlags.Null) {
|
||||
if (!strictNullChecks || target.flags & TypeFlags.Null) return Ternary.True;
|
||||
|
@ -6970,7 +6972,7 @@ namespace ts {
|
|||
if (type.flags & TypeFlags.ObjectLiteral) {
|
||||
for (const p of getPropertiesOfObjectType(type)) {
|
||||
const t = getTypeOfSymbol(p);
|
||||
if (t.flags & TypeFlags.ContainsUndefinedOrNull) {
|
||||
if (t.flags & TypeFlags.ContainsWideningType) {
|
||||
if (!reportWideningErrorsInType(t)) {
|
||||
error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, p.name, typeToString(getWidenedType(t)));
|
||||
}
|
||||
|
@ -7017,7 +7019,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
function reportErrorsFromWidening(declaration: Declaration, type: Type) {
|
||||
if (produceDiagnostics && compilerOptions.noImplicitAny && type.flags & TypeFlags.ContainsUndefinedOrNull) {
|
||||
if (produceDiagnostics && compilerOptions.noImplicitAny && type.flags & TypeFlags.ContainsWideningType) {
|
||||
// Report implicit any error within type if possible, otherwise report error on declaration
|
||||
if (!reportWideningErrorsInType(type)) {
|
||||
reportImplicitAnyError(declaration, type);
|
||||
|
@ -8309,7 +8311,7 @@ namespace ts {
|
|||
const classInstanceType = <InterfaceType>getDeclaredTypeOfSymbol(classSymbol);
|
||||
const baseConstructorType = getBaseConstructorTypeOfClass(classInstanceType);
|
||||
|
||||
return baseConstructorType === nullType;
|
||||
return baseConstructorType === nullWideningType;
|
||||
}
|
||||
|
||||
function checkThisExpression(node: Node): Type {
|
||||
|
@ -9200,7 +9202,7 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
}
|
||||
return createArrayType(elementTypes.length ? getUnionType(elementTypes) : emptyArrayElementType);
|
||||
return createArrayType(elementTypes.length ? getUnionType(elementTypes) : strictNullChecks ? neverType : undefinedWideningType);
|
||||
}
|
||||
|
||||
function isNumericName(name: DeclarationName): boolean {
|
||||
|
@ -12004,7 +12006,7 @@ namespace ts {
|
|||
|
||||
function checkVoidExpression(node: VoidExpression): Type {
|
||||
checkExpression(node.expression);
|
||||
return undefinedType;
|
||||
return undefinedWideningType;
|
||||
}
|
||||
|
||||
function checkAwaitExpression(node: AwaitExpression): Type {
|
||||
|
@ -12411,7 +12413,7 @@ namespace ts {
|
|||
case SyntaxKind.InKeyword:
|
||||
return checkInExpression(left, right, leftType, rightType);
|
||||
case SyntaxKind.AmpersandAmpersandToken:
|
||||
return addNullableKind(rightType, getNullableKind(leftType));
|
||||
return strictNullChecks ? addNullableKind(rightType, getNullableKind(leftType)) : rightType;
|
||||
case SyntaxKind.BarBarToken:
|
||||
return getUnionType([getNonNullableType(leftType), rightType]);
|
||||
case SyntaxKind.EqualsToken:
|
||||
|
@ -12678,7 +12680,7 @@ namespace ts {
|
|||
case SyntaxKind.SuperKeyword:
|
||||
return checkSuperExpression(node);
|
||||
case SyntaxKind.NullKeyword:
|
||||
return nullType;
|
||||
return nullWideningType;
|
||||
case SyntaxKind.TrueKeyword:
|
||||
case SyntaxKind.FalseKeyword:
|
||||
return booleanType;
|
||||
|
@ -12736,7 +12738,7 @@ namespace ts {
|
|||
case SyntaxKind.SpreadElementExpression:
|
||||
return checkSpreadElementExpression(<SpreadElementExpression>node, contextualMapper);
|
||||
case SyntaxKind.OmittedExpression:
|
||||
return undefinedType;
|
||||
return undefinedWideningType;
|
||||
case SyntaxKind.YieldExpression:
|
||||
return checkYieldExpression(<YieldExpression>node);
|
||||
case SyntaxKind.JsxExpression:
|
||||
|
@ -17728,7 +17730,7 @@ namespace ts {
|
|||
// Setup global builtins
|
||||
addToSymbolTable(globals, builtinGlobals, Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0);
|
||||
|
||||
getSymbolLinks(undefinedSymbol).type = undefinedType;
|
||||
getSymbolLinks(undefinedSymbol).type = undefinedWideningType;
|
||||
getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments");
|
||||
getSymbolLinks(unknownSymbol).type = unknownType;
|
||||
|
||||
|
|
|
@ -443,7 +443,14 @@ namespace ts {
|
|||
|
||||
/* @internal */
|
||||
export function parseIsolatedJSDocComment(content: string, start?: number, length?: number) {
|
||||
return Parser.JSDocParser.parseIsolatedJSDocComment(content, start, length);
|
||||
const result = Parser.JSDocParser.parseIsolatedJSDocComment(content, start, length);
|
||||
if (result && result.jsDocComment) {
|
||||
// because the jsDocComment was parsed out of the source file, it might
|
||||
// not be covered by the fixupParentReferences.
|
||||
Parser.fixupParentReferences(result.jsDocComment);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
@ -655,14 +662,14 @@ namespace ts {
|
|||
return node;
|
||||
}
|
||||
|
||||
export function fixupParentReferences(sourceFile: Node) {
|
||||
export function fixupParentReferences(rootNode: Node) {
|
||||
// normally parent references are set during binding. However, for clients that only need
|
||||
// a syntax tree, and no semantic features, then the binding process is an unnecessary
|
||||
// overhead. This functions allows us to set all the parents, without all the expense of
|
||||
// binding.
|
||||
|
||||
let parent: Node = sourceFile;
|
||||
forEachChild(sourceFile, visitNode);
|
||||
let parent: Node = rootNode;
|
||||
forEachChild(rootNode, visitNode);
|
||||
return;
|
||||
|
||||
function visitNode(n: Node): void {
|
||||
|
|
|
@ -2264,7 +2264,7 @@ namespace ts {
|
|||
/* @internal */
|
||||
FreshObjectLiteral = 0x00100000, // Fresh object literal type
|
||||
/* @internal */
|
||||
ContainsUndefinedOrNull = 0x00200000, // Type is or contains undefined or null type
|
||||
ContainsWideningType = 0x00200000, // Type is or contains undefined or null widening type
|
||||
/* @internal */
|
||||
ContainsObjectLiteral = 0x00400000, // Type is or contains object literal type
|
||||
/* @internal */
|
||||
|
@ -2287,9 +2287,9 @@ namespace ts {
|
|||
StructuredType = ObjectType | Union | Intersection,
|
||||
Narrowable = Any | ObjectType | Union | TypeParameter,
|
||||
/* @internal */
|
||||
RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral,
|
||||
RequiresWidening = ContainsWideningType | ContainsObjectLiteral,
|
||||
/* @internal */
|
||||
PropagatingFlags = ContainsUndefinedOrNull | ContainsObjectLiteral | ContainsAnyFunctionType
|
||||
PropagatingFlags = ContainsWideningType | ContainsObjectLiteral | ContainsAnyFunctionType
|
||||
}
|
||||
|
||||
export type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression;
|
||||
|
|
|
@ -1138,7 +1138,7 @@ namespace ts.server {
|
|||
else {
|
||||
this.log("No config files found.");
|
||||
}
|
||||
return {};
|
||||
return configFileName ? { configFileName } : {};
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// array literals are widened upon assignment according to their element type
|
||||
|
||||
var a = []; // any[]
|
||||
var a = [,,];
|
||||
|
||||
var a = [null, null];
|
||||
var a = [undefined, undefined];
|
||||
|
@ -12,11 +13,20 @@ var b = [[undefined, undefined]];
|
|||
|
||||
var c = [[[]]]; // any[][][]
|
||||
var c = [[[null]],[undefined]]
|
||||
|
||||
// no widening when one or more elements are non-widening
|
||||
|
||||
var x: undefined = undefined;
|
||||
|
||||
var d = [x];
|
||||
var d = [, x];
|
||||
var d = [undefined, x];
|
||||
|
||||
|
||||
//// [arrayLiteralWidened.js]
|
||||
// array literals are widened upon assignment according to their element type
|
||||
var a = []; // any[]
|
||||
var a = [, ,];
|
||||
var a = [null, null];
|
||||
var a = [undefined, undefined];
|
||||
var b = [[], [null, null]]; // any[][]
|
||||
|
@ -24,3 +34,8 @@ var b = [[], []];
|
|||
var b = [[undefined, undefined]];
|
||||
var c = [[[]]]; // any[][][]
|
||||
var c = [[[null]], [undefined]];
|
||||
// no widening when one or more elements are non-widening
|
||||
var x = undefined;
|
||||
var d = [x];
|
||||
var d = [, x];
|
||||
var d = [undefined, x];
|
||||
|
|
|
@ -2,31 +2,53 @@
|
|||
// array literals are widened upon assignment according to their element type
|
||||
|
||||
var a = []; // any[]
|
||||
>a : Symbol(a, Decl(arrayLiteralWidened.ts, 2, 3), Decl(arrayLiteralWidened.ts, 4, 3), Decl(arrayLiteralWidened.ts, 5, 3))
|
||||
>a : Symbol(a, Decl(arrayLiteralWidened.ts, 2, 3), Decl(arrayLiteralWidened.ts, 3, 3), Decl(arrayLiteralWidened.ts, 5, 3), Decl(arrayLiteralWidened.ts, 6, 3))
|
||||
|
||||
var a = [,,];
|
||||
>a : Symbol(a, Decl(arrayLiteralWidened.ts, 2, 3), Decl(arrayLiteralWidened.ts, 3, 3), Decl(arrayLiteralWidened.ts, 5, 3), Decl(arrayLiteralWidened.ts, 6, 3))
|
||||
|
||||
var a = [null, null];
|
||||
>a : Symbol(a, Decl(arrayLiteralWidened.ts, 2, 3), Decl(arrayLiteralWidened.ts, 4, 3), Decl(arrayLiteralWidened.ts, 5, 3))
|
||||
>a : Symbol(a, Decl(arrayLiteralWidened.ts, 2, 3), Decl(arrayLiteralWidened.ts, 3, 3), Decl(arrayLiteralWidened.ts, 5, 3), Decl(arrayLiteralWidened.ts, 6, 3))
|
||||
|
||||
var a = [undefined, undefined];
|
||||
>a : Symbol(a, Decl(arrayLiteralWidened.ts, 2, 3), Decl(arrayLiteralWidened.ts, 4, 3), Decl(arrayLiteralWidened.ts, 5, 3))
|
||||
>a : Symbol(a, Decl(arrayLiteralWidened.ts, 2, 3), Decl(arrayLiteralWidened.ts, 3, 3), Decl(arrayLiteralWidened.ts, 5, 3), Decl(arrayLiteralWidened.ts, 6, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
var b = [[], [null, null]]; // any[][]
|
||||
>b : Symbol(b, Decl(arrayLiteralWidened.ts, 7, 3), Decl(arrayLiteralWidened.ts, 8, 3), Decl(arrayLiteralWidened.ts, 9, 3))
|
||||
>b : Symbol(b, Decl(arrayLiteralWidened.ts, 8, 3), Decl(arrayLiteralWidened.ts, 9, 3), Decl(arrayLiteralWidened.ts, 10, 3))
|
||||
|
||||
var b = [[], []];
|
||||
>b : Symbol(b, Decl(arrayLiteralWidened.ts, 7, 3), Decl(arrayLiteralWidened.ts, 8, 3), Decl(arrayLiteralWidened.ts, 9, 3))
|
||||
>b : Symbol(b, Decl(arrayLiteralWidened.ts, 8, 3), Decl(arrayLiteralWidened.ts, 9, 3), Decl(arrayLiteralWidened.ts, 10, 3))
|
||||
|
||||
var b = [[undefined, undefined]];
|
||||
>b : Symbol(b, Decl(arrayLiteralWidened.ts, 7, 3), Decl(arrayLiteralWidened.ts, 8, 3), Decl(arrayLiteralWidened.ts, 9, 3))
|
||||
>b : Symbol(b, Decl(arrayLiteralWidened.ts, 8, 3), Decl(arrayLiteralWidened.ts, 9, 3), Decl(arrayLiteralWidened.ts, 10, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
var c = [[[]]]; // any[][][]
|
||||
>c : Symbol(c, Decl(arrayLiteralWidened.ts, 11, 3), Decl(arrayLiteralWidened.ts, 12, 3))
|
||||
>c : Symbol(c, Decl(arrayLiteralWidened.ts, 12, 3), Decl(arrayLiteralWidened.ts, 13, 3))
|
||||
|
||||
var c = [[[null]],[undefined]]
|
||||
>c : Symbol(c, Decl(arrayLiteralWidened.ts, 11, 3), Decl(arrayLiteralWidened.ts, 12, 3))
|
||||
>c : Symbol(c, Decl(arrayLiteralWidened.ts, 12, 3), Decl(arrayLiteralWidened.ts, 13, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
// no widening when one or more elements are non-widening
|
||||
|
||||
var x: undefined = undefined;
|
||||
>x : Symbol(x, Decl(arrayLiteralWidened.ts, 17, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
var d = [x];
|
||||
>d : Symbol(d, Decl(arrayLiteralWidened.ts, 19, 3), Decl(arrayLiteralWidened.ts, 20, 3), Decl(arrayLiteralWidened.ts, 21, 3))
|
||||
>x : Symbol(x, Decl(arrayLiteralWidened.ts, 17, 3))
|
||||
|
||||
var d = [, x];
|
||||
>d : Symbol(d, Decl(arrayLiteralWidened.ts, 19, 3), Decl(arrayLiteralWidened.ts, 20, 3), Decl(arrayLiteralWidened.ts, 21, 3))
|
||||
>x : Symbol(x, Decl(arrayLiteralWidened.ts, 17, 3))
|
||||
|
||||
var d = [undefined, x];
|
||||
>d : Symbol(d, Decl(arrayLiteralWidened.ts, 19, 3), Decl(arrayLiteralWidened.ts, 20, 3), Decl(arrayLiteralWidened.ts, 21, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
>x : Symbol(x, Decl(arrayLiteralWidened.ts, 17, 3))
|
||||
|
||||
|
|
|
@ -5,6 +5,12 @@ var a = []; // any[]
|
|||
>a : any[]
|
||||
>[] : undefined[]
|
||||
|
||||
var a = [,,];
|
||||
>a : any[]
|
||||
>[,,] : undefined[]
|
||||
> : undefined
|
||||
> : undefined
|
||||
|
||||
var a = [null, null];
|
||||
>a : any[]
|
||||
>[null, null] : null[]
|
||||
|
@ -53,3 +59,26 @@ var c = [[[null]],[undefined]]
|
|||
>[undefined] : undefined[]
|
||||
>undefined : undefined
|
||||
|
||||
// no widening when one or more elements are non-widening
|
||||
|
||||
var x: undefined = undefined;
|
||||
>x : undefined
|
||||
>undefined : undefined
|
||||
|
||||
var d = [x];
|
||||
>d : undefined[]
|
||||
>[x] : undefined[]
|
||||
>x : undefined
|
||||
|
||||
var d = [, x];
|
||||
>d : undefined[]
|
||||
>[, x] : undefined[]
|
||||
> : undefined
|
||||
>x : undefined
|
||||
|
||||
var d = [undefined, x];
|
||||
>d : undefined[]
|
||||
>[undefined, x] : undefined[]
|
||||
>undefined : undefined
|
||||
>x : undefined
|
||||
|
||||
|
|
291
tests/baselines/reference/controlFlowPropertyDeclarations.js
Normal file
291
tests/baselines/reference/controlFlowPropertyDeclarations.js
Normal file
|
@ -0,0 +1,291 @@
|
|||
//// [controlFlowPropertyDeclarations.ts]
|
||||
// Repro from ##8913
|
||||
|
||||
declare var require:any;
|
||||
|
||||
var HTMLDOMPropertyConfig = require('react/lib/HTMLDOMPropertyConfig');
|
||||
|
||||
// Populate property map with ReactJS's attribute and property mappings
|
||||
// TODO handle/use .Properties value eg: MUST_USE_PROPERTY is not HTML attr
|
||||
for (var propname in HTMLDOMPropertyConfig.Properties) {
|
||||
if (!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var mapFrom = HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeats a string a certain number of times.
|
||||
* Also: the future is bright and consists of native string repetition:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
|
||||
*
|
||||
* @param {string} string String to repeat
|
||||
* @param {number} times Number of times to repeat string. Integer.
|
||||
* @see http://jsperf.com/string-repeater/2
|
||||
*/
|
||||
function repeatString(string, times) {
|
||||
if (times === 1) {
|
||||
return string;
|
||||
}
|
||||
if (times < 0) { throw new Error(); }
|
||||
var repeated = '';
|
||||
while (times) {
|
||||
if (times & 1) {
|
||||
repeated += string;
|
||||
}
|
||||
if (times >>= 1) {
|
||||
string += string;
|
||||
}
|
||||
}
|
||||
return repeated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the string ends with the specified substring.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {boolean}
|
||||
*/
|
||||
function endsWith(haystack, needle) {
|
||||
return haystack.slice(-needle.length) === needle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim the specified substring off the string. If the string does not end
|
||||
* with the specified substring, this is a no-op.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {string}
|
||||
*/
|
||||
function trimEnd(haystack, needle) {
|
||||
return endsWith(haystack, needle)
|
||||
? haystack.slice(0, -needle.length)
|
||||
: haystack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a hyphenated string to camelCase.
|
||||
*/
|
||||
function hyphenToCamelCase(string) {
|
||||
return string.replace(/-(.)/g, function(match, chr) {
|
||||
return chr.toUpperCase();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the specified string consists entirely of whitespace.
|
||||
*/
|
||||
function isEmpty(string) {
|
||||
return !/[^\s]/.test(string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the CSS value can be converted from a
|
||||
* 'px' suffixed string to a numeric value
|
||||
*
|
||||
* @param {string} value CSS property value
|
||||
* @return {boolean}
|
||||
*/
|
||||
function isConvertiblePixelValue(value) {
|
||||
return /^\d+px$/.test(value);
|
||||
}
|
||||
|
||||
export class HTMLtoJSX {
|
||||
private output: string;
|
||||
private level: number;
|
||||
private _inPreTag: boolean;
|
||||
|
||||
|
||||
/**
|
||||
* Handles processing of the specified text node
|
||||
*
|
||||
* @param {TextNode} node
|
||||
*/
|
||||
_visitText = (node) => {
|
||||
var parentTag = node.parentNode && node.parentNode.tagName.toLowerCase();
|
||||
if (parentTag === 'textarea' || parentTag === 'style') {
|
||||
// Ignore text content of textareas and styles, as it will have already been moved
|
||||
// to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively.
|
||||
return;
|
||||
}
|
||||
|
||||
var text = ''
|
||||
|
||||
if (this._inPreTag) {
|
||||
// If this text is contained within a <pre>, we need to ensure the JSX
|
||||
// whitespace coalescing rules don't eat the whitespace. This means
|
||||
// wrapping newlines and sequences of two or more spaces in variables.
|
||||
text = text
|
||||
.replace(/\r/g, '')
|
||||
.replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) {
|
||||
return '{' + JSON.stringify(whitespace) + '}';
|
||||
});
|
||||
} else {
|
||||
// If there's a newline in the text, adjust the indent level
|
||||
if (text.indexOf('\n') > -1) {
|
||||
}
|
||||
}
|
||||
this.output += text;
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles parsing of inline styles
|
||||
*/
|
||||
export class StyleParser {
|
||||
styles = {};
|
||||
toJSXString = () => {
|
||||
for (var key in this.styles) {
|
||||
if (!this.styles.hasOwnProperty(key)) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// [controlFlowPropertyDeclarations.js]
|
||||
// Repro from ##8913
|
||||
"use strict";
|
||||
var HTMLDOMPropertyConfig = require('react/lib/HTMLDOMPropertyConfig');
|
||||
// Populate property map with ReactJS's attribute and property mappings
|
||||
// TODO handle/use .Properties value eg: MUST_USE_PROPERTY is not HTML attr
|
||||
for (var propname in HTMLDOMPropertyConfig.Properties) {
|
||||
if (!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname)) {
|
||||
continue;
|
||||
}
|
||||
var mapFrom = HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase();
|
||||
}
|
||||
/**
|
||||
* Repeats a string a certain number of times.
|
||||
* Also: the future is bright and consists of native string repetition:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
|
||||
*
|
||||
* @param {string} string String to repeat
|
||||
* @param {number} times Number of times to repeat string. Integer.
|
||||
* @see http://jsperf.com/string-repeater/2
|
||||
*/
|
||||
function repeatString(string, times) {
|
||||
if (times === 1) {
|
||||
return string;
|
||||
}
|
||||
if (times < 0) {
|
||||
throw new Error();
|
||||
}
|
||||
var repeated = '';
|
||||
while (times) {
|
||||
if (times & 1) {
|
||||
repeated += string;
|
||||
}
|
||||
if (times >>= 1) {
|
||||
string += string;
|
||||
}
|
||||
}
|
||||
return repeated;
|
||||
}
|
||||
/**
|
||||
* Determine if the string ends with the specified substring.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {boolean}
|
||||
*/
|
||||
function endsWith(haystack, needle) {
|
||||
return haystack.slice(-needle.length) === needle;
|
||||
}
|
||||
/**
|
||||
* Trim the specified substring off the string. If the string does not end
|
||||
* with the specified substring, this is a no-op.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {string}
|
||||
*/
|
||||
function trimEnd(haystack, needle) {
|
||||
return endsWith(haystack, needle)
|
||||
? haystack.slice(0, -needle.length)
|
||||
: haystack;
|
||||
}
|
||||
/**
|
||||
* Convert a hyphenated string to camelCase.
|
||||
*/
|
||||
function hyphenToCamelCase(string) {
|
||||
return string.replace(/-(.)/g, function (match, chr) {
|
||||
return chr.toUpperCase();
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Determines if the specified string consists entirely of whitespace.
|
||||
*/
|
||||
function isEmpty(string) {
|
||||
return !/[^\s]/.test(string);
|
||||
}
|
||||
/**
|
||||
* Determines if the CSS value can be converted from a
|
||||
* 'px' suffixed string to a numeric value
|
||||
*
|
||||
* @param {string} value CSS property value
|
||||
* @return {boolean}
|
||||
*/
|
||||
function isConvertiblePixelValue(value) {
|
||||
return /^\d+px$/.test(value);
|
||||
}
|
||||
var HTMLtoJSX = (function () {
|
||||
function HTMLtoJSX() {
|
||||
var _this = this;
|
||||
/**
|
||||
* Handles processing of the specified text node
|
||||
*
|
||||
* @param {TextNode} node
|
||||
*/
|
||||
this._visitText = function (node) {
|
||||
var parentTag = node.parentNode && node.parentNode.tagName.toLowerCase();
|
||||
if (parentTag === 'textarea' || parentTag === 'style') {
|
||||
// Ignore text content of textareas and styles, as it will have already been moved
|
||||
// to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively.
|
||||
return;
|
||||
}
|
||||
var text = '';
|
||||
if (_this._inPreTag) {
|
||||
// If this text is contained within a <pre>, we need to ensure the JSX
|
||||
// whitespace coalescing rules don't eat the whitespace. This means
|
||||
// wrapping newlines and sequences of two or more spaces in variables.
|
||||
text = text
|
||||
.replace(/\r/g, '')
|
||||
.replace(/( {2,}|\n|\t|\{|\})/g, function (whitespace) {
|
||||
return '{' + JSON.stringify(whitespace) + '}';
|
||||
});
|
||||
}
|
||||
else {
|
||||
// If there's a newline in the text, adjust the indent level
|
||||
if (text.indexOf('\n') > -1) {
|
||||
}
|
||||
}
|
||||
_this.output += text;
|
||||
};
|
||||
}
|
||||
return HTMLtoJSX;
|
||||
}());
|
||||
exports.HTMLtoJSX = HTMLtoJSX;
|
||||
;
|
||||
/**
|
||||
* Handles parsing of inline styles
|
||||
*/
|
||||
var StyleParser = (function () {
|
||||
function StyleParser() {
|
||||
var _this = this;
|
||||
this.styles = {};
|
||||
this.toJSXString = function () {
|
||||
for (var key in _this.styles) {
|
||||
if (!_this.styles.hasOwnProperty(key)) {
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
return StyleParser;
|
||||
}());
|
||||
exports.StyleParser = StyleParser;
|
|
@ -0,0 +1,288 @@
|
|||
=== tests/cases/compiler/controlFlowPropertyDeclarations.ts ===
|
||||
// Repro from ##8913
|
||||
|
||||
declare var require:any;
|
||||
>require : Symbol(require, Decl(controlFlowPropertyDeclarations.ts, 2, 11))
|
||||
|
||||
var HTMLDOMPropertyConfig = require('react/lib/HTMLDOMPropertyConfig');
|
||||
>HTMLDOMPropertyConfig : Symbol(HTMLDOMPropertyConfig, Decl(controlFlowPropertyDeclarations.ts, 4, 3))
|
||||
>require : Symbol(require, Decl(controlFlowPropertyDeclarations.ts, 2, 11))
|
||||
|
||||
// Populate property map with ReactJS's attribute and property mappings
|
||||
// TODO handle/use .Properties value eg: MUST_USE_PROPERTY is not HTML attr
|
||||
for (var propname in HTMLDOMPropertyConfig.Properties) {
|
||||
>propname : Symbol(propname, Decl(controlFlowPropertyDeclarations.ts, 8, 8))
|
||||
>HTMLDOMPropertyConfig : Symbol(HTMLDOMPropertyConfig, Decl(controlFlowPropertyDeclarations.ts, 4, 3))
|
||||
|
||||
if (!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname)) {
|
||||
>HTMLDOMPropertyConfig : Symbol(HTMLDOMPropertyConfig, Decl(controlFlowPropertyDeclarations.ts, 4, 3))
|
||||
>propname : Symbol(propname, Decl(controlFlowPropertyDeclarations.ts, 8, 8))
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
var mapFrom = HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase();
|
||||
>mapFrom : Symbol(mapFrom, Decl(controlFlowPropertyDeclarations.ts, 13, 5))
|
||||
>HTMLDOMPropertyConfig : Symbol(HTMLDOMPropertyConfig, Decl(controlFlowPropertyDeclarations.ts, 4, 3))
|
||||
>propname : Symbol(propname, Decl(controlFlowPropertyDeclarations.ts, 8, 8))
|
||||
>propname.toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --))
|
||||
>propname : Symbol(propname, Decl(controlFlowPropertyDeclarations.ts, 8, 8))
|
||||
>toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --))
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeats a string a certain number of times.
|
||||
* Also: the future is bright and consists of native string repetition:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
|
||||
*
|
||||
* @param {string} string String to repeat
|
||||
* @param {number} times Number of times to repeat string. Integer.
|
||||
* @see http://jsperf.com/string-repeater/2
|
||||
*/
|
||||
function repeatString(string, times) {
|
||||
>repeatString : Symbol(repeatString, Decl(controlFlowPropertyDeclarations.ts, 14, 1))
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 25, 22))
|
||||
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
|
||||
|
||||
if (times === 1) {
|
||||
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
|
||||
|
||||
return string;
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 25, 22))
|
||||
}
|
||||
if (times < 0) { throw new Error(); }
|
||||
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
|
||||
>Error : Symbol(Error, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
|
||||
var repeated = '';
|
||||
>repeated : Symbol(repeated, Decl(controlFlowPropertyDeclarations.ts, 30, 5))
|
||||
|
||||
while (times) {
|
||||
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
|
||||
|
||||
if (times & 1) {
|
||||
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
|
||||
|
||||
repeated += string;
|
||||
>repeated : Symbol(repeated, Decl(controlFlowPropertyDeclarations.ts, 30, 5))
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 25, 22))
|
||||
}
|
||||
if (times >>= 1) {
|
||||
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
|
||||
|
||||
string += string;
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 25, 22))
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 25, 22))
|
||||
}
|
||||
}
|
||||
return repeated;
|
||||
>repeated : Symbol(repeated, Decl(controlFlowPropertyDeclarations.ts, 30, 5))
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the string ends with the specified substring.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {boolean}
|
||||
*/
|
||||
function endsWith(haystack, needle) {
|
||||
>endsWith : Symbol(endsWith, Decl(controlFlowPropertyDeclarations.ts, 40, 1))
|
||||
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 49, 18))
|
||||
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 49, 27))
|
||||
|
||||
return haystack.slice(-needle.length) === needle;
|
||||
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 49, 18))
|
||||
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 49, 27))
|
||||
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 49, 27))
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim the specified substring off the string. If the string does not end
|
||||
* with the specified substring, this is a no-op.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {string}
|
||||
*/
|
||||
function trimEnd(haystack, needle) {
|
||||
>trimEnd : Symbol(trimEnd, Decl(controlFlowPropertyDeclarations.ts, 51, 1))
|
||||
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 61, 17))
|
||||
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 61, 26))
|
||||
|
||||
return endsWith(haystack, needle)
|
||||
>endsWith : Symbol(endsWith, Decl(controlFlowPropertyDeclarations.ts, 40, 1))
|
||||
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 61, 17))
|
||||
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 61, 26))
|
||||
|
||||
? haystack.slice(0, -needle.length)
|
||||
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 61, 17))
|
||||
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 61, 26))
|
||||
|
||||
: haystack;
|
||||
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 61, 17))
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a hyphenated string to camelCase.
|
||||
*/
|
||||
function hyphenToCamelCase(string) {
|
||||
>hyphenToCamelCase : Symbol(hyphenToCamelCase, Decl(controlFlowPropertyDeclarations.ts, 65, 1))
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 70, 27))
|
||||
|
||||
return string.replace(/-(.)/g, function(match, chr) {
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 70, 27))
|
||||
>match : Symbol(match, Decl(controlFlowPropertyDeclarations.ts, 71, 42))
|
||||
>chr : Symbol(chr, Decl(controlFlowPropertyDeclarations.ts, 71, 48))
|
||||
|
||||
return chr.toUpperCase();
|
||||
>chr : Symbol(chr, Decl(controlFlowPropertyDeclarations.ts, 71, 48))
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the specified string consists entirely of whitespace.
|
||||
*/
|
||||
function isEmpty(string) {
|
||||
>isEmpty : Symbol(isEmpty, Decl(controlFlowPropertyDeclarations.ts, 74, 1))
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 79, 17))
|
||||
|
||||
return !/[^\s]/.test(string);
|
||||
>/[^\s]/.test : Symbol(RegExp.test, Decl(lib.d.ts, --, --))
|
||||
>test : Symbol(RegExp.test, Decl(lib.d.ts, --, --))
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 79, 17))
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the CSS value can be converted from a
|
||||
* 'px' suffixed string to a numeric value
|
||||
*
|
||||
* @param {string} value CSS property value
|
||||
* @return {boolean}
|
||||
*/
|
||||
function isConvertiblePixelValue(value) {
|
||||
>isConvertiblePixelValue : Symbol(isConvertiblePixelValue, Decl(controlFlowPropertyDeclarations.ts, 81, 1))
|
||||
>value : Symbol(value, Decl(controlFlowPropertyDeclarations.ts, 90, 33))
|
||||
|
||||
return /^\d+px$/.test(value);
|
||||
>/^\d+px$/.test : Symbol(RegExp.test, Decl(lib.d.ts, --, --))
|
||||
>test : Symbol(RegExp.test, Decl(lib.d.ts, --, --))
|
||||
>value : Symbol(value, Decl(controlFlowPropertyDeclarations.ts, 90, 33))
|
||||
}
|
||||
|
||||
export class HTMLtoJSX {
|
||||
>HTMLtoJSX : Symbol(HTMLtoJSX, Decl(controlFlowPropertyDeclarations.ts, 92, 1))
|
||||
|
||||
private output: string;
|
||||
>output : Symbol(HTMLtoJSX.output, Decl(controlFlowPropertyDeclarations.ts, 94, 24))
|
||||
|
||||
private level: number;
|
||||
>level : Symbol(HTMLtoJSX.level, Decl(controlFlowPropertyDeclarations.ts, 95, 27))
|
||||
|
||||
private _inPreTag: boolean;
|
||||
>_inPreTag : Symbol(HTMLtoJSX._inPreTag, Decl(controlFlowPropertyDeclarations.ts, 96, 26))
|
||||
|
||||
|
||||
/**
|
||||
* Handles processing of the specified text node
|
||||
*
|
||||
* @param {TextNode} node
|
||||
*/
|
||||
_visitText = (node) => {
|
||||
>_visitText : Symbol(HTMLtoJSX._visitText, Decl(controlFlowPropertyDeclarations.ts, 97, 31))
|
||||
>node : Symbol(node, Decl(controlFlowPropertyDeclarations.ts, 105, 16))
|
||||
|
||||
var parentTag = node.parentNode && node.parentNode.tagName.toLowerCase();
|
||||
>parentTag : Symbol(parentTag, Decl(controlFlowPropertyDeclarations.ts, 106, 7))
|
||||
>node : Symbol(node, Decl(controlFlowPropertyDeclarations.ts, 105, 16))
|
||||
>node : Symbol(node, Decl(controlFlowPropertyDeclarations.ts, 105, 16))
|
||||
|
||||
if (parentTag === 'textarea' || parentTag === 'style') {
|
||||
>parentTag : Symbol(parentTag, Decl(controlFlowPropertyDeclarations.ts, 106, 7))
|
||||
>parentTag : Symbol(parentTag, Decl(controlFlowPropertyDeclarations.ts, 106, 7))
|
||||
|
||||
// Ignore text content of textareas and styles, as it will have already been moved
|
||||
// to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively.
|
||||
return;
|
||||
}
|
||||
|
||||
var text = ''
|
||||
>text : Symbol(text, Decl(controlFlowPropertyDeclarations.ts, 113, 7))
|
||||
|
||||
if (this._inPreTag) {
|
||||
>this._inPreTag : Symbol(HTMLtoJSX._inPreTag, Decl(controlFlowPropertyDeclarations.ts, 96, 26))
|
||||
>this : Symbol(HTMLtoJSX, Decl(controlFlowPropertyDeclarations.ts, 92, 1))
|
||||
>_inPreTag : Symbol(HTMLtoJSX._inPreTag, Decl(controlFlowPropertyDeclarations.ts, 96, 26))
|
||||
|
||||
// If this text is contained within a <pre>, we need to ensure the JSX
|
||||
// whitespace coalescing rules don't eat the whitespace. This means
|
||||
// wrapping newlines and sequences of two or more spaces in variables.
|
||||
text = text
|
||||
>text : Symbol(text, Decl(controlFlowPropertyDeclarations.ts, 113, 7))
|
||||
>text .replace(/\r/g, '') .replace : Symbol(String.replace, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>text .replace : Symbol(String.replace, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>text : Symbol(text, Decl(controlFlowPropertyDeclarations.ts, 113, 7))
|
||||
|
||||
.replace(/\r/g, '')
|
||||
>replace : Symbol(String.replace, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
|
||||
.replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) {
|
||||
>replace : Symbol(String.replace, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>whitespace : Symbol(whitespace, Decl(controlFlowPropertyDeclarations.ts, 121, 50))
|
||||
|
||||
return '{' + JSON.stringify(whitespace) + '}';
|
||||
>JSON.stringify : Symbol(JSON.stringify, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>JSON : Symbol(JSON, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>stringify : Symbol(JSON.stringify, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>whitespace : Symbol(whitespace, Decl(controlFlowPropertyDeclarations.ts, 121, 50))
|
||||
|
||||
});
|
||||
} else {
|
||||
// If there's a newline in the text, adjust the indent level
|
||||
if (text.indexOf('\n') > -1) {
|
||||
>text.indexOf : Symbol(String.indexOf, Decl(lib.d.ts, --, --))
|
||||
>text : Symbol(text, Decl(controlFlowPropertyDeclarations.ts, 113, 7))
|
||||
>indexOf : Symbol(String.indexOf, Decl(lib.d.ts, --, --))
|
||||
}
|
||||
}
|
||||
this.output += text;
|
||||
>this.output : Symbol(HTMLtoJSX.output, Decl(controlFlowPropertyDeclarations.ts, 94, 24))
|
||||
>this : Symbol(HTMLtoJSX, Decl(controlFlowPropertyDeclarations.ts, 92, 1))
|
||||
>output : Symbol(HTMLtoJSX.output, Decl(controlFlowPropertyDeclarations.ts, 94, 24))
|
||||
>text : Symbol(text, Decl(controlFlowPropertyDeclarations.ts, 113, 7))
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles parsing of inline styles
|
||||
*/
|
||||
export class StyleParser {
|
||||
>StyleParser : Symbol(StyleParser, Decl(controlFlowPropertyDeclarations.ts, 134, 2))
|
||||
|
||||
styles = {};
|
||||
>styles : Symbol(StyleParser.styles, Decl(controlFlowPropertyDeclarations.ts, 139, 26))
|
||||
|
||||
toJSXString = () => {
|
||||
>toJSXString : Symbol(StyleParser.toJSXString, Decl(controlFlowPropertyDeclarations.ts, 140, 14))
|
||||
|
||||
for (var key in this.styles) {
|
||||
>key : Symbol(key, Decl(controlFlowPropertyDeclarations.ts, 142, 12))
|
||||
>this.styles : Symbol(StyleParser.styles, Decl(controlFlowPropertyDeclarations.ts, 139, 26))
|
||||
>this : Symbol(StyleParser, Decl(controlFlowPropertyDeclarations.ts, 134, 2))
|
||||
>styles : Symbol(StyleParser.styles, Decl(controlFlowPropertyDeclarations.ts, 139, 26))
|
||||
|
||||
if (!this.styles.hasOwnProperty(key)) {
|
||||
>this.styles.hasOwnProperty : Symbol(Object.hasOwnProperty, Decl(lib.d.ts, --, --))
|
||||
>this.styles : Symbol(StyleParser.styles, Decl(controlFlowPropertyDeclarations.ts, 139, 26))
|
||||
>this : Symbol(StyleParser, Decl(controlFlowPropertyDeclarations.ts, 134, 2))
|
||||
>styles : Symbol(StyleParser.styles, Decl(controlFlowPropertyDeclarations.ts, 139, 26))
|
||||
>hasOwnProperty : Symbol(Object.hasOwnProperty, Decl(lib.d.ts, --, --))
|
||||
>key : Symbol(key, Decl(controlFlowPropertyDeclarations.ts, 142, 12))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
383
tests/baselines/reference/controlFlowPropertyDeclarations.types
Normal file
383
tests/baselines/reference/controlFlowPropertyDeclarations.types
Normal file
|
@ -0,0 +1,383 @@
|
|||
=== tests/cases/compiler/controlFlowPropertyDeclarations.ts ===
|
||||
// Repro from ##8913
|
||||
|
||||
declare var require:any;
|
||||
>require : any
|
||||
|
||||
var HTMLDOMPropertyConfig = require('react/lib/HTMLDOMPropertyConfig');
|
||||
>HTMLDOMPropertyConfig : any
|
||||
>require('react/lib/HTMLDOMPropertyConfig') : any
|
||||
>require : any
|
||||
>'react/lib/HTMLDOMPropertyConfig' : string
|
||||
|
||||
// Populate property map with ReactJS's attribute and property mappings
|
||||
// TODO handle/use .Properties value eg: MUST_USE_PROPERTY is not HTML attr
|
||||
for (var propname in HTMLDOMPropertyConfig.Properties) {
|
||||
>propname : string
|
||||
>HTMLDOMPropertyConfig.Properties : any
|
||||
>HTMLDOMPropertyConfig : any
|
||||
>Properties : any
|
||||
|
||||
if (!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname)) {
|
||||
>!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname) : boolean
|
||||
>HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname) : any
|
||||
>HTMLDOMPropertyConfig.Properties.hasOwnProperty : any
|
||||
>HTMLDOMPropertyConfig.Properties : any
|
||||
>HTMLDOMPropertyConfig : any
|
||||
>Properties : any
|
||||
>hasOwnProperty : any
|
||||
>propname : string
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
var mapFrom = HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase();
|
||||
>mapFrom : any
|
||||
>HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase() : any
|
||||
>HTMLDOMPropertyConfig.DOMAttributeNames[propname] : any
|
||||
>HTMLDOMPropertyConfig.DOMAttributeNames : any
|
||||
>HTMLDOMPropertyConfig : any
|
||||
>DOMAttributeNames : any
|
||||
>propname : string
|
||||
>propname.toLowerCase() : string
|
||||
>propname.toLowerCase : () => string
|
||||
>propname : string
|
||||
>toLowerCase : () => string
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeats a string a certain number of times.
|
||||
* Also: the future is bright and consists of native string repetition:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
|
||||
*
|
||||
* @param {string} string String to repeat
|
||||
* @param {number} times Number of times to repeat string. Integer.
|
||||
* @see http://jsperf.com/string-repeater/2
|
||||
*/
|
||||
function repeatString(string, times) {
|
||||
>repeatString : (string: any, times: any) => any
|
||||
>string : any
|
||||
>times : any
|
||||
|
||||
if (times === 1) {
|
||||
>times === 1 : boolean
|
||||
>times : any
|
||||
>1 : number
|
||||
|
||||
return string;
|
||||
>string : any
|
||||
}
|
||||
if (times < 0) { throw new Error(); }
|
||||
>times < 0 : boolean
|
||||
>times : any
|
||||
>0 : number
|
||||
>new Error() : Error
|
||||
>Error : ErrorConstructor
|
||||
|
||||
var repeated = '';
|
||||
>repeated : string
|
||||
>'' : string
|
||||
|
||||
while (times) {
|
||||
>times : any
|
||||
|
||||
if (times & 1) {
|
||||
>times & 1 : number
|
||||
>times : any
|
||||
>1 : number
|
||||
|
||||
repeated += string;
|
||||
>repeated += string : string
|
||||
>repeated : string
|
||||
>string : any
|
||||
}
|
||||
if (times >>= 1) {
|
||||
>times >>= 1 : number
|
||||
>times : any
|
||||
>1 : number
|
||||
|
||||
string += string;
|
||||
>string += string : any
|
||||
>string : any
|
||||
>string : any
|
||||
}
|
||||
}
|
||||
return repeated;
|
||||
>repeated : string
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the string ends with the specified substring.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {boolean}
|
||||
*/
|
||||
function endsWith(haystack, needle) {
|
||||
>endsWith : (haystack: any, needle: any) => boolean
|
||||
>haystack : any
|
||||
>needle : any
|
||||
|
||||
return haystack.slice(-needle.length) === needle;
|
||||
>haystack.slice(-needle.length) === needle : boolean
|
||||
>haystack.slice(-needle.length) : any
|
||||
>haystack.slice : any
|
||||
>haystack : any
|
||||
>slice : any
|
||||
>-needle.length : number
|
||||
>needle.length : any
|
||||
>needle : any
|
||||
>length : any
|
||||
>needle : any
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim the specified substring off the string. If the string does not end
|
||||
* with the specified substring, this is a no-op.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {string}
|
||||
*/
|
||||
function trimEnd(haystack, needle) {
|
||||
>trimEnd : (haystack: any, needle: any) => any
|
||||
>haystack : any
|
||||
>needle : any
|
||||
|
||||
return endsWith(haystack, needle)
|
||||
>endsWith(haystack, needle) ? haystack.slice(0, -needle.length) : haystack : any
|
||||
>endsWith(haystack, needle) : boolean
|
||||
>endsWith : (haystack: any, needle: any) => boolean
|
||||
>haystack : any
|
||||
>needle : any
|
||||
|
||||
? haystack.slice(0, -needle.length)
|
||||
>haystack.slice(0, -needle.length) : any
|
||||
>haystack.slice : any
|
||||
>haystack : any
|
||||
>slice : any
|
||||
>0 : number
|
||||
>-needle.length : number
|
||||
>needle.length : any
|
||||
>needle : any
|
||||
>length : any
|
||||
|
||||
: haystack;
|
||||
>haystack : any
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a hyphenated string to camelCase.
|
||||
*/
|
||||
function hyphenToCamelCase(string) {
|
||||
>hyphenToCamelCase : (string: any) => any
|
||||
>string : any
|
||||
|
||||
return string.replace(/-(.)/g, function(match, chr) {
|
||||
>string.replace(/-(.)/g, function(match, chr) { return chr.toUpperCase(); }) : any
|
||||
>string.replace : any
|
||||
>string : any
|
||||
>replace : any
|
||||
>/-(.)/g : RegExp
|
||||
>function(match, chr) { return chr.toUpperCase(); } : (match: any, chr: any) => any
|
||||
>match : any
|
||||
>chr : any
|
||||
|
||||
return chr.toUpperCase();
|
||||
>chr.toUpperCase() : any
|
||||
>chr.toUpperCase : any
|
||||
>chr : any
|
||||
>toUpperCase : any
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the specified string consists entirely of whitespace.
|
||||
*/
|
||||
function isEmpty(string) {
|
||||
>isEmpty : (string: any) => boolean
|
||||
>string : any
|
||||
|
||||
return !/[^\s]/.test(string);
|
||||
>!/[^\s]/.test(string) : boolean
|
||||
>/[^\s]/.test(string) : boolean
|
||||
>/[^\s]/.test : (string: string) => boolean
|
||||
>/[^\s]/ : RegExp
|
||||
>test : (string: string) => boolean
|
||||
>string : any
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the CSS value can be converted from a
|
||||
* 'px' suffixed string to a numeric value
|
||||
*
|
||||
* @param {string} value CSS property value
|
||||
* @return {boolean}
|
||||
*/
|
||||
function isConvertiblePixelValue(value) {
|
||||
>isConvertiblePixelValue : (value: any) => boolean
|
||||
>value : any
|
||||
|
||||
return /^\d+px$/.test(value);
|
||||
>/^\d+px$/.test(value) : boolean
|
||||
>/^\d+px$/.test : (string: string) => boolean
|
||||
>/^\d+px$/ : RegExp
|
||||
>test : (string: string) => boolean
|
||||
>value : any
|
||||
}
|
||||
|
||||
export class HTMLtoJSX {
|
||||
>HTMLtoJSX : HTMLtoJSX
|
||||
|
||||
private output: string;
|
||||
>output : string
|
||||
|
||||
private level: number;
|
||||
>level : number
|
||||
|
||||
private _inPreTag: boolean;
|
||||
>_inPreTag : boolean
|
||||
|
||||
|
||||
/**
|
||||
* Handles processing of the specified text node
|
||||
*
|
||||
* @param {TextNode} node
|
||||
*/
|
||||
_visitText = (node) => {
|
||||
>_visitText : (node: any) => void
|
||||
>(node) => { var parentTag = node.parentNode && node.parentNode.tagName.toLowerCase(); if (parentTag === 'textarea' || parentTag === 'style') { // Ignore text content of textareas and styles, as it will have already been moved // to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively. return; } var text = '' if (this._inPreTag) { // If this text is contained within a <pre>, we need to ensure the JSX // whitespace coalescing rules don't eat the whitespace. This means // wrapping newlines and sequences of two or more spaces in variables. text = text .replace(/\r/g, '') .replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) { return '{' + JSON.stringify(whitespace) + '}'; }); } else { // If there's a newline in the text, adjust the indent level if (text.indexOf('\n') > -1) { } } this.output += text; } : (node: any) => void
|
||||
>node : any
|
||||
|
||||
var parentTag = node.parentNode && node.parentNode.tagName.toLowerCase();
|
||||
>parentTag : any
|
||||
>node.parentNode && node.parentNode.tagName.toLowerCase() : any
|
||||
>node.parentNode : any
|
||||
>node : any
|
||||
>parentNode : any
|
||||
>node.parentNode.tagName.toLowerCase() : any
|
||||
>node.parentNode.tagName.toLowerCase : any
|
||||
>node.parentNode.tagName : any
|
||||
>node.parentNode : any
|
||||
>node : any
|
||||
>parentNode : any
|
||||
>tagName : any
|
||||
>toLowerCase : any
|
||||
|
||||
if (parentTag === 'textarea' || parentTag === 'style') {
|
||||
>parentTag === 'textarea' || parentTag === 'style' : boolean
|
||||
>parentTag === 'textarea' : boolean
|
||||
>parentTag : any
|
||||
>'textarea' : string
|
||||
>parentTag === 'style' : boolean
|
||||
>parentTag : any
|
||||
>'style' : string
|
||||
|
||||
// Ignore text content of textareas and styles, as it will have already been moved
|
||||
// to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively.
|
||||
return;
|
||||
}
|
||||
|
||||
var text = ''
|
||||
>text : string
|
||||
>'' : string
|
||||
|
||||
if (this._inPreTag) {
|
||||
>this._inPreTag : boolean
|
||||
>this : this
|
||||
>_inPreTag : boolean
|
||||
|
||||
// If this text is contained within a <pre>, we need to ensure the JSX
|
||||
// whitespace coalescing rules don't eat the whitespace. This means
|
||||
// wrapping newlines and sequences of two or more spaces in variables.
|
||||
text = text
|
||||
>text = text .replace(/\r/g, '') .replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) { return '{' + JSON.stringify(whitespace) + '}'; }) : string
|
||||
>text : string
|
||||
>text .replace(/\r/g, '') .replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) { return '{' + JSON.stringify(whitespace) + '}'; }) : string
|
||||
>text .replace(/\r/g, '') .replace : { (searchValue: string, replaceValue: string): string; (searchValue: string, replacer: (substring: string, ...args: any[]) => string): string; (searchValue: RegExp, replaceValue: string): string; (searchValue: RegExp, replacer: (substring: string, ...args: any[]) => string): string; }
|
||||
>text .replace(/\r/g, '') : string
|
||||
>text .replace : { (searchValue: string, replaceValue: string): string; (searchValue: string, replacer: (substring: string, ...args: any[]) => string): string; (searchValue: RegExp, replaceValue: string): string; (searchValue: RegExp, replacer: (substring: string, ...args: any[]) => string): string; }
|
||||
>text : string
|
||||
|
||||
.replace(/\r/g, '')
|
||||
>replace : { (searchValue: string, replaceValue: string): string; (searchValue: string, replacer: (substring: string, ...args: any[]) => string): string; (searchValue: RegExp, replaceValue: string): string; (searchValue: RegExp, replacer: (substring: string, ...args: any[]) => string): string; }
|
||||
>/\r/g : RegExp
|
||||
>'' : string
|
||||
|
||||
.replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) {
|
||||
>replace : { (searchValue: string, replaceValue: string): string; (searchValue: string, replacer: (substring: string, ...args: any[]) => string): string; (searchValue: RegExp, replaceValue: string): string; (searchValue: RegExp, replacer: (substring: string, ...args: any[]) => string): string; }
|
||||
>/( {2,}|\n|\t|\{|\})/g : RegExp
|
||||
>function(whitespace) { return '{' + JSON.stringify(whitespace) + '}'; } : (whitespace: string) => string
|
||||
>whitespace : string
|
||||
|
||||
return '{' + JSON.stringify(whitespace) + '}';
|
||||
>'{' + JSON.stringify(whitespace) + '}' : string
|
||||
>'{' + JSON.stringify(whitespace) : string
|
||||
>'{' : string
|
||||
>JSON.stringify(whitespace) : string
|
||||
>JSON.stringify : { (value: any, replacer?: (key: string, value: any) => any, space?: string | number): string; (value: any, replacer?: (number | string)[], space?: string | number): string; }
|
||||
>JSON : JSON
|
||||
>stringify : { (value: any, replacer?: (key: string, value: any) => any, space?: string | number): string; (value: any, replacer?: (number | string)[], space?: string | number): string; }
|
||||
>whitespace : string
|
||||
>'}' : string
|
||||
|
||||
});
|
||||
} else {
|
||||
// If there's a newline in the text, adjust the indent level
|
||||
if (text.indexOf('\n') > -1) {
|
||||
>text.indexOf('\n') > -1 : boolean
|
||||
>text.indexOf('\n') : number
|
||||
>text.indexOf : (searchString: string, position?: number) => number
|
||||
>text : string
|
||||
>indexOf : (searchString: string, position?: number) => number
|
||||
>'\n' : string
|
||||
>-1 : number
|
||||
>1 : number
|
||||
}
|
||||
}
|
||||
this.output += text;
|
||||
>this.output += text : string
|
||||
>this.output : string
|
||||
>this : this
|
||||
>output : string
|
||||
>text : string
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles parsing of inline styles
|
||||
*/
|
||||
export class StyleParser {
|
||||
>StyleParser : StyleParser
|
||||
|
||||
styles = {};
|
||||
>styles : {}
|
||||
>{} : {}
|
||||
|
||||
toJSXString = () => {
|
||||
>toJSXString : () => void
|
||||
>() => { for (var key in this.styles) { if (!this.styles.hasOwnProperty(key)) { } } } : () => void
|
||||
|
||||
for (var key in this.styles) {
|
||||
>key : string
|
||||
>this.styles : {}
|
||||
>this : this
|
||||
>styles : {}
|
||||
|
||||
if (!this.styles.hasOwnProperty(key)) {
|
||||
>!this.styles.hasOwnProperty(key) : boolean
|
||||
>this.styles.hasOwnProperty(key) : boolean
|
||||
>this.styles.hasOwnProperty : (v: string) => boolean
|
||||
>this.styles : {}
|
||||
>this : this
|
||||
>styles : {}
|
||||
>hasOwnProperty : (v: string) => boolean
|
||||
>key : string
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,44 @@
|
|||
//// [initializersWidened.ts]
|
||||
// these are widened to any at the point of assignment
|
||||
|
||||
var x = null;
|
||||
var y = undefined;
|
||||
var x1 = null;
|
||||
var y1 = undefined;
|
||||
var z1 = void 0;
|
||||
|
||||
// these are not widened
|
||||
|
||||
var x2: null;
|
||||
var y2: undefined;
|
||||
|
||||
var x3: null = null;
|
||||
var y3: undefined = undefined;
|
||||
var z3: undefined = void 0;
|
||||
|
||||
// widen only when all constituents of union are widening
|
||||
|
||||
var x4 = null || null;
|
||||
var y4 = undefined || undefined;
|
||||
var z4 = void 0 || void 0;
|
||||
|
||||
var x5 = null || x2;
|
||||
var y5 = undefined || y2;
|
||||
var z5 = void 0 || y2;
|
||||
|
||||
//// [initializersWidened.js]
|
||||
// these are widened to any at the point of assignment
|
||||
var x = null;
|
||||
var y = undefined;
|
||||
var x1 = null;
|
||||
var y1 = undefined;
|
||||
var z1 = void 0;
|
||||
// these are not widened
|
||||
var x2;
|
||||
var y2;
|
||||
var x3 = null;
|
||||
var y3 = undefined;
|
||||
var z3 = void 0;
|
||||
// widen only when all constituents of union are widening
|
||||
var x4 = null || null;
|
||||
var y4 = undefined || undefined;
|
||||
var z4 = void 0 || void 0;
|
||||
var x5 = null || x2;
|
||||
var y5 = undefined || y2;
|
||||
var z5 = void 0 || y2;
|
||||
|
|
|
@ -1,10 +1,57 @@
|
|||
=== tests/cases/conformance/types/typeRelationships/widenedTypes/initializersWidened.ts ===
|
||||
// these are widened to any at the point of assignment
|
||||
|
||||
var x = null;
|
||||
>x : Symbol(x, Decl(initializersWidened.ts, 2, 3))
|
||||
var x1 = null;
|
||||
>x1 : Symbol(x1, Decl(initializersWidened.ts, 2, 3))
|
||||
|
||||
var y = undefined;
|
||||
>y : Symbol(y, Decl(initializersWidened.ts, 3, 3))
|
||||
var y1 = undefined;
|
||||
>y1 : Symbol(y1, Decl(initializersWidened.ts, 3, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
var z1 = void 0;
|
||||
>z1 : Symbol(z1, Decl(initializersWidened.ts, 4, 3))
|
||||
|
||||
// these are not widened
|
||||
|
||||
var x2: null;
|
||||
>x2 : Symbol(x2, Decl(initializersWidened.ts, 8, 3))
|
||||
|
||||
var y2: undefined;
|
||||
>y2 : Symbol(y2, Decl(initializersWidened.ts, 9, 3))
|
||||
|
||||
var x3: null = null;
|
||||
>x3 : Symbol(x3, Decl(initializersWidened.ts, 11, 3))
|
||||
|
||||
var y3: undefined = undefined;
|
||||
>y3 : Symbol(y3, Decl(initializersWidened.ts, 12, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
var z3: undefined = void 0;
|
||||
>z3 : Symbol(z3, Decl(initializersWidened.ts, 13, 3))
|
||||
|
||||
// widen only when all constituents of union are widening
|
||||
|
||||
var x4 = null || null;
|
||||
>x4 : Symbol(x4, Decl(initializersWidened.ts, 17, 3))
|
||||
|
||||
var y4 = undefined || undefined;
|
||||
>y4 : Symbol(y4, Decl(initializersWidened.ts, 18, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
var z4 = void 0 || void 0;
|
||||
>z4 : Symbol(z4, Decl(initializersWidened.ts, 19, 3))
|
||||
|
||||
var x5 = null || x2;
|
||||
>x5 : Symbol(x5, Decl(initializersWidened.ts, 21, 3))
|
||||
>x2 : Symbol(x2, Decl(initializersWidened.ts, 8, 3))
|
||||
|
||||
var y5 = undefined || y2;
|
||||
>y5 : Symbol(y5, Decl(initializersWidened.ts, 22, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
>y2 : Symbol(y2, Decl(initializersWidened.ts, 9, 3))
|
||||
|
||||
var z5 = void 0 || y2;
|
||||
>z5 : Symbol(z5, Decl(initializersWidened.ts, 23, 3))
|
||||
>y2 : Symbol(y2, Decl(initializersWidened.ts, 9, 3))
|
||||
|
||||
|
|
|
@ -1,11 +1,80 @@
|
|||
=== tests/cases/conformance/types/typeRelationships/widenedTypes/initializersWidened.ts ===
|
||||
// these are widened to any at the point of assignment
|
||||
|
||||
var x = null;
|
||||
>x : any
|
||||
var x1 = null;
|
||||
>x1 : any
|
||||
>null : null
|
||||
|
||||
var y = undefined;
|
||||
>y : any
|
||||
var y1 = undefined;
|
||||
>y1 : any
|
||||
>undefined : undefined
|
||||
|
||||
var z1 = void 0;
|
||||
>z1 : any
|
||||
>void 0 : undefined
|
||||
>0 : number
|
||||
|
||||
// these are not widened
|
||||
|
||||
var x2: null;
|
||||
>x2 : null
|
||||
>null : null
|
||||
|
||||
var y2: undefined;
|
||||
>y2 : undefined
|
||||
|
||||
var x3: null = null;
|
||||
>x3 : null
|
||||
>null : null
|
||||
>null : null
|
||||
|
||||
var y3: undefined = undefined;
|
||||
>y3 : undefined
|
||||
>undefined : undefined
|
||||
|
||||
var z3: undefined = void 0;
|
||||
>z3 : undefined
|
||||
>void 0 : undefined
|
||||
>0 : number
|
||||
|
||||
// widen only when all constituents of union are widening
|
||||
|
||||
var x4 = null || null;
|
||||
>x4 : any
|
||||
>null || null : null
|
||||
>null : null
|
||||
>null : null
|
||||
|
||||
var y4 = undefined || undefined;
|
||||
>y4 : any
|
||||
>undefined || undefined : undefined
|
||||
>undefined : undefined
|
||||
>undefined : undefined
|
||||
|
||||
var z4 = void 0 || void 0;
|
||||
>z4 : any
|
||||
>void 0 || void 0 : undefined
|
||||
>void 0 : undefined
|
||||
>0 : number
|
||||
>void 0 : undefined
|
||||
>0 : number
|
||||
|
||||
var x5 = null || x2;
|
||||
>x5 : null
|
||||
>null || x2 : null
|
||||
>null : null
|
||||
>x2 : null
|
||||
|
||||
var y5 = undefined || y2;
|
||||
>y5 : undefined
|
||||
>undefined || y2 : undefined
|
||||
>undefined : undefined
|
||||
>y2 : undefined
|
||||
|
||||
var z5 = void 0 || y2;
|
||||
>z5 : undefined
|
||||
>void 0 || y2 : undefined
|
||||
>void 0 : undefined
|
||||
>0 : number
|
||||
>y2 : undefined
|
||||
|
||||
|
|
|
@ -623,7 +623,7 @@ var rj8 = a8 && undefined;
|
|||
|
||||
var rj9 = null && undefined;
|
||||
>rj9 : any
|
||||
>null && undefined : null
|
||||
>null && undefined : undefined
|
||||
>null : null
|
||||
>undefined : undefined
|
||||
|
||||
|
|
|
@ -1,29 +1,61 @@
|
|||
//// [objectLiteralWidened.ts]
|
||||
// object literal properties are widened to any
|
||||
|
||||
var x = {
|
||||
var x1 = {
|
||||
foo: null,
|
||||
bar: undefined
|
||||
}
|
||||
|
||||
var y = {
|
||||
var y1 = {
|
||||
foo: null,
|
||||
bar: {
|
||||
baz: null,
|
||||
boo: undefined
|
||||
}
|
||||
}
|
||||
|
||||
// these are not widened
|
||||
|
||||
var u: undefined = undefined;
|
||||
var n: null = null;
|
||||
|
||||
var x2 = {
|
||||
foo: n,
|
||||
bar: u
|
||||
}
|
||||
|
||||
var y2 = {
|
||||
foo: n,
|
||||
bar: {
|
||||
baz: n,
|
||||
boo: u
|
||||
}
|
||||
}
|
||||
|
||||
//// [objectLiteralWidened.js]
|
||||
// object literal properties are widened to any
|
||||
var x = {
|
||||
var x1 = {
|
||||
foo: null,
|
||||
bar: undefined
|
||||
};
|
||||
var y = {
|
||||
var y1 = {
|
||||
foo: null,
|
||||
bar: {
|
||||
baz: null,
|
||||
boo: undefined
|
||||
}
|
||||
};
|
||||
// these are not widened
|
||||
var u = undefined;
|
||||
var n = null;
|
||||
var x2 = {
|
||||
foo: n,
|
||||
bar: u
|
||||
};
|
||||
var y2 = {
|
||||
foo: n,
|
||||
bar: {
|
||||
baz: n,
|
||||
boo: u
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
=== tests/cases/conformance/types/typeRelationships/widenedTypes/objectLiteralWidened.ts ===
|
||||
// object literal properties are widened to any
|
||||
|
||||
var x = {
|
||||
>x : Symbol(x, Decl(objectLiteralWidened.ts, 2, 3))
|
||||
var x1 = {
|
||||
>x1 : Symbol(x1, Decl(objectLiteralWidened.ts, 2, 3))
|
||||
|
||||
foo: null,
|
||||
>foo : Symbol(foo, Decl(objectLiteralWidened.ts, 2, 9))
|
||||
>foo : Symbol(foo, Decl(objectLiteralWidened.ts, 2, 10))
|
||||
|
||||
bar: undefined
|
||||
>bar : Symbol(bar, Decl(objectLiteralWidened.ts, 3, 14))
|
||||
>undefined : Symbol(undefined)
|
||||
}
|
||||
|
||||
var y = {
|
||||
>y : Symbol(y, Decl(objectLiteralWidened.ts, 7, 3))
|
||||
var y1 = {
|
||||
>y1 : Symbol(y1, Decl(objectLiteralWidened.ts, 7, 3))
|
||||
|
||||
foo: null,
|
||||
>foo : Symbol(foo, Decl(objectLiteralWidened.ts, 7, 9))
|
||||
>foo : Symbol(foo, Decl(objectLiteralWidened.ts, 7, 10))
|
||||
|
||||
bar: {
|
||||
>bar : Symbol(bar, Decl(objectLiteralWidened.ts, 8, 14))
|
||||
|
@ -29,3 +29,44 @@ var y = {
|
|||
>undefined : Symbol(undefined)
|
||||
}
|
||||
}
|
||||
|
||||
// these are not widened
|
||||
|
||||
var u: undefined = undefined;
|
||||
>u : Symbol(u, Decl(objectLiteralWidened.ts, 17, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
var n: null = null;
|
||||
>n : Symbol(n, Decl(objectLiteralWidened.ts, 18, 3))
|
||||
|
||||
var x2 = {
|
||||
>x2 : Symbol(x2, Decl(objectLiteralWidened.ts, 20, 3))
|
||||
|
||||
foo: n,
|
||||
>foo : Symbol(foo, Decl(objectLiteralWidened.ts, 20, 10))
|
||||
>n : Symbol(n, Decl(objectLiteralWidened.ts, 18, 3))
|
||||
|
||||
bar: u
|
||||
>bar : Symbol(bar, Decl(objectLiteralWidened.ts, 21, 11))
|
||||
>u : Symbol(u, Decl(objectLiteralWidened.ts, 17, 3))
|
||||
}
|
||||
|
||||
var y2 = {
|
||||
>y2 : Symbol(y2, Decl(objectLiteralWidened.ts, 25, 3))
|
||||
|
||||
foo: n,
|
||||
>foo : Symbol(foo, Decl(objectLiteralWidened.ts, 25, 10))
|
||||
>n : Symbol(n, Decl(objectLiteralWidened.ts, 18, 3))
|
||||
|
||||
bar: {
|
||||
>bar : Symbol(bar, Decl(objectLiteralWidened.ts, 26, 11))
|
||||
|
||||
baz: n,
|
||||
>baz : Symbol(baz, Decl(objectLiteralWidened.ts, 27, 10))
|
||||
>n : Symbol(n, Decl(objectLiteralWidened.ts, 18, 3))
|
||||
|
||||
boo: u
|
||||
>boo : Symbol(boo, Decl(objectLiteralWidened.ts, 28, 15))
|
||||
>u : Symbol(u, Decl(objectLiteralWidened.ts, 17, 3))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
=== tests/cases/conformance/types/typeRelationships/widenedTypes/objectLiteralWidened.ts ===
|
||||
// object literal properties are widened to any
|
||||
|
||||
var x = {
|
||||
>x : { foo: any; bar: any; }
|
||||
var x1 = {
|
||||
>x1 : { foo: any; bar: any; }
|
||||
>{ foo: null, bar: undefined} : { foo: null; bar: undefined; }
|
||||
|
||||
foo: null,
|
||||
|
@ -14,8 +14,8 @@ var x = {
|
|||
>undefined : undefined
|
||||
}
|
||||
|
||||
var y = {
|
||||
>y : { foo: any; bar: { baz: any; boo: any; }; }
|
||||
var y1 = {
|
||||
>y1 : { foo: any; bar: { baz: any; boo: any; }; }
|
||||
>{ foo: null, bar: { baz: null, boo: undefined }} : { foo: null; bar: { baz: null; boo: undefined; }; }
|
||||
|
||||
foo: null,
|
||||
|
@ -35,3 +35,49 @@ var y = {
|
|||
>undefined : undefined
|
||||
}
|
||||
}
|
||||
|
||||
// these are not widened
|
||||
|
||||
var u: undefined = undefined;
|
||||
>u : undefined
|
||||
>undefined : undefined
|
||||
|
||||
var n: null = null;
|
||||
>n : null
|
||||
>null : null
|
||||
>null : null
|
||||
|
||||
var x2 = {
|
||||
>x2 : { foo: null; bar: undefined; }
|
||||
>{ foo: n, bar: u} : { foo: null; bar: undefined; }
|
||||
|
||||
foo: n,
|
||||
>foo : null
|
||||
>n : null
|
||||
|
||||
bar: u
|
||||
>bar : undefined
|
||||
>u : undefined
|
||||
}
|
||||
|
||||
var y2 = {
|
||||
>y2 : { foo: null; bar: { baz: null; boo: undefined; }; }
|
||||
>{ foo: n, bar: { baz: n, boo: u }} : { foo: null; bar: { baz: null; boo: undefined; }; }
|
||||
|
||||
foo: n,
|
||||
>foo : null
|
||||
>n : null
|
||||
|
||||
bar: {
|
||||
>bar : { baz: null; boo: undefined; }
|
||||
>{ baz: n, boo: u } : { baz: null; boo: undefined; }
|
||||
|
||||
baz: n,
|
||||
>baz : null
|
||||
>n : null
|
||||
|
||||
boo: u
|
||||
>boo : undefined
|
||||
>u : undefined
|
||||
}
|
||||
}
|
||||
|
|
31
tests/baselines/reference/strictNullChecksNoWidening.js
Normal file
31
tests/baselines/reference/strictNullChecksNoWidening.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
//// [strictNullChecksNoWidening.ts]
|
||||
|
||||
var a1 = null;
|
||||
var a2 = undefined;
|
||||
var a3 = void 0;
|
||||
|
||||
var b1 = [];
|
||||
var b2 = [,];
|
||||
var b3 = [undefined];
|
||||
var b4 = [[], []];
|
||||
var b5 = [[], [,]];
|
||||
|
||||
declare function f<T>(x: T): T;
|
||||
|
||||
var c1 = f(null);
|
||||
var c2 = f(undefined);
|
||||
var c3 = f([]);
|
||||
|
||||
|
||||
//// [strictNullChecksNoWidening.js]
|
||||
var a1 = null;
|
||||
var a2 = undefined;
|
||||
var a3 = void 0;
|
||||
var b1 = [];
|
||||
var b2 = [,];
|
||||
var b3 = [undefined];
|
||||
var b4 = [[], []];
|
||||
var b5 = [[], [,]];
|
||||
var c1 = f(null);
|
||||
var c2 = f(undefined);
|
||||
var c3 = f([]);
|
48
tests/baselines/reference/strictNullChecksNoWidening.symbols
Normal file
48
tests/baselines/reference/strictNullChecksNoWidening.symbols
Normal file
|
@ -0,0 +1,48 @@
|
|||
=== tests/cases/conformance/types/typeRelationships/widenedTypes/strictNullChecksNoWidening.ts ===
|
||||
|
||||
var a1 = null;
|
||||
>a1 : Symbol(a1, Decl(strictNullChecksNoWidening.ts, 1, 3))
|
||||
|
||||
var a2 = undefined;
|
||||
>a2 : Symbol(a2, Decl(strictNullChecksNoWidening.ts, 2, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
var a3 = void 0;
|
||||
>a3 : Symbol(a3, Decl(strictNullChecksNoWidening.ts, 3, 3))
|
||||
|
||||
var b1 = [];
|
||||
>b1 : Symbol(b1, Decl(strictNullChecksNoWidening.ts, 5, 3))
|
||||
|
||||
var b2 = [,];
|
||||
>b2 : Symbol(b2, Decl(strictNullChecksNoWidening.ts, 6, 3))
|
||||
|
||||
var b3 = [undefined];
|
||||
>b3 : Symbol(b3, Decl(strictNullChecksNoWidening.ts, 7, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
var b4 = [[], []];
|
||||
>b4 : Symbol(b4, Decl(strictNullChecksNoWidening.ts, 8, 3))
|
||||
|
||||
var b5 = [[], [,]];
|
||||
>b5 : Symbol(b5, Decl(strictNullChecksNoWidening.ts, 9, 3))
|
||||
|
||||
declare function f<T>(x: T): T;
|
||||
>f : Symbol(f, Decl(strictNullChecksNoWidening.ts, 9, 19))
|
||||
>T : Symbol(T, Decl(strictNullChecksNoWidening.ts, 11, 19))
|
||||
>x : Symbol(x, Decl(strictNullChecksNoWidening.ts, 11, 22))
|
||||
>T : Symbol(T, Decl(strictNullChecksNoWidening.ts, 11, 19))
|
||||
>T : Symbol(T, Decl(strictNullChecksNoWidening.ts, 11, 19))
|
||||
|
||||
var c1 = f(null);
|
||||
>c1 : Symbol(c1, Decl(strictNullChecksNoWidening.ts, 13, 3))
|
||||
>f : Symbol(f, Decl(strictNullChecksNoWidening.ts, 9, 19))
|
||||
|
||||
var c2 = f(undefined);
|
||||
>c2 : Symbol(c2, Decl(strictNullChecksNoWidening.ts, 14, 3))
|
||||
>f : Symbol(f, Decl(strictNullChecksNoWidening.ts, 9, 19))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
var c3 = f([]);
|
||||
>c3 : Symbol(c3, Decl(strictNullChecksNoWidening.ts, 15, 3))
|
||||
>f : Symbol(f, Decl(strictNullChecksNoWidening.ts, 9, 19))
|
||||
|
67
tests/baselines/reference/strictNullChecksNoWidening.types
Normal file
67
tests/baselines/reference/strictNullChecksNoWidening.types
Normal file
|
@ -0,0 +1,67 @@
|
|||
=== tests/cases/conformance/types/typeRelationships/widenedTypes/strictNullChecksNoWidening.ts ===
|
||||
|
||||
var a1 = null;
|
||||
>a1 : null
|
||||
>null : null
|
||||
|
||||
var a2 = undefined;
|
||||
>a2 : undefined
|
||||
>undefined : undefined
|
||||
|
||||
var a3 = void 0;
|
||||
>a3 : undefined
|
||||
>void 0 : undefined
|
||||
>0 : number
|
||||
|
||||
var b1 = [];
|
||||
>b1 : never[]
|
||||
>[] : never[]
|
||||
|
||||
var b2 = [,];
|
||||
>b2 : undefined[]
|
||||
>[,] : undefined[]
|
||||
> : undefined
|
||||
|
||||
var b3 = [undefined];
|
||||
>b3 : undefined[]
|
||||
>[undefined] : undefined[]
|
||||
>undefined : undefined
|
||||
|
||||
var b4 = [[], []];
|
||||
>b4 : never[][]
|
||||
>[[], []] : never[][]
|
||||
>[] : never[]
|
||||
>[] : never[]
|
||||
|
||||
var b5 = [[], [,]];
|
||||
>b5 : undefined[][]
|
||||
>[[], [,]] : undefined[][]
|
||||
>[] : never[]
|
||||
>[,] : undefined[]
|
||||
> : undefined
|
||||
|
||||
declare function f<T>(x: T): T;
|
||||
>f : <T>(x: T) => T
|
||||
>T : T
|
||||
>x : T
|
||||
>T : T
|
||||
>T : T
|
||||
|
||||
var c1 = f(null);
|
||||
>c1 : null
|
||||
>f(null) : null
|
||||
>f : <T>(x: T) => T
|
||||
>null : null
|
||||
|
||||
var c2 = f(undefined);
|
||||
>c2 : undefined
|
||||
>f(undefined) : undefined
|
||||
>f : <T>(x: T) => T
|
||||
>undefined : undefined
|
||||
|
||||
var c3 = f([]);
|
||||
>c3 : never[]
|
||||
>f([]) : never[]
|
||||
>f : <T>(x: T) => T
|
||||
>[] : never[]
|
||||
|
148
tests/cases/compiler/controlFlowPropertyDeclarations.ts
Normal file
148
tests/cases/compiler/controlFlowPropertyDeclarations.ts
Normal file
|
@ -0,0 +1,148 @@
|
|||
// Repro from ##8913
|
||||
|
||||
declare var require:any;
|
||||
|
||||
var HTMLDOMPropertyConfig = require('react/lib/HTMLDOMPropertyConfig');
|
||||
|
||||
// Populate property map with ReactJS's attribute and property mappings
|
||||
// TODO handle/use .Properties value eg: MUST_USE_PROPERTY is not HTML attr
|
||||
for (var propname in HTMLDOMPropertyConfig.Properties) {
|
||||
if (!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var mapFrom = HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeats a string a certain number of times.
|
||||
* Also: the future is bright and consists of native string repetition:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
|
||||
*
|
||||
* @param {string} string String to repeat
|
||||
* @param {number} times Number of times to repeat string. Integer.
|
||||
* @see http://jsperf.com/string-repeater/2
|
||||
*/
|
||||
function repeatString(string, times) {
|
||||
if (times === 1) {
|
||||
return string;
|
||||
}
|
||||
if (times < 0) { throw new Error(); }
|
||||
var repeated = '';
|
||||
while (times) {
|
||||
if (times & 1) {
|
||||
repeated += string;
|
||||
}
|
||||
if (times >>= 1) {
|
||||
string += string;
|
||||
}
|
||||
}
|
||||
return repeated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the string ends with the specified substring.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {boolean}
|
||||
*/
|
||||
function endsWith(haystack, needle) {
|
||||
return haystack.slice(-needle.length) === needle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim the specified substring off the string. If the string does not end
|
||||
* with the specified substring, this is a no-op.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {string}
|
||||
*/
|
||||
function trimEnd(haystack, needle) {
|
||||
return endsWith(haystack, needle)
|
||||
? haystack.slice(0, -needle.length)
|
||||
: haystack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a hyphenated string to camelCase.
|
||||
*/
|
||||
function hyphenToCamelCase(string) {
|
||||
return string.replace(/-(.)/g, function(match, chr) {
|
||||
return chr.toUpperCase();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the specified string consists entirely of whitespace.
|
||||
*/
|
||||
function isEmpty(string) {
|
||||
return !/[^\s]/.test(string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the CSS value can be converted from a
|
||||
* 'px' suffixed string to a numeric value
|
||||
*
|
||||
* @param {string} value CSS property value
|
||||
* @return {boolean}
|
||||
*/
|
||||
function isConvertiblePixelValue(value) {
|
||||
return /^\d+px$/.test(value);
|
||||
}
|
||||
|
||||
export class HTMLtoJSX {
|
||||
private output: string;
|
||||
private level: number;
|
||||
private _inPreTag: boolean;
|
||||
|
||||
|
||||
/**
|
||||
* Handles processing of the specified text node
|
||||
*
|
||||
* @param {TextNode} node
|
||||
*/
|
||||
_visitText = (node) => {
|
||||
var parentTag = node.parentNode && node.parentNode.tagName.toLowerCase();
|
||||
if (parentTag === 'textarea' || parentTag === 'style') {
|
||||
// Ignore text content of textareas and styles, as it will have already been moved
|
||||
// to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively.
|
||||
return;
|
||||
}
|
||||
|
||||
var text = ''
|
||||
|
||||
if (this._inPreTag) {
|
||||
// If this text is contained within a <pre>, we need to ensure the JSX
|
||||
// whitespace coalescing rules don't eat the whitespace. This means
|
||||
// wrapping newlines and sequences of two or more spaces in variables.
|
||||
text = text
|
||||
.replace(/\r/g, '')
|
||||
.replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) {
|
||||
return '{' + JSON.stringify(whitespace) + '}';
|
||||
});
|
||||
} else {
|
||||
// If there's a newline in the text, adjust the indent level
|
||||
if (text.indexOf('\n') > -1) {
|
||||
}
|
||||
}
|
||||
this.output += text;
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles parsing of inline styles
|
||||
*/
|
||||
export class StyleParser {
|
||||
styles = {};
|
||||
toJSXString = () => {
|
||||
for (var key in this.styles) {
|
||||
if (!this.styles.hasOwnProperty(key)) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
// array literals are widened upon assignment according to their element type
|
||||
|
||||
var a = []; // any[]
|
||||
var a = [,,];
|
||||
|
||||
var a = [null, null];
|
||||
var a = [undefined, undefined];
|
||||
|
@ -11,3 +12,11 @@ var b = [[undefined, undefined]];
|
|||
|
||||
var c = [[[]]]; // any[][][]
|
||||
var c = [[[null]],[undefined]]
|
||||
|
||||
// no widening when one or more elements are non-widening
|
||||
|
||||
var x: undefined = undefined;
|
||||
|
||||
var d = [x];
|
||||
var d = [, x];
|
||||
var d = [undefined, x];
|
||||
|
|
|
@ -1,4 +1,24 @@
|
|||
// these are widened to any at the point of assignment
|
||||
|
||||
var x = null;
|
||||
var y = undefined;
|
||||
var x1 = null;
|
||||
var y1 = undefined;
|
||||
var z1 = void 0;
|
||||
|
||||
// these are not widened
|
||||
|
||||
var x2: null;
|
||||
var y2: undefined;
|
||||
|
||||
var x3: null = null;
|
||||
var y3: undefined = undefined;
|
||||
var z3: undefined = void 0;
|
||||
|
||||
// widen only when all constituents of union are widening
|
||||
|
||||
var x4 = null || null;
|
||||
var y4 = undefined || undefined;
|
||||
var z4 = void 0 || void 0;
|
||||
|
||||
var x5 = null || x2;
|
||||
var y5 = undefined || y2;
|
||||
var z5 = void 0 || y2;
|
|
@ -1,14 +1,32 @@
|
|||
// object literal properties are widened to any
|
||||
|
||||
var x = {
|
||||
var x1 = {
|
||||
foo: null,
|
||||
bar: undefined
|
||||
}
|
||||
|
||||
var y = {
|
||||
var y1 = {
|
||||
foo: null,
|
||||
bar: {
|
||||
baz: null,
|
||||
boo: undefined
|
||||
}
|
||||
}
|
||||
|
||||
// these are not widened
|
||||
|
||||
var u: undefined = undefined;
|
||||
var n: null = null;
|
||||
|
||||
var x2 = {
|
||||
foo: n,
|
||||
bar: u
|
||||
}
|
||||
|
||||
var y2 = {
|
||||
foo: n,
|
||||
bar: {
|
||||
baz: n,
|
||||
boo: u
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// @strictNullChecks: true
|
||||
|
||||
var a1 = null;
|
||||
var a2 = undefined;
|
||||
var a3 = void 0;
|
||||
|
||||
var b1 = [];
|
||||
var b2 = [,];
|
||||
var b3 = [undefined];
|
||||
var b4 = [[], []];
|
||||
var b5 = [[], [,]];
|
||||
|
||||
declare function f<T>(x: T): T;
|
||||
|
||||
var c1 = f(null);
|
||||
var c2 = f(undefined);
|
||||
var c3 = f([]);
|
|
@ -0,0 +1,22 @@
|
|||
/// <reference path="fourslash.ts"/>
|
||||
|
||||
/////** @template T */
|
||||
////function ident<T>: T {
|
||||
////}
|
||||
|
||||
var c = classification;
|
||||
verify.syntacticClassificationsAre(
|
||||
c.comment("/** "),
|
||||
c.punctuation("@"),
|
||||
c.docCommentTagName("template"),
|
||||
c.typeParameterName("T"),
|
||||
c.comment(" */"),
|
||||
c.keyword("function"),
|
||||
c.identifier("ident"),
|
||||
c.punctuation("<"),
|
||||
c.typeParameterName("T"),
|
||||
c.punctuation(">"),
|
||||
c.punctuation(":"),
|
||||
c.identifier("T"),
|
||||
c.punctuation("{"),
|
||||
c.punctuation("}"));
|
297
tests/cases/unittests/tsserverProjectSystem.ts
Normal file
297
tests/cases/unittests/tsserverProjectSystem.ts
Normal file
|
@ -0,0 +1,297 @@
|
|||
/// <reference path="..\..\..\src\harness\harness.ts" />
|
||||
|
||||
namespace ts {
|
||||
function notImplemented(): any {
|
||||
throw new Error("Not yet implemented");
|
||||
}
|
||||
|
||||
const nullLogger: server.Logger = {
|
||||
close: () => void 0,
|
||||
isVerbose: () => void 0,
|
||||
loggingEnabled: () => false,
|
||||
perftrc: () => void 0,
|
||||
info: () => void 0,
|
||||
startGroup: () => void 0,
|
||||
endGroup: () => void 0,
|
||||
msg: () => void 0
|
||||
};
|
||||
|
||||
const { content: libFileContent } = Harness.getDefaultLibraryFile(Harness.IO);
|
||||
|
||||
function getExecutingFilePathFromLibFile(libFile: FileOrFolder): string {
|
||||
return combinePaths(getDirectoryPath(libFile.path), "tsc.js");
|
||||
}
|
||||
|
||||
interface FileOrFolder {
|
||||
path: string;
|
||||
content?: string;
|
||||
}
|
||||
|
||||
interface FSEntry {
|
||||
path: Path;
|
||||
fullPath: string;
|
||||
}
|
||||
|
||||
interface File extends FSEntry {
|
||||
content: string;
|
||||
}
|
||||
|
||||
interface Folder extends FSEntry {
|
||||
entries: FSEntry[];
|
||||
}
|
||||
|
||||
function isFolder(s: FSEntry): s is Folder {
|
||||
return isArray((<Folder>s).entries);
|
||||
}
|
||||
|
||||
function isFile(s: FSEntry): s is File {
|
||||
return typeof (<File>s).content === "string";
|
||||
}
|
||||
|
||||
function addFolder(fullPath: string, toPath: (s: string) => Path, fs: FileMap<FSEntry>): Folder {
|
||||
const path = toPath(fullPath);
|
||||
if (fs.contains(path)) {
|
||||
Debug.assert(isFolder(fs.get(path)));
|
||||
return (<Folder>fs.get(path));
|
||||
}
|
||||
|
||||
const entry: Folder = { path, entries: [], fullPath };
|
||||
fs.set(path, entry);
|
||||
|
||||
const baseFullPath = getDirectoryPath(fullPath);
|
||||
if (fullPath !== baseFullPath) {
|
||||
addFolder(baseFullPath, toPath, fs).entries.push(entry);
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
function sizeOfMap(map: Map<any>): number {
|
||||
let n = 0;
|
||||
for (const name in map) {
|
||||
if (hasProperty(map, name)) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
function checkMapKeys(caption: string, map: Map<any>, expectedKeys: string[]) {
|
||||
assert.equal(sizeOfMap(map), expectedKeys.length, `${caption}: incorrect size of map`);
|
||||
for (const name of expectedKeys) {
|
||||
assert.isTrue(hasProperty(map, name), `${caption} is expected to contain ${name}, actual keys: ${getKeys(map)}`);
|
||||
}
|
||||
}
|
||||
|
||||
function checkFileNames(caption: string, actualFileNames: string[], expectedFileNames: string[]) {
|
||||
assert.equal(actualFileNames.length, expectedFileNames.length, `${caption}: incorrect actual number of files, expected ${JSON.stringify(expectedFileNames)}, got ${actualFileNames}`);
|
||||
for (const f of expectedFileNames) {
|
||||
assert.isTrue(contains(actualFileNames, f), `${caption}: expected to find ${f} in ${JSON.stringify(actualFileNames)}`);
|
||||
}
|
||||
}
|
||||
|
||||
function readDirectory(folder: FSEntry, ext: string, excludes: Path[], result: string[]): void {
|
||||
if (!folder || !isFolder(folder) || contains(excludes, folder.path)) {
|
||||
return;
|
||||
}
|
||||
for (const entry of folder.entries) {
|
||||
if (contains(excludes, entry.path)) {
|
||||
continue;
|
||||
}
|
||||
if (isFolder(entry)) {
|
||||
readDirectory(entry, ext, excludes, result);
|
||||
}
|
||||
else if (fileExtensionIs(entry.path, ext)) {
|
||||
result.push(entry.fullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TestServerHost implements server.ServerHost {
|
||||
args: string[] = [];
|
||||
newLine: "\n";
|
||||
|
||||
private fs: ts.FileMap<FSEntry>;
|
||||
private getCanonicalFileName: (s: string) => string;
|
||||
private toPath: (f: string) => Path;
|
||||
readonly watchedDirectories: Map<{ cb: DirectoryWatcherCallback, recursive: boolean }[]> = {};
|
||||
readonly watchedFiles: Map<FileWatcherCallback[]> = {};
|
||||
|
||||
constructor(public useCaseSensitiveFileNames: boolean, private executingFilePath: string, private currentDirectory: string, fileOrFolderList: FileOrFolder[]) {
|
||||
this.getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
|
||||
this.toPath = s => toPath(s, currentDirectory, this.getCanonicalFileName);
|
||||
|
||||
this.reloadFS(fileOrFolderList);
|
||||
}
|
||||
|
||||
reloadFS(filesOrFolders: FileOrFolder[]) {
|
||||
this.fs = createFileMap<FSEntry>();
|
||||
for (const fileOrFolder of filesOrFolders) {
|
||||
const path = this.toPath(fileOrFolder.path);
|
||||
const fullPath = getNormalizedAbsolutePath(fileOrFolder.path, this.currentDirectory);
|
||||
if (typeof fileOrFolder.content === "string") {
|
||||
const entry = { path, content: fileOrFolder.content, fullPath };
|
||||
this.fs.set(path, entry);
|
||||
addFolder(getDirectoryPath(fullPath), this.toPath, this.fs).entries.push(entry);
|
||||
}
|
||||
else {
|
||||
addFolder(fullPath, this.toPath, this.fs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileExists(s: string) {
|
||||
const path = this.toPath(s);
|
||||
return this.fs.contains(path) && isFile(this.fs.get(path));
|
||||
};
|
||||
|
||||
directoryExists(s: string) {
|
||||
const path = this.toPath(s);
|
||||
return this.fs.contains(path) && isFolder(this.fs.get(path));
|
||||
}
|
||||
|
||||
getDirectories(s: string) {
|
||||
const path = this.toPath(s);
|
||||
if (!this.fs.contains(path)) {
|
||||
return [];
|
||||
}
|
||||
else {
|
||||
const entry = this.fs.get(path);
|
||||
return isFolder(entry) ? map(entry.entries, x => getBaseFileName(x.fullPath)) : [];
|
||||
}
|
||||
}
|
||||
|
||||
readDirectory(path: string, ext: string, excludes: string[]): string[] {
|
||||
const result: string[] = [];
|
||||
readDirectory(this.fs.get(this.toPath(path)), ext, map(excludes, e => toPath(e, path, this.getCanonicalFileName)), result);
|
||||
return result;
|
||||
}
|
||||
|
||||
watchDirectory(directoryName: string, callback: DirectoryWatcherCallback, recursive: boolean): DirectoryWatcher {
|
||||
const path = this.toPath(directoryName);
|
||||
const callbacks = lookUp(this.watchedDirectories, path) || (this.watchedDirectories[path] = []);
|
||||
callbacks.push({ cb: callback, recursive });
|
||||
return {
|
||||
referenceCount: 0,
|
||||
directoryName,
|
||||
close: () => {
|
||||
for (let i = 0; i < callbacks.length; i++) {
|
||||
if (callbacks[i].cb === callback) {
|
||||
callbacks.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!callbacks.length) {
|
||||
delete this.watchedDirectories[path];
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
watchFile(fileName: string, callback: FileWatcherCallback) {
|
||||
const path = this.toPath(fileName);
|
||||
const callbacks = lookUp(this.watchedFiles, path) || (this.watchedFiles[path] = []);
|
||||
callbacks.push(callback);
|
||||
return {
|
||||
close: () => {
|
||||
const i = callbacks.indexOf(callback);
|
||||
callbacks.splice(i, 1);
|
||||
if (!callbacks.length) {
|
||||
delete this.watchedFiles[path];
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// TOOD: record and invoke callbacks to simulate timer events
|
||||
readonly setTimeout = (callback: (...args: any[]) => void, ms: number, ...args: any[]): any => void 0;
|
||||
readonly clearTimeout = (timeoutId: any): void => void 0;
|
||||
readonly readFile = (s: string) => (<File>this.fs.get(this.toPath(s))).content;
|
||||
readonly resolvePath = (s: string) => s;
|
||||
readonly getExecutingFilePath = () => this.executingFilePath;
|
||||
readonly getCurrentDirectory = () => this.currentDirectory;
|
||||
readonly writeFile = (path: string, content: string) => notImplemented();
|
||||
readonly write = (s: string) => notImplemented();
|
||||
readonly createDirectory = (s: string) => notImplemented();
|
||||
readonly exit = () => notImplemented();
|
||||
readonly getEnvironmentVariable = (s: string) => notImplemented();
|
||||
readonly tryEnableSourceMapsForHost = () => notImplemented();
|
||||
|
||||
}
|
||||
|
||||
describe("tsserver project system:", () => {
|
||||
it("create inferred project", () => {
|
||||
const appFile: FileOrFolder = {
|
||||
path: "/a/b/c/app.ts",
|
||||
content: `
|
||||
import {f} from "./module"
|
||||
console.log(f)
|
||||
`
|
||||
};
|
||||
const libFile: FileOrFolder = {
|
||||
path: "/a/lib/lib.d.ts",
|
||||
content: libFileContent
|
||||
};
|
||||
const moduleFile: FileOrFolder = {
|
||||
path: "/a/b/c/module.d.ts",
|
||||
content: `export let x: number`
|
||||
};
|
||||
const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", [appFile, moduleFile, libFile]);
|
||||
const projectService = new server.ProjectService(host, nullLogger);
|
||||
const { configFileName } = projectService.openClientFile(appFile.path);
|
||||
|
||||
assert(!configFileName, `should not find config, got: '${configFileName}`);
|
||||
assert.equal(projectService.inferredProjects.length, 1, "expected one inferred project");
|
||||
assert.equal(projectService.configuredProjects.length, 0, "expected no configured project");
|
||||
|
||||
const project = projectService.inferredProjects[0];
|
||||
|
||||
checkFileNames("inferred project", project.getFileNames(), [appFile.path, libFile.path, moduleFile.path]);
|
||||
checkMapKeys("watchedDirectories", host.watchedDirectories, ["/a/b/c", "/a/b", "/a"]);
|
||||
});
|
||||
|
||||
it("create configured project without file list", () => {
|
||||
const configFile: FileOrFolder = {
|
||||
path: "/a/b/tsconfig.json",
|
||||
content: `
|
||||
{
|
||||
"compilerOptions": {},
|
||||
"exclude": [
|
||||
"e"
|
||||
]
|
||||
}`
|
||||
};
|
||||
const libFile: FileOrFolder = {
|
||||
path: "/a/lib/lib.d.ts",
|
||||
content: libFileContent
|
||||
};
|
||||
const file1: FileOrFolder = {
|
||||
path: "/a/b/c/f1.ts",
|
||||
content: "let x = 1"
|
||||
};
|
||||
const file2: FileOrFolder = {
|
||||
path: "/a/b/d/f2.ts",
|
||||
content: "let y = 1"
|
||||
};
|
||||
const file3: FileOrFolder = {
|
||||
path: "/a/b/e/f3.ts",
|
||||
content: "let z = 1"
|
||||
};
|
||||
const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", [ configFile, libFile, file1, file2, file3 ]);
|
||||
const projectService = new server.ProjectService(host, nullLogger);
|
||||
const { configFileName, configFileErrors } = projectService.openClientFile(file1.path);
|
||||
|
||||
assert(configFileName, "should find config file");
|
||||
assert.isTrue(!configFileErrors, `expect no errors in config file, got ${JSON.stringify(configFileErrors)}`);
|
||||
assert.equal(projectService.inferredProjects.length, 0, "expected no inferred project");
|
||||
assert.equal(projectService.configuredProjects.length, 1, "expected one configured project");
|
||||
|
||||
const project = projectService.configuredProjects[0];
|
||||
checkFileNames("configuredProjects project, actualFileNames", project.getFileNames(), [file1.path, libFile.path, file2.path]);
|
||||
checkFileNames("configuredProjects project, rootFileNames", project.getRootFiles(), [file1.path, file2.path]);
|
||||
|
||||
checkMapKeys("watchedFiles", host.watchedFiles, [configFile.path, file2.path, libFile.path]); // watching all files except one that was open
|
||||
checkMapKeys("watchedDirectories", host.watchedDirectories, [getDirectoryPath(configFile.path)]);
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Reference in a new issue