TS: Extract type alias relation

This commit is contained in:
Asger F
2019-11-14 16:00:23 +00:00
parent f11dc11ade
commit e25ee182a0
7 changed files with 84 additions and 4 deletions

View File

@@ -102,6 +102,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 +297,11 @@ export class TypeTable {
propertyTypes: [],
};
private typeAliases: TypeAliasTable = {
aliasTypes: [],
underlyingTypes: [],
};
private signatureMappings: SignatureTable = {
baseTypes: [],
kinds: [],
@@ -304,7 +319,7 @@ export class TypeTable {
propertyTypes: [],
};
private buildTypeWorklist: [ts.Type, number][] = [];
private buildTypeWorklist: [ts.Type, number, boolean][] = [];
private expansiveTypes: Map<number, boolean> = new Map();
@@ -409,7 +424,7 @@ export class TypeTable {
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,7 +441,7 @@ 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;
@@ -789,6 +804,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 +828,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);

View File

@@ -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);

View File

@@ -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();
}

View File

@@ -2287,6 +2287,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 }`.
*/

View File

@@ -703,6 +703,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(

View File

@@ -3,6 +3,13 @@ rightHandSide
| 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 |
getAliasedType
| B<T> | T[] |
| B<number> | number[] |
| Union | One \| Two |
getTypeArgument
| B<T> | 0 | T |
| B<number> | 0 | 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[] |

View File

@@ -6,3 +6,11 @@ select decl, decl.getIdentifier(), decl.getNumTypeParameter(), decl.getDefinitio
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)
}