mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-15 11:35:42 -06:00
Merge branch 'master' into ownJsonParsing
This commit is contained in:
commit
8d771ca044
@ -129,6 +129,7 @@ var harnessSources = harnessCoreSources.concat([
|
||||
"initializeTSConfig.ts",
|
||||
"printer.ts",
|
||||
"textChanges.ts",
|
||||
"telemetry.ts",
|
||||
"transform.ts",
|
||||
"customTransforms.ts",
|
||||
].map(function (f) {
|
||||
@ -1079,7 +1080,7 @@ var loggedIOJsPath = builtLocalDirectory + 'loggedIO.js';
|
||||
file(loggedIOJsPath, [builtLocalDirectory, loggedIOpath], function () {
|
||||
var temp = builtLocalDirectory + 'temp';
|
||||
jake.mkdirP(temp);
|
||||
var options = "--types --outdir " + temp + ' ' + loggedIOpath;
|
||||
var options = "--target es5 --lib es6 --types --outdir " + temp + ' ' + loggedIOpath;
|
||||
var cmd = host + " " + LKGDirectory + compilerFilename + " " + options + " ";
|
||||
console.log(cmd + "\n");
|
||||
var ex = jake.createExec([cmd]);
|
||||
@ -1093,7 +1094,7 @@ file(loggedIOJsPath, [builtLocalDirectory, loggedIOpath], function () {
|
||||
|
||||
var instrumenterPath = harnessDirectory + 'instrumenter.ts';
|
||||
var instrumenterJsPath = builtLocalDirectory + 'instrumenter.js';
|
||||
compileFile(instrumenterJsPath, [instrumenterPath], [tscFile, instrumenterPath].concat(libraryTargets), [], /*useBuiltCompiler*/ true);
|
||||
compileFile(instrumenterJsPath, [instrumenterPath], [tscFile, instrumenterPath].concat(libraryTargets), [], /*useBuiltCompiler*/ true, { lib: "es6", types: ["node"] });
|
||||
|
||||
desc("Builds an instrumented tsc.js");
|
||||
task('tsc-instrumented', [loggedIOJsPath, instrumenterJsPath, tscFile], function () {
|
||||
|
||||
@ -59,7 +59,7 @@
|
||||
"gulp-insert": "latest",
|
||||
"gulp-newer": "latest",
|
||||
"gulp-sourcemaps": "latest",
|
||||
"gulp-typescript": "3.1.5",
|
||||
"gulp-typescript": "latest",
|
||||
"into-stream": "latest",
|
||||
"istanbul": "latest",
|
||||
"jake": "latest",
|
||||
@ -74,7 +74,7 @@
|
||||
"through2": "latest",
|
||||
"travis-fold": "latest",
|
||||
"ts-node": "latest",
|
||||
"tslint": "next",
|
||||
"tslint": "latest",
|
||||
"typescript": "next"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@ -2178,7 +2178,10 @@ namespace ts {
|
||||
case SyntaxKind.JSDocRecordMember:
|
||||
return bindPropertyWorker(node as JSDocRecordMember);
|
||||
case SyntaxKind.JSDocPropertyTag:
|
||||
return declareSymbolAndAddToSymbolTable(node as JSDocPropertyTag, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
|
||||
return declareSymbolAndAddToSymbolTable(node as JSDocPropertyTag,
|
||||
(node as JSDocPropertyTag).isBracketed || ((node as JSDocPropertyTag).typeExpression && (node as JSDocPropertyTag).typeExpression.type.kind === SyntaxKind.JSDocOptionalType) ?
|
||||
SymbolFlags.Property | SymbolFlags.Optional : SymbolFlags.Property,
|
||||
SymbolFlags.PropertyExcludes);
|
||||
case SyntaxKind.JSDocFunctionType:
|
||||
return bindFunctionOrConstructorType(<SignatureDeclaration>node);
|
||||
case SyntaxKind.JSDocTypeLiteral:
|
||||
@ -3593,4 +3596,4 @@ namespace ts {
|
||||
return TransformFlags.NodeExcludes;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5698,6 +5698,7 @@ namespace ts {
|
||||
prop.type = propType;
|
||||
if (propertySymbol) {
|
||||
prop.syntheticOrigin = propertySymbol;
|
||||
prop.declarations = propertySymbol.declarations;
|
||||
}
|
||||
members.set(propName, prop);
|
||||
}
|
||||
@ -6860,6 +6861,7 @@ namespace ts {
|
||||
case "Object":
|
||||
return anyType;
|
||||
case "Function":
|
||||
case "function":
|
||||
return globalFunctionType;
|
||||
case "Array":
|
||||
case "array":
|
||||
@ -7958,23 +7960,14 @@ namespace ts {
|
||||
return mapper;
|
||||
}
|
||||
|
||||
function getInferenceMapper(context: InferenceContext): TypeMapper {
|
||||
if (!context.mapper) {
|
||||
const mapper: TypeMapper = t => {
|
||||
const typeParameters = context.signature.typeParameters;
|
||||
for (let i = 0; i < typeParameters.length; i++) {
|
||||
if (t === typeParameters[i]) {
|
||||
context.inferences[i].isFixed = true;
|
||||
return getInferredType(context, i);
|
||||
}
|
||||
}
|
||||
return t;
|
||||
};
|
||||
mapper.mappedTypes = context.signature.typeParameters;
|
||||
mapper.context = context;
|
||||
context.mapper = mapper;
|
||||
}
|
||||
return context.mapper;
|
||||
function isInferenceContext(mapper: TypeMapper): mapper is InferenceContext {
|
||||
return !!(<InferenceContext>mapper).signature;
|
||||
}
|
||||
|
||||
function cloneTypeMapper(mapper: TypeMapper): TypeMapper {
|
||||
return mapper && isInferenceContext(mapper) ?
|
||||
createInferenceContext(mapper.signature, mapper.flags | InferenceFlags.NoDefault, mapper.inferences) :
|
||||
mapper;
|
||||
}
|
||||
|
||||
function identityMapper(type: Type): Type {
|
||||
@ -10170,23 +10163,45 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function createInferenceContext(signature: Signature, inferUnionTypes: boolean, useAnyForNoInferences: boolean): InferenceContext {
|
||||
const inferences = map(signature.typeParameters, createTypeInferencesObject);
|
||||
function createInferenceContext(signature: Signature, flags: InferenceFlags, baseInferences?: InferenceInfo[]): InferenceContext {
|
||||
const inferences = baseInferences ? map(baseInferences, cloneInferenceInfo) : map(signature.typeParameters, createInferenceInfo);
|
||||
const context = mapper as InferenceContext;
|
||||
context.mappedTypes = signature.typeParameters;
|
||||
context.signature = signature;
|
||||
context.inferences = inferences;
|
||||
context.flags = flags;
|
||||
return context;
|
||||
|
||||
function mapper(t: Type): Type {
|
||||
for (let i = 0; i < inferences.length; i++) {
|
||||
if (t === inferences[i].typeParameter) {
|
||||
inferences[i].isFixed = true;
|
||||
return getInferredType(context, i);
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
function createInferenceInfo(typeParameter: TypeParameter): InferenceInfo {
|
||||
return {
|
||||
signature,
|
||||
inferUnionTypes,
|
||||
inferences,
|
||||
inferredTypes: new Array(signature.typeParameters.length),
|
||||
useAnyForNoInferences
|
||||
typeParameter,
|
||||
candidates: undefined,
|
||||
inferredType: undefined,
|
||||
priority: undefined,
|
||||
topLevel: true,
|
||||
isFixed: false
|
||||
};
|
||||
}
|
||||
|
||||
function createTypeInferencesObject(): TypeInferences {
|
||||
function cloneInferenceInfo(inference: InferenceInfo): InferenceInfo {
|
||||
return {
|
||||
primary: undefined,
|
||||
secondary: undefined,
|
||||
topLevel: true,
|
||||
isFixed: false,
|
||||
typeParameter: inference.typeParameter,
|
||||
candidates: inference.candidates && inference.candidates.slice(),
|
||||
inferredType: inference.inferredType,
|
||||
priority: inference.priority,
|
||||
topLevel: inference.topLevel,
|
||||
isFixed: inference.isFixed
|
||||
};
|
||||
}
|
||||
|
||||
@ -10223,10 +10238,9 @@ namespace ts {
|
||||
if (properties.length === 0 && !indexInfo) {
|
||||
return undefined;
|
||||
}
|
||||
const typeVariable = <TypeVariable>getIndexedAccessType((<IndexType>getConstraintTypeFromMappedType(target)).type, getTypeParameterFromMappedType(target));
|
||||
const typeVariableArray = [typeVariable];
|
||||
const typeInferences = createTypeInferencesObject();
|
||||
const typeInferencesArray = [typeInferences];
|
||||
const typeParameter = <TypeParameter>getIndexedAccessType((<IndexType>getConstraintTypeFromMappedType(target)).type, getTypeParameterFromMappedType(target));
|
||||
const inference = createInferenceInfo(typeParameter);
|
||||
const inferences = [inference];
|
||||
const templateType = getTemplateTypeFromMappedType(target);
|
||||
const readonlyMask = target.declaration.readonlyToken ? false : true;
|
||||
const optionalMask = target.declaration.questionToken ? 0 : SymbolFlags.Optional;
|
||||
@ -10252,22 +10266,15 @@ namespace ts {
|
||||
return createAnonymousType(undefined, members, emptyArray, emptyArray, indexInfo, undefined);
|
||||
|
||||
function inferTargetType(sourceType: Type): Type {
|
||||
typeInferences.primary = undefined;
|
||||
typeInferences.secondary = undefined;
|
||||
inferTypes(typeVariableArray, typeInferencesArray, sourceType, templateType);
|
||||
const inferences = typeInferences.primary || typeInferences.secondary;
|
||||
return inferences && getUnionType(inferences, /*subtypeReduction*/ true);
|
||||
inference.candidates = undefined;
|
||||
inferTypes(inferences, sourceType, templateType);
|
||||
return inference.candidates && getUnionType(inference.candidates, /*subtypeReduction*/ true);
|
||||
}
|
||||
}
|
||||
|
||||
function inferTypesWithContext(context: InferenceContext, originalSource: Type, originalTarget: Type) {
|
||||
inferTypes(context.signature.typeParameters, context.inferences, originalSource, originalTarget);
|
||||
}
|
||||
|
||||
function inferTypes(typeVariables: TypeVariable[], typeInferences: TypeInferences[], originalSource: Type, originalTarget: Type) {
|
||||
function inferTypes(inferences: InferenceInfo[], originalSource: Type, originalTarget: Type, priority: InferencePriority = 0) {
|
||||
let symbolStack: Symbol[];
|
||||
let visited: Map<boolean>;
|
||||
let inferiority = 0;
|
||||
inferFromTypes(originalSource, originalTarget);
|
||||
|
||||
function inferFromTypes(source: Type, target: Type) {
|
||||
@ -10327,32 +10334,26 @@ namespace ts {
|
||||
// Because the anyFunctionType is internal, it should not be exposed to the user by adding
|
||||
// it as an inference candidate. Hopefully, a better candidate will come along that does
|
||||
// not contain anyFunctionType when we come back to this argument for its second round
|
||||
// of inference.
|
||||
if (source.flags & TypeFlags.ContainsAnyFunctionType) {
|
||||
// of inference. Also, we exclude inferences for silentNeverType which is used as a wildcard
|
||||
// when constructing types from type parameters that had no inference candidates.
|
||||
if (source.flags & TypeFlags.ContainsAnyFunctionType || source === silentNeverType) {
|
||||
return;
|
||||
}
|
||||
for (let i = 0; i < typeVariables.length; i++) {
|
||||
if (target === typeVariables[i]) {
|
||||
const inferences = typeInferences[i];
|
||||
if (!inferences.isFixed) {
|
||||
// Any inferences that are made to a type parameter in a union type are inferior
|
||||
// to inferences made to a flat (non-union) type. This is because if we infer to
|
||||
// T | string[], we really don't know if we should be inferring to T or not (because
|
||||
// the correct constituent on the target side could be string[]). Therefore, we put
|
||||
// such inferior inferences into a secondary bucket, and only use them if the primary
|
||||
// bucket is empty.
|
||||
const candidates = inferiority ?
|
||||
inferences.secondary || (inferences.secondary = []) :
|
||||
inferences.primary || (inferences.primary = []);
|
||||
if (!contains(candidates, source)) {
|
||||
candidates.push(source);
|
||||
}
|
||||
if (target.flags & TypeFlags.TypeParameter && !isTypeParameterAtTopLevel(originalTarget, <TypeParameter>target)) {
|
||||
inferences.topLevel = false;
|
||||
}
|
||||
const inference = getInferenceInfoForType(target);
|
||||
if (inference) {
|
||||
if (!inference.isFixed) {
|
||||
if (!inference.candidates || priority < inference.priority) {
|
||||
inference.candidates = [source];
|
||||
inference.priority = priority;
|
||||
}
|
||||
else if (priority === inference.priority) {
|
||||
inference.candidates.push(source);
|
||||
}
|
||||
if (!(priority & InferencePriority.ReturnType) && target.flags & TypeFlags.TypeParameter && !isTypeParameterAtTopLevel(originalTarget, <TypeParameter>target)) {
|
||||
inference.topLevel = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
|
||||
@ -10370,7 +10371,7 @@ namespace ts {
|
||||
let typeVariable: TypeVariable;
|
||||
// First infer to each type in union or intersection that isn't a type variable
|
||||
for (const t of targetTypes) {
|
||||
if (t.flags & TypeFlags.TypeVariable && contains(typeVariables, t)) {
|
||||
if (getInferenceInfoForType(t)) {
|
||||
typeVariable = <TypeVariable>t;
|
||||
typeVariableCount++;
|
||||
}
|
||||
@ -10382,9 +10383,10 @@ namespace ts {
|
||||
// variable. This gives meaningful results for union types in co-variant positions and intersection
|
||||
// types in contra-variant positions (such as callback parameters).
|
||||
if (typeVariableCount === 1) {
|
||||
inferiority++;
|
||||
const savePriority = priority;
|
||||
priority |= InferencePriority.NakedTypeVariable;
|
||||
inferFromTypes(source, typeVariable);
|
||||
inferiority--;
|
||||
priority = savePriority;
|
||||
}
|
||||
}
|
||||
else if (source.flags & TypeFlags.UnionOrIntersection) {
|
||||
@ -10424,6 +10426,17 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getInferenceInfoForType(type: Type) {
|
||||
if (type.flags & TypeFlags.TypeVariable) {
|
||||
for (const inference of inferences) {
|
||||
if (type === inference.typeParameter) {
|
||||
return inference;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function inferFromObjectTypes(source: Type, target: Type) {
|
||||
if (getObjectFlags(target) & ObjectFlags.Mapped) {
|
||||
const constraintType = getConstraintTypeFromMappedType(<MappedType>target);
|
||||
@ -10432,13 +10445,14 @@ namespace ts {
|
||||
// where T is a type variable. Use inferTypeForHomomorphicMappedType to infer a suitable source
|
||||
// type and then make a secondary inference from that type to T. We make a secondary inference
|
||||
// such that direct inferences to T get priority over inferences to Partial<T>, for example.
|
||||
const index = indexOf(typeVariables, (<IndexType>constraintType).type);
|
||||
if (index >= 0 && !typeInferences[index].isFixed) {
|
||||
const inference = getInferenceInfoForType((<IndexType>constraintType).type);
|
||||
if (inference && !inference.isFixed) {
|
||||
const inferredType = inferTypeForHomomorphicMappedType(source, <MappedType>target);
|
||||
if (inferredType) {
|
||||
inferiority++;
|
||||
inferFromTypes(inferredType, typeVariables[index]);
|
||||
inferiority--;
|
||||
const savePriority = priority;
|
||||
priority |= InferencePriority.MappedType;
|
||||
inferFromTypes(inferredType, inference.typeParameter);
|
||||
priority = savePriority;
|
||||
}
|
||||
}
|
||||
return;
|
||||
@ -10537,66 +10551,68 @@ namespace ts {
|
||||
return type.flags & TypeFlags.Union ? getUnionType(reducedTypes) : getIntersectionType(reducedTypes);
|
||||
}
|
||||
|
||||
function getInferenceCandidates(context: InferenceContext, index: number): Type[] {
|
||||
const inferences = context.inferences[index];
|
||||
return inferences.primary || inferences.secondary || emptyArray;
|
||||
}
|
||||
|
||||
function hasPrimitiveConstraint(type: TypeParameter): boolean {
|
||||
const constraint = getConstraintOfTypeParameter(type);
|
||||
return constraint && maybeTypeOfKind(constraint, TypeFlags.Primitive | TypeFlags.Index);
|
||||
}
|
||||
|
||||
function getInferredType(context: InferenceContext, index: number): Type {
|
||||
let inferredType = context.inferredTypes[index];
|
||||
const inference = context.inferences[index];
|
||||
let inferredType = inference.inferredType;
|
||||
let inferenceSucceeded: boolean;
|
||||
if (!inferredType) {
|
||||
const inferences = getInferenceCandidates(context, index);
|
||||
if (inferences.length) {
|
||||
if (inference.candidates) {
|
||||
// We widen inferred literal types if
|
||||
// all inferences were made to top-level ocurrences of the type parameter, and
|
||||
// the type parameter has no constraint or its constraint includes no primitive or literal types, and
|
||||
// the type parameter was fixed during inference or does not occur at top-level in the return type.
|
||||
const signature = context.signature;
|
||||
const widenLiteralTypes = context.inferences[index].topLevel &&
|
||||
!hasPrimitiveConstraint(signature.typeParameters[index]) &&
|
||||
(context.inferences[index].isFixed || !isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), signature.typeParameters[index]));
|
||||
const baseInferences = widenLiteralTypes ? sameMap(inferences, getWidenedLiteralType) : inferences;
|
||||
// Infer widened union or supertype, or the unknown type for no common supertype
|
||||
const unionOrSuperType = context.inferUnionTypes ? getUnionType(baseInferences, /*subtypeReduction*/ true) : getCommonSupertype(baseInferences);
|
||||
const widenLiteralTypes = inference.topLevel &&
|
||||
!hasPrimitiveConstraint(inference.typeParameter) &&
|
||||
(inference.isFixed || !isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), inference.typeParameter));
|
||||
const baseCandidates = widenLiteralTypes ? sameMap(inference.candidates, getWidenedLiteralType) : inference.candidates;
|
||||
// Infer widened union or supertype, or the unknown type for no common supertype. We infer union types
|
||||
// for inferences coming from return types in order to avoid common supertype failures.
|
||||
const unionOrSuperType = context.flags & InferenceFlags.InferUnionTypes || inference.priority & InferencePriority.ReturnType ?
|
||||
getUnionType(baseCandidates, /*subtypeReduction*/ true) : getCommonSupertype(baseCandidates);
|
||||
inferredType = unionOrSuperType ? getWidenedType(unionOrSuperType) : unknownType;
|
||||
inferenceSucceeded = !!unionOrSuperType;
|
||||
}
|
||||
else {
|
||||
// Infer either the default or the empty object type when no inferences were
|
||||
// made. It is important to remember that in this case, inference still
|
||||
// succeeds, meaning there is no error for not having inference candidates. An
|
||||
// inference error only occurs when there are *conflicting* candidates, i.e.
|
||||
// candidates with no common supertype.
|
||||
const defaultType = getDefaultFromTypeParameter(context.signature.typeParameters[index]);
|
||||
if (defaultType) {
|
||||
// Instantiate the default type. Any forward reference to a type
|
||||
// parameter should be instantiated to the empty object type.
|
||||
inferredType = instantiateType(defaultType,
|
||||
combineTypeMappers(
|
||||
createBackreferenceMapper(context.signature.typeParameters, index),
|
||||
getInferenceMapper(context)));
|
||||
if (context.flags & InferenceFlags.NoDefault) {
|
||||
// We use silentNeverType as the wildcard that signals no inferences.
|
||||
inferredType = silentNeverType;
|
||||
}
|
||||
else {
|
||||
inferredType = context.useAnyForNoInferences ? anyType : emptyObjectType;
|
||||
// Infer either the default or the empty object type when no inferences were
|
||||
// made. It is important to remember that in this case, inference still
|
||||
// succeeds, meaning there is no error for not having inference candidates. An
|
||||
// inference error only occurs when there are *conflicting* candidates, i.e.
|
||||
// candidates with no common supertype.
|
||||
const defaultType = getDefaultFromTypeParameter(inference.typeParameter);
|
||||
if (defaultType) {
|
||||
// Instantiate the default type. Any forward reference to a type
|
||||
// parameter should be instantiated to the empty object type.
|
||||
inferredType = instantiateType(defaultType,
|
||||
combineTypeMappers(
|
||||
createBackreferenceMapper(context.signature.typeParameters, index),
|
||||
context));
|
||||
}
|
||||
else {
|
||||
inferredType = context.flags & InferenceFlags.AnyDefault ? anyType : emptyObjectType;
|
||||
}
|
||||
}
|
||||
|
||||
inferenceSucceeded = true;
|
||||
}
|
||||
context.inferredTypes[index] = inferredType;
|
||||
inference.inferredType = inferredType;
|
||||
|
||||
// Only do the constraint check if inference succeeded (to prevent cascading errors)
|
||||
if (inferenceSucceeded) {
|
||||
const constraint = getConstraintOfTypeParameter(context.signature.typeParameters[index]);
|
||||
if (constraint) {
|
||||
const instantiatedConstraint = instantiateType(constraint, getInferenceMapper(context));
|
||||
const instantiatedConstraint = instantiateType(constraint, context);
|
||||
if (!isTypeAssignableTo(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) {
|
||||
context.inferredTypes[index] = inferredType = instantiatedConstraint;
|
||||
inference.inferredType = inferredType = instantiatedConstraint;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -10611,10 +10627,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getInferredTypes(context: InferenceContext): Type[] {
|
||||
for (let i = 0; i < context.inferredTypes.length; i++) {
|
||||
getInferredType(context, i);
|
||||
const result: Type[] = [];
|
||||
for (let i = 0; i < context.inferences.length; i++) {
|
||||
result.push(getInferredType(context, i));
|
||||
}
|
||||
return context.inferredTypes;
|
||||
return result;
|
||||
}
|
||||
|
||||
// EXPRESSION TYPE CHECKING
|
||||
@ -14870,26 +14887,25 @@ namespace ts {
|
||||
|
||||
// Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec)
|
||||
function instantiateSignatureInContextOf(signature: Signature, contextualSignature: Signature, contextualMapper: TypeMapper): Signature {
|
||||
const context = createInferenceContext(signature, /*inferUnionTypes*/ true, /*useAnyForNoInferences*/ false);
|
||||
const context = createInferenceContext(signature, InferenceFlags.InferUnionTypes);
|
||||
forEachMatchingParameterType(contextualSignature, signature, (source, target) => {
|
||||
// Type parameters from outer context referenced by source type are fixed by instantiation of the source type
|
||||
inferTypesWithContext(context, instantiateType(source, contextualMapper), target);
|
||||
inferTypes(context.inferences, instantiateType(source, contextualMapper), target);
|
||||
});
|
||||
return getSignatureInstantiation(signature, getInferredTypes(context));
|
||||
}
|
||||
|
||||
function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: Expression[], excludeArgument: boolean[], context: InferenceContext): void {
|
||||
const typeParameters = signature.typeParameters;
|
||||
const inferenceMapper = getInferenceMapper(context);
|
||||
function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: Expression[], excludeArgument: boolean[], context: InferenceContext): Type[] {
|
||||
const inferences = context.inferences;
|
||||
|
||||
// Clear out all the inference results from the last time inferTypeArguments was called on this context
|
||||
for (let i = 0; i < typeParameters.length; i++) {
|
||||
for (let i = 0; i < inferences.length; i++) {
|
||||
// As an optimization, we don't have to clear (and later recompute) inferred types
|
||||
// for type parameters that have already been fixed on the previous call to inferTypeArguments.
|
||||
// It would be just as correct to reset all of them. But then we'd be repeating the same work
|
||||
// for the type parameters that were fixed, namely the work done by getInferredType.
|
||||
if (!context.inferences[i].isFixed) {
|
||||
context.inferredTypes[i] = undefined;
|
||||
if (!inferences[i].isFixed) {
|
||||
inferences[i].inferredType = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@ -14904,11 +14920,29 @@ namespace ts {
|
||||
context.failedTypeParameterIndex = undefined;
|
||||
}
|
||||
|
||||
// If a contextual type is available, infer from that type to the return type of the call expression. For
|
||||
// example, given a 'function wrap<T, U>(cb: (x: T) => U): (x: T) => U' and a call expression
|
||||
// 'let f: (x: string) => number = wrap(s => s.length)', we infer from the declared type of 'f' to the
|
||||
// return type of 'wrap'.
|
||||
if (isExpression(node)) {
|
||||
const contextualType = getContextualType(node);
|
||||
if (contextualType) {
|
||||
// We clone the contextual mapper to avoid disturbing a resolution in progress for an
|
||||
// outer call expression. Effectively we just want a snapshot of whatever has been
|
||||
// inferred for any outer call expression so far.
|
||||
const mapper = cloneTypeMapper(getContextualMapper(node));
|
||||
const instantiatedType = instantiateType(contextualType, mapper);
|
||||
const returnType = getReturnTypeOfSignature(signature);
|
||||
// Inferences made from return types have lower priority than all other inferences.
|
||||
inferTypes(context.inferences, instantiatedType, returnType, InferencePriority.ReturnType);
|
||||
}
|
||||
}
|
||||
|
||||
const thisType = getThisTypeOfSignature(signature);
|
||||
if (thisType) {
|
||||
const thisArgumentNode = getThisArgumentOfCall(node);
|
||||
const thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType;
|
||||
inferTypesWithContext(context, thisArgumentType, thisType);
|
||||
inferTypes(context.inferences, thisArgumentType, thisType);
|
||||
}
|
||||
|
||||
// We perform two passes over the arguments. In the first pass we infer from all arguments, but use
|
||||
@ -14926,11 +14960,11 @@ namespace ts {
|
||||
if (argType === undefined) {
|
||||
// For context sensitive arguments we pass the identityMapper, which is a signal to treat all
|
||||
// context sensitive function expressions as wildcards
|
||||
const mapper = excludeArgument && excludeArgument[i] !== undefined ? identityMapper : inferenceMapper;
|
||||
const mapper = excludeArgument && excludeArgument[i] !== undefined ? identityMapper : context;
|
||||
argType = checkExpressionWithContextualType(arg, paramType, mapper);
|
||||
}
|
||||
|
||||
inferTypesWithContext(context, argType, paramType);
|
||||
inferTypes(context.inferences, argType, paramType);
|
||||
}
|
||||
}
|
||||
|
||||
@ -14945,12 +14979,11 @@ namespace ts {
|
||||
if (excludeArgument[i] === false) {
|
||||
const arg = args[i];
|
||||
const paramType = getTypeAtPosition(signature, i);
|
||||
inferTypesWithContext(context, checkExpressionWithContextualType(arg, paramType, inferenceMapper), paramType);
|
||||
inferTypes(context.inferences, checkExpressionWithContextualType(arg, paramType, context), paramType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getInferredTypes(context);
|
||||
return getInferredTypes(context);
|
||||
}
|
||||
|
||||
function checkTypeArguments(signature: Signature, typeArgumentNodes: TypeNode[], typeArgumentTypes: Type[], reportErrors: boolean, headMessage?: DiagnosticMessage): boolean {
|
||||
@ -15532,7 +15565,7 @@ namespace ts {
|
||||
else {
|
||||
Debug.assert(resultOfFailedInference.failedTypeParameterIndex >= 0);
|
||||
const failedTypeParameter = candidateForTypeArgumentError.typeParameters[resultOfFailedInference.failedTypeParameterIndex];
|
||||
const inferenceCandidates = getInferenceCandidates(resultOfFailedInference, resultOfFailedInference.failedTypeParameterIndex);
|
||||
const inferenceCandidates = resultOfFailedInference.inferences[resultOfFailedInference.failedTypeParameterIndex].candidates;
|
||||
|
||||
let diagnosticChainHead = chainDiagnosticMessages(/*details*/ undefined, // details will be provided by call to reportNoCommonSupertypeError
|
||||
Diagnostics.The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly,
|
||||
@ -15605,7 +15638,7 @@ namespace ts {
|
||||
let candidate: Signature;
|
||||
let typeArgumentsAreValid: boolean;
|
||||
const inferenceContext = originalCandidate.typeParameters
|
||||
? createInferenceContext(originalCandidate, /*inferUnionTypes*/ false, /*useAnyForNoInferences*/ isInJavaScriptFile(node))
|
||||
? createInferenceContext(originalCandidate, /*flags*/ isInJavaScriptFile(node) ? InferenceFlags.AnyDefault : 0)
|
||||
: undefined;
|
||||
|
||||
while (true) {
|
||||
@ -15617,8 +15650,7 @@ namespace ts {
|
||||
typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false);
|
||||
}
|
||||
else {
|
||||
inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext);
|
||||
typeArgumentTypes = inferenceContext.inferredTypes;
|
||||
typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext);
|
||||
typeArgumentsAreValid = inferenceContext.failedTypeParameterIndex === undefined;
|
||||
}
|
||||
if (!typeArgumentsAreValid) {
|
||||
@ -16192,7 +16224,7 @@ namespace ts {
|
||||
for (let i = 0; i < len; i++) {
|
||||
const declaration = <ParameterDeclaration>signature.parameters[i].valueDeclaration;
|
||||
if (declaration.type) {
|
||||
inferTypesWithContext(mapper.context, getTypeFromTypeNode(declaration.type), getTypeAtPosition(context, i));
|
||||
inferTypes((<InferenceContext>mapper).inferences, getTypeFromTypeNode(declaration.type), getTypeAtPosition(context, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -16278,7 +16310,7 @@ namespace ts {
|
||||
// T in the second overload so that we do not infer Base as a candidate for T
|
||||
// (inferring Base would make type argument inference inconsistent between the two
|
||||
// overloads).
|
||||
inferTypesWithContext(mapper.context, links.type, instantiateType(contextualType, mapper));
|
||||
inferTypes((<InferenceContext>mapper).inferences, links.type, instantiateType(contextualType, mapper));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -692,8 +692,7 @@ namespace ts {
|
||||
return typeAcquisition;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function getOptionNameMap(): OptionNameMap {
|
||||
function getOptionNameMap(): OptionNameMap {
|
||||
if (optionNameMapCache) {
|
||||
return optionNameMapCache;
|
||||
}
|
||||
@ -750,7 +749,6 @@ namespace ts {
|
||||
const options: CompilerOptions = {};
|
||||
const fileNames: string[] = [];
|
||||
const errors: Diagnostic[] = [];
|
||||
const { optionNameMap, shortOptionNames } = getOptionNameMap();
|
||||
|
||||
parseStrings(commandLine);
|
||||
return {
|
||||
@ -762,21 +760,13 @@ namespace ts {
|
||||
function parseStrings(args: string[]) {
|
||||
let i = 0;
|
||||
while (i < args.length) {
|
||||
let s = args[i];
|
||||
const s = args[i];
|
||||
i++;
|
||||
if (s.charCodeAt(0) === CharacterCodes.at) {
|
||||
parseResponseFile(s.slice(1));
|
||||
}
|
||||
else if (s.charCodeAt(0) === CharacterCodes.minus) {
|
||||
s = s.slice(s.charCodeAt(1) === CharacterCodes.minus ? 2 : 1).toLowerCase();
|
||||
|
||||
// Try to translate short option names to their full equivalents.
|
||||
const short = shortOptionNames.get(s);
|
||||
if (short !== undefined) {
|
||||
s = short;
|
||||
}
|
||||
|
||||
const opt = optionNameMap.get(s);
|
||||
const opt = getOptionFromName(s.slice(s.charCodeAt(1) === CharacterCodes.minus ? 2 : 1), /*allowShort*/ true);
|
||||
if (opt) {
|
||||
if (opt.isTSConfigOnly) {
|
||||
errors.push(createCompilerDiagnostic(Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file, opt.name));
|
||||
@ -864,6 +854,19 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getOptionFromName(optionName: string, allowShort = false): CommandLineOption | undefined {
|
||||
optionName = optionName.toLowerCase();
|
||||
const { optionNameMap, shortOptionNames } = getOptionNameMap();
|
||||
// Try to translate short option names to their full equivalents.
|
||||
if (allowShort) {
|
||||
const short = shortOptionNames.get(optionName);
|
||||
if (short !== undefined) {
|
||||
optionName = short;
|
||||
}
|
||||
}
|
||||
return optionNameMap.get(optionName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read tsconfig.json file
|
||||
* @param fileName The path to the config file
|
||||
@ -2173,4 +2176,42 @@ namespace ts {
|
||||
function caseInsensitiveKeyMapper(key: string) {
|
||||
return key.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a cleaned version of compiler options with personally identifiying info (aka, paths) removed.
|
||||
* Also converts enum values back to strings.
|
||||
*/
|
||||
/* @internal */
|
||||
export function convertCompilerOptionsForTelemetry(opts: ts.CompilerOptions): ts.CompilerOptions {
|
||||
const out: ts.CompilerOptions = {};
|
||||
for (const key in opts) if (opts.hasOwnProperty(key)) {
|
||||
const type = getOptionFromName(key);
|
||||
if (type !== undefined) { // Ignore unknown options
|
||||
out[key] = getOptionValueWithEmptyStrings(opts[key], type);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function getOptionValueWithEmptyStrings(value: any, option: CommandLineOption): {} {
|
||||
switch (option.type) {
|
||||
case "object": // "paths". Can't get any useful information from the value since we blank out strings, so just return "".
|
||||
return "";
|
||||
case "string": // Could be any arbitrary string -- use empty string instead.
|
||||
return "";
|
||||
case "number": // Allow numbers, but be sure to check it's actually a number.
|
||||
return typeof value === "number" ? value : "";
|
||||
case "boolean":
|
||||
return typeof value === "boolean" ? value : "";
|
||||
case "list":
|
||||
const elementType = (option as CommandLineOptionOfListType).element;
|
||||
return ts.isArray(value) ? value.map(v => getOptionValueWithEmptyStrings(v, elementType)) : "";
|
||||
default:
|
||||
return ts.forEachEntry(option.type, (optionEnumValue, optionStringValue) => {
|
||||
if (optionEnumValue === value) {
|
||||
return optionStringValue;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -521,6 +521,18 @@ namespace ts {
|
||||
return result || array;
|
||||
}
|
||||
|
||||
export function mapDefined<T>(array: ReadonlyArray<T>, mapFn: (x: T, i: number) => T | undefined): ReadonlyArray<T> {
|
||||
const result: T[] = [];
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
const item = array[i];
|
||||
const mapped = mapFn(item, i);
|
||||
if (mapped !== undefined) {
|
||||
result.push(mapped);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the first matching span of elements and returns a tuple of the first span
|
||||
* and the remaining elements.
|
||||
|
||||
@ -303,7 +303,7 @@ namespace ts {
|
||||
: node;
|
||||
}
|
||||
|
||||
export function createProperty(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression) {
|
||||
export function createProperty(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) {
|
||||
const node = <PropertyDeclaration>createSynthesizedNode(SyntaxKind.PropertyDeclaration);
|
||||
node.decorators = asNodeArray(decorators);
|
||||
node.modifiers = asNodeArray(modifiers);
|
||||
@ -314,7 +314,7 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function updateProperty(node: PropertyDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, name: PropertyName, type: TypeNode | undefined, initializer: Expression) {
|
||||
export function updateProperty(node: PropertyDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, name: PropertyName, type: TypeNode | undefined, initializer: Expression | undefined) {
|
||||
return node.decorators !== decorators
|
||||
|| node.modifiers !== modifiers
|
||||
|| node.name !== name
|
||||
|
||||
@ -6108,7 +6108,10 @@ namespace ts {
|
||||
case SyntaxKind.OpenBraceToken:
|
||||
return parseJSDocRecordType();
|
||||
case SyntaxKind.FunctionKeyword:
|
||||
return parseJSDocFunctionType();
|
||||
if (lookAhead(nextTokenIsOpenParen)) {
|
||||
return parseJSDocFunctionType();
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.DotDotDotToken:
|
||||
return parseJSDocVariadicType();
|
||||
case SyntaxKind.NewKeyword:
|
||||
@ -6124,7 +6127,6 @@ namespace ts {
|
||||
case SyntaxKind.NullKeyword:
|
||||
case SyntaxKind.UndefinedKeyword:
|
||||
case SyntaxKind.NeverKeyword:
|
||||
case SyntaxKind.ObjectKeyword:
|
||||
return parseTokenNode<JSDocType>();
|
||||
case SyntaxKind.StringLiteral:
|
||||
case SyntaxKind.NumericLiteral:
|
||||
@ -6664,10 +6666,7 @@ namespace ts {
|
||||
});
|
||||
}
|
||||
|
||||
function parseParamTag(atToken: AtToken, tagName: Identifier) {
|
||||
let typeExpression = tryParseTypeExpression();
|
||||
skipWhitespace();
|
||||
|
||||
function parseBracketNameInPropertyAndParamTag() {
|
||||
let name: Identifier;
|
||||
let isBracketed: boolean;
|
||||
// Looking for something like '[foo]' or 'foo'
|
||||
@ -6686,6 +6685,14 @@ namespace ts {
|
||||
else if (tokenIsIdentifierOrKeyword(token())) {
|
||||
name = parseJSDocIdentifierName();
|
||||
}
|
||||
return { name, isBracketed };
|
||||
}
|
||||
|
||||
function parseParamTag(atToken: AtToken, tagName: Identifier) {
|
||||
let typeExpression = tryParseTypeExpression();
|
||||
skipWhitespace();
|
||||
|
||||
const { name, isBracketed } = parseBracketNameInPropertyAndParamTag();
|
||||
|
||||
if (!name) {
|
||||
parseErrorAtPosition(scanner.getStartPos(), 0, Diagnostics.Identifier_expected);
|
||||
@ -6742,8 +6749,9 @@ namespace ts {
|
||||
function parsePropertyTag(atToken: AtToken, tagName: Identifier): JSDocPropertyTag {
|
||||
const typeExpression = tryParseTypeExpression();
|
||||
skipWhitespace();
|
||||
const name = parseJSDocIdentifierName();
|
||||
const { name, isBracketed } = parseBracketNameInPropertyAndParamTag();
|
||||
skipWhitespace();
|
||||
|
||||
if (!name) {
|
||||
parseErrorAtPosition(scanner.getStartPos(), /*length*/ 0, Diagnostics.Identifier_expected);
|
||||
return undefined;
|
||||
@ -6754,6 +6762,7 @@ namespace ts {
|
||||
result.tagName = tagName;
|
||||
result.name = name;
|
||||
result.typeExpression = typeExpression;
|
||||
result.isBracketed = isBracketed;
|
||||
return finishNode(result);
|
||||
}
|
||||
|
||||
@ -6795,7 +6804,7 @@ namespace ts {
|
||||
const jsDocTypeReference = <JSDocTypeReference>typeExpression.type;
|
||||
if (jsDocTypeReference.name.kind === SyntaxKind.Identifier) {
|
||||
const name = <Identifier>jsDocTypeReference.name;
|
||||
if (name.text === "Object") {
|
||||
if (name.text === "Object" || name.text === "object") {
|
||||
typedefTag.jsDocTypeLiteral = scanChildTags();
|
||||
}
|
||||
}
|
||||
|
||||
@ -429,6 +429,7 @@ namespace ts {
|
||||
case CharacterCodes.slash:
|
||||
// starts of normal trivia
|
||||
case CharacterCodes.lessThan:
|
||||
case CharacterCodes.bar:
|
||||
case CharacterCodes.equals:
|
||||
case CharacterCodes.greaterThan:
|
||||
// Starts of conflict marker trivia
|
||||
@ -496,6 +497,7 @@ namespace ts {
|
||||
break;
|
||||
|
||||
case CharacterCodes.lessThan:
|
||||
case CharacterCodes.bar:
|
||||
case CharacterCodes.equals:
|
||||
case CharacterCodes.greaterThan:
|
||||
if (isConflictMarkerTrivia(text, pos)) {
|
||||
@ -562,12 +564,12 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else {
|
||||
Debug.assert(ch === CharacterCodes.equals);
|
||||
// Consume everything from the start of the mid-conflict marker to the start of the next
|
||||
// end-conflict marker.
|
||||
Debug.assert(ch === CharacterCodes.bar || ch === CharacterCodes.equals);
|
||||
// Consume everything from the start of a ||||||| or ======= marker to the start
|
||||
// of the next ======= or >>>>>>> marker.
|
||||
while (pos < len) {
|
||||
const ch = text.charCodeAt(pos);
|
||||
if (ch === CharacterCodes.greaterThan && isConflictMarkerTrivia(text, pos)) {
|
||||
const currentChar = text.charCodeAt(pos);
|
||||
if ((currentChar === CharacterCodes.equals || currentChar === CharacterCodes.greaterThan) && currentChar !== ch && isConflictMarkerTrivia(text, pos)) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1562,6 +1564,16 @@ namespace ts {
|
||||
pos++;
|
||||
return token = SyntaxKind.OpenBraceToken;
|
||||
case CharacterCodes.bar:
|
||||
if (isConflictMarkerTrivia(text, pos)) {
|
||||
pos = scanConflictMarkerTrivia(text, pos, error);
|
||||
if (skipTrivia) {
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
return token = SyntaxKind.ConflictMarkerTrivia;
|
||||
}
|
||||
}
|
||||
|
||||
if (text.charCodeAt(pos + 1) === CharacterCodes.bar) {
|
||||
return pos += 2, token = SyntaxKind.BarBarToken;
|
||||
}
|
||||
|
||||
@ -2102,6 +2102,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export interface JSDocTag extends Node {
|
||||
parent: JSDoc;
|
||||
atToken: AtToken;
|
||||
tagName: Identifier;
|
||||
comment: string | undefined;
|
||||
@ -2132,6 +2133,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export interface JSDocTypedefTag extends JSDocTag, NamedDeclaration {
|
||||
parent: JSDoc;
|
||||
kind: SyntaxKind.JSDocTypedefTag;
|
||||
fullName?: JSDocNamespaceDeclaration | Identifier;
|
||||
name?: Identifier;
|
||||
@ -2140,9 +2142,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
export interface JSDocPropertyTag extends JSDocTag, TypeElement {
|
||||
parent: JSDoc;
|
||||
kind: SyntaxKind.JSDocPropertyTag;
|
||||
name: Identifier;
|
||||
typeExpression: JSDocTypeExpression;
|
||||
isBracketed: boolean;
|
||||
}
|
||||
|
||||
export interface JSDocTypeLiteral extends JSDocType {
|
||||
@ -3344,30 +3348,36 @@ namespace ts {
|
||||
(t: TypeParameter): Type;
|
||||
mappedTypes?: Type[]; // Types mapped by this mapper
|
||||
instantiations?: Type[]; // Cache of instantiations created using this type mapper.
|
||||
context?: InferenceContext; // The inference context this mapper was created from.
|
||||
// Only inference mappers have this set (in createInferenceMapper).
|
||||
// The identity mapper and regular instantiation mappers do not need it.
|
||||
}
|
||||
|
||||
export const enum InferencePriority {
|
||||
NakedTypeVariable = 1 << 0, // Naked type variable in union or intersection type
|
||||
MappedType = 1 << 1, // Reverse inference for mapped type
|
||||
ReturnType = 1 << 2, // Inference made from return type of generic function
|
||||
}
|
||||
|
||||
export interface InferenceInfo {
|
||||
typeParameter: TypeParameter;
|
||||
candidates: Type[];
|
||||
inferredType: Type;
|
||||
priority: InferencePriority;
|
||||
topLevel: boolean;
|
||||
isFixed: boolean;
|
||||
}
|
||||
|
||||
export const enum InferenceFlags {
|
||||
InferUnionTypes = 1 << 0, // Infer union types for disjoint candidates (otherwise unknownType)
|
||||
NoDefault = 1 << 1, // Infer unknownType for no inferences (otherwise anyType or emptyObjectType)
|
||||
AnyDefault = 1 << 2, // Infer anyType for no inferences (otherwise emptyObjectType)
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface TypeInferences {
|
||||
primary: Type[]; // Inferences made directly to a type parameter
|
||||
secondary: Type[]; // Inferences made to a type parameter in a union type
|
||||
topLevel: boolean; // True if all inferences were made from top-level (not nested in object type) locations
|
||||
isFixed: boolean; // Whether the type parameter is fixed, as defined in section 4.12.2 of the TypeScript spec
|
||||
// If a type parameter is fixed, no more inferences can be made for the type parameter
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface InferenceContext {
|
||||
export interface InferenceContext extends TypeMapper {
|
||||
signature: Signature; // Generic signature for which inferences are made
|
||||
inferUnionTypes: boolean; // Infer union types for disjoint candidates (otherwise undefinedType)
|
||||
inferences: TypeInferences[]; // Inferences made for each type parameter
|
||||
inferredTypes: Type[]; // Inferred type for each type parameter
|
||||
mapper?: TypeMapper; // Type mapper for this inference context
|
||||
inferences: InferenceInfo[]; // Inferences made for each type parameter
|
||||
flags: InferenceFlags; // Inference flags
|
||||
failedTypeParameterIndex?: number; // Index of type parameter for which inference failed
|
||||
// It is optional because in contextual signature instantiation, nothing fails
|
||||
useAnyForNoInferences?: boolean; // Use any instead of {} for no inferences
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
||||
@ -288,6 +288,14 @@ namespace ts {
|
||||
return node.kind >= SyntaxKind.FirstJSDocNode && node.kind <= SyntaxKind.LastJSDocNode;
|
||||
}
|
||||
|
||||
export function isJSDoc(node: Node): node is JSDoc {
|
||||
return node.kind === SyntaxKind.JSDocComment;
|
||||
}
|
||||
|
||||
export function isJSDocTypedefTag(node: Node): node is JSDocTypedefTag {
|
||||
return node.kind === SyntaxKind.JSDocTypedefTag;
|
||||
}
|
||||
|
||||
export function isJSDocTag(node: Node) {
|
||||
return node.kind >= SyntaxKind.FirstJSDocTagNode && node.kind <= SyntaxKind.LastJSDocTagNode;
|
||||
}
|
||||
@ -1562,6 +1570,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function getJSDocs(node: Node): (JSDoc | JSDocTag)[] {
|
||||
if (isJSDocTypedefTag(node)) {
|
||||
return [node.parent];
|
||||
}
|
||||
|
||||
let cache: (JSDoc | JSDocTag)[] = node.jsDocCache;
|
||||
if (!cache) {
|
||||
getJSDocsWorker(node);
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
declare const require: any, process: any;
|
||||
const fs: any = require("fs");
|
||||
const path: any = require("path");
|
||||
|
||||
|
||||
@ -128,6 +128,7 @@
|
||||
"./unittests/printer.ts",
|
||||
"./unittests/transform.ts",
|
||||
"./unittests/customTransforms.ts",
|
||||
"./unittests/textChanges.ts"
|
||||
"./unittests/textChanges.ts",
|
||||
"./unittests/telemetry.ts"
|
||||
]
|
||||
}
|
||||
|
||||
@ -424,6 +424,50 @@ class D { }\r\n\
|
||||
comment("=======\r\nclass D { }\r\n"),
|
||||
comment(">>>>>>> Branch - a"),
|
||||
finalEndOfLineState(ts.EndOfLineState.None));
|
||||
|
||||
testLexicalClassification(
|
||||
"class C {\r\n\
|
||||
<<<<<<< HEAD\r\n\
|
||||
v = 1;\r\n\
|
||||
||||||| merged common ancestors\r\n\
|
||||
v = 3;\r\n\
|
||||
=======\r\n\
|
||||
v = 2;\r\n\
|
||||
>>>>>>> Branch - a\r\n\
|
||||
}",
|
||||
ts.EndOfLineState.None,
|
||||
keyword("class"),
|
||||
identifier("C"),
|
||||
punctuation("{"),
|
||||
comment("<<<<<<< HEAD"),
|
||||
identifier("v"),
|
||||
operator("="),
|
||||
numberLiteral("1"),
|
||||
punctuation(";"),
|
||||
comment("||||||| merged common ancestors\r\n v = 3;\r\n"),
|
||||
comment("=======\r\n v = 2;\r\n"),
|
||||
comment(">>>>>>> Branch - a"),
|
||||
punctuation("}"),
|
||||
finalEndOfLineState(ts.EndOfLineState.None));
|
||||
|
||||
testLexicalClassification(
|
||||
"<<<<<<< HEAD\r\n\
|
||||
class C { }\r\n\
|
||||
||||||| merged common ancestors\r\n\
|
||||
class E { }\r\n\
|
||||
=======\r\n\
|
||||
class D { }\r\n\
|
||||
>>>>>>> Branch - a\r\n",
|
||||
ts.EndOfLineState.None,
|
||||
comment("<<<<<<< HEAD"),
|
||||
keyword("class"),
|
||||
identifier("C"),
|
||||
punctuation("{"),
|
||||
punctuation("}"),
|
||||
comment("||||||| merged common ancestors\r\nclass E { }\r\n"),
|
||||
comment("=======\r\nclass D { }\r\n"),
|
||||
comment(">>>>>>> Branch - a"),
|
||||
finalEndOfLineState(ts.EndOfLineState.None));
|
||||
});
|
||||
|
||||
it("'of' keyword", function () {
|
||||
|
||||
289
src/harness/unittests/telemetry.ts
Normal file
289
src/harness/unittests/telemetry.ts
Normal file
@ -0,0 +1,289 @@
|
||||
/// <reference path="../harness.ts" />
|
||||
/// <reference path="./tsserverProjectSystem.ts" />
|
||||
|
||||
namespace ts.projectSystem {
|
||||
describe("project telemetry", () => {
|
||||
it("does nothing for inferred project", () => {
|
||||
const file = makeFile("/a.js");
|
||||
const et = new EventTracker([file]);
|
||||
et.service.openClientFile(file.path);
|
||||
assert.equal(et.getEvents().length, 0);
|
||||
});
|
||||
it("only sends an event once", () => {
|
||||
const file = makeFile("/a.ts");
|
||||
const tsconfig = makeFile("/tsconfig.json", {});
|
||||
|
||||
const et = new EventTracker([file, tsconfig]);
|
||||
et.service.openClientFile(file.path);
|
||||
et.assertProjectInfoTelemetryEvent({});
|
||||
|
||||
et.service.closeClientFile(file.path);
|
||||
checkNumberOfProjects(et.service, { configuredProjects: 0 });
|
||||
|
||||
et.service.openClientFile(file.path);
|
||||
checkNumberOfProjects(et.service, { configuredProjects: 1 });
|
||||
|
||||
assert.equal(et.getEvents().length, 0);
|
||||
});
|
||||
|
||||
it("counts files by extension", () => {
|
||||
const files = ["ts.ts", "tsx.tsx", "moo.ts", "dts.d.ts", "jsx.jsx", "js.js", "badExtension.badExtension"].map(f => makeFile(`/src/${f}`));
|
||||
const notIncludedFile = makeFile("/bin/ts.js");
|
||||
const compilerOptions: ts.CompilerOptions = { allowJs: true };
|
||||
const tsconfig = makeFile("/tsconfig.json", { compilerOptions, include: ["src"] });
|
||||
|
||||
const et = new EventTracker([...files, notIncludedFile, tsconfig]);
|
||||
et.service.openClientFile(files[0].path);
|
||||
et.assertProjectInfoTelemetryEvent({
|
||||
fileStats: { ts: 2, tsx: 1, js: 1, jsx: 1, dts: 1 },
|
||||
compilerOptions,
|
||||
include: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("works with external project", () => {
|
||||
const file1 = makeFile("/a.ts");
|
||||
const et = new EventTracker([file1]);
|
||||
const compilerOptions: ts.server.protocol.CompilerOptions = { strict: true };
|
||||
|
||||
const projectFileName = "foo.csproj";
|
||||
|
||||
open();
|
||||
|
||||
// TODO: Apparently compilerOptions is mutated, so have to repeat it here!
|
||||
et.assertProjectInfoTelemetryEvent({
|
||||
compilerOptions: { strict: true },
|
||||
compileOnSave: true,
|
||||
// These properties can't be present for an external project, so they are undefined instead of false.
|
||||
extends: undefined,
|
||||
files: undefined,
|
||||
include: undefined,
|
||||
exclude: undefined,
|
||||
configFileName: "other",
|
||||
projectType: "external",
|
||||
});
|
||||
|
||||
// Also test that opening an external project only sends an event once.
|
||||
|
||||
et.service.closeExternalProject(projectFileName);
|
||||
checkNumberOfProjects(et.service, { externalProjects: 0 });
|
||||
|
||||
open();
|
||||
assert.equal(et.getEvents().length, 0);
|
||||
|
||||
function open(): void {
|
||||
et.service.openExternalProject({
|
||||
rootFiles: toExternalFiles([file1.path]),
|
||||
options: compilerOptions,
|
||||
projectFileName: projectFileName,
|
||||
});
|
||||
checkNumberOfProjects(et.service, { externalProjects: 1 });
|
||||
}
|
||||
});
|
||||
|
||||
it("does not expose paths", () => {
|
||||
const file = makeFile("/a.ts");
|
||||
|
||||
const compilerOptions: ts.CompilerOptions = {
|
||||
project: "",
|
||||
outFile: "hunter2.js",
|
||||
outDir: "hunter2",
|
||||
rootDir: "hunter2",
|
||||
baseUrl: "hunter2",
|
||||
rootDirs: ["hunter2"],
|
||||
typeRoots: ["hunter2"],
|
||||
types: ["hunter2"],
|
||||
sourceRoot: "hunter2",
|
||||
mapRoot: "hunter2",
|
||||
jsxFactory: "hunter2",
|
||||
out: "hunter2",
|
||||
reactNamespace: "hunter2",
|
||||
charset: "hunter2",
|
||||
locale: "hunter2",
|
||||
declarationDir: "hunter2",
|
||||
paths: {
|
||||
"*": ["hunter2"],
|
||||
},
|
||||
|
||||
// Boolean / number options get through
|
||||
declaration: true,
|
||||
|
||||
// List of string enum gets through -- but only if legitimately a member of the enum
|
||||
lib: ["es6", "dom", "hunter2"],
|
||||
|
||||
// Sensitive data doesn't get through even if sent to an option of safe type
|
||||
checkJs: "hunter2" as any as boolean,
|
||||
};
|
||||
const safeCompilerOptions: ts.CompilerOptions = {
|
||||
project: "",
|
||||
outFile: "",
|
||||
outDir: "",
|
||||
rootDir: "",
|
||||
baseUrl: "",
|
||||
rootDirs: [""],
|
||||
typeRoots: [""],
|
||||
types: [""],
|
||||
sourceRoot: "",
|
||||
mapRoot: "",
|
||||
jsxFactory: "",
|
||||
out: "",
|
||||
reactNamespace: "",
|
||||
charset: "",
|
||||
locale: "",
|
||||
declarationDir: "",
|
||||
paths: "" as any,
|
||||
|
||||
declaration: true,
|
||||
|
||||
lib: ["es6", "dom"],
|
||||
};
|
||||
(compilerOptions as any).unknownCompilerOption = "hunter2"; // These are always ignored.
|
||||
const tsconfig = makeFile("/tsconfig.json", { compilerOptions, files: ["/a.ts"] });
|
||||
|
||||
const et = new EventTracker([file, tsconfig]);
|
||||
et.service.openClientFile(file.path);
|
||||
|
||||
et.assertProjectInfoTelemetryEvent({
|
||||
compilerOptions: safeCompilerOptions,
|
||||
files: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("sends telemetry for extends, files, include, exclude, and compileOnSave", () => {
|
||||
const file = makeFile("/hunter2/a.ts");
|
||||
const tsconfig = makeFile("/tsconfig.json", {
|
||||
compilerOptions: {},
|
||||
extends: "hunter2.json",
|
||||
files: ["hunter2/a.ts"],
|
||||
include: ["hunter2"],
|
||||
exclude: ["hunter2"],
|
||||
compileOnSave: true,
|
||||
});
|
||||
|
||||
const et = new EventTracker([tsconfig, file]);
|
||||
et.service.openClientFile(file.path);
|
||||
et.assertProjectInfoTelemetryEvent({
|
||||
extends: true,
|
||||
files: true,
|
||||
include: true,
|
||||
exclude: true,
|
||||
compileOnSave: true,
|
||||
});
|
||||
});
|
||||
|
||||
const autoJsCompilerOptions = {
|
||||
// Apparently some options are added by default.
|
||||
allowJs: true,
|
||||
allowSyntheticDefaultImports: true,
|
||||
maxNodeModuleJsDepth: 2,
|
||||
skipLibCheck: true,
|
||||
};
|
||||
|
||||
it("sends telemetry for typeAcquisition settings", () => {
|
||||
const file = makeFile("/a.js");
|
||||
const jsconfig = makeFile("/jsconfig.json", {
|
||||
compilerOptions: {},
|
||||
typeAcquisition: {
|
||||
enable: true,
|
||||
enableAutoDiscovery: false,
|
||||
include: ["hunter2", "hunter3"],
|
||||
exclude: [],
|
||||
},
|
||||
});
|
||||
const et = new EventTracker([jsconfig, file]);
|
||||
et.service.openClientFile(file.path);
|
||||
et.assertProjectInfoTelemetryEvent({
|
||||
fileStats: fileStats({ js: 1 }),
|
||||
compilerOptions: autoJsCompilerOptions,
|
||||
typeAcquisition: {
|
||||
enable: true,
|
||||
include: true,
|
||||
exclude: false,
|
||||
},
|
||||
configFileName: "jsconfig.json",
|
||||
});
|
||||
});
|
||||
|
||||
it("detects whether language service was disabled", () => {
|
||||
const file = makeFile("/a.js");
|
||||
const tsconfig = makeFile("/jsconfig.json", {});
|
||||
const et = new EventTracker([tsconfig, file]);
|
||||
et.host.getFileSize = () => server.maxProgramSizeForNonTsFiles + 1;
|
||||
et.service.openClientFile(file.path);
|
||||
et.getEvent<server.ProjectLanguageServiceStateEvent>(server.ProjectLanguageServiceStateEvent, /*mayBeMore*/ true);
|
||||
et.assertProjectInfoTelemetryEvent({
|
||||
fileStats: fileStats({ js: 1 }),
|
||||
compilerOptions: autoJsCompilerOptions,
|
||||
configFileName: "jsconfig.json",
|
||||
typeAcquisition: {
|
||||
enable: true,
|
||||
include: false,
|
||||
exclude: false,
|
||||
},
|
||||
languageServiceEnabled: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
class EventTracker {
|
||||
private events: server.ProjectServiceEvent[] = [];
|
||||
readonly service: TestProjectService;
|
||||
readonly host: projectSystem.TestServerHost;
|
||||
|
||||
constructor(files: projectSystem.FileOrFolder[]) {
|
||||
this.host = createServerHost(files);
|
||||
this.service = createProjectService(this.host, {
|
||||
eventHandler: event => {
|
||||
this.events.push(event);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
getEvents(): ReadonlyArray<server.ProjectServiceEvent> {
|
||||
const events = this.events;
|
||||
this.events = [];
|
||||
return events;
|
||||
}
|
||||
|
||||
assertProjectInfoTelemetryEvent(partial: Partial<server.ProjectInfoTelemetryEventData>): void {
|
||||
assert.deepEqual(this.getEvent<server.ProjectInfoTelemetryEvent>(ts.server.ProjectInfoTelemetryEvent), makePayload(partial));
|
||||
}
|
||||
|
||||
getEvent<T extends server.ProjectServiceEvent>(eventName: T["eventName"], mayBeMore = false): T["data"] {
|
||||
if (mayBeMore) assert(this.events.length !== 0); else assert.equal(this.events.length, 1);
|
||||
const event = this.events.shift();
|
||||
assert.equal(event.eventName, eventName);
|
||||
return event.data;
|
||||
}
|
||||
}
|
||||
|
||||
function makePayload(partial: Partial<server.ProjectInfoTelemetryEventData>): server.ProjectInfoTelemetryEventData {
|
||||
return {
|
||||
fileStats: fileStats({ ts: 1 }),
|
||||
compilerOptions: {},
|
||||
extends: false,
|
||||
files: false,
|
||||
include: false,
|
||||
exclude: false,
|
||||
compileOnSave: false,
|
||||
typeAcquisition: {
|
||||
enable: false,
|
||||
exclude: false,
|
||||
include: false,
|
||||
},
|
||||
configFileName: "tsconfig.json",
|
||||
projectType: "configured",
|
||||
languageServiceEnabled: true,
|
||||
version: ts.version,
|
||||
...partial
|
||||
};
|
||||
}
|
||||
|
||||
function makeFile(path: string, content: {} = ""): projectSystem.FileOrFolder {
|
||||
return { path, content: typeof content === "string" ? "" : JSON.stringify(content) };
|
||||
}
|
||||
|
||||
function fileStats(nonZeroStats: Partial<server.FileStats>): server.FileStats {
|
||||
return { ts: 0, tsx: 0, dts: 0, js: 0, jsx: 0, ...nonZeroStats };
|
||||
}
|
||||
}
|
||||
@ -2234,7 +2234,7 @@ namespace ts.projectSystem {
|
||||
|
||||
let lastEvent: server.ProjectLanguageServiceStateEvent;
|
||||
const session = createSession(host, /*typingsInstaller*/ undefined, e => {
|
||||
if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ContextEvent) {
|
||||
if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ContextEvent || e.eventName === server.ProjectInfoTelemetryEvent) {
|
||||
return;
|
||||
}
|
||||
assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent);
|
||||
@ -2284,7 +2284,7 @@ namespace ts.projectSystem {
|
||||
filePath === f2.path ? server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath);
|
||||
let lastEvent: server.ProjectLanguageServiceStateEvent;
|
||||
const session = createSession(host, /*typingsInstaller*/ undefined, e => {
|
||||
if (e.eventName === server.ConfigFileDiagEvent) {
|
||||
if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ProjectInfoTelemetryEvent) {
|
||||
return;
|
||||
}
|
||||
assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent);
|
||||
|
||||
@ -44,7 +44,7 @@ namespace ts.projectSystem {
|
||||
});
|
||||
}
|
||||
|
||||
import typingsName = server.typingsInstaller.typingsName;
|
||||
import typingsName = TI.typingsName;
|
||||
|
||||
describe("local module", () => {
|
||||
it("should not be picked up", () => {
|
||||
@ -73,7 +73,7 @@ namespace ts.projectSystem {
|
||||
constructor() {
|
||||
super(host, { typesRegistry: createTypesRegistry("config"), globalTypingsCacheLocation: typesCache });
|
||||
}
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, _cb: server.typingsInstaller.RequestCompletedAction) {
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, _cb: TI.RequestCompletedAction) {
|
||||
assert(false, "should not be called");
|
||||
}
|
||||
})();
|
||||
@ -121,7 +121,7 @@ namespace ts.projectSystem {
|
||||
constructor() {
|
||||
super(host, { typesRegistry: createTypesRegistry("jquery") });
|
||||
}
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) {
|
||||
const installedTypings = ["@types/jquery"];
|
||||
const typingFiles = [jquery];
|
||||
executeCommand(this, host, installedTypings, typingFiles, cb);
|
||||
@ -165,7 +165,7 @@ namespace ts.projectSystem {
|
||||
constructor() {
|
||||
super(host, { typesRegistry: createTypesRegistry("jquery") });
|
||||
}
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) {
|
||||
const installedTypings = ["@types/jquery"];
|
||||
const typingFiles = [jquery];
|
||||
executeCommand(this, host, installedTypings, typingFiles, cb);
|
||||
@ -672,7 +672,7 @@ namespace ts.projectSystem {
|
||||
constructor() {
|
||||
super(host, { globalTypingsCacheLocation: "/tmp", typesRegistry: createTypesRegistry("jquery") });
|
||||
}
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) {
|
||||
const installedTypings = ["@types/jquery"];
|
||||
const typingFiles = [jqueryDTS];
|
||||
executeCommand(this, host, installedTypings, typingFiles, cb);
|
||||
@ -718,7 +718,7 @@ namespace ts.projectSystem {
|
||||
constructor() {
|
||||
super(host, { globalTypingsCacheLocation: "/tmp", typesRegistry: createTypesRegistry("jquery") });
|
||||
}
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) {
|
||||
const installedTypings = ["@types/jquery"];
|
||||
const typingFiles = [jqueryDTS];
|
||||
executeCommand(this, host, installedTypings, typingFiles, cb);
|
||||
@ -765,7 +765,7 @@ namespace ts.projectSystem {
|
||||
constructor() {
|
||||
super(host, { globalTypingsCacheLocation: "/tmp", typesRegistry: createTypesRegistry("jquery") });
|
||||
}
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) {
|
||||
const installedTypings = ["@types/jquery"];
|
||||
const typingFiles = [jqueryDTS];
|
||||
executeCommand(this, host, installedTypings, typingFiles, cb);
|
||||
@ -808,7 +808,7 @@ namespace ts.projectSystem {
|
||||
constructor() {
|
||||
super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry("commander") });
|
||||
}
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) {
|
||||
const installedTypings = ["@types/commander"];
|
||||
const typingFiles = [commander];
|
||||
executeCommand(this, host, installedTypings, typingFiles, cb);
|
||||
@ -849,7 +849,7 @@ namespace ts.projectSystem {
|
||||
constructor() {
|
||||
super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry("node", "commander") });
|
||||
}
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) {
|
||||
const installedTypings = ["@types/node", "@types/commander"];
|
||||
const typingFiles = [node, commander];
|
||||
executeCommand(this, host, installedTypings, typingFiles, cb);
|
||||
@ -888,7 +888,7 @@ namespace ts.projectSystem {
|
||||
constructor() {
|
||||
super(host, { globalTypingsCacheLocation: "/tmp", typesRegistry: createTypesRegistry("foo") });
|
||||
}
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) {
|
||||
executeCommand(this, host, ["foo"], [], cb);
|
||||
}
|
||||
})();
|
||||
@ -996,7 +996,7 @@ namespace ts.projectSystem {
|
||||
constructor() {
|
||||
super(host, { globalTypingsCacheLocation: "/tmp" }, { isEnabled: () => true, writeLine: msg => messages.push(msg) });
|
||||
}
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, _cb: server.typingsInstaller.RequestCompletedAction) {
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, _cb: TI.RequestCompletedAction) {
|
||||
assert(false, "runCommand should not be invoked");
|
||||
}
|
||||
})();
|
||||
@ -1060,7 +1060,7 @@ namespace ts.projectSystem {
|
||||
constructor() {
|
||||
super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry("commander") });
|
||||
}
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) {
|
||||
const installedTypings = ["@types/commander"];
|
||||
const typingFiles = [commander];
|
||||
executeCommand(this, host, installedTypings, typingFiles, cb);
|
||||
@ -1110,7 +1110,7 @@ namespace ts.projectSystem {
|
||||
constructor() {
|
||||
super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry("commander") });
|
||||
}
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) {
|
||||
const installedTypings = ["@types/commander"];
|
||||
const typingFiles = [commander];
|
||||
executeCommand(this, host, installedTypings, typingFiles, cb);
|
||||
@ -1157,7 +1157,7 @@ namespace ts.projectSystem {
|
||||
constructor() {
|
||||
super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry("commander") });
|
||||
}
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) {
|
||||
executeCommand(this, host, "", [], cb);
|
||||
}
|
||||
sendResponse(response: server.SetTypings | server.InvalidateCachedTypings | server.BeginInstallTypes | server.EndInstallTypes) {
|
||||
|
||||
@ -13,6 +13,7 @@ namespace ts.server {
|
||||
export const ContextEvent = "context";
|
||||
export const ConfigFileDiagEvent = "configFileDiag";
|
||||
export const ProjectLanguageServiceStateEvent = "projectLanguageServiceState";
|
||||
export const ProjectInfoTelemetryEvent = "projectInfo";
|
||||
|
||||
export interface ContextEvent {
|
||||
eventName: typeof ContextEvent;
|
||||
@ -29,7 +30,52 @@ namespace ts.server {
|
||||
data: { project: Project, languageServiceEnabled: boolean };
|
||||
}
|
||||
|
||||
export type ProjectServiceEvent = ContextEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent;
|
||||
/** This will be converted to the payload of a protocol.TelemetryEvent in session.defaultEventHandler. */
|
||||
export interface ProjectInfoTelemetryEvent {
|
||||
readonly eventName: typeof ProjectInfoTelemetryEvent;
|
||||
readonly data: ProjectInfoTelemetryEventData;
|
||||
}
|
||||
|
||||
export interface ProjectInfoTelemetryEventData {
|
||||
/** Count of file extensions seen in the project. */
|
||||
readonly fileStats: FileStats;
|
||||
/**
|
||||
* Any compiler options that might contain paths will be taken out.
|
||||
* Enum compiler options will be converted to strings.
|
||||
*/
|
||||
readonly compilerOptions: ts.CompilerOptions;
|
||||
// "extends", "files", "include", or "exclude" will be undefined if an external config is used.
|
||||
// Otherwise, we will use "true" if the property is present and "false" if it is missing.
|
||||
readonly extends: boolean | undefined;
|
||||
readonly files: boolean | undefined;
|
||||
readonly include: boolean | undefined;
|
||||
readonly exclude: boolean | undefined;
|
||||
readonly compileOnSave: boolean;
|
||||
readonly typeAcquisition: ProjectInfoTypeAcquisitionData;
|
||||
|
||||
readonly configFileName: "tsconfig.json" | "jsconfig.json" | "other";
|
||||
readonly projectType: "external" | "configured";
|
||||
readonly languageServiceEnabled: boolean;
|
||||
/** TypeScript version used by the server. */
|
||||
readonly version: string;
|
||||
}
|
||||
|
||||
export interface ProjectInfoTypeAcquisitionData {
|
||||
readonly enable: boolean;
|
||||
// Actual values of include/exclude entries are scrubbed.
|
||||
readonly include: boolean;
|
||||
readonly exclude: boolean;
|
||||
}
|
||||
|
||||
export interface FileStats {
|
||||
readonly js: number;
|
||||
readonly jsx: number;
|
||||
readonly ts: number;
|
||||
readonly tsx: number;
|
||||
readonly dts: number;
|
||||
}
|
||||
|
||||
export type ProjectServiceEvent = ContextEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent;
|
||||
|
||||
export interface ProjectServiceEventHandler {
|
||||
(event: ProjectServiceEvent): void;
|
||||
@ -345,6 +391,9 @@ namespace ts.server {
|
||||
public readonly pluginProbeLocations: ReadonlyArray<string>;
|
||||
public readonly allowLocalPluginLoads: boolean;
|
||||
|
||||
/** Tracks projects that we have already sent telemetry for. */
|
||||
private readonly seenProjects = createMap<true>();
|
||||
|
||||
constructor(opts: ProjectServiceOptions) {
|
||||
this.host = opts.host;
|
||||
this.logger = opts.logger;
|
||||
@ -928,7 +977,10 @@ namespace ts.server {
|
||||
const projectOptions: ProjectOptions = {
|
||||
files: parsedCommandLine.fileNames,
|
||||
compilerOptions: parsedCommandLine.options,
|
||||
configHasExtendsProperty: parsedCommandLine.raw["extends"] !== undefined,
|
||||
configHasFilesProperty: parsedCommandLine.raw["files"] !== undefined,
|
||||
configHasIncludeProperty: parsedCommandLine.raw["include"] !== undefined,
|
||||
configHasExcludeProperty: parsedCommandLine.raw["exclude"] !== undefined,
|
||||
wildcardDirectories: createMapFromTemplate(parsedCommandLine.wildcardDirectories),
|
||||
typeAcquisition: parsedCommandLine.typeAcquisition,
|
||||
compileOnSave: parsedCommandLine.compileOnSave
|
||||
@ -978,9 +1030,53 @@ namespace ts.server {
|
||||
|
||||
this.addFilesToProjectAndUpdateGraph(project, files, externalFilePropertyReader, /*clientFileName*/ undefined, typeAcquisition, /*configFileErrors*/ undefined);
|
||||
this.externalProjects.push(project);
|
||||
this.sendProjectTelemetry(project.externalProjectName, project);
|
||||
return project;
|
||||
}
|
||||
|
||||
private sendProjectTelemetry(projectKey: string, project: server.ExternalProject | server.ConfiguredProject, projectOptions?: ProjectOptions): void {
|
||||
if (this.seenProjects.has(projectKey)) {
|
||||
return;
|
||||
}
|
||||
this.seenProjects.set(projectKey, true);
|
||||
|
||||
if (!this.eventHandler) return;
|
||||
|
||||
const data: ProjectInfoTelemetryEventData = {
|
||||
fileStats: countEachFileTypes(project.getScriptInfos()),
|
||||
compilerOptions: convertCompilerOptionsForTelemetry(project.getCompilerOptions()),
|
||||
typeAcquisition: convertTypeAcquisition(project.getTypeAcquisition()),
|
||||
extends: projectOptions && projectOptions.configHasExtendsProperty,
|
||||
files: projectOptions && projectOptions.configHasFilesProperty,
|
||||
include: projectOptions && projectOptions.configHasIncludeProperty,
|
||||
exclude: projectOptions && projectOptions.configHasExcludeProperty,
|
||||
compileOnSave: project.compileOnSaveEnabled,
|
||||
configFileName: configFileName(),
|
||||
projectType: project instanceof server.ExternalProject ? "external" : "configured",
|
||||
languageServiceEnabled: project.languageServiceEnabled,
|
||||
version: ts.version,
|
||||
};
|
||||
this.eventHandler({ eventName: ProjectInfoTelemetryEvent, data });
|
||||
|
||||
function configFileName(): ProjectInfoTelemetryEventData["configFileName"] {
|
||||
if (!(project instanceof server.ConfiguredProject)) {
|
||||
return "other";
|
||||
}
|
||||
|
||||
const configFilePath = project instanceof server.ConfiguredProject && project.getConfigFilePath();
|
||||
const base = ts.getBaseFileName(configFilePath);
|
||||
return base === "tsconfig.json" || base === "jsconfig.json" ? base : "other";
|
||||
}
|
||||
|
||||
function convertTypeAcquisition({ enable, include, exclude }: TypeAcquisition): ProjectInfoTypeAcquisitionData {
|
||||
return {
|
||||
enable,
|
||||
include: include !== undefined && include.length !== 0,
|
||||
exclude: exclude !== undefined && exclude.length !== 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private reportConfigFileDiagnostics(configFileName: string, diagnostics: Diagnostic[], triggerFile: string) {
|
||||
if (!this.eventHandler) {
|
||||
return;
|
||||
@ -1014,6 +1110,7 @@ namespace ts.server {
|
||||
project.watchTypeRoots((project, path) => this.onTypeRootFileChanged(project, path));
|
||||
|
||||
this.configuredProjects.push(project);
|
||||
this.sendProjectTelemetry(project.getConfigFilePath(), project, projectOptions);
|
||||
return project;
|
||||
}
|
||||
|
||||
@ -1046,7 +1143,7 @@ namespace ts.server {
|
||||
const conversionResult = this.convertConfigFileContentToProjectOptions(configFileName);
|
||||
const projectOptions: ProjectOptions = conversionResult.success
|
||||
? conversionResult.projectOptions
|
||||
: { files: [], compilerOptions: {}, typeAcquisition: { enable: false } };
|
||||
: { files: [], compilerOptions: {}, configHasExtendsProperty: false, configHasFilesProperty: false, configHasIncludeProperty: false, configHasExcludeProperty: false, typeAcquisition: { enable: false } };
|
||||
const project = this.createAndAddConfiguredProject(configFileName, projectOptions, conversionResult.configFileErrors, clientFileName);
|
||||
return {
|
||||
success: conversionResult.success,
|
||||
|
||||
@ -13,7 +13,8 @@ namespace ts.server {
|
||||
External
|
||||
}
|
||||
|
||||
function countEachFileTypes(infos: ScriptInfo[]): { js: number, jsx: number, ts: number, tsx: number, dts: number } {
|
||||
/* @internal */
|
||||
export function countEachFileTypes(infos: ScriptInfo[]): FileStats {
|
||||
const result = { js: 0, jsx: 0, ts: 0, tsx: 0, dts: 0 };
|
||||
for (const info of infos) {
|
||||
switch (info.scriptKind) {
|
||||
@ -767,6 +768,10 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If a file is opened and no tsconfig (or jsconfig) is found,
|
||||
* the file and its imports/references are put into an InferredProject.
|
||||
*/
|
||||
export class InferredProject extends Project {
|
||||
|
||||
private static newName = (() => {
|
||||
@ -860,6 +865,11 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If a file is opened, the server will look for a tsconfig (or jsconfig)
|
||||
* and if successfull create a ConfiguredProject for it.
|
||||
* Otherwise it will create an InferredProject.
|
||||
*/
|
||||
export class ConfiguredProject extends Project {
|
||||
private typeAcquisition: TypeAcquisition;
|
||||
private projectFileWatcher: FileWatcher;
|
||||
@ -1085,6 +1095,10 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Project whose configuration is handled externally, such as in a '.csproj'.
|
||||
* These are created only if a host explicitly calls `openExternalProject`.
|
||||
*/
|
||||
export class ExternalProject extends Project {
|
||||
private typeAcquisition: TypeAcquisition;
|
||||
constructor(public externalProjectName: string,
|
||||
|
||||
@ -13,6 +13,7 @@ namespace ts.server {
|
||||
globalTypingsCacheLocation: string;
|
||||
logger: Logger;
|
||||
typingSafeListLocation: string;
|
||||
npmLocation: string | undefined;
|
||||
telemetryEnabled: boolean;
|
||||
globalPlugins: string[];
|
||||
pluginProbeLocations: string[];
|
||||
@ -234,6 +235,7 @@ namespace ts.server {
|
||||
eventPort: number,
|
||||
readonly globalTypingsCacheLocation: string,
|
||||
readonly typingSafeListLocation: string,
|
||||
private readonly npmLocation: string | undefined,
|
||||
private newLine: string) {
|
||||
this.throttledOperations = new ThrottledOperations(host);
|
||||
if (eventPort) {
|
||||
@ -278,19 +280,21 @@ namespace ts.server {
|
||||
if (this.typingSafeListLocation) {
|
||||
args.push(Arguments.TypingSafeListLocation, this.typingSafeListLocation);
|
||||
}
|
||||
if (this.npmLocation) {
|
||||
args.push(Arguments.NpmLocation, this.npmLocation);
|
||||
}
|
||||
|
||||
const execArgv: string[] = [];
|
||||
{
|
||||
for (const arg of process.execArgv) {
|
||||
const match = /^--(debug|inspect)(=(\d+))?$/.exec(arg);
|
||||
if (match) {
|
||||
// if port is specified - use port + 1
|
||||
// otherwise pick a default port depending on if 'debug' or 'inspect' and use its value + 1
|
||||
const currentPort = match[3] !== undefined
|
||||
? +match[3]
|
||||
: match[1] === "debug" ? 5858 : 9229;
|
||||
execArgv.push(`--${match[1]}=${currentPort + 1}`);
|
||||
break;
|
||||
}
|
||||
for (const arg of process.execArgv) {
|
||||
const match = /^--(debug|inspect)(=(\d+))?$/.exec(arg);
|
||||
if (match) {
|
||||
// if port is specified - use port + 1
|
||||
// otherwise pick a default port depending on if 'debug' or 'inspect' and use its value + 1
|
||||
const currentPort = match[3] !== undefined
|
||||
? +match[3]
|
||||
: match[1] === "debug" ? 5858 : 9229;
|
||||
execArgv.push(`--${match[1]}=${currentPort + 1}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -389,10 +393,10 @@ namespace ts.server {
|
||||
|
||||
class IOSession extends Session {
|
||||
constructor(options: IOSessionOptions) {
|
||||
const { host, installerEventPort, globalTypingsCacheLocation, typingSafeListLocation, canUseEvents } = options;
|
||||
const { host, installerEventPort, globalTypingsCacheLocation, typingSafeListLocation, npmLocation, canUseEvents } = options;
|
||||
const typingsInstaller = disableAutomaticTypingAcquisition
|
||||
? undefined
|
||||
: new NodeTypingsInstaller(telemetryEnabled, logger, host, installerEventPort, globalTypingsCacheLocation, typingSafeListLocation, host.newLine);
|
||||
: new NodeTypingsInstaller(telemetryEnabled, logger, host, installerEventPort, globalTypingsCacheLocation, typingSafeListLocation, npmLocation, host.newLine);
|
||||
|
||||
super({
|
||||
host,
|
||||
@ -741,7 +745,8 @@ namespace ts.server {
|
||||
validateLocaleAndSetLanguage(localeStr, sys);
|
||||
}
|
||||
|
||||
const typingSafeListLocation = findArgument("--typingSafeListLocation");
|
||||
const typingSafeListLocation = findArgument(Arguments.TypingSafeListLocation);
|
||||
const npmLocation = findArgument(Arguments.NpmLocation);
|
||||
|
||||
const globalPlugins = (findArgument("--globalPlugins") || "").split(",");
|
||||
const pluginProbeLocations = (findArgument("--pluginProbeLocations") || "").split(",");
|
||||
@ -760,6 +765,7 @@ namespace ts.server {
|
||||
disableAutomaticTypingAcquisition,
|
||||
globalTypingsCacheLocation: getGlobalTypingsCacheLocation(),
|
||||
typingSafeListLocation,
|
||||
npmLocation,
|
||||
telemetryEnabled,
|
||||
logger,
|
||||
globalPlugins,
|
||||
|
||||
@ -343,13 +343,22 @@ namespace ts.server {
|
||||
const { triggerFile, configFileName, diagnostics } = event.data;
|
||||
this.configFileDiagnosticEvent(triggerFile, configFileName, diagnostics);
|
||||
break;
|
||||
case ProjectLanguageServiceStateEvent:
|
||||
case ProjectLanguageServiceStateEvent: {
|
||||
const eventName: protocol.ProjectLanguageServiceStateEventName = "projectLanguageServiceState";
|
||||
this.event<protocol.ProjectLanguageServiceStateEventBody>({
|
||||
projectName: event.data.project.getProjectName(),
|
||||
languageServiceEnabled: event.data.languageServiceEnabled
|
||||
}, eventName);
|
||||
break;
|
||||
}
|
||||
case ProjectInfoTelemetryEvent: {
|
||||
const eventName: protocol.TelemetryEventName = "telemetry";
|
||||
this.event<protocol.TelemetryEventBody>({
|
||||
telemetryEventName: event.eventName,
|
||||
payload: event.data,
|
||||
}, eventName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -12,13 +12,18 @@ namespace ts.server {
|
||||
export const LogFile = "--logFile";
|
||||
export const EnableTelemetry = "--enableTelemetry";
|
||||
export const TypingSafeListLocation = "--typingSafeListLocation";
|
||||
/**
|
||||
* This argument specifies the location of the NPM executable.
|
||||
* typingsInstaller will run the command with `${npmLocation} install ...`.
|
||||
*/
|
||||
export const NpmLocation = "--npmLocation";
|
||||
}
|
||||
|
||||
export function hasArgument(argumentName: string) {
|
||||
return sys.args.indexOf(argumentName) >= 0;
|
||||
}
|
||||
|
||||
export function findArgument(argumentName: string) {
|
||||
export function findArgument(argumentName: string): string | undefined {
|
||||
const index = sys.args.indexOf(argumentName);
|
||||
return index >= 0 && index < sys.args.length - 1
|
||||
? sys.args[index + 1]
|
||||
|
||||
@ -30,7 +30,8 @@ namespace ts.server.typingsInstaller {
|
||||
}
|
||||
}
|
||||
|
||||
function getNPMLocation(processName: string) {
|
||||
/** Used if `--npmLocation` is not passed. */
|
||||
function getDefaultNPMLocation(processName: string) {
|
||||
if (path.basename(processName).indexOf("node") === 0) {
|
||||
return `"${path.join(path.dirname(process.argv[0]), "npm")}"`;
|
||||
}
|
||||
@ -76,17 +77,23 @@ namespace ts.server.typingsInstaller {
|
||||
|
||||
private delayedInitializationError: InitializationFailedResponse;
|
||||
|
||||
constructor(globalTypingsCacheLocation: string, typingSafeListLocation: string, throttleLimit: number, log: Log) {
|
||||
constructor(globalTypingsCacheLocation: string, typingSafeListLocation: string, npmLocation: string | undefined, throttleLimit: number, log: Log) {
|
||||
super(
|
||||
sys,
|
||||
globalTypingsCacheLocation,
|
||||
typingSafeListLocation ? toPath(typingSafeListLocation, "", createGetCanonicalFileName(sys.useCaseSensitiveFileNames)) : toPath("typingSafeList.json", __dirname, createGetCanonicalFileName(sys.useCaseSensitiveFileNames)),
|
||||
throttleLimit,
|
||||
log);
|
||||
this.npmPath = npmLocation !== undefined ? npmLocation : getDefaultNPMLocation(process.argv[0]);
|
||||
|
||||
// If the NPM path contains spaces and isn't wrapped in quotes, do so.
|
||||
if (this.npmPath.indexOf(" ") !== -1 && this.npmPath[0] !== `"`) {
|
||||
this.npmPath = `"${this.npmPath}"`;
|
||||
}
|
||||
if (this.log.isEnabled()) {
|
||||
this.log.writeLine(`Process id: ${process.pid}`);
|
||||
this.log.writeLine(`NPM location: ${this.npmPath} (explicit '${Arguments.NpmLocation}' ${npmLocation === undefined ? "not " : ""} provided)`);
|
||||
}
|
||||
this.npmPath = getNPMLocation(process.argv[0]);
|
||||
({ execSync: this.execSync } = require("child_process"));
|
||||
|
||||
this.ensurePackageDirectoryExists(globalTypingsCacheLocation);
|
||||
@ -168,6 +175,7 @@ namespace ts.server.typingsInstaller {
|
||||
const logFilePath = findArgument(server.Arguments.LogFile);
|
||||
const globalTypingsCacheLocation = findArgument(server.Arguments.GlobalCacheLocation);
|
||||
const typingSafeListLocation = findArgument(server.Arguments.TypingSafeListLocation);
|
||||
const npmLocation = findArgument(server.Arguments.NpmLocation);
|
||||
|
||||
const log = new FileLog(logFilePath);
|
||||
if (log.isEnabled()) {
|
||||
@ -181,6 +189,6 @@ namespace ts.server.typingsInstaller {
|
||||
}
|
||||
process.exit(0);
|
||||
});
|
||||
const installer = new NodeTypingsInstaller(globalTypingsCacheLocation, typingSafeListLocation, /*throttleLimit*/5, log);
|
||||
const installer = new NodeTypingsInstaller(globalTypingsCacheLocation, typingSafeListLocation, npmLocation, /*throttleLimit*/5, log);
|
||||
installer.listen();
|
||||
}
|
||||
}
|
||||
|
||||
@ -164,10 +164,13 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
export interface ProjectOptions {
|
||||
configHasExtendsProperty: boolean;
|
||||
/**
|
||||
* true if config file explicitly listed files
|
||||
*/
|
||||
configHasFilesProperty?: boolean;
|
||||
configHasFilesProperty: boolean;
|
||||
configHasIncludeProperty: boolean;
|
||||
configHasExcludeProperty: boolean;
|
||||
/**
|
||||
* these fields can be present in the project file
|
||||
*/
|
||||
|
||||
@ -685,9 +685,9 @@ namespace ts {
|
||||
continue;
|
||||
}
|
||||
|
||||
// for the ======== add a comment for the first line, and then lex all
|
||||
// subsequent lines up until the end of the conflict marker.
|
||||
Debug.assert(ch === CharacterCodes.equals);
|
||||
// for the ||||||| and ======== markers, add a comment for the first line,
|
||||
// and then lex all subsequent lines up until the end of the conflict marker.
|
||||
Debug.assert(ch === CharacterCodes.bar || ch === CharacterCodes.equals);
|
||||
classifyDisabledMergeCode(text, start, end);
|
||||
}
|
||||
}
|
||||
@ -782,8 +782,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function classifyDisabledMergeCode(text: string, start: number, end: number) {
|
||||
// Classify the line that the ======= marker is on as a comment. Then just lex
|
||||
// all further tokens and add them to the result.
|
||||
// Classify the line that the ||||||| or ======= marker is on as a comment.
|
||||
// Then just lex all further tokens and add them to the result.
|
||||
let i: number;
|
||||
for (i = start; i < end; i++) {
|
||||
if (isLineBreak(text.charCodeAt(i))) {
|
||||
|
||||
@ -386,7 +386,7 @@ namespace ts.FindAllReferences.Core {
|
||||
const searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), symbol.declarations);
|
||||
|
||||
const result: SymbolAndEntries[] = [];
|
||||
const state = createState(sourceFiles, node, checker, cancellationToken, searchMeaning, options, result);
|
||||
const state = new State(sourceFiles, /*isForConstructor*/ node.kind === SyntaxKind.ConstructorKeyword, checker, cancellationToken, searchMeaning, options, result);
|
||||
const search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { allSearchSymbols: populateSearchSymbolSet(symbol, node, checker, options.implementations) });
|
||||
|
||||
// Try to get the smallest valid scope that we can limit our search to;
|
||||
@ -446,35 +446,9 @@ namespace ts.FindAllReferences.Core {
|
||||
* Holds all state needed for the finding references.
|
||||
* Unlike `Search`, there is only one `State`.
|
||||
*/
|
||||
interface State extends Options {
|
||||
/** True if we're searching for constructor references. */
|
||||
readonly isForConstructor: boolean;
|
||||
|
||||
readonly sourceFiles: SourceFile[];
|
||||
readonly checker: TypeChecker;
|
||||
readonly cancellationToken: CancellationToken;
|
||||
readonly searchMeaning: SemanticMeaning;
|
||||
|
||||
class State {
|
||||
/** Cache for `explicitlyinheritsFrom`. */
|
||||
readonly inheritsFromCache: Map<boolean>;
|
||||
|
||||
/** Gets every place to look for references of an exported symbols. See `ImportsResult` in `importTracker.ts` for more documentation. */
|
||||
getImportSearches(exportSymbol: Symbol, exportInfo: ExportInfo): ImportsResult;
|
||||
|
||||
/** @param allSearchSymbols set of additinal symbols for use by `includes`. */
|
||||
createSearch(location: Node, symbol: Symbol, comingFrom: ImportExport | undefined, searchOptions?: { text?: string, allSearchSymbols?: Symbol[] }): Search;
|
||||
|
||||
/**
|
||||
* Callback to add references for a particular searched symbol.
|
||||
* This initializes a reference group, so only call this if you will add at least one reference.
|
||||
*/
|
||||
referenceAdder(searchSymbol: Symbol, searchLocation: Node): (node: Node) => void;
|
||||
|
||||
/** Add a reference with no associated definition. */
|
||||
addStringOrCommentReference(fileName: string, textSpan: TextSpan): void;
|
||||
|
||||
/** Returns `true` the first time we search for a symbol in a file and `false` afterwards. */
|
||||
markSearchedSymbol(sourceFile: SourceFile, symbol: Symbol): boolean;
|
||||
readonly inheritsFromCache = createMap<boolean>();
|
||||
|
||||
/**
|
||||
* Type nodes can contain multiple references to the same type. For example:
|
||||
@ -483,7 +457,7 @@ namespace ts.FindAllReferences.Core {
|
||||
* duplicate entries would be returned here as each of the type references is part of
|
||||
* the same implementation. For that reason, check before we add a new entry.
|
||||
*/
|
||||
markSeenContainingTypeReference(containingTypeReference: Node): boolean;
|
||||
readonly markSeenContainingTypeReference = nodeSeenTracker();
|
||||
|
||||
/**
|
||||
* It's possible that we will encounter the right side of `export { foo as bar } from "x";` more than once.
|
||||
@ -496,33 +470,31 @@ namespace ts.FindAllReferences.Core {
|
||||
* But another reference to it may appear in the same source file.
|
||||
* See `tests/cases/fourslash/transitiveExportImports3.ts`.
|
||||
*/
|
||||
markSeenReExportRHS(rhs: Identifier): boolean;
|
||||
}
|
||||
readonly markSeenReExportRHS = nodeSeenTracker();
|
||||
|
||||
function createState(sourceFiles: SourceFile[], originalLocation: Node, checker: TypeChecker, cancellationToken: CancellationToken, searchMeaning: SemanticMeaning, options: Options, result: Push<SymbolAndEntries>): State {
|
||||
const symbolIdToReferences: Entry[][] = [];
|
||||
const inheritsFromCache = createMap<boolean>();
|
||||
// Source file ID → symbol ID → Whether the symbol has been searched for in the source file.
|
||||
const sourceFileToSeenSymbols: Array<Array<true>> = [];
|
||||
const isForConstructor = originalLocation.kind === SyntaxKind.ConstructorKeyword;
|
||||
let importTracker: ImportTracker | undefined;
|
||||
constructor(
|
||||
readonly sourceFiles: SourceFile[],
|
||||
/** True if we're searching for constructor references. */
|
||||
readonly isForConstructor: boolean,
|
||||
readonly checker: TypeChecker,
|
||||
readonly cancellationToken: CancellationToken,
|
||||
readonly searchMeaning: SemanticMeaning,
|
||||
readonly options: Options,
|
||||
private readonly result: Push<SymbolAndEntries>) {}
|
||||
|
||||
return {
|
||||
...options,
|
||||
sourceFiles, isForConstructor, checker, cancellationToken, searchMeaning, inheritsFromCache, getImportSearches, createSearch, referenceAdder, addStringOrCommentReference,
|
||||
markSearchedSymbol, markSeenContainingTypeReference: nodeSeenTracker(), markSeenReExportRHS: nodeSeenTracker(),
|
||||
};
|
||||
|
||||
function getImportSearches(exportSymbol: Symbol, exportInfo: ExportInfo): ImportsResult {
|
||||
if (!importTracker) importTracker = createImportTracker(sourceFiles, checker, cancellationToken);
|
||||
return importTracker(exportSymbol, exportInfo, options.isForRename);
|
||||
private importTracker: ImportTracker | undefined;
|
||||
/** Gets every place to look for references of an exported symbols. See `ImportsResult` in `importTracker.ts` for more documentation. */
|
||||
getImportSearches(exportSymbol: Symbol, exportInfo: ExportInfo): ImportsResult {
|
||||
if (!this.importTracker) this.importTracker = createImportTracker(this.sourceFiles, this.checker, this.cancellationToken);
|
||||
return this.importTracker(exportSymbol, exportInfo, this.options.isForRename);
|
||||
}
|
||||
|
||||
function createSearch(location: Node, symbol: Symbol, comingFrom: ImportExport, searchOptions: { text?: string, allSearchSymbols?: Symbol[] } = {}): Search {
|
||||
/** @param allSearchSymbols set of additinal symbols for use by `includes`. */
|
||||
createSearch(location: Node, symbol: Symbol, comingFrom: ImportExport | undefined, searchOptions: { text?: string, allSearchSymbols?: Symbol[] } = {}): Search {
|
||||
// Note: if this is an external module symbol, the name doesn't include quotes.
|
||||
const { text = stripQuotes(getDeclaredName(checker, symbol, location)), allSearchSymbols = undefined } = searchOptions;
|
||||
const { text = stripQuotes(getDeclaredName(this.checker, symbol, location)), allSearchSymbols = undefined } = searchOptions;
|
||||
const escapedText = escapeIdentifier(text);
|
||||
const parents = options.implementations && getParentSymbolsOfPropertyAccess(location, symbol, checker);
|
||||
const parents = this.options.implementations && getParentSymbolsOfPropertyAccess(location, symbol, this.checker);
|
||||
return { location, symbol, comingFrom, text, escapedText, parents, includes };
|
||||
|
||||
function includes(referenceSymbol: Symbol): boolean {
|
||||
@ -530,27 +502,36 @@ namespace ts.FindAllReferences.Core {
|
||||
}
|
||||
}
|
||||
|
||||
function referenceAdder(referenceSymbol: Symbol, searchLocation: Node): (node: Node) => void {
|
||||
const symbolId = getSymbolId(referenceSymbol);
|
||||
let references = symbolIdToReferences[symbolId];
|
||||
private readonly symbolIdToReferences: Entry[][] = [];
|
||||
/**
|
||||
* Callback to add references for a particular searched symbol.
|
||||
* This initializes a reference group, so only call this if you will add at least one reference.
|
||||
*/
|
||||
referenceAdder(searchSymbol: Symbol, searchLocation: Node): (node: Node) => void {
|
||||
const symbolId = getSymbolId(searchSymbol);
|
||||
let references = this.symbolIdToReferences[symbolId];
|
||||
if (!references) {
|
||||
references = symbolIdToReferences[symbolId] = [];
|
||||
result.push({ definition: { type: "symbol", symbol: referenceSymbol, node: searchLocation }, references });
|
||||
references = this.symbolIdToReferences[symbolId] = [];
|
||||
this.result.push({ definition: { type: "symbol", symbol: searchSymbol, node: searchLocation }, references });
|
||||
}
|
||||
return node => references.push(nodeEntry(node));
|
||||
}
|
||||
|
||||
function addStringOrCommentReference(fileName: string, textSpan: TextSpan): void {
|
||||
result.push({
|
||||
/** Add a reference with no associated definition. */
|
||||
addStringOrCommentReference(fileName: string, textSpan: TextSpan): void {
|
||||
this.result.push({
|
||||
definition: undefined,
|
||||
references: [{ type: "span", fileName, textSpan }]
|
||||
});
|
||||
}
|
||||
|
||||
function markSearchedSymbol(sourceFile: SourceFile, symbol: Symbol): boolean {
|
||||
// Source file ID → symbol ID → Whether the symbol has been searched for in the source file.
|
||||
private readonly sourceFileToSeenSymbols: Array<Array<true>> = [];
|
||||
/** Returns `true` the first time we search for a symbol in a file and `false` afterwards. */
|
||||
markSearchedSymbol(sourceFile: SourceFile, symbol: Symbol): boolean {
|
||||
const sourceId = getNodeId(sourceFile);
|
||||
const symbolId = getSymbolId(symbol);
|
||||
const seenSymbols = sourceFileToSeenSymbols[sourceId] || (sourceFileToSeenSymbols[sourceId] = []);
|
||||
const seenSymbols = this.sourceFileToSeenSymbols[sourceId] || (this.sourceFileToSeenSymbols[sourceId] = []);
|
||||
return !seenSymbols[symbolId] && (seenSymbols[symbolId] = true);
|
||||
}
|
||||
}
|
||||
@ -580,7 +561,7 @@ namespace ts.FindAllReferences.Core {
|
||||
break;
|
||||
case ExportKind.Default:
|
||||
// Search for a property access to '.default'. This can't be renamed.
|
||||
indirectSearch = state.isForRename ? undefined : state.createSearch(exportLocation, exportSymbol, ImportExport.Export, { text: "default" });
|
||||
indirectSearch = state.options.isForRename ? undefined : state.createSearch(exportLocation, exportSymbol, ImportExport.Export, { text: "default" });
|
||||
break;
|
||||
case ExportKind.ExportEquals:
|
||||
break;
|
||||
@ -650,10 +631,12 @@ namespace ts.FindAllReferences.Core {
|
||||
|
||||
// If this is private property or method, the scope is the containing class
|
||||
if (flags & (SymbolFlags.Property | SymbolFlags.Method)) {
|
||||
const privateDeclaration = find(declarations, d => !!(getModifierFlags(d) & ModifierFlags.Private));
|
||||
const privateDeclaration = find(declarations, d => hasModifier(d, ModifierFlags.Private));
|
||||
if (privateDeclaration) {
|
||||
return getAncestor(privateDeclaration, SyntaxKind.ClassDeclaration);
|
||||
}
|
||||
// Else this is a public property and could be accessed from anywhere.
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// If symbol is of object binding pattern element without property name we would want to
|
||||
@ -669,11 +652,6 @@ namespace ts.FindAllReferences.Core {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// If this is a synthetic property, it's a property and must be searched for globally.
|
||||
if ((flags & SymbolFlags.Transient && (<TransientSymbol>symbol).checkFlags & CheckFlags.Synthetic)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let scope: Node | undefined;
|
||||
for (const declaration of declarations) {
|
||||
const container = getContainerNode(declaration);
|
||||
@ -806,7 +784,8 @@ namespace ts.FindAllReferences.Core {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const position of getPossibleSymbolReferencePositions(sourceFile, search.text, container, /*fullStart*/ state.findInComments || container.jsDoc !== undefined)) {
|
||||
const fullStart = state.options.findInComments || container.jsDoc !== undefined || forEach(search.symbol.declarations, d => d.kind === ts.SyntaxKind.JSDocTypedefTag);
|
||||
for (const position of getPossibleSymbolReferencePositions(sourceFile, search.text, container, fullStart)) {
|
||||
getReferencesAtLocation(sourceFile, position, search, state);
|
||||
}
|
||||
}
|
||||
@ -818,7 +797,7 @@ namespace ts.FindAllReferences.Core {
|
||||
// This wasn't the start of a token. Check to see if it might be a
|
||||
// match in a comment or string if that's what the caller is asking
|
||||
// for.
|
||||
if (!state.implementations && (state.findInStrings && isInString(sourceFile, position) || state.findInComments && isInNonReferenceComment(sourceFile, position))) {
|
||||
if (!state.options.implementations && (state.options.findInStrings && isInString(sourceFile, position) || state.options.findInComments && isInNonReferenceComment(sourceFile, position))) {
|
||||
// In the case where we're looking inside comments/strings, we don't have
|
||||
// an actual definition. So just use 'undefined' here. Features like
|
||||
// 'Rename' won't care (as they ignore the definitions), and features like
|
||||
@ -884,7 +863,7 @@ namespace ts.FindAllReferences.Core {
|
||||
addRef();
|
||||
}
|
||||
|
||||
if (!state.isForRename && state.markSeenReExportRHS(name)) {
|
||||
if (!state.options.isForRename && state.markSeenReExportRHS(name)) {
|
||||
addReference(name, referenceSymbol, name, state);
|
||||
}
|
||||
}
|
||||
@ -895,7 +874,7 @@ namespace ts.FindAllReferences.Core {
|
||||
}
|
||||
|
||||
// For `export { foo as bar }`, rename `foo`, but not `bar`.
|
||||
if (!(referenceLocation === propertyName && state.isForRename)) {
|
||||
if (!(referenceLocation === propertyName && state.options.isForRename)) {
|
||||
const exportKind = (referenceLocation as Identifier).originalKeywordKind === ts.SyntaxKind.DefaultKeyword ? ExportKind.Default : ExportKind.Named;
|
||||
const exportInfo = getExportInfo(referenceSymbol, exportKind, state.checker);
|
||||
Debug.assert(!!exportInfo);
|
||||
@ -937,7 +916,7 @@ namespace ts.FindAllReferences.Core {
|
||||
const { symbol } = importOrExport;
|
||||
|
||||
if (importOrExport.kind === ImportExport.Import) {
|
||||
if (!state.isForRename || importOrExport.isNamedImport) {
|
||||
if (!state.options.isForRename || importOrExport.isNamedImport) {
|
||||
searchForImportedSymbol(symbol, state);
|
||||
}
|
||||
}
|
||||
@ -963,7 +942,7 @@ namespace ts.FindAllReferences.Core {
|
||||
|
||||
function addReference(referenceLocation: Node, relatedSymbol: Symbol, searchLocation: Node, state: State): void {
|
||||
const addRef = state.referenceAdder(relatedSymbol, searchLocation);
|
||||
if (state.implementations) {
|
||||
if (state.options.implementations) {
|
||||
addImplementationReferences(referenceLocation, addRef, state);
|
||||
}
|
||||
else {
|
||||
|
||||
@ -8,7 +8,7 @@ namespace ts.GoToDefinition {
|
||||
if (referenceFile) {
|
||||
return [getDefinitionInfoForFileReference(comment.fileName, referenceFile.fileName)];
|
||||
}
|
||||
return undefined;
|
||||
// Might still be on jsdoc, so keep looking.
|
||||
}
|
||||
|
||||
// Type reference directives
|
||||
|
||||
@ -39,13 +39,14 @@ namespace ts {
|
||||
case SyntaxKind.TypeLiteral:
|
||||
return SemanticMeaning.Type;
|
||||
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
// If it has no name node, it shares the name with the value declaration below it.
|
||||
return (node as JSDocTypedefTag).name === undefined ? SemanticMeaning.Value | SemanticMeaning.Type : SemanticMeaning.Type;
|
||||
|
||||
case SyntaxKind.EnumMember:
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
return SemanticMeaning.Value | SemanticMeaning.Type;
|
||||
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
return SemanticMeaning.All;
|
||||
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
if (isAmbientModule(<ModuleDeclaration>node)) {
|
||||
return SemanticMeaning.Namespace | SemanticMeaning.Value;
|
||||
@ -57,6 +58,7 @@ namespace ts {
|
||||
return SemanticMeaning.Namespace;
|
||||
}
|
||||
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
case SyntaxKind.NamedImports:
|
||||
case SyntaxKind.ImportSpecifier:
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
@ -70,7 +72,7 @@ namespace ts {
|
||||
return SemanticMeaning.Namespace | SemanticMeaning.Value;
|
||||
}
|
||||
|
||||
return SemanticMeaning.Value | SemanticMeaning.Type | SemanticMeaning.Namespace;
|
||||
return SemanticMeaning.All;
|
||||
}
|
||||
|
||||
export function getMeaningFromLocation(node: Node): SemanticMeaning {
|
||||
@ -78,7 +80,7 @@ namespace ts {
|
||||
return SemanticMeaning.Value;
|
||||
}
|
||||
else if (node.parent.kind === SyntaxKind.ExportAssignment) {
|
||||
return SemanticMeaning.Value | SemanticMeaning.Type | SemanticMeaning.Namespace;
|
||||
return SemanticMeaning.All;
|
||||
}
|
||||
else if (isInRightSideOfImport(node)) {
|
||||
return getMeaningFromRightHandSideOfImportEquals(node);
|
||||
@ -162,10 +164,22 @@ namespace ts {
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
return node.parent.kind === SyntaxKind.TypeReference ||
|
||||
(node.parent.kind === SyntaxKind.ExpressionWithTypeArguments && !isExpressionWithTypeArgumentsInClassExtendsClause(<ExpressionWithTypeArguments>node.parent)) ||
|
||||
(node.kind === SyntaxKind.ThisKeyword && !isPartOfExpression(node)) ||
|
||||
node.kind === SyntaxKind.ThisType;
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ThisKeyword:
|
||||
return !isPartOfExpression(node);
|
||||
case SyntaxKind.ThisType:
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (node.parent.kind) {
|
||||
case SyntaxKind.TypeReference:
|
||||
case SyntaxKind.JSDocTypeReference:
|
||||
return true;
|
||||
case SyntaxKind.ExpressionWithTypeArguments:
|
||||
return !isExpressionWithTypeArgumentsInClassExtendsClause(<ExpressionWithTypeArguments>node.parent);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isCallExpressionTarget(node: Node): boolean {
|
||||
|
||||
60
tests/baselines/reference/checkJsdocTypedefInParamTag1.js
Normal file
60
tests/baselines/reference/checkJsdocTypedefInParamTag1.js
Normal file
@ -0,0 +1,60 @@
|
||||
//// [0.js]
|
||||
// @ts-check
|
||||
/**
|
||||
* @typedef {Object} Opts
|
||||
* @property {string} x
|
||||
* @property {string=} y
|
||||
* @property {string} [z]
|
||||
* @property {string} [w="hi"]
|
||||
*
|
||||
* @param {Opts} opts
|
||||
*/
|
||||
function foo(opts) {
|
||||
opts.x;
|
||||
}
|
||||
|
||||
foo({x: 'abc'});
|
||||
|
||||
/**
|
||||
* @typedef {object} Opts1
|
||||
* @property {string} x
|
||||
* @property {string=} y
|
||||
* @property {string} [z]
|
||||
* @property {string} [w="hi"]
|
||||
*
|
||||
* @param {Opts1} opts
|
||||
*/
|
||||
function foo1(opts) {
|
||||
opts.x;
|
||||
}
|
||||
foo1({x: 'abc'});
|
||||
|
||||
|
||||
//// [0.js]
|
||||
// @ts-check
|
||||
/**
|
||||
* @typedef {Object} Opts
|
||||
* @property {string} x
|
||||
* @property {string=} y
|
||||
* @property {string} [z]
|
||||
* @property {string} [w="hi"]
|
||||
*
|
||||
* @param {Opts} opts
|
||||
*/
|
||||
function foo(opts) {
|
||||
opts.x;
|
||||
}
|
||||
foo({ x: 'abc' });
|
||||
/**
|
||||
* @typedef {object} Opts1
|
||||
* @property {string} x
|
||||
* @property {string=} y
|
||||
* @property {string} [z]
|
||||
* @property {string} [w="hi"]
|
||||
*
|
||||
* @param {Opts1} opts
|
||||
*/
|
||||
function foo1(opts) {
|
||||
opts.x;
|
||||
}
|
||||
foo1({ x: 'abc' });
|
||||
@ -0,0 +1,47 @@
|
||||
=== tests/cases/conformance/jsdoc/0.js ===
|
||||
// @ts-check
|
||||
/**
|
||||
* @typedef {Object} Opts
|
||||
* @property {string} x
|
||||
* @property {string=} y
|
||||
* @property {string} [z]
|
||||
* @property {string} [w="hi"]
|
||||
*
|
||||
* @param {Opts} opts
|
||||
*/
|
||||
function foo(opts) {
|
||||
>foo : Symbol(foo, Decl(0.js, 0, 0))
|
||||
>opts : Symbol(opts, Decl(0.js, 10, 13))
|
||||
|
||||
opts.x;
|
||||
>opts.x : Symbol(x, Decl(0.js, 3, 3))
|
||||
>opts : Symbol(opts, Decl(0.js, 10, 13))
|
||||
>x : Symbol(x, Decl(0.js, 3, 3))
|
||||
}
|
||||
|
||||
foo({x: 'abc'});
|
||||
>foo : Symbol(foo, Decl(0.js, 0, 0))
|
||||
>x : Symbol(x, Decl(0.js, 14, 5))
|
||||
|
||||
/**
|
||||
* @typedef {object} Opts1
|
||||
* @property {string} x
|
||||
* @property {string=} y
|
||||
* @property {string} [z]
|
||||
* @property {string} [w="hi"]
|
||||
*
|
||||
* @param {Opts1} opts
|
||||
*/
|
||||
function foo1(opts) {
|
||||
>foo1 : Symbol(foo1, Decl(0.js, 14, 16))
|
||||
>opts : Symbol(opts, Decl(0.js, 25, 14))
|
||||
|
||||
opts.x;
|
||||
>opts.x : Symbol(x, Decl(0.js, 18, 3))
|
||||
>opts : Symbol(opts, Decl(0.js, 25, 14))
|
||||
>x : Symbol(x, Decl(0.js, 18, 3))
|
||||
}
|
||||
foo1({x: 'abc'});
|
||||
>foo1 : Symbol(foo1, Decl(0.js, 14, 16))
|
||||
>x : Symbol(x, Decl(0.js, 28, 6))
|
||||
|
||||
53
tests/baselines/reference/checkJsdocTypedefInParamTag1.types
Normal file
53
tests/baselines/reference/checkJsdocTypedefInParamTag1.types
Normal file
@ -0,0 +1,53 @@
|
||||
=== tests/cases/conformance/jsdoc/0.js ===
|
||||
// @ts-check
|
||||
/**
|
||||
* @typedef {Object} Opts
|
||||
* @property {string} x
|
||||
* @property {string=} y
|
||||
* @property {string} [z]
|
||||
* @property {string} [w="hi"]
|
||||
*
|
||||
* @param {Opts} opts
|
||||
*/
|
||||
function foo(opts) {
|
||||
>foo : (opts: { x: string; y?: string; z?: string; w?: string; }) => void
|
||||
>opts : { x: string; y?: string; z?: string; w?: string; }
|
||||
|
||||
opts.x;
|
||||
>opts.x : string
|
||||
>opts : { x: string; y?: string; z?: string; w?: string; }
|
||||
>x : string
|
||||
}
|
||||
|
||||
foo({x: 'abc'});
|
||||
>foo({x: 'abc'}) : void
|
||||
>foo : (opts: { x: string; y?: string; z?: string; w?: string; }) => void
|
||||
>{x: 'abc'} : { x: string; }
|
||||
>x : string
|
||||
>'abc' : "abc"
|
||||
|
||||
/**
|
||||
* @typedef {object} Opts1
|
||||
* @property {string} x
|
||||
* @property {string=} y
|
||||
* @property {string} [z]
|
||||
* @property {string} [w="hi"]
|
||||
*
|
||||
* @param {Opts1} opts
|
||||
*/
|
||||
function foo1(opts) {
|
||||
>foo1 : (opts: { x: string; y?: string; z?: string; w?: string; }) => void
|
||||
>opts : { x: string; y?: string; z?: string; w?: string; }
|
||||
|
||||
opts.x;
|
||||
>opts.x : string
|
||||
>opts : { x: string; y?: string; z?: string; w?: string; }
|
||||
>x : string
|
||||
}
|
||||
foo1({x: 'abc'});
|
||||
>foo1({x: 'abc'}) : void
|
||||
>foo1 : (opts: { x: string; y?: string; z?: string; w?: string; }) => void
|
||||
>{x: 'abc'} : { x: string; }
|
||||
>x : string
|
||||
>'abc' : "abc"
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
tests/cases/compiler/conflictMarkerDiff3Trivia1.ts(2,1): error TS1185: Merge conflict marker encountered.
|
||||
tests/cases/compiler/conflictMarkerDiff3Trivia1.ts(4,1): error TS1185: Merge conflict marker encountered.
|
||||
tests/cases/compiler/conflictMarkerDiff3Trivia1.ts(6,1): error TS1185: Merge conflict marker encountered.
|
||||
tests/cases/compiler/conflictMarkerDiff3Trivia1.ts(8,1): error TS1185: Merge conflict marker encountered.
|
||||
|
||||
|
||||
==== tests/cases/compiler/conflictMarkerDiff3Trivia1.ts (4 errors) ====
|
||||
class C {
|
||||
<<<<<<< HEAD
|
||||
~~~~~~~
|
||||
!!! error TS1185: Merge conflict marker encountered.
|
||||
v = 1;
|
||||
||||||| merged common ancestors
|
||||
~~~~~~~
|
||||
!!! error TS1185: Merge conflict marker encountered.
|
||||
v = 3;
|
||||
=======
|
||||
~~~~~~~
|
||||
!!! error TS1185: Merge conflict marker encountered.
|
||||
v = 2;
|
||||
>>>>>>> Branch-a
|
||||
~~~~~~~
|
||||
!!! error TS1185: Merge conflict marker encountered.
|
||||
}
|
||||
18
tests/baselines/reference/conflictMarkerDiff3Trivia1.js
Normal file
18
tests/baselines/reference/conflictMarkerDiff3Trivia1.js
Normal file
@ -0,0 +1,18 @@
|
||||
//// [conflictMarkerDiff3Trivia1.ts]
|
||||
class C {
|
||||
<<<<<<< HEAD
|
||||
v = 1;
|
||||
||||||| merged common ancestors
|
||||
v = 3;
|
||||
=======
|
||||
v = 2;
|
||||
>>>>>>> Branch-a
|
||||
}
|
||||
|
||||
//// [conflictMarkerDiff3Trivia1.js]
|
||||
var C = (function () {
|
||||
function C() {
|
||||
this.v = 1;
|
||||
}
|
||||
return C;
|
||||
}());
|
||||
@ -0,0 +1,34 @@
|
||||
tests/cases/compiler/conflictMarkerDiff3Trivia2.ts(3,1): error TS1185: Merge conflict marker encountered.
|
||||
tests/cases/compiler/conflictMarkerDiff3Trivia2.ts(4,6): error TS2304: Cannot find name 'a'.
|
||||
tests/cases/compiler/conflictMarkerDiff3Trivia2.ts(6,1): error TS1185: Merge conflict marker encountered.
|
||||
tests/cases/compiler/conflictMarkerDiff3Trivia2.ts(9,1): error TS1185: Merge conflict marker encountered.
|
||||
tests/cases/compiler/conflictMarkerDiff3Trivia2.ts(12,1): error TS1185: Merge conflict marker encountered.
|
||||
|
||||
|
||||
==== tests/cases/compiler/conflictMarkerDiff3Trivia2.ts (5 errors) ====
|
||||
class C {
|
||||
foo() {
|
||||
<<<<<<< B
|
||||
~~~~~~~
|
||||
!!! error TS1185: Merge conflict marker encountered.
|
||||
a();
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'a'.
|
||||
}
|
||||
||||||| merged common ancestors
|
||||
~~~~~~~
|
||||
!!! error TS1185: Merge conflict marker encountered.
|
||||
c();
|
||||
}
|
||||
=======
|
||||
~~~~~~~
|
||||
!!! error TS1185: Merge conflict marker encountered.
|
||||
b();
|
||||
}
|
||||
>>>>>>> A
|
||||
~~~~~~~
|
||||
!!! error TS1185: Merge conflict marker encountered.
|
||||
|
||||
public bar() { }
|
||||
}
|
||||
|
||||
28
tests/baselines/reference/conflictMarkerDiff3Trivia2.js
Normal file
28
tests/baselines/reference/conflictMarkerDiff3Trivia2.js
Normal file
@ -0,0 +1,28 @@
|
||||
//// [conflictMarkerDiff3Trivia2.ts]
|
||||
class C {
|
||||
foo() {
|
||||
<<<<<<< B
|
||||
a();
|
||||
}
|
||||
||||||| merged common ancestors
|
||||
c();
|
||||
}
|
||||
=======
|
||||
b();
|
||||
}
|
||||
>>>>>>> A
|
||||
|
||||
public bar() { }
|
||||
}
|
||||
|
||||
|
||||
//// [conflictMarkerDiff3Trivia2.js]
|
||||
var C = (function () {
|
||||
function C() {
|
||||
}
|
||||
C.prototype.foo = function () {
|
||||
a();
|
||||
};
|
||||
C.prototype.bar = function () { };
|
||||
return C;
|
||||
}());
|
||||
@ -26,7 +26,7 @@ var c3 = new C<number>();
|
||||
var c4: C<any> = new C();
|
||||
>c4 : C<any>
|
||||
>C : C<T>
|
||||
>new C() : C<{}>
|
||||
>new C() : C<any>
|
||||
>C : typeof C
|
||||
|
||||
class D<T> {
|
||||
|
||||
@ -0,0 +1,77 @@
|
||||
tests/cases/compiler/inferFromGenericFunctionReturnTypes1.ts(68,16): error TS2339: Property 'toUpperCase' does not exist on type 'number'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/inferFromGenericFunctionReturnTypes1.ts (1 errors) ====
|
||||
// Repro from #15680
|
||||
|
||||
// This is a contrived class. We could do the same thing with Observables, etc.
|
||||
class SetOf<A> {
|
||||
_store: A[];
|
||||
|
||||
add(a: A) {
|
||||
this._store.push(a);
|
||||
}
|
||||
|
||||
transform<B>(transformer: (a: SetOf<A>) => SetOf<B>): SetOf<B> {
|
||||
return transformer(this);
|
||||
}
|
||||
|
||||
forEach(fn: (a: A, index: number) => void) {
|
||||
this._store.forEach((a, i) => fn(a, i));
|
||||
}
|
||||
}
|
||||
|
||||
function compose<A, B, C, D, E>(
|
||||
fnA: (a: SetOf<A>) => SetOf<B>,
|
||||
fnB: (b: SetOf<B>) => SetOf<C>,
|
||||
fnC: (c: SetOf<C>) => SetOf<D>,
|
||||
fnD: (c: SetOf<D>) => SetOf<E>,
|
||||
):(x: SetOf<A>) => SetOf<E>;
|
||||
/* ... etc ... */
|
||||
function compose<T>(...fns: ((x: T) => T)[]): (x: T) => T {
|
||||
return (x: T) => fns.reduce((prev, fn) => fn(prev), x);
|
||||
}
|
||||
|
||||
function map<A, B>(fn: (a: A) => B): (s: SetOf<A>) => SetOf<B> {
|
||||
return (a: SetOf<A>) => {
|
||||
const b: SetOf<B> = new SetOf();
|
||||
a.forEach(x => b.add(fn(x)));
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
function filter<A>(predicate: (a: A) => boolean): (s: SetOf<A>) => SetOf<A> {
|
||||
return (a: SetOf<A>) => {
|
||||
const result = new SetOf<A>();
|
||||
a.forEach(x => {
|
||||
if (predicate(x)) result.add(x);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
const testSet = new SetOf<number>();
|
||||
testSet.add(1);
|
||||
testSet.add(2);
|
||||
testSet.add(3);
|
||||
|
||||
testSet.transform(
|
||||
compose(
|
||||
filter(x => x % 1 === 0),
|
||||
map(x => x + x),
|
||||
map(x => x + '!!!'),
|
||||
map(x => x.toUpperCase())
|
||||
)
|
||||
)
|
||||
|
||||
testSet.transform(
|
||||
compose(
|
||||
filter(x => x % 1 === 0),
|
||||
map(x => x + x),
|
||||
map(x => 123), // Whoops a bug
|
||||
map(x => x.toUpperCase()) // causes an error!
|
||||
~~~~~~~~~~~
|
||||
!!! error TS2339: Property 'toUpperCase' does not exist on type 'number'.
|
||||
)
|
||||
)
|
||||
|
||||
@ -0,0 +1,123 @@
|
||||
//// [inferFromGenericFunctionReturnTypes1.ts]
|
||||
// Repro from #15680
|
||||
|
||||
// This is a contrived class. We could do the same thing with Observables, etc.
|
||||
class SetOf<A> {
|
||||
_store: A[];
|
||||
|
||||
add(a: A) {
|
||||
this._store.push(a);
|
||||
}
|
||||
|
||||
transform<B>(transformer: (a: SetOf<A>) => SetOf<B>): SetOf<B> {
|
||||
return transformer(this);
|
||||
}
|
||||
|
||||
forEach(fn: (a: A, index: number) => void) {
|
||||
this._store.forEach((a, i) => fn(a, i));
|
||||
}
|
||||
}
|
||||
|
||||
function compose<A, B, C, D, E>(
|
||||
fnA: (a: SetOf<A>) => SetOf<B>,
|
||||
fnB: (b: SetOf<B>) => SetOf<C>,
|
||||
fnC: (c: SetOf<C>) => SetOf<D>,
|
||||
fnD: (c: SetOf<D>) => SetOf<E>,
|
||||
):(x: SetOf<A>) => SetOf<E>;
|
||||
/* ... etc ... */
|
||||
function compose<T>(...fns: ((x: T) => T)[]): (x: T) => T {
|
||||
return (x: T) => fns.reduce((prev, fn) => fn(prev), x);
|
||||
}
|
||||
|
||||
function map<A, B>(fn: (a: A) => B): (s: SetOf<A>) => SetOf<B> {
|
||||
return (a: SetOf<A>) => {
|
||||
const b: SetOf<B> = new SetOf();
|
||||
a.forEach(x => b.add(fn(x)));
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
function filter<A>(predicate: (a: A) => boolean): (s: SetOf<A>) => SetOf<A> {
|
||||
return (a: SetOf<A>) => {
|
||||
const result = new SetOf<A>();
|
||||
a.forEach(x => {
|
||||
if (predicate(x)) result.add(x);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
const testSet = new SetOf<number>();
|
||||
testSet.add(1);
|
||||
testSet.add(2);
|
||||
testSet.add(3);
|
||||
|
||||
testSet.transform(
|
||||
compose(
|
||||
filter(x => x % 1 === 0),
|
||||
map(x => x + x),
|
||||
map(x => x + '!!!'),
|
||||
map(x => x.toUpperCase())
|
||||
)
|
||||
)
|
||||
|
||||
testSet.transform(
|
||||
compose(
|
||||
filter(x => x % 1 === 0),
|
||||
map(x => x + x),
|
||||
map(x => 123), // Whoops a bug
|
||||
map(x => x.toUpperCase()) // causes an error!
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
//// [inferFromGenericFunctionReturnTypes1.js]
|
||||
// Repro from #15680
|
||||
// This is a contrived class. We could do the same thing with Observables, etc.
|
||||
var SetOf = (function () {
|
||||
function SetOf() {
|
||||
}
|
||||
SetOf.prototype.add = function (a) {
|
||||
this._store.push(a);
|
||||
};
|
||||
SetOf.prototype.transform = function (transformer) {
|
||||
return transformer(this);
|
||||
};
|
||||
SetOf.prototype.forEach = function (fn) {
|
||||
this._store.forEach(function (a, i) { return fn(a, i); });
|
||||
};
|
||||
return SetOf;
|
||||
}());
|
||||
/* ... etc ... */
|
||||
function compose() {
|
||||
var fns = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
fns[_i] = arguments[_i];
|
||||
}
|
||||
return function (x) { return fns.reduce(function (prev, fn) { return fn(prev); }, x); };
|
||||
}
|
||||
function map(fn) {
|
||||
return function (a) {
|
||||
var b = new SetOf();
|
||||
a.forEach(function (x) { return b.add(fn(x)); });
|
||||
return b;
|
||||
};
|
||||
}
|
||||
function filter(predicate) {
|
||||
return function (a) {
|
||||
var result = new SetOf();
|
||||
a.forEach(function (x) {
|
||||
if (predicate(x))
|
||||
result.add(x);
|
||||
});
|
||||
return result;
|
||||
};
|
||||
}
|
||||
var testSet = new SetOf();
|
||||
testSet.add(1);
|
||||
testSet.add(2);
|
||||
testSet.add(3);
|
||||
testSet.transform(compose(filter(function (x) { return x % 1 === 0; }), map(function (x) { return x + x; }), map(function (x) { return x + '!!!'; }), map(function (x) { return x.toUpperCase(); })));
|
||||
testSet.transform(compose(filter(function (x) { return x % 1 === 0; }), map(function (x) { return x + x; }), map(function (x) { return 123; }), // Whoops a bug
|
||||
map(function (x) { return x.toUpperCase(); }) // causes an error!
|
||||
));
|
||||
@ -0,0 +1,155 @@
|
||||
//// [inferFromGenericFunctionReturnTypes2.ts]
|
||||
type Mapper<T, U> = (x: T) => U;
|
||||
|
||||
declare function wrap<T, U>(cb: Mapper<T, U>): Mapper<T, U>;
|
||||
|
||||
declare function arrayize<T, U>(cb: Mapper<T, U>): Mapper<T, U[]>;
|
||||
|
||||
declare function combine<A, B, C>(f: (x: A) => B, g: (x: B) => C): (x: A) => C;
|
||||
|
||||
declare function foo(f: Mapper<string, number>): void;
|
||||
|
||||
let f1: Mapper<string, number> = s => s.length;
|
||||
let f2: Mapper<string, number> = wrap(s => s.length);
|
||||
let f3: Mapper<string, number[]> = arrayize(wrap(s => s.length));
|
||||
let f4: Mapper<string, boolean> = combine(wrap(s => s.length), wrap(n => n >= 10));
|
||||
|
||||
foo(wrap(s => s.length));
|
||||
|
||||
let a1 = ["a", "b"].map(s => s.length);
|
||||
let a2 = ["a", "b"].map(wrap(s => s.length));
|
||||
let a3 = ["a", "b"].map(wrap(arrayize(s => s.length)));
|
||||
let a4 = ["a", "b"].map(combine(wrap(s => s.length), wrap(n => n > 10)));
|
||||
let a5 = ["a", "b"].map(combine(identity, wrap(s => s.length)));
|
||||
let a6 = ["a", "b"].map(combine(wrap(s => s.length), identity));
|
||||
|
||||
// This is a contrived class. We could do the same thing with Observables, etc.
|
||||
class SetOf<A> {
|
||||
_store: A[];
|
||||
|
||||
add(a: A) {
|
||||
this._store.push(a);
|
||||
}
|
||||
|
||||
transform<B>(transformer: (a: SetOf<A>) => SetOf<B>): SetOf<B> {
|
||||
return transformer(this);
|
||||
}
|
||||
|
||||
forEach(fn: (a: A, index: number) => void) {
|
||||
this._store.forEach((a, i) => fn(a, i));
|
||||
}
|
||||
}
|
||||
|
||||
function compose<A, B, C, D, E>(
|
||||
fnA: (a: SetOf<A>) => SetOf<B>,
|
||||
fnB: (b: SetOf<B>) => SetOf<C>,
|
||||
fnC: (c: SetOf<C>) => SetOf<D>,
|
||||
fnD: (c: SetOf<D>) => SetOf<E>,
|
||||
):(x: SetOf<A>) => SetOf<E>;
|
||||
/* ... etc ... */
|
||||
function compose<T>(...fns: ((x: T) => T)[]): (x: T) => T {
|
||||
return (x: T) => fns.reduce((prev, fn) => fn(prev), x);
|
||||
}
|
||||
|
||||
function map<A, B>(fn: (a: A) => B): (s: SetOf<A>) => SetOf<B> {
|
||||
return (a: SetOf<A>) => {
|
||||
const b: SetOf<B> = new SetOf();
|
||||
a.forEach(x => b.add(fn(x)));
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
function filter<A>(predicate: (a: A) => boolean): (s: SetOf<A>) => SetOf<A> {
|
||||
return (a: SetOf<A>) => {
|
||||
const result = new SetOf<A>();
|
||||
a.forEach(x => {
|
||||
if (predicate(x)) result.add(x);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
const testSet = new SetOf<number>();
|
||||
testSet.add(1);
|
||||
testSet.add(2);
|
||||
testSet.add(3);
|
||||
|
||||
const t1 = testSet.transform(
|
||||
compose(
|
||||
filter(x => x % 1 === 0),
|
||||
map(x => x + x),
|
||||
map(x => x + '!!!'),
|
||||
map(x => x.toUpperCase())
|
||||
)
|
||||
)
|
||||
|
||||
declare function identity<T>(x: T): T;
|
||||
|
||||
const t2 = testSet.transform(
|
||||
compose(
|
||||
filter(x => x % 1 === 0),
|
||||
identity,
|
||||
map(x => x + '!!!'),
|
||||
map(x => x.toUpperCase())
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
//// [inferFromGenericFunctionReturnTypes2.js]
|
||||
var f1 = function (s) { return s.length; };
|
||||
var f2 = wrap(function (s) { return s.length; });
|
||||
var f3 = arrayize(wrap(function (s) { return s.length; }));
|
||||
var f4 = combine(wrap(function (s) { return s.length; }), wrap(function (n) { return n >= 10; }));
|
||||
foo(wrap(function (s) { return s.length; }));
|
||||
var a1 = ["a", "b"].map(function (s) { return s.length; });
|
||||
var a2 = ["a", "b"].map(wrap(function (s) { return s.length; }));
|
||||
var a3 = ["a", "b"].map(wrap(arrayize(function (s) { return s.length; })));
|
||||
var a4 = ["a", "b"].map(combine(wrap(function (s) { return s.length; }), wrap(function (n) { return n > 10; })));
|
||||
var a5 = ["a", "b"].map(combine(identity, wrap(function (s) { return s.length; })));
|
||||
var a6 = ["a", "b"].map(combine(wrap(function (s) { return s.length; }), identity));
|
||||
// This is a contrived class. We could do the same thing with Observables, etc.
|
||||
var SetOf = (function () {
|
||||
function SetOf() {
|
||||
}
|
||||
SetOf.prototype.add = function (a) {
|
||||
this._store.push(a);
|
||||
};
|
||||
SetOf.prototype.transform = function (transformer) {
|
||||
return transformer(this);
|
||||
};
|
||||
SetOf.prototype.forEach = function (fn) {
|
||||
this._store.forEach(function (a, i) { return fn(a, i); });
|
||||
};
|
||||
return SetOf;
|
||||
}());
|
||||
/* ... etc ... */
|
||||
function compose() {
|
||||
var fns = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
fns[_i] = arguments[_i];
|
||||
}
|
||||
return function (x) { return fns.reduce(function (prev, fn) { return fn(prev); }, x); };
|
||||
}
|
||||
function map(fn) {
|
||||
return function (a) {
|
||||
var b = new SetOf();
|
||||
a.forEach(function (x) { return b.add(fn(x)); });
|
||||
return b;
|
||||
};
|
||||
}
|
||||
function filter(predicate) {
|
||||
return function (a) {
|
||||
var result = new SetOf();
|
||||
a.forEach(function (x) {
|
||||
if (predicate(x))
|
||||
result.add(x);
|
||||
});
|
||||
return result;
|
||||
};
|
||||
}
|
||||
var testSet = new SetOf();
|
||||
testSet.add(1);
|
||||
testSet.add(2);
|
||||
testSet.add(3);
|
||||
var t1 = testSet.transform(compose(filter(function (x) { return x % 1 === 0; }), map(function (x) { return x + x; }), map(function (x) { return x + '!!!'; }), map(function (x) { return x.toUpperCase(); })));
|
||||
var t2 = testSet.transform(compose(filter(function (x) { return x % 1 === 0; }), identity, map(function (x) { return x + '!!!'; }), map(function (x) { return x.toUpperCase(); })));
|
||||
@ -0,0 +1,480 @@
|
||||
=== tests/cases/compiler/inferFromGenericFunctionReturnTypes2.ts ===
|
||||
type Mapper<T, U> = (x: T) => U;
|
||||
>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 12))
|
||||
>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 14))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 21))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 12))
|
||||
>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 14))
|
||||
|
||||
declare function wrap<T, U>(cb: Mapper<T, U>): Mapper<T, U>;
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 22))
|
||||
>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 24))
|
||||
>cb : Symbol(cb, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 28))
|
||||
>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 22))
|
||||
>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 24))
|
||||
>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 22))
|
||||
>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 24))
|
||||
|
||||
declare function arrayize<T, U>(cb: Mapper<T, U>): Mapper<T, U[]>;
|
||||
>arrayize : Symbol(arrayize, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 60))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 26))
|
||||
>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 28))
|
||||
>cb : Symbol(cb, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 32))
|
||||
>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 26))
|
||||
>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 28))
|
||||
>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 26))
|
||||
>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 28))
|
||||
|
||||
declare function combine<A, B, C>(f: (x: A) => B, g: (x: B) => C): (x: A) => C;
|
||||
>combine : Symbol(combine, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 66))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 25))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 27))
|
||||
>C : Symbol(C, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 30))
|
||||
>f : Symbol(f, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 34))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 38))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 25))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 27))
|
||||
>g : Symbol(g, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 49))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 54))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 27))
|
||||
>C : Symbol(C, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 30))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 68))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 25))
|
||||
>C : Symbol(C, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 30))
|
||||
|
||||
declare function foo(f: Mapper<string, number>): void;
|
||||
>foo : Symbol(foo, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 79))
|
||||
>f : Symbol(f, Decl(inferFromGenericFunctionReturnTypes2.ts, 8, 21))
|
||||
>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0))
|
||||
|
||||
let f1: Mapper<string, number> = s => s.length;
|
||||
>f1 : Symbol(f1, Decl(inferFromGenericFunctionReturnTypes2.ts, 10, 3))
|
||||
>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 10, 32))
|
||||
>s.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 10, 32))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
|
||||
let f2: Mapper<string, number> = wrap(s => s.length);
|
||||
>f2 : Symbol(f2, Decl(inferFromGenericFunctionReturnTypes2.ts, 11, 3))
|
||||
>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0))
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 11, 38))
|
||||
>s.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 11, 38))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
|
||||
let f3: Mapper<string, number[]> = arrayize(wrap(s => s.length));
|
||||
>f3 : Symbol(f3, Decl(inferFromGenericFunctionReturnTypes2.ts, 12, 3))
|
||||
>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0))
|
||||
>arrayize : Symbol(arrayize, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 60))
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 12, 49))
|
||||
>s.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 12, 49))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
|
||||
let f4: Mapper<string, boolean> = combine(wrap(s => s.length), wrap(n => n >= 10));
|
||||
>f4 : Symbol(f4, Decl(inferFromGenericFunctionReturnTypes2.ts, 13, 3))
|
||||
>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0))
|
||||
>combine : Symbol(combine, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 66))
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 13, 47))
|
||||
>s.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 13, 47))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>n : Symbol(n, Decl(inferFromGenericFunctionReturnTypes2.ts, 13, 68))
|
||||
>n : Symbol(n, Decl(inferFromGenericFunctionReturnTypes2.ts, 13, 68))
|
||||
|
||||
foo(wrap(s => s.length));
|
||||
>foo : Symbol(foo, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 79))
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 15, 9))
|
||||
>s.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 15, 9))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
|
||||
let a1 = ["a", "b"].map(s => s.length);
|
||||
>a1 : Symbol(a1, Decl(inferFromGenericFunctionReturnTypes2.ts, 17, 3))
|
||||
>["a", "b"].map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 17, 24))
|
||||
>s.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 17, 24))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
|
||||
let a2 = ["a", "b"].map(wrap(s => s.length));
|
||||
>a2 : Symbol(a2, Decl(inferFromGenericFunctionReturnTypes2.ts, 18, 3))
|
||||
>["a", "b"].map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 18, 29))
|
||||
>s.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 18, 29))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
|
||||
let a3 = ["a", "b"].map(wrap(arrayize(s => s.length)));
|
||||
>a3 : Symbol(a3, Decl(inferFromGenericFunctionReturnTypes2.ts, 19, 3))
|
||||
>["a", "b"].map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>arrayize : Symbol(arrayize, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 60))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 19, 38))
|
||||
>s.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 19, 38))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
|
||||
let a4 = ["a", "b"].map(combine(wrap(s => s.length), wrap(n => n > 10)));
|
||||
>a4 : Symbol(a4, Decl(inferFromGenericFunctionReturnTypes2.ts, 20, 3))
|
||||
>["a", "b"].map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>combine : Symbol(combine, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 66))
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 20, 37))
|
||||
>s.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 20, 37))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>n : Symbol(n, Decl(inferFromGenericFunctionReturnTypes2.ts, 20, 58))
|
||||
>n : Symbol(n, Decl(inferFromGenericFunctionReturnTypes2.ts, 20, 58))
|
||||
|
||||
let a5 = ["a", "b"].map(combine(identity, wrap(s => s.length)));
|
||||
>a5 : Symbol(a5, Decl(inferFromGenericFunctionReturnTypes2.ts, 21, 3))
|
||||
>["a", "b"].map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>combine : Symbol(combine, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 66))
|
||||
>identity : Symbol(identity, Decl(inferFromGenericFunctionReturnTypes2.ts, 82, 1))
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 21, 47))
|
||||
>s.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 21, 47))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
|
||||
let a6 = ["a", "b"].map(combine(wrap(s => s.length), identity));
|
||||
>a6 : Symbol(a6, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 3))
|
||||
>["a", "b"].map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>combine : Symbol(combine, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 66))
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 37))
|
||||
>s.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 37))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>identity : Symbol(identity, Decl(inferFromGenericFunctionReturnTypes2.ts, 82, 1))
|
||||
|
||||
// This is a contrived class. We could do the same thing with Observables, etc.
|
||||
class SetOf<A> {
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 12))
|
||||
|
||||
_store: A[];
|
||||
>_store : Symbol(SetOf._store, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 16))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 12))
|
||||
|
||||
add(a: A) {
|
||||
>add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14))
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 28, 6))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 12))
|
||||
|
||||
this._store.push(a);
|
||||
>this._store.push : Symbol(Array.push, Decl(lib.d.ts, --, --))
|
||||
>this._store : Symbol(SetOf._store, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 16))
|
||||
>this : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>_store : Symbol(SetOf._store, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 16))
|
||||
>push : Symbol(Array.push, Decl(lib.d.ts, --, --))
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 28, 6))
|
||||
}
|
||||
|
||||
transform<B>(transformer: (a: SetOf<A>) => SetOf<B>): SetOf<B> {
|
||||
>transform : Symbol(SetOf.transform, Decl(inferFromGenericFunctionReturnTypes2.ts, 30, 3))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 32, 12))
|
||||
>transformer : Symbol(transformer, Decl(inferFromGenericFunctionReturnTypes2.ts, 32, 15))
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 32, 29))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 12))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 32, 12))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 32, 12))
|
||||
|
||||
return transformer(this);
|
||||
>transformer : Symbol(transformer, Decl(inferFromGenericFunctionReturnTypes2.ts, 32, 15))
|
||||
>this : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
}
|
||||
|
||||
forEach(fn: (a: A, index: number) => void) {
|
||||
>forEach : Symbol(SetOf.forEach, Decl(inferFromGenericFunctionReturnTypes2.ts, 34, 3))
|
||||
>fn : Symbol(fn, Decl(inferFromGenericFunctionReturnTypes2.ts, 36, 10))
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 36, 15))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 12))
|
||||
>index : Symbol(index, Decl(inferFromGenericFunctionReturnTypes2.ts, 36, 20))
|
||||
|
||||
this._store.forEach((a, i) => fn(a, i));
|
||||
>this._store.forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>this._store : Symbol(SetOf._store, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 16))
|
||||
>this : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>_store : Symbol(SetOf._store, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 16))
|
||||
>forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 37, 27))
|
||||
>i : Symbol(i, Decl(inferFromGenericFunctionReturnTypes2.ts, 37, 29))
|
||||
>fn : Symbol(fn, Decl(inferFromGenericFunctionReturnTypes2.ts, 36, 10))
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 37, 27))
|
||||
>i : Symbol(i, Decl(inferFromGenericFunctionReturnTypes2.ts, 37, 29))
|
||||
}
|
||||
}
|
||||
|
||||
function compose<A, B, C, D, E>(
|
||||
>compose : Symbol(compose, Decl(inferFromGenericFunctionReturnTypes2.ts, 39, 1), Decl(inferFromGenericFunctionReturnTypes2.ts, 46, 28))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 17))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 19))
|
||||
>C : Symbol(C, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 22))
|
||||
>D : Symbol(D, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 25))
|
||||
>E : Symbol(E, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 28))
|
||||
|
||||
fnA: (a: SetOf<A>) => SetOf<B>,
|
||||
>fnA : Symbol(fnA, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 32))
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 42, 8))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 17))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 19))
|
||||
|
||||
fnB: (b: SetOf<B>) => SetOf<C>,
|
||||
>fnB : Symbol(fnB, Decl(inferFromGenericFunctionReturnTypes2.ts, 42, 33))
|
||||
>b : Symbol(b, Decl(inferFromGenericFunctionReturnTypes2.ts, 43, 8))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 19))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>C : Symbol(C, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 22))
|
||||
|
||||
fnC: (c: SetOf<C>) => SetOf<D>,
|
||||
>fnC : Symbol(fnC, Decl(inferFromGenericFunctionReturnTypes2.ts, 43, 33))
|
||||
>c : Symbol(c, Decl(inferFromGenericFunctionReturnTypes2.ts, 44, 8))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>C : Symbol(C, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 22))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>D : Symbol(D, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 25))
|
||||
|
||||
fnD: (c: SetOf<D>) => SetOf<E>,
|
||||
>fnD : Symbol(fnD, Decl(inferFromGenericFunctionReturnTypes2.ts, 44, 33))
|
||||
>c : Symbol(c, Decl(inferFromGenericFunctionReturnTypes2.ts, 45, 8))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>D : Symbol(D, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 25))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>E : Symbol(E, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 28))
|
||||
|
||||
):(x: SetOf<A>) => SetOf<E>;
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 46, 3))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 17))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>E : Symbol(E, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 28))
|
||||
|
||||
/* ... etc ... */
|
||||
function compose<T>(...fns: ((x: T) => T)[]): (x: T) => T {
|
||||
>compose : Symbol(compose, Decl(inferFromGenericFunctionReturnTypes2.ts, 39, 1), Decl(inferFromGenericFunctionReturnTypes2.ts, 46, 28))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 17))
|
||||
>fns : Symbol(fns, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 20))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 30))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 17))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 17))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 47))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 17))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 17))
|
||||
|
||||
return (x: T) => fns.reduce((prev, fn) => fn(prev), x);
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 49, 10))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 17))
|
||||
>fns.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>fns : Symbol(fns, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 20))
|
||||
>reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>prev : Symbol(prev, Decl(inferFromGenericFunctionReturnTypes2.ts, 49, 31))
|
||||
>fn : Symbol(fn, Decl(inferFromGenericFunctionReturnTypes2.ts, 49, 36))
|
||||
>fn : Symbol(fn, Decl(inferFromGenericFunctionReturnTypes2.ts, 49, 36))
|
||||
>prev : Symbol(prev, Decl(inferFromGenericFunctionReturnTypes2.ts, 49, 31))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 49, 10))
|
||||
}
|
||||
|
||||
function map<A, B>(fn: (a: A) => B): (s: SetOf<A>) => SetOf<B> {
|
||||
>map : Symbol(map, Decl(inferFromGenericFunctionReturnTypes2.ts, 50, 1))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 13))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 15))
|
||||
>fn : Symbol(fn, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 19))
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 24))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 13))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 15))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 38))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 13))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 15))
|
||||
|
||||
return (a: SetOf<A>) => {
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 53, 10))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 13))
|
||||
|
||||
const b: SetOf<B> = new SetOf();
|
||||
>b : Symbol(b, Decl(inferFromGenericFunctionReturnTypes2.ts, 54, 9))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 15))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
|
||||
a.forEach(x => b.add(fn(x)));
|
||||
>a.forEach : Symbol(SetOf.forEach, Decl(inferFromGenericFunctionReturnTypes2.ts, 34, 3))
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 53, 10))
|
||||
>forEach : Symbol(SetOf.forEach, Decl(inferFromGenericFunctionReturnTypes2.ts, 34, 3))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 55, 14))
|
||||
>b.add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14))
|
||||
>b : Symbol(b, Decl(inferFromGenericFunctionReturnTypes2.ts, 54, 9))
|
||||
>add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14))
|
||||
>fn : Symbol(fn, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 19))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 55, 14))
|
||||
|
||||
return b;
|
||||
>b : Symbol(b, Decl(inferFromGenericFunctionReturnTypes2.ts, 54, 9))
|
||||
}
|
||||
}
|
||||
|
||||
function filter<A>(predicate: (a: A) => boolean): (s: SetOf<A>) => SetOf<A> {
|
||||
>filter : Symbol(filter, Decl(inferFromGenericFunctionReturnTypes2.ts, 58, 1))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 16))
|
||||
>predicate : Symbol(predicate, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 19))
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 31))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 16))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 51))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 16))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 16))
|
||||
|
||||
return (a: SetOf<A>) => {
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 61, 10))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 16))
|
||||
|
||||
const result = new SetOf<A>();
|
||||
>result : Symbol(result, Decl(inferFromGenericFunctionReturnTypes2.ts, 62, 9))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 16))
|
||||
|
||||
a.forEach(x => {
|
||||
>a.forEach : Symbol(SetOf.forEach, Decl(inferFromGenericFunctionReturnTypes2.ts, 34, 3))
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 61, 10))
|
||||
>forEach : Symbol(SetOf.forEach, Decl(inferFromGenericFunctionReturnTypes2.ts, 34, 3))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 63, 14))
|
||||
|
||||
if (predicate(x)) result.add(x);
|
||||
>predicate : Symbol(predicate, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 19))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 63, 14))
|
||||
>result.add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14))
|
||||
>result : Symbol(result, Decl(inferFromGenericFunctionReturnTypes2.ts, 62, 9))
|
||||
>add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 63, 14))
|
||||
|
||||
});
|
||||
return result;
|
||||
>result : Symbol(result, Decl(inferFromGenericFunctionReturnTypes2.ts, 62, 9))
|
||||
}
|
||||
}
|
||||
|
||||
const testSet = new SetOf<number>();
|
||||
>testSet : Symbol(testSet, Decl(inferFromGenericFunctionReturnTypes2.ts, 70, 5))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
|
||||
testSet.add(1);
|
||||
>testSet.add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14))
|
||||
>testSet : Symbol(testSet, Decl(inferFromGenericFunctionReturnTypes2.ts, 70, 5))
|
||||
>add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14))
|
||||
|
||||
testSet.add(2);
|
||||
>testSet.add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14))
|
||||
>testSet : Symbol(testSet, Decl(inferFromGenericFunctionReturnTypes2.ts, 70, 5))
|
||||
>add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14))
|
||||
|
||||
testSet.add(3);
|
||||
>testSet.add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14))
|
||||
>testSet : Symbol(testSet, Decl(inferFromGenericFunctionReturnTypes2.ts, 70, 5))
|
||||
>add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14))
|
||||
|
||||
const t1 = testSet.transform(
|
||||
>t1 : Symbol(t1, Decl(inferFromGenericFunctionReturnTypes2.ts, 75, 5))
|
||||
>testSet.transform : Symbol(SetOf.transform, Decl(inferFromGenericFunctionReturnTypes2.ts, 30, 3))
|
||||
>testSet : Symbol(testSet, Decl(inferFromGenericFunctionReturnTypes2.ts, 70, 5))
|
||||
>transform : Symbol(SetOf.transform, Decl(inferFromGenericFunctionReturnTypes2.ts, 30, 3))
|
||||
|
||||
compose(
|
||||
>compose : Symbol(compose, Decl(inferFromGenericFunctionReturnTypes2.ts, 39, 1), Decl(inferFromGenericFunctionReturnTypes2.ts, 46, 28))
|
||||
|
||||
filter(x => x % 1 === 0),
|
||||
>filter : Symbol(filter, Decl(inferFromGenericFunctionReturnTypes2.ts, 58, 1))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 77, 11))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 77, 11))
|
||||
|
||||
map(x => x + x),
|
||||
>map : Symbol(map, Decl(inferFromGenericFunctionReturnTypes2.ts, 50, 1))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 78, 8))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 78, 8))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 78, 8))
|
||||
|
||||
map(x => x + '!!!'),
|
||||
>map : Symbol(map, Decl(inferFromGenericFunctionReturnTypes2.ts, 50, 1))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 79, 8))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 79, 8))
|
||||
|
||||
map(x => x.toUpperCase())
|
||||
>map : Symbol(map, Decl(inferFromGenericFunctionReturnTypes2.ts, 50, 1))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 80, 8))
|
||||
>x.toUpperCase : Symbol(String.toUpperCase, Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 80, 8))
|
||||
>toUpperCase : Symbol(String.toUpperCase, Decl(lib.d.ts, --, --))
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
declare function identity<T>(x: T): T;
|
||||
>identity : Symbol(identity, Decl(inferFromGenericFunctionReturnTypes2.ts, 82, 1))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 84, 26))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 84, 29))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 84, 26))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 84, 26))
|
||||
|
||||
const t2 = testSet.transform(
|
||||
>t2 : Symbol(t2, Decl(inferFromGenericFunctionReturnTypes2.ts, 86, 5))
|
||||
>testSet.transform : Symbol(SetOf.transform, Decl(inferFromGenericFunctionReturnTypes2.ts, 30, 3))
|
||||
>testSet : Symbol(testSet, Decl(inferFromGenericFunctionReturnTypes2.ts, 70, 5))
|
||||
>transform : Symbol(SetOf.transform, Decl(inferFromGenericFunctionReturnTypes2.ts, 30, 3))
|
||||
|
||||
compose(
|
||||
>compose : Symbol(compose, Decl(inferFromGenericFunctionReturnTypes2.ts, 39, 1), Decl(inferFromGenericFunctionReturnTypes2.ts, 46, 28))
|
||||
|
||||
filter(x => x % 1 === 0),
|
||||
>filter : Symbol(filter, Decl(inferFromGenericFunctionReturnTypes2.ts, 58, 1))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 88, 11))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 88, 11))
|
||||
|
||||
identity,
|
||||
>identity : Symbol(identity, Decl(inferFromGenericFunctionReturnTypes2.ts, 82, 1))
|
||||
|
||||
map(x => x + '!!!'),
|
||||
>map : Symbol(map, Decl(inferFromGenericFunctionReturnTypes2.ts, 50, 1))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 90, 8))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 90, 8))
|
||||
|
||||
map(x => x.toUpperCase())
|
||||
>map : Symbol(map, Decl(inferFromGenericFunctionReturnTypes2.ts, 50, 1))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 91, 8))
|
||||
>x.toUpperCase : Symbol(String.toUpperCase, Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 91, 8))
|
||||
>toUpperCase : Symbol(String.toUpperCase, Decl(lib.d.ts, --, --))
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
@ -0,0 +1,600 @@
|
||||
=== tests/cases/compiler/inferFromGenericFunctionReturnTypes2.ts ===
|
||||
type Mapper<T, U> = (x: T) => U;
|
||||
>Mapper : Mapper<T, U>
|
||||
>T : T
|
||||
>U : U
|
||||
>x : T
|
||||
>T : T
|
||||
>U : U
|
||||
|
||||
declare function wrap<T, U>(cb: Mapper<T, U>): Mapper<T, U>;
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>T : T
|
||||
>U : U
|
||||
>cb : Mapper<T, U>
|
||||
>Mapper : Mapper<T, U>
|
||||
>T : T
|
||||
>U : U
|
||||
>Mapper : Mapper<T, U>
|
||||
>T : T
|
||||
>U : U
|
||||
|
||||
declare function arrayize<T, U>(cb: Mapper<T, U>): Mapper<T, U[]>;
|
||||
>arrayize : <T, U>(cb: Mapper<T, U>) => Mapper<T, U[]>
|
||||
>T : T
|
||||
>U : U
|
||||
>cb : Mapper<T, U>
|
||||
>Mapper : Mapper<T, U>
|
||||
>T : T
|
||||
>U : U
|
||||
>Mapper : Mapper<T, U>
|
||||
>T : T
|
||||
>U : U
|
||||
|
||||
declare function combine<A, B, C>(f: (x: A) => B, g: (x: B) => C): (x: A) => C;
|
||||
>combine : <A, B, C>(f: (x: A) => B, g: (x: B) => C) => (x: A) => C
|
||||
>A : A
|
||||
>B : B
|
||||
>C : C
|
||||
>f : (x: A) => B
|
||||
>x : A
|
||||
>A : A
|
||||
>B : B
|
||||
>g : (x: B) => C
|
||||
>x : B
|
||||
>B : B
|
||||
>C : C
|
||||
>x : A
|
||||
>A : A
|
||||
>C : C
|
||||
|
||||
declare function foo(f: Mapper<string, number>): void;
|
||||
>foo : (f: Mapper<string, number>) => void
|
||||
>f : Mapper<string, number>
|
||||
>Mapper : Mapper<T, U>
|
||||
|
||||
let f1: Mapper<string, number> = s => s.length;
|
||||
>f1 : Mapper<string, number>
|
||||
>Mapper : Mapper<T, U>
|
||||
>s => s.length : (s: string) => number
|
||||
>s : string
|
||||
>s.length : number
|
||||
>s : string
|
||||
>length : number
|
||||
|
||||
let f2: Mapper<string, number> = wrap(s => s.length);
|
||||
>f2 : Mapper<string, number>
|
||||
>Mapper : Mapper<T, U>
|
||||
>wrap(s => s.length) : Mapper<string, number>
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>s => s.length : (s: string) => number
|
||||
>s : string
|
||||
>s.length : number
|
||||
>s : string
|
||||
>length : number
|
||||
|
||||
let f3: Mapper<string, number[]> = arrayize(wrap(s => s.length));
|
||||
>f3 : Mapper<string, number[]>
|
||||
>Mapper : Mapper<T, U>
|
||||
>arrayize(wrap(s => s.length)) : Mapper<string, number[]>
|
||||
>arrayize : <T, U>(cb: Mapper<T, U>) => Mapper<T, U[]>
|
||||
>wrap(s => s.length) : Mapper<string, number>
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>s => s.length : (s: string) => number
|
||||
>s : string
|
||||
>s.length : number
|
||||
>s : string
|
||||
>length : number
|
||||
|
||||
let f4: Mapper<string, boolean> = combine(wrap(s => s.length), wrap(n => n >= 10));
|
||||
>f4 : Mapper<string, boolean>
|
||||
>Mapper : Mapper<T, U>
|
||||
>combine(wrap(s => s.length), wrap(n => n >= 10)) : (x: string) => boolean
|
||||
>combine : <A, B, C>(f: (x: A) => B, g: (x: B) => C) => (x: A) => C
|
||||
>wrap(s => s.length) : Mapper<string, number>
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>s => s.length : (s: string) => number
|
||||
>s : string
|
||||
>s.length : number
|
||||
>s : string
|
||||
>length : number
|
||||
>wrap(n => n >= 10) : Mapper<number, boolean>
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>n => n >= 10 : (n: number) => boolean
|
||||
>n : number
|
||||
>n >= 10 : boolean
|
||||
>n : number
|
||||
>10 : 10
|
||||
|
||||
foo(wrap(s => s.length));
|
||||
>foo(wrap(s => s.length)) : void
|
||||
>foo : (f: Mapper<string, number>) => void
|
||||
>wrap(s => s.length) : Mapper<string, number>
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>s => s.length : (s: string) => number
|
||||
>s : string
|
||||
>s.length : number
|
||||
>s : string
|
||||
>length : number
|
||||
|
||||
let a1 = ["a", "b"].map(s => s.length);
|
||||
>a1 : number[]
|
||||
>["a", "b"].map(s => s.length) : number[]
|
||||
>["a", "b"].map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>["a", "b"] : string[]
|
||||
>"a" : "a"
|
||||
>"b" : "b"
|
||||
>map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>s => s.length : (this: void, s: string) => number
|
||||
>s : string
|
||||
>s.length : number
|
||||
>s : string
|
||||
>length : number
|
||||
|
||||
let a2 = ["a", "b"].map(wrap(s => s.length));
|
||||
>a2 : number[]
|
||||
>["a", "b"].map(wrap(s => s.length)) : number[]
|
||||
>["a", "b"].map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>["a", "b"] : string[]
|
||||
>"a" : "a"
|
||||
>"b" : "b"
|
||||
>map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>wrap(s => s.length) : Mapper<string, number>
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>s => s.length : (s: string) => number
|
||||
>s : string
|
||||
>s.length : number
|
||||
>s : string
|
||||
>length : number
|
||||
|
||||
let a3 = ["a", "b"].map(wrap(arrayize(s => s.length)));
|
||||
>a3 : number[][]
|
||||
>["a", "b"].map(wrap(arrayize(s => s.length))) : number[][]
|
||||
>["a", "b"].map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>["a", "b"] : string[]
|
||||
>"a" : "a"
|
||||
>"b" : "b"
|
||||
>map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>wrap(arrayize(s => s.length)) : Mapper<string, number[]>
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>arrayize(s => s.length) : Mapper<string, number[]>
|
||||
>arrayize : <T, U>(cb: Mapper<T, U>) => Mapper<T, U[]>
|
||||
>s => s.length : (s: string) => number
|
||||
>s : string
|
||||
>s.length : number
|
||||
>s : string
|
||||
>length : number
|
||||
|
||||
let a4 = ["a", "b"].map(combine(wrap(s => s.length), wrap(n => n > 10)));
|
||||
>a4 : boolean[]
|
||||
>["a", "b"].map(combine(wrap(s => s.length), wrap(n => n > 10))) : boolean[]
|
||||
>["a", "b"].map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>["a", "b"] : string[]
|
||||
>"a" : "a"
|
||||
>"b" : "b"
|
||||
>map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>combine(wrap(s => s.length), wrap(n => n > 10)) : (x: string) => boolean
|
||||
>combine : <A, B, C>(f: (x: A) => B, g: (x: B) => C) => (x: A) => C
|
||||
>wrap(s => s.length) : Mapper<string, number>
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>s => s.length : (s: string) => number
|
||||
>s : string
|
||||
>s.length : number
|
||||
>s : string
|
||||
>length : number
|
||||
>wrap(n => n > 10) : Mapper<number, boolean>
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>n => n > 10 : (n: number) => boolean
|
||||
>n : number
|
||||
>n > 10 : boolean
|
||||
>n : number
|
||||
>10 : 10
|
||||
|
||||
let a5 = ["a", "b"].map(combine(identity, wrap(s => s.length)));
|
||||
>a5 : number[]
|
||||
>["a", "b"].map(combine(identity, wrap(s => s.length))) : number[]
|
||||
>["a", "b"].map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>["a", "b"] : string[]
|
||||
>"a" : "a"
|
||||
>"b" : "b"
|
||||
>map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>combine(identity, wrap(s => s.length)) : (x: string) => number
|
||||
>combine : <A, B, C>(f: (x: A) => B, g: (x: B) => C) => (x: A) => C
|
||||
>identity : <T>(x: T) => T
|
||||
>wrap(s => s.length) : Mapper<string, number>
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>s => s.length : (s: string) => number
|
||||
>s : string
|
||||
>s.length : number
|
||||
>s : string
|
||||
>length : number
|
||||
|
||||
let a6 = ["a", "b"].map(combine(wrap(s => s.length), identity));
|
||||
>a6 : number[]
|
||||
>["a", "b"].map(combine(wrap(s => s.length), identity)) : number[]
|
||||
>["a", "b"].map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>["a", "b"] : string[]
|
||||
>"a" : "a"
|
||||
>"b" : "b"
|
||||
>map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>combine(wrap(s => s.length), identity) : (x: string) => number
|
||||
>combine : <A, B, C>(f: (x: A) => B, g: (x: B) => C) => (x: A) => C
|
||||
>wrap(s => s.length) : Mapper<string, number>
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>s => s.length : (s: string) => number
|
||||
>s : string
|
||||
>s.length : number
|
||||
>s : string
|
||||
>length : number
|
||||
>identity : <T>(x: T) => T
|
||||
|
||||
// This is a contrived class. We could do the same thing with Observables, etc.
|
||||
class SetOf<A> {
|
||||
>SetOf : SetOf<A>
|
||||
>A : A
|
||||
|
||||
_store: A[];
|
||||
>_store : A[]
|
||||
>A : A
|
||||
|
||||
add(a: A) {
|
||||
>add : (a: A) => void
|
||||
>a : A
|
||||
>A : A
|
||||
|
||||
this._store.push(a);
|
||||
>this._store.push(a) : number
|
||||
>this._store.push : (...items: A[]) => number
|
||||
>this._store : A[]
|
||||
>this : this
|
||||
>_store : A[]
|
||||
>push : (...items: A[]) => number
|
||||
>a : A
|
||||
}
|
||||
|
||||
transform<B>(transformer: (a: SetOf<A>) => SetOf<B>): SetOf<B> {
|
||||
>transform : <B>(transformer: (a: SetOf<A>) => SetOf<B>) => SetOf<B>
|
||||
>B : B
|
||||
>transformer : (a: SetOf<A>) => SetOf<B>
|
||||
>a : SetOf<A>
|
||||
>SetOf : SetOf<A>
|
||||
>A : A
|
||||
>SetOf : SetOf<A>
|
||||
>B : B
|
||||
>SetOf : SetOf<A>
|
||||
>B : B
|
||||
|
||||
return transformer(this);
|
||||
>transformer(this) : SetOf<B>
|
||||
>transformer : (a: SetOf<A>) => SetOf<B>
|
||||
>this : this
|
||||
}
|
||||
|
||||
forEach(fn: (a: A, index: number) => void) {
|
||||
>forEach : (fn: (a: A, index: number) => void) => void
|
||||
>fn : (a: A, index: number) => void
|
||||
>a : A
|
||||
>A : A
|
||||
>index : number
|
||||
|
||||
this._store.forEach((a, i) => fn(a, i));
|
||||
>this._store.forEach((a, i) => fn(a, i)) : void
|
||||
>this._store.forEach : { (callbackfn: (this: void, value: A, index: number, array: A[]) => void): void; (callbackfn: (this: void, value: A, index: number, array: A[]) => void, thisArg: undefined): void; <Z>(callbackfn: (this: Z, value: A, index: number, array: A[]) => void, thisArg: Z): void; }
|
||||
>this._store : A[]
|
||||
>this : this
|
||||
>_store : A[]
|
||||
>forEach : { (callbackfn: (this: void, value: A, index: number, array: A[]) => void): void; (callbackfn: (this: void, value: A, index: number, array: A[]) => void, thisArg: undefined): void; <Z>(callbackfn: (this: Z, value: A, index: number, array: A[]) => void, thisArg: Z): void; }
|
||||
>(a, i) => fn(a, i) : (this: void, a: A, i: number) => void
|
||||
>a : A
|
||||
>i : number
|
||||
>fn(a, i) : void
|
||||
>fn : (a: A, index: number) => void
|
||||
>a : A
|
||||
>i : number
|
||||
}
|
||||
}
|
||||
|
||||
function compose<A, B, C, D, E>(
|
||||
>compose : <A, B, C, D, E>(fnA: (a: SetOf<A>) => SetOf<B>, fnB: (b: SetOf<B>) => SetOf<C>, fnC: (c: SetOf<C>) => SetOf<D>, fnD: (c: SetOf<D>) => SetOf<E>) => (x: SetOf<A>) => SetOf<E>
|
||||
>A : A
|
||||
>B : B
|
||||
>C : C
|
||||
>D : D
|
||||
>E : E
|
||||
|
||||
fnA: (a: SetOf<A>) => SetOf<B>,
|
||||
>fnA : (a: SetOf<A>) => SetOf<B>
|
||||
>a : SetOf<A>
|
||||
>SetOf : SetOf<A>
|
||||
>A : A
|
||||
>SetOf : SetOf<A>
|
||||
>B : B
|
||||
|
||||
fnB: (b: SetOf<B>) => SetOf<C>,
|
||||
>fnB : (b: SetOf<B>) => SetOf<C>
|
||||
>b : SetOf<B>
|
||||
>SetOf : SetOf<A>
|
||||
>B : B
|
||||
>SetOf : SetOf<A>
|
||||
>C : C
|
||||
|
||||
fnC: (c: SetOf<C>) => SetOf<D>,
|
||||
>fnC : (c: SetOf<C>) => SetOf<D>
|
||||
>c : SetOf<C>
|
||||
>SetOf : SetOf<A>
|
||||
>C : C
|
||||
>SetOf : SetOf<A>
|
||||
>D : D
|
||||
|
||||
fnD: (c: SetOf<D>) => SetOf<E>,
|
||||
>fnD : (c: SetOf<D>) => SetOf<E>
|
||||
>c : SetOf<D>
|
||||
>SetOf : SetOf<A>
|
||||
>D : D
|
||||
>SetOf : SetOf<A>
|
||||
>E : E
|
||||
|
||||
):(x: SetOf<A>) => SetOf<E>;
|
||||
>x : SetOf<A>
|
||||
>SetOf : SetOf<A>
|
||||
>A : A
|
||||
>SetOf : SetOf<A>
|
||||
>E : E
|
||||
|
||||
/* ... etc ... */
|
||||
function compose<T>(...fns: ((x: T) => T)[]): (x: T) => T {
|
||||
>compose : <A, B, C, D, E>(fnA: (a: SetOf<A>) => SetOf<B>, fnB: (b: SetOf<B>) => SetOf<C>, fnC: (c: SetOf<C>) => SetOf<D>, fnD: (c: SetOf<D>) => SetOf<E>) => (x: SetOf<A>) => SetOf<E>
|
||||
>T : T
|
||||
>fns : ((x: T) => T)[]
|
||||
>x : T
|
||||
>T : T
|
||||
>T : T
|
||||
>x : T
|
||||
>T : T
|
||||
>T : T
|
||||
|
||||
return (x: T) => fns.reduce((prev, fn) => fn(prev), x);
|
||||
>(x: T) => fns.reduce((prev, fn) => fn(prev), x) : (x: T) => T
|
||||
>x : T
|
||||
>T : T
|
||||
>fns.reduce((prev, fn) => fn(prev), x) : T
|
||||
>fns.reduce : { (callbackfn: (previousValue: (x: T) => T, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => (x: T) => T, initialValue?: (x: T) => T): (x: T) => T; <U>(callbackfn: (previousValue: U, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => U, initialValue: U): U; }
|
||||
>fns : ((x: T) => T)[]
|
||||
>reduce : { (callbackfn: (previousValue: (x: T) => T, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => (x: T) => T, initialValue?: (x: T) => T): (x: T) => T; <U>(callbackfn: (previousValue: U, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => U, initialValue: U): U; }
|
||||
>(prev, fn) => fn(prev) : (prev: T, fn: (x: T) => T) => T
|
||||
>prev : T
|
||||
>fn : (x: T) => T
|
||||
>fn(prev) : T
|
||||
>fn : (x: T) => T
|
||||
>prev : T
|
||||
>x : T
|
||||
}
|
||||
|
||||
function map<A, B>(fn: (a: A) => B): (s: SetOf<A>) => SetOf<B> {
|
||||
>map : <A, B>(fn: (a: A) => B) => (s: SetOf<A>) => SetOf<B>
|
||||
>A : A
|
||||
>B : B
|
||||
>fn : (a: A) => B
|
||||
>a : A
|
||||
>A : A
|
||||
>B : B
|
||||
>s : SetOf<A>
|
||||
>SetOf : SetOf<A>
|
||||
>A : A
|
||||
>SetOf : SetOf<A>
|
||||
>B : B
|
||||
|
||||
return (a: SetOf<A>) => {
|
||||
>(a: SetOf<A>) => { const b: SetOf<B> = new SetOf(); a.forEach(x => b.add(fn(x))); return b; } : (a: SetOf<A>) => SetOf<B>
|
||||
>a : SetOf<A>
|
||||
>SetOf : SetOf<A>
|
||||
>A : A
|
||||
|
||||
const b: SetOf<B> = new SetOf();
|
||||
>b : SetOf<B>
|
||||
>SetOf : SetOf<A>
|
||||
>B : B
|
||||
>new SetOf() : SetOf<B>
|
||||
>SetOf : typeof SetOf
|
||||
|
||||
a.forEach(x => b.add(fn(x)));
|
||||
>a.forEach(x => b.add(fn(x))) : void
|
||||
>a.forEach : (fn: (a: A, index: number) => void) => void
|
||||
>a : SetOf<A>
|
||||
>forEach : (fn: (a: A, index: number) => void) => void
|
||||
>x => b.add(fn(x)) : (x: A) => void
|
||||
>x : A
|
||||
>b.add(fn(x)) : void
|
||||
>b.add : (a: B) => void
|
||||
>b : SetOf<B>
|
||||
>add : (a: B) => void
|
||||
>fn(x) : B
|
||||
>fn : (a: A) => B
|
||||
>x : A
|
||||
|
||||
return b;
|
||||
>b : SetOf<B>
|
||||
}
|
||||
}
|
||||
|
||||
function filter<A>(predicate: (a: A) => boolean): (s: SetOf<A>) => SetOf<A> {
|
||||
>filter : <A>(predicate: (a: A) => boolean) => (s: SetOf<A>) => SetOf<A>
|
||||
>A : A
|
||||
>predicate : (a: A) => boolean
|
||||
>a : A
|
||||
>A : A
|
||||
>s : SetOf<A>
|
||||
>SetOf : SetOf<A>
|
||||
>A : A
|
||||
>SetOf : SetOf<A>
|
||||
>A : A
|
||||
|
||||
return (a: SetOf<A>) => {
|
||||
>(a: SetOf<A>) => { const result = new SetOf<A>(); a.forEach(x => { if (predicate(x)) result.add(x); }); return result; } : (a: SetOf<A>) => SetOf<A>
|
||||
>a : SetOf<A>
|
||||
>SetOf : SetOf<A>
|
||||
>A : A
|
||||
|
||||
const result = new SetOf<A>();
|
||||
>result : SetOf<A>
|
||||
>new SetOf<A>() : SetOf<A>
|
||||
>SetOf : typeof SetOf
|
||||
>A : A
|
||||
|
||||
a.forEach(x => {
|
||||
>a.forEach(x => { if (predicate(x)) result.add(x); }) : void
|
||||
>a.forEach : (fn: (a: A, index: number) => void) => void
|
||||
>a : SetOf<A>
|
||||
>forEach : (fn: (a: A, index: number) => void) => void
|
||||
>x => { if (predicate(x)) result.add(x); } : (x: A) => void
|
||||
>x : A
|
||||
|
||||
if (predicate(x)) result.add(x);
|
||||
>predicate(x) : boolean
|
||||
>predicate : (a: A) => boolean
|
||||
>x : A
|
||||
>result.add(x) : void
|
||||
>result.add : (a: A) => void
|
||||
>result : SetOf<A>
|
||||
>add : (a: A) => void
|
||||
>x : A
|
||||
|
||||
});
|
||||
return result;
|
||||
>result : SetOf<A>
|
||||
}
|
||||
}
|
||||
|
||||
const testSet = new SetOf<number>();
|
||||
>testSet : SetOf<number>
|
||||
>new SetOf<number>() : SetOf<number>
|
||||
>SetOf : typeof SetOf
|
||||
|
||||
testSet.add(1);
|
||||
>testSet.add(1) : void
|
||||
>testSet.add : (a: number) => void
|
||||
>testSet : SetOf<number>
|
||||
>add : (a: number) => void
|
||||
>1 : 1
|
||||
|
||||
testSet.add(2);
|
||||
>testSet.add(2) : void
|
||||
>testSet.add : (a: number) => void
|
||||
>testSet : SetOf<number>
|
||||
>add : (a: number) => void
|
||||
>2 : 2
|
||||
|
||||
testSet.add(3);
|
||||
>testSet.add(3) : void
|
||||
>testSet.add : (a: number) => void
|
||||
>testSet : SetOf<number>
|
||||
>add : (a: number) => void
|
||||
>3 : 3
|
||||
|
||||
const t1 = testSet.transform(
|
||||
>t1 : SetOf<string>
|
||||
>testSet.transform( compose( filter(x => x % 1 === 0), map(x => x + x), map(x => x + '!!!'), map(x => x.toUpperCase()) )) : SetOf<string>
|
||||
>testSet.transform : <B>(transformer: (a: SetOf<number>) => SetOf<B>) => SetOf<B>
|
||||
>testSet : SetOf<number>
|
||||
>transform : <B>(transformer: (a: SetOf<number>) => SetOf<B>) => SetOf<B>
|
||||
|
||||
compose(
|
||||
>compose( filter(x => x % 1 === 0), map(x => x + x), map(x => x + '!!!'), map(x => x.toUpperCase()) ) : (x: SetOf<number>) => SetOf<string>
|
||||
>compose : <A, B, C, D, E>(fnA: (a: SetOf<A>) => SetOf<B>, fnB: (b: SetOf<B>) => SetOf<C>, fnC: (c: SetOf<C>) => SetOf<D>, fnD: (c: SetOf<D>) => SetOf<E>) => (x: SetOf<A>) => SetOf<E>
|
||||
|
||||
filter(x => x % 1 === 0),
|
||||
>filter(x => x % 1 === 0) : (s: SetOf<number>) => SetOf<number>
|
||||
>filter : <A>(predicate: (a: A) => boolean) => (s: SetOf<A>) => SetOf<A>
|
||||
>x => x % 1 === 0 : (x: number) => boolean
|
||||
>x : number
|
||||
>x % 1 === 0 : boolean
|
||||
>x % 1 : number
|
||||
>x : number
|
||||
>1 : 1
|
||||
>0 : 0
|
||||
|
||||
map(x => x + x),
|
||||
>map(x => x + x) : (s: SetOf<number>) => SetOf<number>
|
||||
>map : <A, B>(fn: (a: A) => B) => (s: SetOf<A>) => SetOf<B>
|
||||
>x => x + x : (x: number) => number
|
||||
>x : number
|
||||
>x + x : number
|
||||
>x : number
|
||||
>x : number
|
||||
|
||||
map(x => x + '!!!'),
|
||||
>map(x => x + '!!!') : (s: SetOf<number>) => SetOf<string>
|
||||
>map : <A, B>(fn: (a: A) => B) => (s: SetOf<A>) => SetOf<B>
|
||||
>x => x + '!!!' : (x: number) => string
|
||||
>x : number
|
||||
>x + '!!!' : string
|
||||
>x : number
|
||||
>'!!!' : "!!!"
|
||||
|
||||
map(x => x.toUpperCase())
|
||||
>map(x => x.toUpperCase()) : (s: SetOf<string>) => SetOf<string>
|
||||
>map : <A, B>(fn: (a: A) => B) => (s: SetOf<A>) => SetOf<B>
|
||||
>x => x.toUpperCase() : (x: string) => string
|
||||
>x : string
|
||||
>x.toUpperCase() : string
|
||||
>x.toUpperCase : () => string
|
||||
>x : string
|
||||
>toUpperCase : () => string
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
declare function identity<T>(x: T): T;
|
||||
>identity : <T>(x: T) => T
|
||||
>T : T
|
||||
>x : T
|
||||
>T : T
|
||||
>T : T
|
||||
|
||||
const t2 = testSet.transform(
|
||||
>t2 : SetOf<string>
|
||||
>testSet.transform( compose( filter(x => x % 1 === 0), identity, map(x => x + '!!!'), map(x => x.toUpperCase()) )) : SetOf<string>
|
||||
>testSet.transform : <B>(transformer: (a: SetOf<number>) => SetOf<B>) => SetOf<B>
|
||||
>testSet : SetOf<number>
|
||||
>transform : <B>(transformer: (a: SetOf<number>) => SetOf<B>) => SetOf<B>
|
||||
|
||||
compose(
|
||||
>compose( filter(x => x % 1 === 0), identity, map(x => x + '!!!'), map(x => x.toUpperCase()) ) : (x: SetOf<number>) => SetOf<string>
|
||||
>compose : <A, B, C, D, E>(fnA: (a: SetOf<A>) => SetOf<B>, fnB: (b: SetOf<B>) => SetOf<C>, fnC: (c: SetOf<C>) => SetOf<D>, fnD: (c: SetOf<D>) => SetOf<E>) => (x: SetOf<A>) => SetOf<E>
|
||||
|
||||
filter(x => x % 1 === 0),
|
||||
>filter(x => x % 1 === 0) : (s: SetOf<number>) => SetOf<number>
|
||||
>filter : <A>(predicate: (a: A) => boolean) => (s: SetOf<A>) => SetOf<A>
|
||||
>x => x % 1 === 0 : (x: number) => boolean
|
||||
>x : number
|
||||
>x % 1 === 0 : boolean
|
||||
>x % 1 : number
|
||||
>x : number
|
||||
>1 : 1
|
||||
>0 : 0
|
||||
|
||||
identity,
|
||||
>identity : <T>(x: T) => T
|
||||
|
||||
map(x => x + '!!!'),
|
||||
>map(x => x + '!!!') : (s: SetOf<number>) => SetOf<string>
|
||||
>map : <A, B>(fn: (a: A) => B) => (s: SetOf<A>) => SetOf<B>
|
||||
>x => x + '!!!' : (x: number) => string
|
||||
>x : number
|
||||
>x + '!!!' : string
|
||||
>x : number
|
||||
>'!!!' : "!!!"
|
||||
|
||||
map(x => x.toUpperCase())
|
||||
>map(x => x.toUpperCase()) : (s: SetOf<string>) => SetOf<string>
|
||||
>map : <A, B>(fn: (a: A) => B) => (s: SetOf<A>) => SetOf<B>
|
||||
>x => x.toUpperCase() : (x: string) => string
|
||||
>x : string
|
||||
>x.toUpperCase() : string
|
||||
>x.toUpperCase : () => string
|
||||
>x : string
|
||||
>toUpperCase : () => string
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
@ -149,9 +149,9 @@ function f1() {
|
||||
let x: number = b.a.value;
|
||||
>x : Symbol(x, Decl(isomorphicMappedTypeInference.ts, 45, 7))
|
||||
>b.a.value : Symbol(value, Decl(isomorphicMappedTypeInference.ts, 0, 15))
|
||||
>b.a : Symbol(a)
|
||||
>b.a : Symbol(a, Decl(isomorphicMappedTypeInference.ts, 39, 13))
|
||||
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 44, 7))
|
||||
>a : Symbol(a)
|
||||
>a : Symbol(a, Decl(isomorphicMappedTypeInference.ts, 39, 13))
|
||||
>value : Symbol(value, Decl(isomorphicMappedTypeInference.ts, 0, 15))
|
||||
}
|
||||
|
||||
|
||||
@ -431,28 +431,8 @@
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "(",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": ")",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "=>",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "any",
|
||||
"kind": "keyword"
|
||||
"text": "Function",
|
||||
"kind": "localName"
|
||||
}
|
||||
],
|
||||
"documentation": [],
|
||||
|
||||
234
tests/baselines/reference/jsDocTypedef1.js
Normal file
234
tests/baselines/reference/jsDocTypedef1.js
Normal file
@ -0,0 +1,234 @@
|
||||
[
|
||||
{
|
||||
"marker": {
|
||||
"fileName": "/tests/cases/fourslash/jsDocTypedef1.js",
|
||||
"position": 189
|
||||
},
|
||||
"quickInfo": {
|
||||
"kind": "parameter",
|
||||
"kindModifiers": "",
|
||||
"textSpan": {
|
||||
"start": 189,
|
||||
"length": 4
|
||||
},
|
||||
"displayParts": [
|
||||
{
|
||||
"text": "(",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": "parameter",
|
||||
"kind": "text"
|
||||
},
|
||||
{
|
||||
"text": ")",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "opts",
|
||||
"kind": "parameterName"
|
||||
},
|
||||
{
|
||||
"text": ":",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "{",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": "\n",
|
||||
"kind": "lineBreak"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "x",
|
||||
"kind": "propertyName"
|
||||
},
|
||||
{
|
||||
"text": ":",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "string",
|
||||
"kind": "keyword"
|
||||
},
|
||||
{
|
||||
"text": ";",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": "\n",
|
||||
"kind": "lineBreak"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "y",
|
||||
"kind": "propertyName"
|
||||
},
|
||||
{
|
||||
"text": "?",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": ":",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "string",
|
||||
"kind": "keyword"
|
||||
},
|
||||
{
|
||||
"text": ";",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": "\n",
|
||||
"kind": "lineBreak"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "z",
|
||||
"kind": "propertyName"
|
||||
},
|
||||
{
|
||||
"text": "?",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": ":",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "string",
|
||||
"kind": "keyword"
|
||||
},
|
||||
{
|
||||
"text": ";",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": "\n",
|
||||
"kind": "lineBreak"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "w",
|
||||
"kind": "propertyName"
|
||||
},
|
||||
{
|
||||
"text": "?",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": ":",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "string",
|
||||
"kind": "keyword"
|
||||
},
|
||||
{
|
||||
"text": ";",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": "\n",
|
||||
"kind": "lineBreak"
|
||||
},
|
||||
{
|
||||
"text": "}",
|
||||
"kind": "punctuation"
|
||||
}
|
||||
],
|
||||
"documentation": [],
|
||||
"tags": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"marker": {
|
||||
"fileName": "/tests/cases/fourslash/jsDocTypedef1.js",
|
||||
"position": 424
|
||||
},
|
||||
"quickInfo": {
|
||||
"kind": "parameter",
|
||||
"kindModifiers": "",
|
||||
"textSpan": {
|
||||
"start": 424,
|
||||
"length": 5
|
||||
},
|
||||
"displayParts": [
|
||||
{
|
||||
"text": "(",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": "parameter",
|
||||
"kind": "text"
|
||||
},
|
||||
{
|
||||
"text": ")",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "opts1",
|
||||
"kind": "parameterName"
|
||||
},
|
||||
{
|
||||
"text": ":",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "any",
|
||||
"kind": "keyword"
|
||||
}
|
||||
],
|
||||
"documentation": [],
|
||||
"tags": []
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -11,6 +11,10 @@ anyT1 = "hi";
|
||||
const x = (a) => a + 1;
|
||||
x(1);
|
||||
|
||||
/** @type {function} */
|
||||
const y = (a) => a + 1;
|
||||
x(1);
|
||||
|
||||
/** @type {function (number)} */
|
||||
const x1 = (a) => a + 1;
|
||||
x1(0);
|
||||
@ -29,6 +33,9 @@ anyT1 = "hi";
|
||||
/** @type {Function} */
|
||||
var x = function (a) { return a + 1; };
|
||||
x(1);
|
||||
/** @type {function} */
|
||||
var y = function (a) { return a + 1; };
|
||||
x(1);
|
||||
/** @type {function (number)} */
|
||||
var x1 = function (a) { return a + 1; };
|
||||
x1(0);
|
||||
|
||||
@ -20,21 +20,30 @@ const x = (a) => a + 1;
|
||||
x(1);
|
||||
>x : Symbol(x, Decl(0.js, 9, 5))
|
||||
|
||||
/** @type {function} */
|
||||
const y = (a) => a + 1;
|
||||
>y : Symbol(y, Decl(0.js, 13, 5))
|
||||
>a : Symbol(a, Decl(0.js, 13, 11))
|
||||
>a : Symbol(a, Decl(0.js, 13, 11))
|
||||
|
||||
x(1);
|
||||
>x : Symbol(x, Decl(0.js, 9, 5))
|
||||
|
||||
/** @type {function (number)} */
|
||||
const x1 = (a) => a + 1;
|
||||
>x1 : Symbol(x1, Decl(0.js, 13, 5))
|
||||
>a : Symbol(a, Decl(0.js, 13, 12))
|
||||
>a : Symbol(a, Decl(0.js, 13, 12))
|
||||
>x1 : Symbol(x1, Decl(0.js, 17, 5))
|
||||
>a : Symbol(a, Decl(0.js, 17, 12))
|
||||
>a : Symbol(a, Decl(0.js, 17, 12))
|
||||
|
||||
x1(0);
|
||||
>x1 : Symbol(x1, Decl(0.js, 13, 5))
|
||||
>x1 : Symbol(x1, Decl(0.js, 17, 5))
|
||||
|
||||
/** @type {function (number): number} */
|
||||
const x2 = (a) => a + 1;
|
||||
>x2 : Symbol(x2, Decl(0.js, 17, 5))
|
||||
>a : Symbol(a, Decl(0.js, 17, 12))
|
||||
>a : Symbol(a, Decl(0.js, 17, 12))
|
||||
>x2 : Symbol(x2, Decl(0.js, 21, 5))
|
||||
>a : Symbol(a, Decl(0.js, 21, 12))
|
||||
>a : Symbol(a, Decl(0.js, 21, 12))
|
||||
|
||||
x2(0);
|
||||
>x2 : Symbol(x2, Decl(0.js, 17, 5))
|
||||
>x2 : Symbol(x2, Decl(0.js, 21, 5))
|
||||
|
||||
|
||||
@ -29,6 +29,20 @@ x(1);
|
||||
>x : Function
|
||||
>1 : 1
|
||||
|
||||
/** @type {function} */
|
||||
const y = (a) => a + 1;
|
||||
>y : Function
|
||||
>(a) => a + 1 : (a: any) => any
|
||||
>a : any
|
||||
>a + 1 : any
|
||||
>a : any
|
||||
>1 : 1
|
||||
|
||||
x(1);
|
||||
>x(1) : any
|
||||
>x : Function
|
||||
>1 : 1
|
||||
|
||||
/** @type {function (number)} */
|
||||
const x1 = (a) => a + 1;
|
||||
>x1 : (arg0: number) => any
|
||||
|
||||
@ -820,19 +820,19 @@ function f71(func: <T, U>(x: T, y: U) => Partial<T & U>) {
|
||||
>c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 226, 40))
|
||||
|
||||
x.a; // number | undefined
|
||||
>x.a : Symbol(a)
|
||||
>x.a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 226, 18))
|
||||
>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 226, 7))
|
||||
>a : Symbol(a)
|
||||
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 226, 18))
|
||||
|
||||
x.b; // string | undefined
|
||||
>x.b : Symbol(b)
|
||||
>x.b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 226, 24))
|
||||
>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 226, 7))
|
||||
>b : Symbol(b)
|
||||
>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 226, 24))
|
||||
|
||||
x.c; // boolean | undefined
|
||||
>x.c : Symbol(c)
|
||||
>x.c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 226, 40))
|
||||
>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 226, 7))
|
||||
>c : Symbol(c)
|
||||
>c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 226, 40))
|
||||
}
|
||||
|
||||
function f72(func: <T, U, K extends keyof T | keyof U>(x: T, y: U, k: K) => (T & U)[K]) {
|
||||
@ -1951,11 +1951,11 @@ class AnotherSampleClass<T> extends SampleClass<T & Foo> {
|
||||
|
||||
this.props.foo.concat;
|
||||
>this.props.foo.concat : Symbol(String.concat, Decl(lib.d.ts, --, --))
|
||||
>this.props.foo : Symbol(foo)
|
||||
>this.props.foo : Symbol(foo, Decl(keyofAndIndexedAccess.ts, 536, 15))
|
||||
>this.props : Symbol(SampleClass.props, Decl(keyofAndIndexedAccess.ts, 529, 22))
|
||||
>this : Symbol(AnotherSampleClass, Decl(keyofAndIndexedAccess.ts, 540, 54))
|
||||
>props : Symbol(SampleClass.props, Decl(keyofAndIndexedAccess.ts, 529, 22))
|
||||
>foo : Symbol(foo)
|
||||
>foo : Symbol(foo, Decl(keyofAndIndexedAccess.ts, 536, 15))
|
||||
>concat : Symbol(String.concat, Decl(lib.d.ts, --, --))
|
||||
}
|
||||
}
|
||||
|
||||
@ -364,9 +364,9 @@ function f1(x: Partial<Foo>) {
|
||||
>Foo : Symbol(Foo, Decl(mappedTypeModifiers.ts, 74, 30))
|
||||
|
||||
x.prop; // ok
|
||||
>x.prop : Symbol(prop)
|
||||
>x.prop : Symbol(prop, Decl(mappedTypeModifiers.ts, 76, 12))
|
||||
>x : Symbol(x, Decl(mappedTypeModifiers.ts, 78, 12))
|
||||
>prop : Symbol(prop)
|
||||
>prop : Symbol(prop, Decl(mappedTypeModifiers.ts, 76, 12))
|
||||
|
||||
(x["other"] || 0).toFixed();
|
||||
>(x["other"] || 0).toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --))
|
||||
@ -381,9 +381,9 @@ function f2(x: Readonly<Foo>) {
|
||||
>Foo : Symbol(Foo, Decl(mappedTypeModifiers.ts, 74, 30))
|
||||
|
||||
x.prop; // ok
|
||||
>x.prop : Symbol(prop)
|
||||
>x.prop : Symbol(prop, Decl(mappedTypeModifiers.ts, 76, 12))
|
||||
>x : Symbol(x, Decl(mappedTypeModifiers.ts, 83, 12))
|
||||
>prop : Symbol(prop)
|
||||
>prop : Symbol(prop, Decl(mappedTypeModifiers.ts, 76, 12))
|
||||
|
||||
x["other"].toFixed();
|
||||
>x["other"].toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --))
|
||||
@ -398,9 +398,9 @@ function f3(x: Boxified<Foo>) {
|
||||
>Foo : Symbol(Foo, Decl(mappedTypeModifiers.ts, 74, 30))
|
||||
|
||||
x.prop; // ok
|
||||
>x.prop : Symbol(prop)
|
||||
>x.prop : Symbol(prop, Decl(mappedTypeModifiers.ts, 76, 12))
|
||||
>x : Symbol(x, Decl(mappedTypeModifiers.ts, 88, 12))
|
||||
>prop : Symbol(prop)
|
||||
>prop : Symbol(prop, Decl(mappedTypeModifiers.ts, 76, 12))
|
||||
|
||||
x["other"].x.toFixed();
|
||||
>x["other"].x.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --))
|
||||
@ -419,9 +419,9 @@ function f4(x: { [P in keyof Foo]: Foo[P] }) {
|
||||
>P : Symbol(P, Decl(mappedTypeModifiers.ts, 93, 18))
|
||||
|
||||
x.prop; // ok
|
||||
>x.prop : Symbol(prop)
|
||||
>x.prop : Symbol(prop, Decl(mappedTypeModifiers.ts, 76, 12))
|
||||
>x : Symbol(x, Decl(mappedTypeModifiers.ts, 93, 12))
|
||||
>prop : Symbol(prop)
|
||||
>prop : Symbol(prop, Decl(mappedTypeModifiers.ts, 76, 12))
|
||||
|
||||
x["other"].toFixed();
|
||||
>x["other"].toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --))
|
||||
|
||||
@ -313,16 +313,16 @@ function f5(shape: Shape) {
|
||||
let name = p.name.get();
|
||||
>name : Symbol(name, Decl(mappedTypes2.ts, 84, 7))
|
||||
>p.name.get : Symbol(get, Decl(mappedTypes2.ts, 11, 17))
|
||||
>p.name : Symbol(name)
|
||||
>p.name : Symbol(name, Decl(mappedTypes2.ts, 35, 17))
|
||||
>p : Symbol(p, Decl(mappedTypes2.ts, 83, 9))
|
||||
>name : Symbol(name)
|
||||
>name : Symbol(name, Decl(mappedTypes2.ts, 35, 17))
|
||||
>get : Symbol(get, Decl(mappedTypes2.ts, 11, 17))
|
||||
|
||||
p.width.set(42);
|
||||
>p.width.set : Symbol(set, Decl(mappedTypes2.ts, 12, 13))
|
||||
>p.width : Symbol(width)
|
||||
>p.width : Symbol(width, Decl(mappedTypes2.ts, 36, 17))
|
||||
>p : Symbol(p, Decl(mappedTypes2.ts, 83, 9))
|
||||
>width : Symbol(width)
|
||||
>width : Symbol(width, Decl(mappedTypes2.ts, 36, 17))
|
||||
>set : Symbol(set, Decl(mappedTypes2.ts, 12, 13))
|
||||
}
|
||||
|
||||
@ -334,19 +334,19 @@ function f6(shape: DeepReadonly<Shape>) {
|
||||
|
||||
let name = shape.name; // string
|
||||
>name : Symbol(name, Decl(mappedTypes2.ts, 89, 7))
|
||||
>shape.name : Symbol(name)
|
||||
>shape.name : Symbol(name, Decl(mappedTypes2.ts, 35, 17))
|
||||
>shape : Symbol(shape, Decl(mappedTypes2.ts, 88, 12))
|
||||
>name : Symbol(name)
|
||||
>name : Symbol(name, Decl(mappedTypes2.ts, 35, 17))
|
||||
|
||||
let location = shape.location; // DeepReadonly<Point>
|
||||
>location : Symbol(location, Decl(mappedTypes2.ts, 90, 7))
|
||||
>shape.location : Symbol(location)
|
||||
>shape.location : Symbol(location, Decl(mappedTypes2.ts, 38, 19))
|
||||
>shape : Symbol(shape, Decl(mappedTypes2.ts, 88, 12))
|
||||
>location : Symbol(location)
|
||||
>location : Symbol(location, Decl(mappedTypes2.ts, 38, 19))
|
||||
|
||||
let x = location.x; // number
|
||||
>x : Symbol(x, Decl(mappedTypes2.ts, 91, 7))
|
||||
>location.x : Symbol(x)
|
||||
>location.x : Symbol(x, Decl(mappedTypes2.ts, 30, 17))
|
||||
>location : Symbol(location, Decl(mappedTypes2.ts, 90, 7))
|
||||
>x : Symbol(x)
|
||||
>x : Symbol(x, Decl(mappedTypes2.ts, 30, 17))
|
||||
}
|
||||
|
||||
@ -71,17 +71,17 @@ function f1(b: Bacon) {
|
||||
let isPerfect = bb.isPerfect.value;
|
||||
>isPerfect : Symbol(isPerfect, Decl(mappedTypes3.ts, 23, 7))
|
||||
>bb.isPerfect.value : Symbol(Box.value, Decl(mappedTypes3.ts, 0, 14))
|
||||
>bb.isPerfect : Symbol(isPerfect)
|
||||
>bb.isPerfect : Symbol(isPerfect, Decl(mappedTypes3.ts, 11, 17))
|
||||
>bb : Symbol(bb, Decl(mappedTypes3.ts, 22, 7))
|
||||
>isPerfect : Symbol(isPerfect)
|
||||
>isPerfect : Symbol(isPerfect, Decl(mappedTypes3.ts, 11, 17))
|
||||
>value : Symbol(Box.value, Decl(mappedTypes3.ts, 0, 14))
|
||||
|
||||
let weight = bb.weight.value;
|
||||
>weight : Symbol(weight, Decl(mappedTypes3.ts, 24, 7))
|
||||
>bb.weight.value : Symbol(Box.value, Decl(mappedTypes3.ts, 0, 14))
|
||||
>bb.weight : Symbol(weight)
|
||||
>bb.weight : Symbol(weight, Decl(mappedTypes3.ts, 12, 23))
|
||||
>bb : Symbol(bb, Decl(mappedTypes3.ts, 22, 7))
|
||||
>weight : Symbol(weight)
|
||||
>weight : Symbol(weight, Decl(mappedTypes3.ts, 12, 23))
|
||||
>value : Symbol(Box.value, Decl(mappedTypes3.ts, 0, 14))
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
tests/cases/compiler/recursiveTypeComparison2.ts(13,80): error TS2304: Cannot find name 'StateValue'.
|
||||
tests/cases/compiler/recursiveTypeComparison2.ts(30,5): error TS2322: Type 'Bus<{}>' is not assignable to type 'Bus<number>'.
|
||||
Type '{}' is not assignable to type 'number'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/recursiveTypeComparison2.ts (2 errors) ====
|
||||
==== tests/cases/compiler/recursiveTypeComparison2.ts (1 errors) ====
|
||||
// Before fix this would cause compiler to hang (#1170)
|
||||
|
||||
declare module Bacon {
|
||||
@ -35,7 +33,4 @@ tests/cases/compiler/recursiveTypeComparison2.ts(30,5): error TS2322: Type 'Bus<
|
||||
var Bus: new <T>() => Bus<T>;
|
||||
}
|
||||
|
||||
var stuck: Bacon.Bus<number> = new Bacon.Bus();
|
||||
~~~~~
|
||||
!!! error TS2322: Type 'Bus<{}>' is not assignable to type 'Bus<number>'.
|
||||
!!! error TS2322: Type '{}' is not assignable to type 'number'.
|
||||
var stuck: Bacon.Bus<number> = new Bacon.Bus();
|
||||
@ -23,16 +23,16 @@ class A<P extends Partial<Foo>> {
|
||||
>doSomething : Symbol(A.doSomething, Decl(typeVariableTypeGuards.ts, 7, 22))
|
||||
|
||||
this.props.foo && this.props.foo()
|
||||
>this.props.foo : Symbol(foo)
|
||||
>this.props.foo : Symbol(foo, Decl(typeVariableTypeGuards.ts, 2, 15))
|
||||
>this.props : Symbol(A.props, Decl(typeVariableTypeGuards.ts, 6, 33))
|
||||
>this : Symbol(A, Decl(typeVariableTypeGuards.ts, 4, 1))
|
||||
>props : Symbol(A.props, Decl(typeVariableTypeGuards.ts, 6, 33))
|
||||
>foo : Symbol(foo)
|
||||
>this.props.foo : Symbol(foo)
|
||||
>foo : Symbol(foo, Decl(typeVariableTypeGuards.ts, 2, 15))
|
||||
>this.props.foo : Symbol(foo, Decl(typeVariableTypeGuards.ts, 2, 15))
|
||||
>this.props : Symbol(A.props, Decl(typeVariableTypeGuards.ts, 6, 33))
|
||||
>this : Symbol(A, Decl(typeVariableTypeGuards.ts, 4, 1))
|
||||
>props : Symbol(A.props, Decl(typeVariableTypeGuards.ts, 6, 33))
|
||||
>foo : Symbol(foo)
|
||||
>foo : Symbol(foo, Decl(typeVariableTypeGuards.ts, 2, 15))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
9
tests/cases/compiler/conflictMarkerDiff3Trivia1.ts
Normal file
9
tests/cases/compiler/conflictMarkerDiff3Trivia1.ts
Normal file
@ -0,0 +1,9 @@
|
||||
class C {
|
||||
<<<<<<< HEAD
|
||||
v = 1;
|
||||
||||||| merged common ancestors
|
||||
v = 3;
|
||||
=======
|
||||
v = 2;
|
||||
>>>>>>> Branch-a
|
||||
}
|
||||
15
tests/cases/compiler/conflictMarkerDiff3Trivia2.ts
Normal file
15
tests/cases/compiler/conflictMarkerDiff3Trivia2.ts
Normal file
@ -0,0 +1,15 @@
|
||||
class C {
|
||||
foo() {
|
||||
<<<<<<< B
|
||||
a();
|
||||
}
|
||||
||||||| merged common ancestors
|
||||
c();
|
||||
}
|
||||
=======
|
||||
b();
|
||||
}
|
||||
>>>>>>> A
|
||||
|
||||
public bar() { }
|
||||
}
|
||||
70
tests/cases/compiler/inferFromGenericFunctionReturnTypes1.ts
Normal file
70
tests/cases/compiler/inferFromGenericFunctionReturnTypes1.ts
Normal file
@ -0,0 +1,70 @@
|
||||
// Repro from #15680
|
||||
|
||||
// This is a contrived class. We could do the same thing with Observables, etc.
|
||||
class SetOf<A> {
|
||||
_store: A[];
|
||||
|
||||
add(a: A) {
|
||||
this._store.push(a);
|
||||
}
|
||||
|
||||
transform<B>(transformer: (a: SetOf<A>) => SetOf<B>): SetOf<B> {
|
||||
return transformer(this);
|
||||
}
|
||||
|
||||
forEach(fn: (a: A, index: number) => void) {
|
||||
this._store.forEach((a, i) => fn(a, i));
|
||||
}
|
||||
}
|
||||
|
||||
function compose<A, B, C, D, E>(
|
||||
fnA: (a: SetOf<A>) => SetOf<B>,
|
||||
fnB: (b: SetOf<B>) => SetOf<C>,
|
||||
fnC: (c: SetOf<C>) => SetOf<D>,
|
||||
fnD: (c: SetOf<D>) => SetOf<E>,
|
||||
):(x: SetOf<A>) => SetOf<E>;
|
||||
/* ... etc ... */
|
||||
function compose<T>(...fns: ((x: T) => T)[]): (x: T) => T {
|
||||
return (x: T) => fns.reduce((prev, fn) => fn(prev), x);
|
||||
}
|
||||
|
||||
function map<A, B>(fn: (a: A) => B): (s: SetOf<A>) => SetOf<B> {
|
||||
return (a: SetOf<A>) => {
|
||||
const b: SetOf<B> = new SetOf();
|
||||
a.forEach(x => b.add(fn(x)));
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
function filter<A>(predicate: (a: A) => boolean): (s: SetOf<A>) => SetOf<A> {
|
||||
return (a: SetOf<A>) => {
|
||||
const result = new SetOf<A>();
|
||||
a.forEach(x => {
|
||||
if (predicate(x)) result.add(x);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
const testSet = new SetOf<number>();
|
||||
testSet.add(1);
|
||||
testSet.add(2);
|
||||
testSet.add(3);
|
||||
|
||||
testSet.transform(
|
||||
compose(
|
||||
filter(x => x % 1 === 0),
|
||||
map(x => x + x),
|
||||
map(x => x + '!!!'),
|
||||
map(x => x.toUpperCase())
|
||||
)
|
||||
)
|
||||
|
||||
testSet.transform(
|
||||
compose(
|
||||
filter(x => x % 1 === 0),
|
||||
map(x => x + x),
|
||||
map(x => 123), // Whoops a bug
|
||||
map(x => x.toUpperCase()) // causes an error!
|
||||
)
|
||||
)
|
||||
94
tests/cases/compiler/inferFromGenericFunctionReturnTypes2.ts
Normal file
94
tests/cases/compiler/inferFromGenericFunctionReturnTypes2.ts
Normal file
@ -0,0 +1,94 @@
|
||||
type Mapper<T, U> = (x: T) => U;
|
||||
|
||||
declare function wrap<T, U>(cb: Mapper<T, U>): Mapper<T, U>;
|
||||
|
||||
declare function arrayize<T, U>(cb: Mapper<T, U>): Mapper<T, U[]>;
|
||||
|
||||
declare function combine<A, B, C>(f: (x: A) => B, g: (x: B) => C): (x: A) => C;
|
||||
|
||||
declare function foo(f: Mapper<string, number>): void;
|
||||
|
||||
let f1: Mapper<string, number> = s => s.length;
|
||||
let f2: Mapper<string, number> = wrap(s => s.length);
|
||||
let f3: Mapper<string, number[]> = arrayize(wrap(s => s.length));
|
||||
let f4: Mapper<string, boolean> = combine(wrap(s => s.length), wrap(n => n >= 10));
|
||||
|
||||
foo(wrap(s => s.length));
|
||||
|
||||
let a1 = ["a", "b"].map(s => s.length);
|
||||
let a2 = ["a", "b"].map(wrap(s => s.length));
|
||||
let a3 = ["a", "b"].map(wrap(arrayize(s => s.length)));
|
||||
let a4 = ["a", "b"].map(combine(wrap(s => s.length), wrap(n => n > 10)));
|
||||
let a5 = ["a", "b"].map(combine(identity, wrap(s => s.length)));
|
||||
let a6 = ["a", "b"].map(combine(wrap(s => s.length), identity));
|
||||
|
||||
// This is a contrived class. We could do the same thing with Observables, etc.
|
||||
class SetOf<A> {
|
||||
_store: A[];
|
||||
|
||||
add(a: A) {
|
||||
this._store.push(a);
|
||||
}
|
||||
|
||||
transform<B>(transformer: (a: SetOf<A>) => SetOf<B>): SetOf<B> {
|
||||
return transformer(this);
|
||||
}
|
||||
|
||||
forEach(fn: (a: A, index: number) => void) {
|
||||
this._store.forEach((a, i) => fn(a, i));
|
||||
}
|
||||
}
|
||||
|
||||
function compose<A, B, C, D, E>(
|
||||
fnA: (a: SetOf<A>) => SetOf<B>,
|
||||
fnB: (b: SetOf<B>) => SetOf<C>,
|
||||
fnC: (c: SetOf<C>) => SetOf<D>,
|
||||
fnD: (c: SetOf<D>) => SetOf<E>,
|
||||
):(x: SetOf<A>) => SetOf<E>;
|
||||
/* ... etc ... */
|
||||
function compose<T>(...fns: ((x: T) => T)[]): (x: T) => T {
|
||||
return (x: T) => fns.reduce((prev, fn) => fn(prev), x);
|
||||
}
|
||||
|
||||
function map<A, B>(fn: (a: A) => B): (s: SetOf<A>) => SetOf<B> {
|
||||
return (a: SetOf<A>) => {
|
||||
const b: SetOf<B> = new SetOf();
|
||||
a.forEach(x => b.add(fn(x)));
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
function filter<A>(predicate: (a: A) => boolean): (s: SetOf<A>) => SetOf<A> {
|
||||
return (a: SetOf<A>) => {
|
||||
const result = new SetOf<A>();
|
||||
a.forEach(x => {
|
||||
if (predicate(x)) result.add(x);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
const testSet = new SetOf<number>();
|
||||
testSet.add(1);
|
||||
testSet.add(2);
|
||||
testSet.add(3);
|
||||
|
||||
const t1 = testSet.transform(
|
||||
compose(
|
||||
filter(x => x % 1 === 0),
|
||||
map(x => x + x),
|
||||
map(x => x + '!!!'),
|
||||
map(x => x.toUpperCase())
|
||||
)
|
||||
)
|
||||
|
||||
declare function identity<T>(x: T): T;
|
||||
|
||||
const t2 = testSet.transform(
|
||||
compose(
|
||||
filter(x => x % 1 === 0),
|
||||
identity,
|
||||
map(x => x + '!!!'),
|
||||
map(x => x.toUpperCase())
|
||||
)
|
||||
)
|
||||
@ -0,0 +1,33 @@
|
||||
// @allowJS: true
|
||||
// @suppressOutputPathCheck: true
|
||||
|
||||
// @filename: 0.js
|
||||
// @ts-check
|
||||
/**
|
||||
* @typedef {Object} Opts
|
||||
* @property {string} x
|
||||
* @property {string=} y
|
||||
* @property {string} [z]
|
||||
* @property {string} [w="hi"]
|
||||
*
|
||||
* @param {Opts} opts
|
||||
*/
|
||||
function foo(opts) {
|
||||
opts.x;
|
||||
}
|
||||
|
||||
foo({x: 'abc'});
|
||||
|
||||
/**
|
||||
* @typedef {object} Opts1
|
||||
* @property {string} x
|
||||
* @property {string=} y
|
||||
* @property {string} [z]
|
||||
* @property {string} [w="hi"]
|
||||
*
|
||||
* @param {Opts1} opts
|
||||
*/
|
||||
function foo1(opts) {
|
||||
opts.x;
|
||||
}
|
||||
foo1({x: 'abc'});
|
||||
@ -14,6 +14,10 @@ anyT1 = "hi";
|
||||
const x = (a) => a + 1;
|
||||
x(1);
|
||||
|
||||
/** @type {function} */
|
||||
const y = (a) => a + 1;
|
||||
x(1);
|
||||
|
||||
/** @type {function (number)} */
|
||||
const x1 = (a) => a + 1;
|
||||
x1(0);
|
||||
|
||||
22
tests/cases/fourslash/formatConflictDiff3Marker1.ts
Normal file
22
tests/cases/fourslash/formatConflictDiff3Marker1.ts
Normal file
@ -0,0 +1,22 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////class C {
|
||||
////<<<<<<< HEAD
|
||||
////v = 1;
|
||||
////||||||| merged common ancestors
|
||||
////v = 3;
|
||||
////=======
|
||||
////v = 2;
|
||||
////>>>>>>> Branch - a
|
||||
////}
|
||||
|
||||
format.document();
|
||||
verify.currentFileContentIs("class C {\r\n\
|
||||
<<<<<<< HEAD\r\n\
|
||||
v = 1;\r\n\
|
||||
||||||| merged common ancestors\r\n\
|
||||
v = 3;\r\n\
|
||||
=======\r\n\
|
||||
v = 2;\r\n\
|
||||
>>>>>>> Branch - a\r\n\
|
||||
}");
|
||||
@ -1,48 +1,48 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////interface Collection<T, U> {
|
||||
//// length: number;
|
||||
//// add(x: T, y: U): void ;
|
||||
//// remove(x: T, y: U): boolean;
|
||||
////}
|
||||
//// length: number;
|
||||
//// add(x: T, y: U): void ;
|
||||
//// remove(x: T, y: U): boolean;
|
||||
////}
|
||||
////
|
||||
////interface Combinators {
|
||||
//// map<T, U, V>(c: Collection<T, U>, f: (x: T, y: U) => V): Collection<T, V>;
|
||||
//// map<T, U>(c: Collection<T, U>, f: (x: T, y: U) => any): Collection<any, any>;
|
||||
////}
|
||||
//// map<T, U, V>(c: Collection<T, U>, f: (x: T, y: U) => V): Collection<T, V>;
|
||||
//// map<T, U>(c: Collection<T, U>, f: (x: T, y: U) => any): Collection<any, any>;
|
||||
////}
|
||||
////
|
||||
////class A {
|
||||
//// foo<T>(): T { return null; }
|
||||
////}
|
||||
//// foo<T>(): T { return null; }
|
||||
////}
|
||||
////
|
||||
////class B<T> {
|
||||
//// foo(x: T): T { return null; }
|
||||
////}
|
||||
//// foo(x: T): T { return null; }
|
||||
////}
|
||||
////
|
||||
////var c1: Collection<any, any>;
|
||||
////var c2: Collection<number, string>;
|
||||
////var c3: Collection<Collection<number, number>, string>;
|
||||
////var c4: Collection<number, A>;
|
||||
////var c5: Collection<number, B<any>>;
|
||||
////}
|
||||
////
|
||||
////var _: Combinators;
|
||||
////// param help on open paren for arg 2 should show 'number' not T or 'any'
|
||||
////// x should be contextually typed to number
|
||||
////var rf1 = (x: number, y: string) => { return x.toFixed() };
|
||||
////var rf2 = (x: Collection<number, number>, y: string) => { return x.length };
|
||||
////var rf3 = (x: number, y: A) => { return y.foo() };
|
||||
////}
|
||||
////
|
||||
////var /*9*/r1a = _.map/*1c*/(c2, (/*1a*/x, /*1b*/y) => { return x.toFixed() });
|
||||
////var /*10*/r1b = _.map(c2, rf1);
|
||||
////}
|
||||
////
|
||||
////var /*11*/r2a = _.map(c3, (/*2a*/x, /*2b*/y) => { return x.length });
|
||||
////var /*12*/r2b = _.map(c3, rf2);
|
||||
////}
|
||||
////
|
||||
////var /*13*/r3a = _.map(c4, (/*3a*/x, /*3b*/y) => { return y.foo() });
|
||||
////var /*14*/r3b = _.map(c4, rf3);
|
||||
////}
|
||||
////
|
||||
////var /*15*/r4a = _.map(c5, (/*4a*/x, /*4b*/y) => { return y.foo() });
|
||||
////}
|
||||
////
|
||||
////var /*17*/r5a = _.map<number, string, Date>(c2, /*17error1*/(/*5a*/x, /*5b*/y) => { return x.toFixed() }/*17error2*/);
|
||||
////var rf1b = (x: number, y: string) => { return new Date() };
|
||||
////var /*18*/r5b = _.map<number, string, Date>(c2, rf1b);
|
||||
@ -51,7 +51,7 @@
|
||||
////var rf2b = (x: Collection<number, number>, y: string) => { return new Date(); };
|
||||
////var /*20*/r6b = _.map<Collection<number, number>, string, Date>(c3, rf2b);
|
||||
////
|
||||
////var /*21*/r7a = _.map<number, A, string>(c4, /*21error1*/(/*7a*/x,/*7b*/y) => { return y.foo() }/*21error2*/);
|
||||
////var /*21*/r7a = _.map<number, A, string>(c4, (/*7a*/x,/*7b*/y) => { return y.foo() });
|
||||
////var /*22*/r7b = _.map<number, A, string>(c4, /*22error1*/rf3/*22error2*/);
|
||||
////
|
||||
////var /*23*/r8a = _.map<number, /*error1*/B/*error2*/, string>(c5, (/*8a*/x,/*8b*/y) => { return y.foo() });
|
||||
@ -89,5 +89,4 @@ verify.quickInfos({
|
||||
|
||||
verify.errorExistsBetweenMarkers('error1', 'error2');
|
||||
verify.errorExistsBetweenMarkers('17error1', '17error2');
|
||||
verify.errorExistsBetweenMarkers('21error1', '21error2');
|
||||
verify.errorExistsBetweenMarkers('22error1', '22error2');
|
||||
33
tests/cases/fourslash/jsDocTypedefQuickInfo1.ts
Normal file
33
tests/cases/fourslash/jsDocTypedefQuickInfo1.ts
Normal file
@ -0,0 +1,33 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
// @allowJs: true
|
||||
// @Filename: jsDocTypedef1.js
|
||||
//// /**
|
||||
//// * @typedef {Object} Opts
|
||||
//// * @property {string} x
|
||||
//// * @property {string=} y
|
||||
//// * @property {string} [z]
|
||||
//// * @property {string} [w="hi"]
|
||||
//// *
|
||||
//// * @param {Opts} opts
|
||||
//// */
|
||||
//// function foo(/*1*/opts) {
|
||||
//// opts.x;
|
||||
///// }
|
||||
|
||||
//// foo({x: 'abc'});
|
||||
|
||||
//// /**
|
||||
//// * @typedef {object} Opts1
|
||||
//// * @property {string} x
|
||||
//// * @property {string=} y
|
||||
//// * @property {string} [z]
|
||||
//// * @property {string} [w="hi"]
|
||||
//// *
|
||||
//// * @param {Opts1} opts
|
||||
//// */
|
||||
//// function foo1(/*2*/opts1) {
|
||||
//// opts1.x;
|
||||
//// }
|
||||
//// foo1({x: 'abc'});
|
||||
|
||||
verify.baselineQuickInfo();
|
||||
16
tests/cases/fourslash/jsdocTypedefTagSemanticMeaning0.ts
Normal file
16
tests/cases/fourslash/jsdocTypedefTagSemanticMeaning0.ts
Normal file
@ -0,0 +1,16 @@
|
||||
///<reference path="fourslash.ts" />
|
||||
|
||||
// @allowJs: true
|
||||
// @Filename: a.js
|
||||
|
||||
/////** @typedef {number} [|{| "isWriteAccess": true, "isDefinition": true |}T|] */
|
||||
|
||||
////const [|{| "isWriteAccess": true, "isDefinition": true |}T|] = 1;
|
||||
|
||||
/////** @type {[|T|]} */
|
||||
////const n = [|T|];
|
||||
|
||||
const [t0, v0, t1, v1] = test.ranges();
|
||||
|
||||
verify.singleReferenceGroup("type T = number\nconst T: 1", [t0, t1]);
|
||||
verify.singleReferenceGroup("type T = number\nconst T: 1", [v0, v1]);
|
||||
12
tests/cases/fourslash/jsdocTypedefTagSemanticMeaning1.ts
Normal file
12
tests/cases/fourslash/jsdocTypedefTagSemanticMeaning1.ts
Normal file
@ -0,0 +1,12 @@
|
||||
///<reference path="fourslash.ts" />
|
||||
|
||||
// @allowJs: true
|
||||
// @Filename: a.js
|
||||
|
||||
/////** @typedef {number} */
|
||||
////const [|{| "isWriteAccess": true, "isDefinition": true |}T|] = 1;
|
||||
|
||||
/////** @type {[|T|]} */
|
||||
////const n = [|T|];
|
||||
|
||||
verify.singleReferenceGroup("type T = number\nconst T: 1");
|
||||
28
tests/cases/fourslash/jsdocTypedefTagServices.ts
Normal file
28
tests/cases/fourslash/jsdocTypedefTagServices.ts
Normal file
@ -0,0 +1,28 @@
|
||||
///<reference path="fourslash.ts" />
|
||||
|
||||
// @allowJs: true
|
||||
// @Filename: a.js
|
||||
|
||||
/////**
|
||||
//// * Doc comment
|
||||
//// * @typedef /*def*/[|{| "isWriteAccess": true, "isDefinition": true |}Product|]
|
||||
//// * @property {string} title
|
||||
//// */
|
||||
|
||||
/////**
|
||||
//// * @type {/*use*/[|Product|]}
|
||||
//// */
|
||||
////const product = null;
|
||||
|
||||
const desc = `type Product = {
|
||||
title: string;
|
||||
}`;
|
||||
|
||||
verify.quickInfoAt("use", desc, "Doc comment");
|
||||
|
||||
verify.goToDefinition("use", "def");
|
||||
|
||||
verify.rangesAreOccurrences();
|
||||
verify.rangesAreDocumentHighlights();
|
||||
verify.singleReferenceGroup(desc);
|
||||
verify.rangesAreRenameLocations();
|
||||
30
tests/cases/fourslash/server/quickInfoMappedSpreadTypes.ts
Normal file
30
tests/cases/fourslash/server/quickInfoMappedSpreadTypes.ts
Normal file
@ -0,0 +1,30 @@
|
||||
/// <reference path="../fourslash.ts"/>
|
||||
|
||||
////interface Foo {
|
||||
//// /** Doc */
|
||||
//// bar: number;
|
||||
////}
|
||||
////
|
||||
////const f: Foo = { bar: 0 };
|
||||
////f./*f*/bar;
|
||||
////
|
||||
////const f2: { [TKey in keyof Foo]: string } = { bar: "0" };
|
||||
////f2./*f2*/bar;
|
||||
////
|
||||
////const f3 = { ...f };
|
||||
////f3./*f3*/bar;
|
||||
////
|
||||
////const f4 = { ...f2 };
|
||||
////f4./*f4*/bar;
|
||||
|
||||
goTo.marker("f");
|
||||
verify.quickInfoIs("(property) Foo.bar: number", "Doc ");
|
||||
|
||||
goTo.marker("f2");
|
||||
verify.quickInfoIs("(property) bar: string", "Doc ");
|
||||
|
||||
goTo.marker("f3");
|
||||
verify.quickInfoIs("(property) Foo.bar: number", "Doc ");
|
||||
|
||||
goTo.marker("f4");
|
||||
verify.quickInfoIs("(property) bar: string", "Doc ");
|
||||
@ -0,0 +1,23 @@
|
||||
/// <reference path="fourslash.ts"/>
|
||||
|
||||
////class C {
|
||||
////<<<<<<< HEAD
|
||||
//// v = 1;
|
||||
////||||||| merged common ancestors
|
||||
//// v = 3;
|
||||
////=======
|
||||
//// v = 2;
|
||||
////>>>>>>> Branch - a
|
||||
////}
|
||||
|
||||
const c = classification;
|
||||
verify.syntacticClassificationsAre(
|
||||
c.keyword("class"), c.className("C"), c.punctuation("{"),
|
||||
c.comment("<<<<<<< HEAD"),
|
||||
c.identifier("v"), c.operator("="), c.numericLiteral("1"), c.punctuation(";"),
|
||||
c.comment("||||||| merged common ancestors"),
|
||||
c.identifier("v"), c.punctuation("="), c.numericLiteral("3"), c.punctuation(";"),
|
||||
c.comment("======="),
|
||||
c.identifier("v"), c.punctuation("="), c.numericLiteral("2"), c.punctuation(";"),
|
||||
c.comment(">>>>>>> Branch - a"),
|
||||
c.punctuation("}"));
|
||||
@ -0,0 +1,19 @@
|
||||
/// <reference path="fourslash.ts"/>
|
||||
|
||||
////<<<<<<< HEAD
|
||||
////class C { }
|
||||
////||||||| merged common ancestors
|
||||
////class E { }
|
||||
////=======
|
||||
////class D { }
|
||||
////>>>>>>> Branch - a
|
||||
|
||||
const c = classification;
|
||||
verify.syntacticClassificationsAre(
|
||||
c.comment("<<<<<<< HEAD"),
|
||||
c.keyword("class"), c.className("C"), c.punctuation("{"), c.punctuation("}"),
|
||||
c.comment("||||||| merged common ancestors"),
|
||||
c.keyword("class"), c.identifier("E"), c.punctuation("{"), c.punctuation("}"),
|
||||
c.comment("======="),
|
||||
c.keyword("class"), c.identifier("D"), c.punctuation("{"), c.punctuation("}"),
|
||||
c.comment(">>>>>>> Branch - a"));
|
||||
Loading…
x
Reference in New Issue
Block a user