mirror of
https://github.com/github/codeql.git
synced 2026-07-21 03:08:25 +02:00
Merge pull request #2379 from asger-semmle/typescript-fixes
TS: A bunch of TypeScript fixes
This commit is contained in:
@@ -8,7 +8,8 @@
|
||||
"build": "tsc --project tsconfig.json",
|
||||
"check": "tsc --noEmit --project . && tslint --project .",
|
||||
"lint": "tslint --project .",
|
||||
"lint-fix": "tslint --project . --fix"
|
||||
"lint-fix": "tslint --project . --fix",
|
||||
"watch": "tsc -p . -w --sourceMap"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "12.7.11",
|
||||
|
||||
@@ -198,7 +198,9 @@ export function augmentAst(ast: AugmentedSourceFile, code: string, project: Proj
|
||||
: null;
|
||||
let type = contextualType || typeChecker.getTypeAtLocation(node);
|
||||
if (type != null) {
|
||||
let id = typeTable.buildType(type);
|
||||
let parent = node.parent;
|
||||
let unfoldAlias = ts.isTypeAliasDeclaration(parent) && node === parent.type;
|
||||
let id = typeTable.buildType(type, unfoldAlias);
|
||||
if (id != null) {
|
||||
node.$type = id;
|
||||
}
|
||||
|
||||
@@ -253,7 +253,7 @@ function handleOpenProjectCommand(command: OpenProjectCommand) {
|
||||
fileExists: (path: string) => fs.existsSync(path),
|
||||
readFile: ts.sys.readFile,
|
||||
};
|
||||
let config = ts.parseJsonConfigFileContent(tsConfig, parseConfigHost, basePath);
|
||||
let config = ts.parseJsonConfigFileContent(tsConfig.config, parseConfigHost, basePath);
|
||||
let project = new Project(tsConfigFilename, config, state.typeTable);
|
||||
project.load();
|
||||
|
||||
@@ -272,7 +272,9 @@ function handleOpenProjectCommand(command: OpenProjectCommand) {
|
||||
});
|
||||
|
||||
for (let typeRoot of typeRoots || []) {
|
||||
traverseTypeRoot(typeRoot, "");
|
||||
if (fs.existsSync(typeRoot) && fs.statSync(typeRoot).isDirectory()) {
|
||||
traverseTypeRoot(typeRoot, "");
|
||||
}
|
||||
}
|
||||
|
||||
for (let sourceFile of program.getSourceFiles()) {
|
||||
|
||||
@@ -92,6 +92,20 @@ function isTypeofCandidateSymbol(symbol: ts.Symbol) {
|
||||
|
||||
const signatureKinds = [ts.SignatureKind.Call, ts.SignatureKind.Construct];
|
||||
|
||||
/**
|
||||
* Bitmask of flags set on a signature, but not exposed in the public API.
|
||||
*/
|
||||
const enum InternalSignatureFlags {
|
||||
HasRestParameter = 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Signature interface with some internal properties exposed.
|
||||
*/
|
||||
interface AugmentedSignature extends ts.Signature {
|
||||
flags?: InternalSignatureFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes property lookup tuples `(baseType, name, property)` as three
|
||||
* staggered arrays.
|
||||
@@ -102,6 +116,16 @@ interface PropertyLookupTable {
|
||||
propertyTypes: number[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes `(aliasType, underlyingType)` tuples as two staggered arrays.
|
||||
*
|
||||
* Such a tuple denotes that `aliasType` is an alias for `underlyingType`.
|
||||
*/
|
||||
interface TypeAliasTable {
|
||||
aliasTypes: number[];
|
||||
underlyingTypes: number[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes type signature tuples `(baseType, kind, index, signature)` as four
|
||||
* staggered arrays.
|
||||
@@ -287,6 +311,11 @@ export class TypeTable {
|
||||
propertyTypes: [],
|
||||
};
|
||||
|
||||
private typeAliases: TypeAliasTable = {
|
||||
aliasTypes: [],
|
||||
underlyingTypes: [],
|
||||
};
|
||||
|
||||
private signatureMappings: SignatureTable = {
|
||||
baseTypes: [],
|
||||
kinds: [],
|
||||
@@ -304,7 +333,7 @@ export class TypeTable {
|
||||
propertyTypes: [],
|
||||
};
|
||||
|
||||
private buildTypeWorklist: [ts.Type, number][] = [];
|
||||
private buildTypeWorklist: [ts.Type, number, boolean][] = [];
|
||||
|
||||
private expansiveTypes: Map<number, boolean> = new Map();
|
||||
|
||||
@@ -372,9 +401,9 @@ export class TypeTable {
|
||||
/**
|
||||
* Gets the canonical ID for the given type, generating a fresh ID if necessary.
|
||||
*/
|
||||
public buildType(type: ts.Type): number | null {
|
||||
public buildType(type: ts.Type, unfoldAlias: boolean): number | null {
|
||||
this.isInShallowTypeContext = false;
|
||||
let id = this.getId(type);
|
||||
let id = this.getId(type, unfoldAlias);
|
||||
this.iterateBuildTypeWorklist();
|
||||
if (id == null) return null;
|
||||
return id;
|
||||
@@ -385,7 +414,7 @@ export class TypeTable {
|
||||
*
|
||||
* Returns `null` if we do not support extraction of this type.
|
||||
*/
|
||||
public getId(type: ts.Type): number | null {
|
||||
public getId(type: ts.Type, unfoldAlias: boolean): number | null {
|
||||
if (this.typeRecursionDepth > 100) {
|
||||
// Ignore infinitely nested anonymous types, such as `{x: {x: {x: ... }}}`.
|
||||
// Such a type can't be written directly with TypeScript syntax (as it would need to be named),
|
||||
@@ -397,19 +426,19 @@ export class TypeTable {
|
||||
type = this.typeChecker.getBaseTypeOfLiteralType(type);
|
||||
}
|
||||
++this.typeRecursionDepth;
|
||||
let content = this.getTypeString(type);
|
||||
let content = this.getTypeString(type, unfoldAlias);
|
||||
--this.typeRecursionDepth;
|
||||
if (content == null) return null; // Type not supported.
|
||||
let id = this.typeIds.get(content);
|
||||
if (id == null) {
|
||||
let stringValue = this.stringifyType(type);
|
||||
let stringValue = this.stringifyType(type, unfoldAlias);
|
||||
if (stringValue == null) {
|
||||
return null; // Type not supported.
|
||||
}
|
||||
id = this.typeIds.size;
|
||||
this.typeIds.set(content, id);
|
||||
this.typeToStringValues.push(stringValue);
|
||||
this.buildTypeWorklist.push([type, id]);
|
||||
this.buildTypeWorklist.push([type, id, unfoldAlias]);
|
||||
this.typeExtractionState.push(
|
||||
this.isInShallowTypeContext ? TypeExtractionState.PendingShallow : TypeExtractionState.PendingFull);
|
||||
// If the type is the self-type for a named type (not a generic instantiation of it),
|
||||
@@ -426,20 +455,20 @@ export class TypeTable {
|
||||
this.typeExtractionState[id] = TypeExtractionState.PendingFull;
|
||||
} else if (state === TypeExtractionState.DoneShallow) {
|
||||
this.typeExtractionState[id] = TypeExtractionState.PendingFull;
|
||||
this.buildTypeWorklist.push([type, id]);
|
||||
this.buildTypeWorklist.push([type, id, unfoldAlias]);
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
private stringifyType(type: ts.Type): string {
|
||||
private stringifyType(type: ts.Type, unfoldAlias: boolean): string {
|
||||
let formatFlags = unfoldAlias
|
||||
? ts.TypeFormatFlags.InTypeAlias
|
||||
: ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope;
|
||||
let toStringValue: string;
|
||||
// Some types can't be stringified. Just discard the type if we can't stringify it.
|
||||
try {
|
||||
toStringValue = this.typeChecker.typeToString(
|
||||
type,
|
||||
undefined,
|
||||
ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope);
|
||||
toStringValue = this.typeChecker.typeToString(type, undefined, formatFlags);
|
||||
} catch (e) {
|
||||
console.warn("Recovered from a compiler crash while stringifying a type. Discarding the type.");
|
||||
console.warn(e.stack);
|
||||
@@ -477,9 +506,9 @@ export class TypeTable {
|
||||
/**
|
||||
* Gets a string representing the kind and contents of the given type.
|
||||
*/
|
||||
private getTypeString(type: AugmentedType): string | null {
|
||||
private getTypeString(type: AugmentedType, unfoldAlias: boolean): string | null {
|
||||
// Reference to a type alias.
|
||||
if (type.aliasSymbol != null) {
|
||||
if (!unfoldAlias && type.aliasSymbol != null) {
|
||||
let tag = "reference;" + this.getSymbolId(type.aliasSymbol);
|
||||
return type.aliasTypeArguments == null
|
||||
? tag
|
||||
@@ -499,7 +528,7 @@ export class TypeTable {
|
||||
if (flags & ts.TypeFlags.TypeVariable) {
|
||||
let enclosingType = getEnclosingTypeOfThisType(type);
|
||||
if (enclosingType != null) {
|
||||
return "this;" + this.getId(enclosingType);
|
||||
return "this;" + this.getId(enclosingType, false);
|
||||
} else if (symbol.parent == null) {
|
||||
// The type variable is bound on a call signature. Only extract it by name.
|
||||
return "lextypevar;" + symbol.name;
|
||||
@@ -730,7 +759,7 @@ export class TypeTable {
|
||||
private makeTypeStringVector(tag: string, types: ReadonlyArray<ts.Type>, length = types.length): string | null {
|
||||
let hash = tag;
|
||||
for (let i = 0; i < length; ++i) {
|
||||
let id = this.getId(types[i]);
|
||||
let id = this.getId(types[i], false);
|
||||
if (id == null) return null;
|
||||
hash += ";" + id;
|
||||
}
|
||||
@@ -748,7 +777,7 @@ export class TypeTable {
|
||||
for (let property of type.getProperties()) {
|
||||
let propertyType = this.typeChecker.getTypeOfSymbolAtLocation(property, this.arbitraryAstNode);
|
||||
if (propertyType == null) return null;
|
||||
let propertyTypeId = this.getId(propertyType);
|
||||
let propertyTypeId = this.getId(propertyType, false);
|
||||
if (propertyTypeId == null) return null;
|
||||
hash += ";p" + this.getSymbolId(property) + ';' + propertyTypeId;
|
||||
}
|
||||
@@ -761,13 +790,13 @@ export class TypeTable {
|
||||
}
|
||||
let indexType = type.getStringIndexType();
|
||||
if (indexType != null) {
|
||||
let indexTypeId = this.getId(indexType);
|
||||
let indexTypeId = this.getId(indexType, false);
|
||||
if (indexTypeId == null) return null;
|
||||
hash += ";s" + indexTypeId;
|
||||
}
|
||||
indexType = type.getNumberIndexType();
|
||||
if (indexType != null) {
|
||||
let indexTypeId = this.getId(indexType);
|
||||
let indexTypeId = this.getId(indexType, false);
|
||||
if (indexTypeId == null) return null;
|
||||
hash += ";i" + indexTypeId;
|
||||
}
|
||||
@@ -789,6 +818,7 @@ export class TypeTable {
|
||||
typeStrings: Array.from(this.typeIds.keys()),
|
||||
typeToStringValues: this.typeToStringValues,
|
||||
propertyLookups: this.propertyLookups,
|
||||
typeAliases: this.typeAliases,
|
||||
symbolStrings: Array.from(this.symbolIds.keys()),
|
||||
moduleMappings: this.moduleMappings,
|
||||
globalMappings: this.globalMappings,
|
||||
@@ -812,10 +842,17 @@ export class TypeTable {
|
||||
let worklist = this.buildTypeWorklist;
|
||||
let typeExtractionState = this.typeExtractionState;
|
||||
while (worklist.length > 0) {
|
||||
let [type, id] = worklist.pop();
|
||||
let [type, id, unfoldAlias] = worklist.pop();
|
||||
let isShallowContext = typeExtractionState[id] === TypeExtractionState.PendingShallow;
|
||||
if (isShallowContext && !isTypeAlwaysSafeToExpand(type)) {
|
||||
typeExtractionState[id] = TypeExtractionState.DoneShallow;
|
||||
} else if (type.aliasSymbol != null && !unfoldAlias) {
|
||||
typeExtractionState[id] = TypeExtractionState.DoneFull;
|
||||
let underlyingTypeId = this.getId(type, true);
|
||||
if (underlyingTypeId != null) {
|
||||
this.typeAliases.aliasTypes.push(id);
|
||||
this.typeAliases.underlyingTypes.push(underlyingTypeId);
|
||||
}
|
||||
} else {
|
||||
typeExtractionState[id] = TypeExtractionState.DoneFull;
|
||||
this.isInShallowTypeContext = isShallowContext || this.isExpansiveTypeReference(type);
|
||||
@@ -847,7 +884,7 @@ export class TypeTable {
|
||||
for (let symbol of props) {
|
||||
let propertyType = this.typeChecker.getTypeOfSymbolAtLocation(symbol, this.arbitraryAstNode);
|
||||
if (propertyType == null) continue;
|
||||
let propertyTypeId = this.getId(propertyType);
|
||||
let propertyTypeId = this.getId(propertyType, false);
|
||||
if (propertyTypeId == null) continue;
|
||||
this.propertyLookups.baseTypes.push(id);
|
||||
this.propertyLookups.names.push(symbol.name);
|
||||
@@ -879,7 +916,7 @@ export class TypeTable {
|
||||
/**
|
||||
* Returns a unique string for the given call/constructor signature.
|
||||
*/
|
||||
private getSignatureString(kind: ts.SignatureKind, signature: ts.Signature): string {
|
||||
private getSignatureString(kind: ts.SignatureKind, signature: AugmentedSignature): string {
|
||||
let parameters = signature.getParameters();
|
||||
let numberOfTypeParameters = signature.typeParameters == null
|
||||
? 0
|
||||
@@ -892,27 +929,51 @@ export class TypeTable {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let returnTypeId = this.getId(signature.getReturnType());
|
||||
let hasRestParam = (signature.flags & InternalSignatureFlags.HasRestParameter) !== 0;
|
||||
let restParameterTag = '';
|
||||
if (hasRestParam) {
|
||||
if (requiredParameters === parameters.length) {
|
||||
// Do not count the rest parameter as a required parameter
|
||||
requiredParameters = parameters.length - 1;
|
||||
}
|
||||
if (parameters.length === 0) return null;
|
||||
let restParameter = parameters[parameters.length - 1];
|
||||
let restParameterType = this.typeChecker.getTypeOfSymbolAtLocation(restParameter, this.arbitraryAstNode);
|
||||
if (restParameterType == null) return null;
|
||||
let restParameterTypeId = this.getId(restParameterType, false);
|
||||
if (restParameterTypeId == null) return null;
|
||||
restParameterTag = '' + restParameterTypeId;
|
||||
}
|
||||
let returnTypeId = this.getId(signature.getReturnType(), false);
|
||||
if (returnTypeId == null) {
|
||||
return null;
|
||||
}
|
||||
let tag = `${kind};${numberOfTypeParameters};${requiredParameters};${returnTypeId}`;
|
||||
let tag = `${kind};${numberOfTypeParameters};${requiredParameters};${restParameterTag};${returnTypeId}`;
|
||||
for (let typeParameter of signature.typeParameters || []) {
|
||||
tag += ";" + typeParameter.symbol.name;
|
||||
let constraint = typeParameter.getConstraint();
|
||||
let constraintId: number;
|
||||
if (constraint == null || (constraintId = this.getId(constraint)) == null) {
|
||||
if (constraint == null || (constraintId = this.getId(constraint, false)) == null) {
|
||||
tag += ";";
|
||||
} else {
|
||||
tag += ";" + constraintId;
|
||||
}
|
||||
}
|
||||
for (let parameter of parameters) {
|
||||
for (let paramIndex = 0; paramIndex < parameters.length; ++paramIndex) {
|
||||
let parameter = parameters[paramIndex];
|
||||
let parameterType = this.typeChecker.getTypeOfSymbolAtLocation(parameter, this.arbitraryAstNode);
|
||||
if (parameterType == null) {
|
||||
return null;
|
||||
}
|
||||
let parameterTypeId = this.getId(parameterType);
|
||||
let isRestParameter = hasRestParam && (paramIndex === parameters.length - 1);
|
||||
if (isRestParameter) {
|
||||
// The type of the rest parameter is the array type, but we wish to extract the non-array type.
|
||||
if (!isTypeReference(parameterType)) return null;
|
||||
let typeArguments = parameterType.typeArguments;
|
||||
if (typeArguments == null || typeArguments.length === 0) return null;
|
||||
parameterType = typeArguments[0];
|
||||
}
|
||||
let parameterTypeId = this.getId(parameterType, false);
|
||||
if (parameterTypeId == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -946,7 +1007,7 @@ export class TypeTable {
|
||||
|
||||
private extractIndexer(baseType: number, indexType: ts.Type, table: IndexerTable) {
|
||||
if (indexType == null) return;
|
||||
let indexTypeId = this.getId(indexType);
|
||||
let indexTypeId = this.getId(indexType, false);
|
||||
if (indexTypeId == null) return;
|
||||
table.baseTypes.push(baseType);
|
||||
table.propertyTypes.push(indexTypeId);
|
||||
@@ -1017,7 +1078,7 @@ export class TypeTable {
|
||||
let selfType = this.getSelfType(type);
|
||||
if (selfType != null) {
|
||||
this.checkExpansiveness(selfType);
|
||||
let id = this.getId(selfType);
|
||||
let id = this.getId(selfType, false);
|
||||
return this.expansiveTypes.get(id);
|
||||
}
|
||||
return false;
|
||||
@@ -1086,7 +1147,7 @@ export class TypeTable {
|
||||
search(type, 0);
|
||||
|
||||
function search(type: ts.TypeReference, expansionDepth: number): number | null {
|
||||
let id = typeTable.getId(type);
|
||||
let id = typeTable.getId(type, false);
|
||||
if (id == null) return null;
|
||||
|
||||
let index = indexTable.get(id);
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.semmle.js.ast;
|
||||
import com.semmle.ts.ast.DecoratorList;
|
||||
import com.semmle.ts.ast.ITypeExpression;
|
||||
import com.semmle.ts.ast.TypeParameter;
|
||||
import com.semmle.util.data.IntList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -18,6 +19,9 @@ public class AFunction<B> {
|
||||
private final List<ITypeExpression> parameterTypes;
|
||||
private final ITypeExpression thisParameterType;
|
||||
private final List<DecoratorList> parameterDecorators;
|
||||
private final IntList optionalParameterIndices;
|
||||
|
||||
public static final IntList noOptionalParams = IntList.create(0, 0);
|
||||
|
||||
public AFunction(
|
||||
Identifier id,
|
||||
@@ -29,7 +33,8 @@ public class AFunction<B> {
|
||||
List<ITypeExpression> parameterTypes,
|
||||
List<DecoratorList> parameterDecorators,
|
||||
ITypeExpression returnType,
|
||||
ITypeExpression thisParameterType) {
|
||||
ITypeExpression thisParameterType,
|
||||
IntList optionalParameterIndices) {
|
||||
this.id = id;
|
||||
this.params = new ArrayList<IPattern>(params.size());
|
||||
this.defaults = new ArrayList<Expression>(params.size());
|
||||
@@ -42,6 +47,7 @@ public class AFunction<B> {
|
||||
this.returnType = returnType;
|
||||
this.thisParameterType = thisParameterType;
|
||||
this.parameterDecorators = parameterDecorators;
|
||||
this.optionalParameterIndices = optionalParameterIndices;
|
||||
|
||||
IPattern rest = null;
|
||||
for (Expression param : params) {
|
||||
@@ -143,4 +149,8 @@ public class AFunction<B> {
|
||||
public List<DecoratorList> getParameterDecorators() {
|
||||
return parameterDecorators;
|
||||
}
|
||||
|
||||
public IntList getOptionalParmaeterIndices() {
|
||||
return optionalParameterIndices;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.semmle.js.ast;
|
||||
import com.semmle.ts.ast.DecoratorList;
|
||||
import com.semmle.ts.ast.ITypeExpression;
|
||||
import com.semmle.ts.ast.TypeParameter;
|
||||
import com.semmle.util.data.IntList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -26,7 +27,8 @@ public abstract class AFunctionExpression extends Expression implements IFunctio
|
||||
List<ITypeExpression> parameterTypes,
|
||||
List<DecoratorList> parameterDecorators,
|
||||
ITypeExpression returnType,
|
||||
ITypeExpression thisParameterType) {
|
||||
ITypeExpression thisParameterType,
|
||||
IntList optionalParameterIndices) {
|
||||
super(type, loc);
|
||||
this.fn =
|
||||
new AFunction<Node>(
|
||||
@@ -39,7 +41,8 @@ public abstract class AFunctionExpression extends Expression implements IFunctio
|
||||
parameterTypes,
|
||||
parameterDecorators,
|
||||
returnType,
|
||||
thisParameterType);
|
||||
thisParameterType,
|
||||
optionalParameterIndices);
|
||||
}
|
||||
|
||||
public AFunctionExpression(String type, SourceLocation loc, AFunction<? extends Node> fn) {
|
||||
@@ -155,4 +158,8 @@ public abstract class AFunctionExpression extends Expression implements IFunctio
|
||||
public void setDeclaredSignatureId(int id) {
|
||||
declaredSignature = id;
|
||||
}
|
||||
|
||||
public IntList getOptionalParameterIndices() {
|
||||
return fn.getOptionalParmaeterIndices();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.semmle.js.ast;
|
||||
|
||||
import com.semmle.ts.ast.ITypeExpression;
|
||||
import com.semmle.ts.ast.TypeParameter;
|
||||
import com.semmle.util.data.IntList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -21,7 +22,8 @@ public class ArrowFunctionExpression extends AFunctionExpression {
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList(),
|
||||
null,
|
||||
null);
|
||||
null,
|
||||
AFunction.noOptionalParams);
|
||||
}
|
||||
|
||||
public ArrowFunctionExpression(
|
||||
@@ -32,7 +34,8 @@ public class ArrowFunctionExpression extends AFunctionExpression {
|
||||
Boolean async,
|
||||
List<TypeParameter> typeParameters,
|
||||
List<ITypeExpression> parameterTypes,
|
||||
ITypeExpression returnType) {
|
||||
ITypeExpression returnType,
|
||||
IntList optionalParameterIndices) {
|
||||
super(
|
||||
"ArrowFunctionExpression",
|
||||
loc,
|
||||
@@ -45,7 +48,8 @@ public class ArrowFunctionExpression extends AFunctionExpression {
|
||||
parameterTypes,
|
||||
Collections.emptyList(),
|
||||
returnType,
|
||||
null);
|
||||
null,
|
||||
optionalParameterIndices);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.semmle.js.ast;
|
||||
import com.semmle.ts.ast.DecoratorList;
|
||||
import com.semmle.ts.ast.ITypeExpression;
|
||||
import com.semmle.ts.ast.TypeParameter;
|
||||
import com.semmle.util.data.IntList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -41,7 +42,8 @@ public class FunctionDeclaration extends Statement implements IFunction {
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList(),
|
||||
null,
|
||||
null),
|
||||
null,
|
||||
AFunction.noOptionalParams),
|
||||
false);
|
||||
}
|
||||
|
||||
@@ -56,7 +58,8 @@ public class FunctionDeclaration extends Statement implements IFunction {
|
||||
List<TypeParameter> typeParameters,
|
||||
List<ITypeExpression> parameterTypes,
|
||||
ITypeExpression returnType,
|
||||
ITypeExpression thisParameterType) {
|
||||
ITypeExpression thisParameterType,
|
||||
IntList optionalParameterIndices) {
|
||||
this(
|
||||
loc,
|
||||
new AFunction<>(
|
||||
@@ -69,7 +72,8 @@ public class FunctionDeclaration extends Statement implements IFunction {
|
||||
parameterTypes,
|
||||
Collections.emptyList(),
|
||||
returnType,
|
||||
thisParameterType),
|
||||
thisParameterType,
|
||||
optionalParameterIndices),
|
||||
hasDeclareKeyword);
|
||||
}
|
||||
|
||||
@@ -207,4 +211,8 @@ public class FunctionDeclaration extends Statement implements IFunction {
|
||||
public void setDeclaredSignatureId(int id) {
|
||||
declaredSignature = id;
|
||||
}
|
||||
|
||||
public IntList getOptionalParameterIndices() {
|
||||
return fn.getOptionalParmaeterIndices();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.semmle.js.ast;
|
||||
import com.semmle.ts.ast.DecoratorList;
|
||||
import com.semmle.ts.ast.ITypeExpression;
|
||||
import com.semmle.ts.ast.TypeParameter;
|
||||
import com.semmle.util.data.IntList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -27,7 +28,8 @@ public class FunctionExpression extends AFunctionExpression {
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList(),
|
||||
null,
|
||||
null);
|
||||
null,
|
||||
AFunction.noOptionalParams);
|
||||
}
|
||||
|
||||
public FunctionExpression(
|
||||
@@ -41,7 +43,8 @@ public class FunctionExpression extends AFunctionExpression {
|
||||
List<ITypeExpression> parameterTypes,
|
||||
List<DecoratorList> parameterDecorators,
|
||||
ITypeExpression returnType,
|
||||
ITypeExpression thisParameterType) {
|
||||
ITypeExpression thisParameterType,
|
||||
IntList optionalParameterIndices) {
|
||||
super(
|
||||
"FunctionExpression",
|
||||
loc,
|
||||
@@ -54,7 +57,8 @@ public class FunctionExpression extends AFunctionExpression {
|
||||
parameterTypes,
|
||||
parameterDecorators,
|
||||
returnType,
|
||||
thisParameterType);
|
||||
thisParameterType,
|
||||
optionalParameterIndices);
|
||||
}
|
||||
|
||||
public FunctionExpression(SourceLocation loc, AFunction<? extends Node> fn) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.semmle.ts.ast.INodeWithSymbol;
|
||||
import com.semmle.ts.ast.ITypeExpression;
|
||||
import com.semmle.ts.ast.ITypedAstNode;
|
||||
import com.semmle.ts.ast.TypeParameter;
|
||||
import com.semmle.util.data.IntList;
|
||||
import java.util.List;
|
||||
|
||||
/** A function declaration or expression. */
|
||||
@@ -75,4 +76,6 @@ public interface IFunction extends IStatementContainer, INodeWithSymbol, ITypedA
|
||||
public int getDeclaredSignatureId();
|
||||
|
||||
public void setDeclaredSignatureId(int id);
|
||||
|
||||
public IntList getOptionalParameterIndices();
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ import com.semmle.ts.ast.TypeParameter;
|
||||
import com.semmle.ts.ast.TypeofTypeExpr;
|
||||
import com.semmle.ts.ast.UnaryTypeExpr;
|
||||
import com.semmle.ts.ast.UnionTypeExpr;
|
||||
import com.semmle.util.data.IntList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -70,6 +71,10 @@ public class NodeCopier implements Visitor<Void, INode> {
|
||||
return result;
|
||||
}
|
||||
|
||||
private IntList copy(IntList list) {
|
||||
return new IntList(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AssignmentExpression visit(AssignmentExpression nd, Void q) {
|
||||
return new AssignmentExpression(
|
||||
@@ -138,7 +143,8 @@ public class NodeCopier implements Visitor<Void, INode> {
|
||||
copy(nd.getTypeParameters()),
|
||||
copy(nd.getParameterTypes()),
|
||||
copy(nd.getReturnType()),
|
||||
copy(nd.getThisParameterType()));
|
||||
copy(nd.getThisParameterType()),
|
||||
copy(nd.getOptionalParameterIndices()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -367,7 +373,8 @@ public class NodeCopier implements Visitor<Void, INode> {
|
||||
copy(nd.getParameterTypes()),
|
||||
copy(nd.getParameterDecorators()),
|
||||
copy(nd.getReturnType()),
|
||||
copy(nd.getThisParameterType()));
|
||||
copy(nd.getThisParameterType()),
|
||||
copy(nd.getOptionalParameterIndices()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -427,7 +434,8 @@ public class NodeCopier implements Visitor<Void, INode> {
|
||||
nd.isAsync(),
|
||||
copy(nd.getTypeParameters()),
|
||||
copy(nd.getParameterTypes()),
|
||||
copy(nd.getReturnType()));
|
||||
copy(nd.getReturnType()),
|
||||
copy(nd.getOptionalParameterIndices()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -900,7 +900,12 @@ public class ASTExtractor {
|
||||
for (IPattern param : nd.getAllParams()) {
|
||||
scopeManager.addNames(
|
||||
scopeManager.collectDeclaredNames(param, isStrict, false, DeclKind.var));
|
||||
visit(param, key, i, IdContext.varDecl);
|
||||
Label paramKey = visit(param, key, i, IdContext.varDecl);
|
||||
|
||||
// Extract optional parameters
|
||||
if (nd.getOptionalParameterIndices().contains(i)) {
|
||||
trapwriter.addTuple("isOptionalParameterDeclaration", paramKey);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
@@ -1393,7 +1398,8 @@ public class ASTExtractor {
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList(),
|
||||
null,
|
||||
null);
|
||||
null,
|
||||
AFunction.noOptionalParams);
|
||||
String fnSrc = hasSuperClass ? "(...args) { super(...args); }" : "() {}";
|
||||
SourceLocation fnloc = fakeLoc(fnSrc, loc);
|
||||
FunctionExpression fn = new FunctionExpression(fnloc, fndef);
|
||||
|
||||
@@ -578,6 +578,11 @@ public class AutoBuild {
|
||||
for (File sourceFile : project.getSourceFiles()) {
|
||||
Path sourcePath = sourceFile.toPath();
|
||||
if (!files.contains(normalizePath(sourcePath))) continue;
|
||||
if (!FileType.TYPESCRIPT.getExtensions().contains(FileUtil.extension(sourcePath))) {
|
||||
// For the time being, skip non-TypeScript files, even if the TypeScript
|
||||
// compiler can parse them for us.
|
||||
continue;
|
||||
}
|
||||
if (!extractedFiles.contains(sourcePath)) {
|
||||
typeScriptFiles.add(sourcePath.toFile());
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public class Main {
|
||||
* A version identifier that should be updated every time the extractor changes in such a way that
|
||||
* it may produce different tuples for the same file under the same {@link ExtractorConfig}.
|
||||
*/
|
||||
public static final String EXTRACTOR_VERSION = "2019-11-17";
|
||||
public static final String EXTRACTOR_VERSION = "2019-11-19";
|
||||
|
||||
public static final Pattern NEWLINE = Pattern.compile("\n");
|
||||
|
||||
@@ -147,7 +147,8 @@ public class Main {
|
||||
List<File> filesToExtract = new ArrayList<>();
|
||||
for (File sourceFile : project.getSourceFiles()) {
|
||||
if (files.contains(normalizeFile(sourceFile))
|
||||
&& !extractedFiles.contains(sourceFile.getAbsoluteFile())) {
|
||||
&& !extractedFiles.contains(sourceFile.getAbsoluteFile())
|
||||
&& FileType.TYPESCRIPT.getExtensions().contains(FileUtil.extension(sourceFile))) {
|
||||
filesToExtract.add(sourceFile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,6 +143,7 @@ import com.semmle.ts.ast.TypeofTypeExpr;
|
||||
import com.semmle.ts.ast.UnaryTypeExpr;
|
||||
import com.semmle.ts.ast.UnionTypeExpr;
|
||||
import com.semmle.util.collections.CollectionUtil;
|
||||
import com.semmle.util.data.IntList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -804,7 +805,8 @@ public class TypeScriptASTConverter {
|
||||
hasModifier(node, "AsyncKeyword"),
|
||||
convertChildrenNotNull(node, "typeParameters"),
|
||||
convertParameterTypes(node),
|
||||
convertChildAsType(node, "type"));
|
||||
convertChildAsType(node, "type"),
|
||||
getOptionalParameterIndices(node));
|
||||
attachDeclaredSignature(function, node);
|
||||
return function;
|
||||
}
|
||||
@@ -1063,7 +1065,8 @@ public class TypeScriptASTConverter {
|
||||
paramTypes,
|
||||
paramDecorators,
|
||||
null,
|
||||
null);
|
||||
null,
|
||||
getOptionalParameterIndices(node));
|
||||
attachSymbolInformation(value, node);
|
||||
attachStaticType(value, node);
|
||||
attachDeclaredSignature(value, node);
|
||||
@@ -1262,7 +1265,8 @@ public class TypeScriptASTConverter {
|
||||
typeParameters,
|
||||
paramTypes,
|
||||
returnType,
|
||||
thisParam);
|
||||
thisParam,
|
||||
getOptionalParameterIndices(node));
|
||||
attachSymbolInformation(function, node);
|
||||
attachStaticType(function, node);
|
||||
attachDeclaredSignature(function, node);
|
||||
@@ -1291,7 +1295,8 @@ public class TypeScriptASTConverter {
|
||||
paramTypes,
|
||||
paramDecorators,
|
||||
returnType,
|
||||
thisParam);
|
||||
thisParam,
|
||||
getOptionalParameterIndices(node));
|
||||
attachStaticType(function, node);
|
||||
attachDeclaredSignature(function, node);
|
||||
return function;
|
||||
@@ -1645,7 +1650,8 @@ public class TypeScriptASTConverter {
|
||||
paramTypes,
|
||||
paramDecorators,
|
||||
returnType,
|
||||
thisType);
|
||||
thisType,
|
||||
getOptionalParameterIndices(node));
|
||||
attachSymbolInformation(function, node);
|
||||
attachStaticType(function, node);
|
||||
attachDeclaredSignature(function, node);
|
||||
@@ -1890,6 +1896,18 @@ public class TypeScriptASTConverter {
|
||||
return result;
|
||||
}
|
||||
|
||||
private IntList getOptionalParameterIndices(JsonObject function) throws ParseError {
|
||||
IntList list = IntList.create(0);
|
||||
int index = -1;
|
||||
for (JsonElement param : getProperParameters(function)) {
|
||||
++index;
|
||||
if (param.getAsJsonObject().has("questionToken")) {
|
||||
list.add(index);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<FieldDefinition> convertParameterFields(JsonObject function) throws ParseError {
|
||||
List<FieldDefinition> result = new ArrayList<>();
|
||||
int index = -1;
|
||||
|
||||
@@ -291,10 +291,10 @@ public class TypeScriptParser {
|
||||
LogbackUtils.getLogger(AbstractProcessBuilder.class).setLevel(Level.INFO);
|
||||
String explicitPath = Env.systemEnv().get(PARSER_WRAPPER_PATH_ENV_VAR);
|
||||
String semmleDistVar = Env.systemEnv().get(Env.Var.SEMMLE_DIST.name());
|
||||
if (semmleDistVar != null && !semmleDistVar.isEmpty()) {
|
||||
parserWrapper = new File(semmleDistVar, "tools/typescript-parser-wrapper/main.js");
|
||||
} else if (explicitPath != null) {
|
||||
if (explicitPath != null) {
|
||||
parserWrapper = new File(explicitPath);
|
||||
} else if (semmleDistVar != null && !semmleDistVar.isEmpty()) {
|
||||
parserWrapper = new File(semmleDistVar, "tools/typescript-parser-wrapper/main.js");
|
||||
} else {
|
||||
throw new CatastrophicError(
|
||||
"Could not find TypeScript parser: " + Env.Var.SEMMLE_DIST.name() + " is not set.");
|
||||
|
||||
@@ -81,6 +81,7 @@ public class TypeExtractor {
|
||||
extractType(i);
|
||||
}
|
||||
extractPropertyLookups(table.getPropertyLookups());
|
||||
extractTypeAliases(table.getTypeAliases());
|
||||
for (int i = 0; i < table.getNumberOfSymbols(); ++i) {
|
||||
extractSymbol(i);
|
||||
}
|
||||
@@ -161,6 +162,19 @@ public class TypeExtractor {
|
||||
}
|
||||
}
|
||||
|
||||
private void extractTypeAliases(JsonObject aliases) {
|
||||
JsonArray aliasTypes = aliases.get("aliasTypes").getAsJsonArray();
|
||||
JsonArray underlyingTypes = aliases.get("underlyingTypes").getAsJsonArray();
|
||||
for (int i = 0; i < aliasTypes.size(); ++i) {
|
||||
int aliasType = aliasTypes.get(i).getAsInt();
|
||||
int underlyingType = underlyingTypes.get(i).getAsInt();
|
||||
trapWriter.addTuple(
|
||||
"type_alias",
|
||||
trapWriter.globalID("type;" + aliasType),
|
||||
trapWriter.globalID("type;" + underlyingType));
|
||||
}
|
||||
}
|
||||
|
||||
private void extractSymbol(int index) {
|
||||
// Format is: kind;decl;parent;name
|
||||
String[] parts = split(table.getSymbolString(index), 4);
|
||||
@@ -187,13 +201,18 @@ public class TypeExtractor {
|
||||
|
||||
private void extractSignature(int index) {
|
||||
// Format is:
|
||||
// kind;numTypeParams;requiredParams;returnType(;paramName;paramType)*
|
||||
// kind;numTypeParams;requiredParams;restParamType;returnType(;paramName;paramType)*
|
||||
String[] parts = split(table.getSignatureString(index));
|
||||
Label label = trapWriter.globalID("signature;" + index);
|
||||
int kind = Integer.parseInt(parts[0]);
|
||||
int numberOfTypeParameters = Integer.parseInt(parts[1]);
|
||||
int requiredParameters = Integer.parseInt(parts[2]);
|
||||
Label returnType = trapWriter.globalID("type;" + parts[3]);
|
||||
String restParamTypeTag = parts[3];
|
||||
if (!restParamTypeTag.isEmpty()) {
|
||||
trapWriter.addTuple(
|
||||
"signature_rest_parameter", label, trapWriter.globalID("type;" + restParamTypeTag));
|
||||
}
|
||||
Label returnType = trapWriter.globalID("type;" + parts[4]);
|
||||
trapWriter.addTuple(
|
||||
"signature_types",
|
||||
label,
|
||||
@@ -202,9 +221,9 @@ public class TypeExtractor {
|
||||
numberOfTypeParameters,
|
||||
requiredParameters);
|
||||
trapWriter.addTuple("signature_contains_type", returnType, label, -1);
|
||||
int numberOfParameters = (parts.length - 4) / 2; // includes type parameters
|
||||
int numberOfParameters = (parts.length - 5) / 2; // includes type parameters
|
||||
for (int i = 0; i < numberOfParameters; ++i) {
|
||||
int partIndex = 4 + (2 * i);
|
||||
int partIndex = 5 + (2 * i);
|
||||
String paramName = parts[partIndex];
|
||||
String paramTypeId = parts[partIndex + 1];
|
||||
if (paramTypeId.length() > 0) { // Unconstrained type parameters have an empty type ID.
|
||||
|
||||
@@ -12,6 +12,7 @@ public class TypeTable {
|
||||
private final JsonArray typeStrings;
|
||||
private final JsonArray typeToStringValues;
|
||||
private final JsonObject propertyLookups;
|
||||
private final JsonObject typeAliases;
|
||||
private final JsonArray symbolStrings;
|
||||
private final JsonObject moduleMappings;
|
||||
private final JsonObject globalMappings;
|
||||
@@ -27,6 +28,7 @@ public class TypeTable {
|
||||
this.typeStrings = typeTable.get("typeStrings").getAsJsonArray();
|
||||
this.typeToStringValues = typeTable.get("typeToStringValues").getAsJsonArray();
|
||||
this.propertyLookups = typeTable.get("propertyLookups").getAsJsonObject();
|
||||
this.typeAliases = typeTable.get("typeAliases").getAsJsonObject();
|
||||
this.symbolStrings = typeTable.get("symbolStrings").getAsJsonArray();
|
||||
this.moduleMappings = typeTable.get("moduleMappings").getAsJsonObject();
|
||||
this.globalMappings = typeTable.get("globalMappings").getAsJsonObject();
|
||||
@@ -51,6 +53,10 @@ public class TypeTable {
|
||||
return propertyLookups;
|
||||
}
|
||||
|
||||
public JsonObject getTypeAliases() {
|
||||
return typeAliases;
|
||||
}
|
||||
|
||||
public int getNumberOfTypes() {
|
||||
return typeStrings.size();
|
||||
}
|
||||
|
||||
@@ -1816,7 +1816,7 @@ class Type extends @type {
|
||||
*
|
||||
* For example, for a type `(S & T) | U` this gets the types `S`, `T`, and `U`.
|
||||
*/
|
||||
Type unfold() {
|
||||
Type unfoldUnionAndIntersection() {
|
||||
not result instanceof UnionOrIntersectionType and
|
||||
(
|
||||
result = this
|
||||
@@ -1829,6 +1829,27 @@ class Type extends @type {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeatedly unfolds unions, intersections, and type aliases and gets any of the underlying types,
|
||||
* or this type itself if it is not a union or intersection.
|
||||
*
|
||||
* For example, the type `(S & T) | U` unfolds to `S`, `T`, and `U`.
|
||||
*
|
||||
* If this is a type alias, the alias is itself included in the result, but this is not the case for intermediate type aliases.
|
||||
* For example:
|
||||
* ```js
|
||||
* type One = number | string;
|
||||
* type Two = One | Function & {x: string};
|
||||
* One; // unfolds to number, string, and One
|
||||
* Two; // unfolds to number, string, One, Function, {x: string}, and Two
|
||||
* ```
|
||||
*/
|
||||
Type unfold() {
|
||||
result = unfoldUnionAndIntersection()
|
||||
or
|
||||
result = this.(TypeAliasReference).getAliasedType().unfoldUnionAndIntersection()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this refers to the given named type, or is declared as a subtype thereof,
|
||||
* or is a union or intersection containing such a type.
|
||||
@@ -2287,6 +2308,24 @@ class EnumLiteralType extends TypeReference {
|
||||
EnumMember getEnumMember() { result = declaration }
|
||||
}
|
||||
|
||||
/**
|
||||
* A type that refers to a type alias.
|
||||
*/
|
||||
class TypeAliasReference extends TypeReference {
|
||||
TypeAliasReference() {
|
||||
type_alias(this, _)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type behind the type alias.
|
||||
*
|
||||
* For example, for `type B<T> = T[][]`, this maps the type `B<number>` to `number[][]`.
|
||||
*/
|
||||
Type getAliasedType() {
|
||||
type_alias(this, result)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An anonymous interface type, such as `{ x: number }`.
|
||||
*/
|
||||
@@ -2516,17 +2555,19 @@ class CallSignatureType extends @signature_type {
|
||||
predicate hasTypeParameters() { getNumTypeParameter() > 0 }
|
||||
|
||||
/**
|
||||
* Gets the type of the `n`th parameter of this signature.
|
||||
* Gets the type of the `n`th parameter declared in this signature.
|
||||
*
|
||||
* If the `n`th parameter is a rest parameter `...T[]`, gets type `T`.
|
||||
*/
|
||||
Type getParameter(int n) { n >= 0 and result = getChild(n + getNumTypeParameter()) }
|
||||
|
||||
/**
|
||||
* Gets the type of a parameter of this signature.
|
||||
* Gets the type of a parameter of this signature, including the rest parameter, if any.
|
||||
*/
|
||||
Type getAParameter() { result = getParameter(_) }
|
||||
|
||||
/**
|
||||
* Gets the number of parameters.
|
||||
* Gets the number of parameters, including the rest parameter, if any.
|
||||
*/
|
||||
int getNumParameter() { result = count(int i | exists(getParameter(i))) }
|
||||
|
||||
@@ -2538,7 +2579,7 @@ class CallSignatureType extends @signature_type {
|
||||
|
||||
/**
|
||||
* Gets the number of optional parameters, that is,
|
||||
* parameters that are marked as optional with the `?` suffix.
|
||||
* parameters that are marked as optional with the `?` suffix or is a rest parameter.
|
||||
*/
|
||||
int getNumOptionalParameter() { result = getNumParameter() - getNumRequiredParameter() }
|
||||
|
||||
@@ -2552,7 +2593,9 @@ class CallSignatureType extends @signature_type {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the `n`th parameter is declared optional with the `?` suffix.
|
||||
* Holds if the `n`th parameter is declared optional with the `?` suffix or is the rest parameter.
|
||||
*
|
||||
* Note that rest parameters are not considered optional in this sense.
|
||||
*/
|
||||
predicate isOptionalParameter(int n) {
|
||||
exists(getParameter(n)) and
|
||||
@@ -2571,6 +2614,30 @@ class CallSignatureType extends @signature_type {
|
||||
* Gets the name of a parameter of this signature.
|
||||
*/
|
||||
string getAParameterName() { result = getParameterName(_) }
|
||||
|
||||
/**
|
||||
* Holds if this signature declares a rest parameter, such as `(x: number, ...y: string[])`.
|
||||
*/
|
||||
predicate hasRestParameter() { signature_rest_parameter(this, _) }
|
||||
|
||||
/**
|
||||
* Gets the type of the rest parameter, if any.
|
||||
*
|
||||
* For example, for the signature `(...y: string[])`, this gets the type `string`.
|
||||
*/
|
||||
Type getRestParameterType() {
|
||||
hasRestParameter() and
|
||||
result = getParameter(getNumParameter() - 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of the rest parameter as an array, if it exists.
|
||||
*
|
||||
* For example, for the signature `(...y: string[])`, this gets the type `string[]`.
|
||||
*/
|
||||
PlainArrayType getRestParameterArrayType() {
|
||||
signature_rest_parameter(this, result)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -749,6 +749,21 @@ class Parameter extends BindingPattern {
|
||||
JSDocTag getJSDocTag() {
|
||||
none() // overridden in SimpleParameter
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this is a parameter declared optional with the `?` token.
|
||||
*
|
||||
* Note that this does not hold for rest parameters, and does not in general
|
||||
* hold for parameters with defaults.
|
||||
*
|
||||
* For example, `x`, is declared optional below:
|
||||
* ```
|
||||
* function f(x?: number) {}
|
||||
* ```
|
||||
*/
|
||||
predicate isDeclaredOptional() {
|
||||
isOptionalParameterDeclaration(this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -520,6 +520,7 @@ hasProtectedKeyword (int id: @property ref);
|
||||
hasReadonlyKeyword (int id: @property ref);
|
||||
isOptionalMember (int id: @property ref);
|
||||
hasDefiniteAssignmentAssertion (int id: @field_or_vardeclarator ref);
|
||||
isOptionalParameterDeclaration (unique int parameter: @pattern ref);
|
||||
|
||||
#keyset[constructor, param_index]
|
||||
parameter_fields(
|
||||
@@ -703,6 +704,10 @@ type_property(
|
||||
varchar(900) name: string ref,
|
||||
int propertyType: @type ref);
|
||||
|
||||
type_alias(
|
||||
unique int aliasType: @type ref,
|
||||
int underlyingType: @type ref);
|
||||
|
||||
@literaltype = @stringliteraltype | @numberliteraltype | @booleanliteraltype | @bigintliteraltype;
|
||||
@type_with_literal_value = @stringliteraltype | @numberliteraltype | @bigintliteraltype;
|
||||
type_literal_value(
|
||||
@@ -717,6 +722,11 @@ signature_types (
|
||||
int required_params: int ref
|
||||
);
|
||||
|
||||
signature_rest_parameter(
|
||||
unique int sig: @signature_type ref,
|
||||
int rest_param_arra_type: @type ref
|
||||
);
|
||||
|
||||
case @signature_type.kind of
|
||||
0 = @function_signature_type
|
||||
| 1 = @constructor_signature_type
|
||||
|
||||
@@ -8006,6 +8006,17 @@
|
||||
<dependencies/>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>isOptionalParameterDeclaration</name>
|
||||
<cardinality>3966</cardinality>
|
||||
<columnsizes>
|
||||
<e>
|
||||
<k>parameter</k>
|
||||
<v>3966</v>
|
||||
</e>
|
||||
</columnsizes>
|
||||
<dependencies/>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>parameter_fields</name>
|
||||
<cardinality>2693</cardinality>
|
||||
<columnsizes>
|
||||
@@ -13516,6 +13527,54 @@
|
||||
<dependencies/>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>type_alias</name>
|
||||
<cardinality>1386</cardinality>
|
||||
<columnsizes>
|
||||
<e>
|
||||
<k>aliasType</k>
|
||||
<v>1386</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>underlyingType</k>
|
||||
<v>1361</v>
|
||||
</e>
|
||||
</columnsizes>
|
||||
<dependencies>
|
||||
<dep>
|
||||
<src>underlyingType</src>
|
||||
<trg>aliasType</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>1</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>aliasType</src>
|
||||
<trg>underlyingType</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>1</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
</dependencies>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>type_literal_value</name>
|
||||
<cardinality>31882</cardinality>
|
||||
<columnsizes>
|
||||
@@ -14222,6 +14281,54 @@
|
||||
</dependencies>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>signature_rest_parameter</name>
|
||||
<cardinality>19521</cardinality>
|
||||
<columnsizes>
|
||||
<e>
|
||||
<k>sig</k>
|
||||
<v>19521</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>rest_param_arra_type</k>
|
||||
<v>14259</v>
|
||||
</e>
|
||||
</columnsizes>
|
||||
<dependencies>
|
||||
<dep>
|
||||
<src>rest_param_arra_type</src>
|
||||
<trg>sig</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>1</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>sig</src>
|
||||
<trg>rest_param_arra_type</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>1</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
</dependencies>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>type_contains_signature</name>
|
||||
<cardinality>87640</cardinality>
|
||||
<columnsizes>
|
||||
|
||||
@@ -47,14 +47,39 @@ test_ExprSignature
|
||||
| tst.ts:45:15:45:15 | x | string |
|
||||
| tst.ts:46:3:46:25 | constru ... umber); | any |
|
||||
| tst.ts:46:15:46:15 | x | number |
|
||||
| tst.ts:50:3:50:36 | method( ... ing[]); | (x: number, ...y: string[]): any |
|
||||
| tst.ts:50:10:50:10 | x | number |
|
||||
| tst.ts:50:24:50:24 | y | string[] |
|
||||
| tst.ts:51:4:51:4 | x | number |
|
||||
| tst.ts:51:18:51:18 | y | string[] |
|
||||
| tst.ts:52:7:52:7 | x | number |
|
||||
| tst.ts:52:21:52:21 | y | string[] |
|
||||
| tst.ts:54:3:54:34 | method2 ... ing[]); | (x: number, y: string[]): any |
|
||||
| tst.ts:54:11:54:11 | x | number |
|
||||
| tst.ts:54:22:54:22 | y | string[] |
|
||||
| tst.ts:55:3:55:32 | method3 ... tring); | (x: number, y: string): any |
|
||||
| tst.ts:55:11:55:11 | x | number |
|
||||
| tst.ts:55:22:55:22 | y | string |
|
||||
| tst.ts:59:3:59:25 | method( ... ing[]); | (...y: string[]): any |
|
||||
| tst.ts:59:13:59:13 | y | string[] |
|
||||
| tst.ts:60:7:60:7 | y | string[] |
|
||||
| tst.ts:61:10:61:10 | y | string[] |
|
||||
| tst.ts:63:3:63:23 | method2 ... ing[]); | (y: string[]): any |
|
||||
| tst.ts:63:11:63:11 | y | string[] |
|
||||
| tst.ts:64:3:64:21 | method3(y: string); | (y: string): any |
|
||||
| tst.ts:64:11:64:11 | y | string |
|
||||
test_TypeReferenceSig
|
||||
| Callable | function | 0 | (x: number): string |
|
||||
| Newable | constructor | 0 | new (x: number): any |
|
||||
| OnlyRestParams | constructor | 0 | new (...y: string[]): any |
|
||||
| OnlyRestParams | function | 0 | (...y: string[]): any |
|
||||
| OverloadedCallable | function | 0 | (x: number): number |
|
||||
| OverloadedCallable | function | 1 | (x: string): string |
|
||||
| OverloadedCallable | function | 2 | (x: any): any |
|
||||
| OverloadedNewable | constructor | 0 | new (x: number): OverloadedNewable |
|
||||
| OverloadedNewable | constructor | 1 | new (x: any): any |
|
||||
| WithRestParams | constructor | 0 | new (x: number, ...y: string[]): any |
|
||||
| WithRestParams | function | 0 | (x: number, ...y: string[]): any |
|
||||
test_FunctionCallSig
|
||||
| tst.ts:2:3:2:22 | (x: number): string; | (x: number): string |
|
||||
| tst.ts:6:3:6:22 | (x: number): number; | (x: number): number |
|
||||
@@ -72,3 +97,62 @@ test_FunctionCallSig
|
||||
| tst.ts:40:1:42:1 | functio ... oo");\\n} | (g: Generic<string>): string |
|
||||
| tst.ts:45:3:45:25 | constru ... tring); | new (x: string): C |
|
||||
| tst.ts:46:3:46:25 | constru ... umber); | new (x: number): C |
|
||||
| tst.ts:50:3:50:36 | method( ... ing[]); | (x: number, ...y: string[]): any |
|
||||
| tst.ts:51:3:51:30 | (x: num ... ing[]); | (x: number, ...y: string[]): any |
|
||||
| tst.ts:52:3:52:33 | new(x: ... ing[]); | new (x: number, ...y: string[]): any |
|
||||
| tst.ts:54:3:54:34 | method2 ... ing[]); | (x: number, y: string[]): any |
|
||||
| tst.ts:55:3:55:32 | method3 ... tring); | (x: number, y: string): any |
|
||||
| tst.ts:59:3:59:25 | method( ... ing[]); | (...y: string[]): any |
|
||||
| tst.ts:60:3:60:19 | (...y: string[]); | (...y: string[]): any |
|
||||
| tst.ts:61:3:61:22 | new(...y: string[]); | new (...y: string[]): any |
|
||||
| tst.ts:63:3:63:23 | method2 ... ing[]); | (y: string[]): any |
|
||||
| tst.ts:64:3:64:21 | method3(y: string); | (y: string): any |
|
||||
test_getRestParameterType
|
||||
| (...items: (string \| ConcatArray<string>)[]): string[] | string \| ConcatArray<string> |
|
||||
| (...items: ConcatArray<string>[]): string[] | ConcatArray<string> |
|
||||
| (...items: string[]): number | string |
|
||||
| (...strings: string[]): string | string |
|
||||
| (...y: string[]): any | string |
|
||||
| (start: number, deleteCount: number, ...items: string[]): string[] | string |
|
||||
| (substring: string, ...args: any[]): string | any |
|
||||
| (x: number, ...y: string[]): any | string |
|
||||
| new (...y: string[]): any | string |
|
||||
| new (x: number, ...y: string[]): any | string |
|
||||
test_getRestParameterArray
|
||||
| (...items: (string \| ConcatArray<string>)[]): string[] | (string \| ConcatArray<string>)[] |
|
||||
| (...items: ConcatArray<string>[]): string[] | ConcatArray<string>[] |
|
||||
| (...items: string[]): number | string[] |
|
||||
| (...strings: string[]): string | string[] |
|
||||
| (...y: string[]): any | string[] |
|
||||
| (start: number, deleteCount: number, ...items: string[]): string[] | string[] |
|
||||
| (substring: string, ...args: any[]): string | any[] |
|
||||
| (x: number, ...y: string[]): any | string[] |
|
||||
| new (...y: string[]): any | string[] |
|
||||
| new (x: number, ...y: string[]): any | string[] |
|
||||
test_RestSig_getParameter
|
||||
| (...items: (string \| ConcatArray<string>)[]): string[] | 0 | items | string \| ConcatArray<string> |
|
||||
| (...items: ConcatArray<string>[]): string[] | 0 | items | ConcatArray<string> |
|
||||
| (...items: string[]): number | 0 | items | string |
|
||||
| (...strings: string[]): string | 0 | strings | string |
|
||||
| (...y: string[]): any | 0 | y | string |
|
||||
| (start: number, deleteCount: number, ...items: string[]): string[] | 0 | start | number |
|
||||
| (start: number, deleteCount: number, ...items: string[]): string[] | 1 | deleteCount | number |
|
||||
| (start: number, deleteCount: number, ...items: string[]): string[] | 2 | items | string |
|
||||
| (substring: string, ...args: any[]): string | 0 | substring | string |
|
||||
| (substring: string, ...args: any[]): string | 1 | args | any |
|
||||
| (x: number, ...y: string[]): any | 0 | x | number |
|
||||
| (x: number, ...y: string[]): any | 1 | y | string |
|
||||
| new (...y: string[]): any | 0 | y | string |
|
||||
| new (x: number, ...y: string[]): any | 0 | x | number |
|
||||
| new (x: number, ...y: string[]): any | 1 | y | string |
|
||||
test_RestSig_numRequiredParams
|
||||
| (...items: (string \| ConcatArray<string>)[]): string[] | 0 |
|
||||
| (...items: ConcatArray<string>[]): string[] | 0 |
|
||||
| (...items: string[]): number | 0 |
|
||||
| (...strings: string[]): string | 0 |
|
||||
| (...y: string[]): any | 0 |
|
||||
| (start: number, deleteCount: number, ...items: string[]): string[] | 2 |
|
||||
| (substring: string, ...args: any[]): string | 1 |
|
||||
| (x: number, ...y: string[]): any | 1 |
|
||||
| new (...y: string[]): any | 0 |
|
||||
| new (x: number, ...y: string[]): any | 1 |
|
||||
|
||||
@@ -20,3 +20,22 @@ query predicate test_TypeReferenceSig(TypeReference type, SignatureKind kind, in
|
||||
query predicate test_FunctionCallSig(Function f, CallSignatureType sig) {
|
||||
sig = f.getCallSignature()
|
||||
}
|
||||
|
||||
query Type test_getRestParameterType(CallSignatureType sig) {
|
||||
result = sig.getRestParameterType()
|
||||
}
|
||||
|
||||
query Type test_getRestParameterArray(CallSignatureType sig) {
|
||||
result = sig.getRestParameterArrayType()
|
||||
}
|
||||
|
||||
query predicate test_RestSig_getParameter(CallSignatureType sig, int n, string name, Type type) {
|
||||
sig.hasRestParameter() and
|
||||
name = sig.getParameterName(n) and
|
||||
type = sig.getParameter(n)
|
||||
}
|
||||
|
||||
query int test_RestSig_numRequiredParams(CallSignatureType sig) {
|
||||
sig.hasRestParameter() and
|
||||
result = sig.getNumRequiredParameter()
|
||||
}
|
||||
|
||||
@@ -45,3 +45,21 @@ declare class C {
|
||||
constructor(x: string);
|
||||
constructor(x: number);
|
||||
}
|
||||
|
||||
interface WithRestParams {
|
||||
method(x: number, ...y: string[]);
|
||||
(x: number, ...y: string[]);
|
||||
new(x: number, ...y: string[]);
|
||||
|
||||
method2(x: number, y: string[]);
|
||||
method3(x: number, y: string);
|
||||
}
|
||||
|
||||
interface OnlyRestParams {
|
||||
method(...y: string[]);
|
||||
(...y: string[]);
|
||||
new(...y: string[]);
|
||||
|
||||
method2(y: string[]);
|
||||
method3(y: string);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
exprType
|
||||
| tst.ts:1:5:1:16 | stringOrNUll | string \| null |
|
||||
| tst.ts:2:5:2:21 | stringOrUndefined | string \| undefined |
|
||||
| tst.ts:3:5:3:27 | stringO ... defined | string \| null \| undefined |
|
||||
| tst.ts:4:5:4:16 | stringOrVoid | string \| void |
|
||||
| tst.ts:7:5:7:21 | stringOrNullAlias | string \| null |
|
||||
| tst.ts:8:5:8:32 | stringO ... defined | string \| null \| undefined |
|
||||
| tst.ts:10:5:10:23 | arrayOfStringOrNull | (string \| null)[] |
|
||||
unaliasedType
|
||||
@@ -0,0 +1,5 @@
|
||||
import javascript
|
||||
|
||||
query Type exprType(Expr e) { result = e.getType() }
|
||||
|
||||
query Type unaliasedType(TypeAliasReference ref) { result = ref.getAliasedType() }
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"include": ["."],
|
||||
"compilerOptions": {
|
||||
"strict": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
let stringOrNUll: string | null;
|
||||
let stringOrUndefined: string | undefined;
|
||||
let stringOrNullOrUndefined: string | null | undefined;
|
||||
let stringOrVoid: string | void;
|
||||
|
||||
type StringOrNullAlias = string | null;
|
||||
let stringOrNullAlias: StringOrNullAlias;
|
||||
let stringOrNullAliasOrUndefined: StringOrNullAlias | undefined;
|
||||
|
||||
let arrayOfStringOrNull: Array<string | null>;
|
||||
@@ -0,0 +1,15 @@
|
||||
| tst.ts:1:23:1:23 | y |
|
||||
| tst.ts:2:16:2:16 | y |
|
||||
| tst.ts:6:28:6:28 | y |
|
||||
| tst.ts:8:12:8:12 | x |
|
||||
| tst.ts:8:24:8:24 | y |
|
||||
| tst.ts:9:13:9:13 | x |
|
||||
| tst.ts:13:7:13:7 | x |
|
||||
| tst.ts:14:13:14:13 | x |
|
||||
| tst.ts:15:17:15:17 | y |
|
||||
| tst.ts:18:26:18:26 | y |
|
||||
| tst.ts:18:30:18:30 | z |
|
||||
| tst.ts:18:34:18:34 | w |
|
||||
| tst.ts:20:40:20:45 | {x, y} |
|
||||
| tst.ts:20:49:20:51 | [w] |
|
||||
| withDefault.ts:1:22:1:22 | x |
|
||||
@@ -0,0 +1,3 @@
|
||||
import javascript
|
||||
|
||||
query Parameter optionalParams() { result.isDeclaredOptional() }
|
||||
@@ -0,0 +1,20 @@
|
||||
function f(x: number, y?: string) {
|
||||
return (x, y?) => {};
|
||||
}
|
||||
|
||||
class C {
|
||||
constructor(x: number, y?: string) {}
|
||||
|
||||
method(x?: number, y?: string) {}
|
||||
noTypes(x?) {}
|
||||
}
|
||||
|
||||
interface I {
|
||||
m(x?: number);
|
||||
field: (x?: number) => void;
|
||||
(x: number, y?: string): void;
|
||||
}
|
||||
|
||||
function manyDefaults(x, y?, z?, w?) {}
|
||||
|
||||
declare function optionalDestructuring({x, y}?, [w]?);
|
||||
@@ -0,0 +1 @@
|
||||
function withDefault(x? = 5) {} // not valid syntax
|
||||
@@ -0,0 +1,2 @@
|
||||
import f = require("./tst");
|
||||
f("world");
|
||||
@@ -0,0 +1,5 @@
|
||||
| main.ts:1:8:1:8 | f | (x: string) => string |
|
||||
| main.ts:1:20:1:26 | "./tst" | any |
|
||||
| main.ts:2:1:2:1 | f | (x: string) => string |
|
||||
| main.ts:2:1:2:10 | f("world") | string |
|
||||
| main.ts:2:3:2:9 | "world" | "world" |
|
||||
@@ -0,0 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from Expr e
|
||||
select e, e.getType()
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"allowJs": true
|
||||
},
|
||||
"include": ["."]
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* @param {String} x
|
||||
*/
|
||||
module.exports = function(x) {
|
||||
return 'Hello ' + x;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
| tst.ts:0:0:0:0 | tst.ts |
|
||||
@@ -0,0 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from File file
|
||||
select file
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"include": ["."],
|
||||
"compilerOptions": {
|
||||
"typeRoots": ["does-not-exist"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
let x = 5;
|
||||
@@ -1,2 +0,0 @@
|
||||
| test.ts:3:1:7:6 | type Di ... \\n T; | Disjunction<T> |
|
||||
| test.ts:9:8:9:65 | type Tr ... n<T>>>; | Disjunction<Disjunction<Disjunction<T>>> |
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
{}
|
||||
{
|
||||
"include": ["."]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
| tst.ts:0:0:0:0 | tst.ts |
|
||||
| typeroot.d.ts:0:0:0:0 | typeroot.d.ts |
|
||||
@@ -0,0 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from File file
|
||||
select file
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"include": ["."],
|
||||
"compilerOptions": {
|
||||
"typeRoots": ["typeroot.d.ts"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
let x = 5;
|
||||
0
javascript/ql/test/library-tests/TypeScript/RegressionTests/TypeRootFile/typeroot.d.ts
vendored
Normal file
0
javascript/ql/test/library-tests/TypeScript/RegressionTests/TypeRootFile/typeroot.d.ts
vendored
Normal file
@@ -1,3 +1,44 @@
|
||||
rightHandSide
|
||||
| tst.ts:1:1:1:16 | type A = number; | number |
|
||||
| tst.ts:2:1:2:16 | type B<T> = T[]; | T[] |
|
||||
| tst.ts:8:10:8:20 | type C = A; | number |
|
||||
| tst.ts:15:1:15:23 | type Un ... \| Two; | One \| Two |
|
||||
| tst.ts:17:1:17:36 | type Un ... mber }; | (One & { x: number; }) \| (Two & { x: number; }) |
|
||||
| tst.ts:18:1:18:21 | type Un ... Union2; | (One & { x: number; }) \| (Two & { x: number; }) |
|
||||
| tst.ts:19:1:19:21 | type Un ... Union3; | (One & { x: number; }) \| (Two & { x: number; }) |
|
||||
| tst.ts:20:1:20:30 | type Un ... number; | number \| (One & { x: number; }) \| (Two & { x: n... |
|
||||
getAliasedType
|
||||
| B<T> | T[] |
|
||||
| B<number> | number[] |
|
||||
| Union | One \| Two |
|
||||
| Union2 | (One & { x: number; }) \| (Two & { x: number; }) |
|
||||
| Union5 | number \| (One & { x: number; }) \| (Two & { x: n... |
|
||||
getTypeArgument
|
||||
| B<T> | 0 | T |
|
||||
| B<number> | 0 | number |
|
||||
unfold
|
||||
| B<T> | B<T> |
|
||||
| B<T> | T[] |
|
||||
| B<number> | B<number> |
|
||||
| B<number> | number[] |
|
||||
| Union | One |
|
||||
| Union | Two |
|
||||
| Union | Union |
|
||||
| Union2 | One |
|
||||
| Union2 | Two |
|
||||
| Union2 | Union2 |
|
||||
| Union2 | { x: number; } |
|
||||
| Union5 | One |
|
||||
| Union5 | Two |
|
||||
| Union5 | Union5 |
|
||||
| Union5 | number |
|
||||
| Union5 | { x: number; } |
|
||||
#select
|
||||
| tst.ts:1:1:1:16 | type A = number; | tst.ts:1:6:1:6 | A | 0 | tst.ts:1:10:1:15 | number |
|
||||
| tst.ts:2:1:2:16 | type B<T> = T[]; | tst.ts:2:6:2:6 | B | 1 | tst.ts:2:13:2:15 | T[] |
|
||||
| tst.ts:8:10:8:20 | type C = A; | tst.ts:8:15:8:15 | C | 0 | tst.ts:8:19:8:19 | A |
|
||||
| tst.ts:15:1:15:23 | type Un ... \| Two; | tst.ts:15:6:15:10 | Union | 0 | tst.ts:15:14:15:22 | One \| Two |
|
||||
| tst.ts:17:1:17:36 | type Un ... mber }; | tst.ts:17:6:17:11 | Union2 | 0 | tst.ts:17:15:17:35 | Union & ... umber } |
|
||||
| tst.ts:18:1:18:21 | type Un ... Union2; | tst.ts:18:6:18:11 | Union3 | 0 | tst.ts:18:15:18:20 | Union2 |
|
||||
| tst.ts:19:1:19:21 | type Un ... Union3; | tst.ts:19:6:19:11 | Union4 | 0 | tst.ts:19:15:19:20 | Union3 |
|
||||
| tst.ts:20:1:20:30 | type Un ... number; | tst.ts:20:6:20:11 | Union5 | 0 | tst.ts:20:15:20:29 | Union4 \| number |
|
||||
|
||||
@@ -2,3 +2,19 @@ import javascript
|
||||
|
||||
from TypeAliasDeclaration decl
|
||||
select decl, decl.getIdentifier(), decl.getNumTypeParameter(), decl.getDefinition()
|
||||
|
||||
query Type rightHandSide(TypeAliasDeclaration decl) {
|
||||
result = decl.getDefinition().getType()
|
||||
}
|
||||
|
||||
query Type getAliasedType(TypeAliasReference ref) {
|
||||
result = ref.getAliasedType()
|
||||
}
|
||||
|
||||
query Type getTypeArgument(TypeAliasReference ref, int n) {
|
||||
result = ref.getTypeArgument(n)
|
||||
}
|
||||
|
||||
query Type unfold(TypeAliasReference t) {
|
||||
result = t.unfold()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"include": ["."]
|
||||
}
|
||||
@@ -8,3 +8,13 @@ namespace Q {
|
||||
export type C = A;
|
||||
}
|
||||
var z: Q.C;
|
||||
|
||||
interface One { a: number }
|
||||
interface Two { b: number }
|
||||
|
||||
type Union = One | Two;
|
||||
|
||||
type Union2 = Union & { x: number };
|
||||
type Union3 = Union2;
|
||||
type Union4 = Union3;
|
||||
type Union5 = Union4 | number;
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
| type_alias.ts:5:6:5:17 | ValueOrArray | ValueOrArray<T> |
|
||||
| type_alias.ts:5:19:5:19 | T | T |
|
||||
| type_alias.ts:5:24:5:24 | T | T |
|
||||
| type_alias.ts:5:24:5:49 | T \| Arr ... ray<T>> | ValueOrArray<T> |
|
||||
| type_alias.ts:5:24:5:49 | T \| Arr ... ray<T>> | T \| ValueOrArray<T>[] |
|
||||
| type_alias.ts:5:28:5:32 | Array | T[] |
|
||||
| type_alias.ts:5:28:5:49 | Array<V ... ray<T>> | ValueOrArray<T>[] |
|
||||
| type_alias.ts:5:34:5:45 | ValueOrArray | ValueOrArray<T> |
|
||||
@@ -84,7 +84,7 @@
|
||||
| type_alias.ts:7:8:7:27 | ValueOrArray<number> | ValueOrArray<number> |
|
||||
| type_alias.ts:7:21:7:26 | number | number |
|
||||
| type_alias.ts:9:6:9:9 | Json | Json |
|
||||
| type_alias.ts:10:5:15:12 | \| strin ... Json[] | Json |
|
||||
| type_alias.ts:10:5:15:12 | \| strin ... Json[] | string \| number \| boolean \| { [property: string... |
|
||||
| type_alias.ts:10:7:10:12 | string | string |
|
||||
| type_alias.ts:11:7:11:12 | number | number |
|
||||
| type_alias.ts:12:7:12:13 | boolean | boolean |
|
||||
@@ -96,7 +96,7 @@
|
||||
| type_alias.ts:15:7:15:12 | Json[] | Json[] |
|
||||
| type_alias.ts:17:11:17:14 | Json | Json |
|
||||
| type_alias.ts:19:6:19:16 | VirtualNode | VirtualNode |
|
||||
| type_alias.ts:20:5:21:56 | \| strin ... Node[]] | VirtualNode |
|
||||
| type_alias.ts:20:5:21:56 | \| strin ... Node[]] | string \| [string, { [key: string]: any; }, ...V... |
|
||||
| type_alias.ts:20:7:20:12 | string | string |
|
||||
| type_alias.ts:21:7:21:56 | [string ... Node[]] | [string, { [key: string]: any; }, ...VirtualNod... |
|
||||
| type_alias.ts:21:8:21:13 | string | string |
|
||||
@@ -123,7 +123,7 @@
|
||||
| type_definitions.ts:21:6:21:10 | Alias | Alias<T> |
|
||||
| type_definitions.ts:21:12:21:12 | T | T |
|
||||
| type_definitions.ts:21:17:21:17 | T | T |
|
||||
| type_definitions.ts:21:17:21:19 | T[] | Alias<T> |
|
||||
| type_definitions.ts:21:17:21:19 | T[] | T[] |
|
||||
| type_definitions.ts:22:26:22:30 | Alias | Alias<T> |
|
||||
| type_definitions.ts:22:26:22:38 | Alias<number> | Alias<number> |
|
||||
| type_definitions.ts:22:32:22:37 | number | number |
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": ["es2015.symbol"]
|
||||
"lib": ["es2015"]
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: improve TypeScript support for type aliases, rest parameters, and optional parameters
|
||||
compatibility: backwards
|
||||
Reference in New Issue
Block a user