mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
TS: Extract type args to tagged template exprs
This commit is contained in:
@@ -31,7 +31,6 @@ import com.semmle.ts.ast.InterfaceDeclaration;
|
||||
import com.semmle.ts.ast.InterfaceTypeExpr;
|
||||
import com.semmle.ts.ast.IntersectionTypeExpr;
|
||||
import com.semmle.ts.ast.IsTypeExpr;
|
||||
import com.semmle.ts.ast.UnaryTypeExpr;
|
||||
import com.semmle.ts.ast.KeywordTypeExpr;
|
||||
import com.semmle.ts.ast.MappedTypeExpr;
|
||||
import com.semmle.ts.ast.NamespaceDeclaration;
|
||||
@@ -44,6 +43,7 @@ import com.semmle.ts.ast.TypeAliasDeclaration;
|
||||
import com.semmle.ts.ast.TypeAssertion;
|
||||
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 java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -413,7 +413,8 @@ public class NodeCopier implements Visitor<Void, INode> {
|
||||
|
||||
@Override
|
||||
public TaggedTemplateExpression visit(TaggedTemplateExpression nd, Void q) {
|
||||
return new TaggedTemplateExpression(visit(nd.getLoc()), copy(nd.getTag()), copy(nd.getQuasi()));
|
||||
return new TaggedTemplateExpression(
|
||||
visit(nd.getLoc()), copy(nd.getTag()), copy(nd.getQuasi()), copy(nd.getTypeArguments()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,14 +1,28 @@
|
||||
package com.semmle.js.ast;
|
||||
|
||||
import com.semmle.ts.ast.ITypeExpression;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/** A tagged template expression. */
|
||||
public class TaggedTemplateExpression extends Expression {
|
||||
private final Expression tag;
|
||||
private final TemplateLiteral quasi;
|
||||
private final List<ITypeExpression> typeArguments;
|
||||
|
||||
public TaggedTemplateExpression(SourceLocation loc, Expression tag, TemplateLiteral quasi) {
|
||||
public TaggedTemplateExpression(
|
||||
SourceLocation loc,
|
||||
Expression tag,
|
||||
TemplateLiteral quasi,
|
||||
List<ITypeExpression> typeArguments) {
|
||||
super("TaggedTemplateExpression", loc);
|
||||
this.tag = tag;
|
||||
this.quasi = quasi;
|
||||
this.typeArguments = typeArguments;
|
||||
}
|
||||
|
||||
public TaggedTemplateExpression(SourceLocation loc, Expression tag, TemplateLiteral quasi) {
|
||||
this(loc, tag, quasi, Collections.emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -25,4 +39,9 @@ public class TaggedTemplateExpression extends Expression {
|
||||
public TemplateLiteral getQuasi() {
|
||||
return quasi;
|
||||
}
|
||||
|
||||
/** The type arguments, or an empty list if there are none. */
|
||||
public List<ITypeExpression> getTypeArguments() {
|
||||
return typeArguments;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
package com.semmle.js.extractor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
import com.semmle.js.ast.AClass;
|
||||
import com.semmle.js.ast.AFunction;
|
||||
import com.semmle.js.ast.AFunctionExpression;
|
||||
@@ -125,7 +131,6 @@ import com.semmle.ts.ast.InterfaceDeclaration;
|
||||
import com.semmle.ts.ast.InterfaceTypeExpr;
|
||||
import com.semmle.ts.ast.IntersectionTypeExpr;
|
||||
import com.semmle.ts.ast.IsTypeExpr;
|
||||
import com.semmle.ts.ast.UnaryTypeExpr;
|
||||
import com.semmle.ts.ast.KeywordTypeExpr;
|
||||
import com.semmle.ts.ast.MappedTypeExpr;
|
||||
import com.semmle.ts.ast.NamespaceDeclaration;
|
||||
@@ -139,15 +144,11 @@ import com.semmle.ts.ast.TypeAssertion;
|
||||
import com.semmle.ts.ast.TypeExpression;
|
||||
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.collections.CollectionUtil;
|
||||
import com.semmle.util.trap.TrapWriter;
|
||||
import com.semmle.util.trap.TrapWriter.Label;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
/** Extractor for AST-based information; invoked by the {@link JSExtractor}. */
|
||||
public class ASTExtractor {
|
||||
@@ -1120,6 +1121,7 @@ public class ASTExtractor {
|
||||
Label key = super.visit(nd, c);
|
||||
visit(nd.getTag(), key, 0);
|
||||
visit(nd.getQuasi(), key, 1);
|
||||
visitAll(nd.getTypeArguments(), key, IdContext.typeBind, 2);
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
package com.semmle.js.parser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonNull;
|
||||
@@ -126,7 +134,6 @@ import com.semmle.ts.ast.InterfaceDeclaration;
|
||||
import com.semmle.ts.ast.InterfaceTypeExpr;
|
||||
import com.semmle.ts.ast.IntersectionTypeExpr;
|
||||
import com.semmle.ts.ast.IsTypeExpr;
|
||||
import com.semmle.ts.ast.UnaryTypeExpr;
|
||||
import com.semmle.ts.ast.KeywordTypeExpr;
|
||||
import com.semmle.ts.ast.MappedTypeExpr;
|
||||
import com.semmle.ts.ast.NamespaceDeclaration;
|
||||
@@ -139,15 +146,9 @@ import com.semmle.ts.ast.TypeAliasDeclaration;
|
||||
import com.semmle.ts.ast.TypeAssertion;
|
||||
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.collections.CollectionUtil;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Utility class for converting a <a
|
||||
@@ -2034,7 +2035,8 @@ public class TypeScriptASTConverter {
|
||||
private Node convertTaggedTemplateExpression(JsonObject node, SourceLocation loc)
|
||||
throws ParseError {
|
||||
return new TaggedTemplateExpression(
|
||||
loc, convertChild(node, "tag"), convertChild(node, "template"));
|
||||
loc, convertChild(node, "tag"), convertChild(node, "template"),
|
||||
convertChildrenAsTypes(node, "typeArguments"));
|
||||
}
|
||||
|
||||
private Node convertTemplateExpression(JsonObject node, SourceLocation loc) throws ParseError {
|
||||
|
||||
@@ -18,6 +18,15 @@ class TaggedTemplateExpr extends Expr, @taggedtemplateexpr {
|
||||
/** Gets the tagged template itself. */
|
||||
TemplateLiteral getTemplate() { result = getChildExpr(1) }
|
||||
|
||||
/** Gets the `i`th type argument to the tag of this template literal. */
|
||||
TypeExpr getTypeArgument(int i) { i >= 0 and result = getChildTypeExpr(2 + i) }
|
||||
|
||||
/** Gets a type argument of the tag of this template literal. */
|
||||
TypeExpr getATypeArgument() { result = getTypeArgument(_) }
|
||||
|
||||
/** Gets the number of type arguments appearing on the tag of this template literal. */
|
||||
int getNumTypeArgument() { result = count(getATypeArgument()) }
|
||||
|
||||
override predicate isImpure() { any() }
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import javascript
|
||||
|
||||
query predicate test_TaggedTemplateLiteralTypeArgument(TaggedTemplateExpr expr, int i, TypeExpr arg) {
|
||||
arg = expr.getTypeArgument(i)
|
||||
}
|
||||
@@ -257,3 +257,7 @@ test_ReturnTypes
|
||||
test_KeyofTypeExpr
|
||||
| tst.ts:49:16:49:30 | keyof Interface | tst.ts:49:22:49:30 | Interface |
|
||||
| tst.ts:113:26:113:35 | keyof Node | tst.ts:113:32:113:35 | Node |
|
||||
test_TaggedTemplateLiteralTypeArgument
|
||||
| tst.ts:139:37:139:58 | someTag ... `Hello` | 0 | tst.ts:139:45:139:50 | number |
|
||||
| tst.ts:140:37:140:66 | someTag ... `Hello` | 0 | tst.ts:140:45:140:50 | number |
|
||||
| tst.ts:140:37:140:66 | someTag ... `Hello` | 1 | tst.ts:140:53:140:58 | string |
|
||||
|
||||
@@ -27,3 +27,4 @@ import RestTypeExpr
|
||||
import Containers
|
||||
import ReturnTypes
|
||||
import KeyofTypeExpr
|
||||
import TemplateLiterals
|
||||
|
||||
@@ -135,3 +135,6 @@ let emptyTuple: [];
|
||||
let tupleWithRestElement: [number, ...string[]];
|
||||
let tupleWithOptionalAndRestElements: [number, string?, ...number[]];
|
||||
let unknownType: unknown;
|
||||
|
||||
let taggedTemplateLiteralTypeArg1 = someTag<number>`Hello`;
|
||||
let taggedTemplateLiteralTypeArg2 = someTag<number, string>`Hello`;
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { SomeInterface } from 'somwhere1'; // OK
|
||||
import { AnotherInterface } from 'somwhere2'; // OK
|
||||
import { foo } from 'somewhere3'; // OK
|
||||
|
||||
let x = "world";
|
||||
|
||||
console.log(foo<SomeInterface>`Hello world`);
|
||||
console.log(foo<AnotherInterface>`Hello ${x}`);
|
||||
Reference in New Issue
Block a user