mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #519 from esben-semmle/js/nullish-coalescing-extractor-and-ql
JS: nullish coalescing support in extractor and QL
This commit is contained in:
21
change-notes/1.20/extractor-javascript.md
Normal file
21
change-notes/1.20/extractor-javascript.md
Normal file
@@ -0,0 +1,21 @@
|
||||
[[ condition: enterprise-only ]]
|
||||
|
||||
# Improvements to JavaScript analysis
|
||||
|
||||
> NOTES
|
||||
>
|
||||
> Please describe your changes in terms that are suitable for
|
||||
> customers to read. These notes will have only minor tidying up
|
||||
> before they are published as part of the release notes.
|
||||
>
|
||||
> This file is written for lgtm users and should contain *only*
|
||||
> notes about changes that affect lgtm enterprise users. Add
|
||||
> any other customer-facing changes to the `studio-java.md`
|
||||
> file.
|
||||
>
|
||||
|
||||
## General improvements
|
||||
|
||||
## Changes to code extraction
|
||||
|
||||
* The extractor now supports [Nullish Coalescing](https://github.com/tc39/proposal-nullish-coalescing) expressions.
|
||||
@@ -508,8 +508,12 @@ public class Parser {
|
||||
private Token readToken_question() { // '?'
|
||||
int next = charAt(this.pos + 1);
|
||||
int next2 = charAt(this.pos + 2);
|
||||
if (this.options.esnext() && next == '.' && !('0' <= next2 && next2 <= '9')) // '?.', but not '?.X' where X is a digit
|
||||
return this.finishOp(TokenType.questiondot, 2);
|
||||
if (this.options.esnext()) {
|
||||
if (next == '.' && !('0' <= next2 && next2 <= '9')) // '?.', but not '?.X' where X is a digit
|
||||
return this.finishOp(TokenType.questiondot, 2);
|
||||
if (next == '?') // '??'
|
||||
return this.finishOp(TokenType.questionquestion, 2);
|
||||
}
|
||||
return this.finishOp(TokenType.question, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -123,6 +123,7 @@ public class TokenType {
|
||||
}
|
||||
},
|
||||
prefix = new TokenType(new Properties("prefix").beforeExpr().prefix().startsExpr()),
|
||||
questionquestion = new TokenType(binop("??", 1)),
|
||||
logicalOR = new TokenType(binop("||", 1)),
|
||||
logicalAND = new TokenType(binop("&&", 2)),
|
||||
bitwiseOR = new TokenType(binop("|", 3)),
|
||||
|
||||
@@ -331,9 +331,11 @@ public class CFGExtractor {
|
||||
return nd.getKey().accept(this, v);
|
||||
}
|
||||
|
||||
// for binary operators, the operands come first (but not for LogicalExpression, see above)
|
||||
// for binary operators, the operands come first (but not for short-circuiting expressions), see above)
|
||||
@Override
|
||||
public Node visit(BinaryExpression nd, Void v) {
|
||||
if ("??".equals(nd.getOperator()))
|
||||
return nd;
|
||||
return nd.getLeft().accept(this, v);
|
||||
}
|
||||
|
||||
@@ -1583,8 +1585,16 @@ public class CFGExtractor {
|
||||
|
||||
@Override
|
||||
public Void visit(BinaryExpression nd, SuccessorInfo i) {
|
||||
this.seq(nd.getLeft(), nd.getRight(), nd);
|
||||
succ(nd, i.getGuardedSuccessors(nd));
|
||||
if ("??".equals(nd.getOperator())) {
|
||||
// the nullish coalescing operator is short-circuiting, but we do not add guards for it
|
||||
succ(nd, First.of(nd.getLeft()));
|
||||
Object leftSucc = union(First.of(nd.getRight()), i.getAllSuccessors()); // short-circuiting happens with both truthy and falsy values
|
||||
visit(nd.getLeft(), leftSucc, null);
|
||||
nd.getRight().accept(this, i);
|
||||
} else {
|
||||
this.seq(nd.getLeft(), nd.getRight(), nd);
|
||||
succ(nd, i.getGuardedSuccessors(nd));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ public class ExprKinds {
|
||||
binOpKinds.put("&=", 58);
|
||||
binOpKinds.put("**", 87);
|
||||
binOpKinds.put("**=", 88);
|
||||
binOpKinds.put("??", 107);
|
||||
}
|
||||
|
||||
private static final Map<String, Integer> unOpKinds = new LinkedHashMap<String, Integer>();
|
||||
|
||||
@@ -41,7 +41,7 @@ public class Main {
|
||||
* such a way that it may produce different tuples for the same file under the same
|
||||
* {@link ExtractorConfig}.
|
||||
*/
|
||||
public static final String EXTRACTOR_VERSION = "2018-11-22_a";
|
||||
public static final String EXTRACTOR_VERSION = "2018-11-23";
|
||||
|
||||
public static final Pattern NEWLINE = Pattern.compile("\n");
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
x1 ?? y1;
|
||||
|
||||
x2 || y2 ?? z2;
|
||||
x3 ?? y3 || z3;
|
||||
|
||||
x4 && y4 ?? z4;
|
||||
x5 ?? y5 && z5;
|
||||
@@ -0,0 +1,494 @@
|
||||
#10000=@"/nullish-coalescing.js;sourcefile"
|
||||
files(#10000,"/nullish-coalescing.js","nullish-coalescing","js",0)
|
||||
#10001=@"/;folder"
|
||||
folders(#10001,"/","")
|
||||
containerparent(#10001,#10000)
|
||||
#10002=@"loc,{#10000},0,0,0,0"
|
||||
locations_default(#10002,#10000,0,0,0,0)
|
||||
hasLocation(#10000,#10002)
|
||||
#20000=@"global_scope"
|
||||
scopes(#20000,0)
|
||||
#20001=@"script;{#10000},1,1"
|
||||
toplevels(#20001,0)
|
||||
#20002=@"loc,{#10000},1,1,7,15"
|
||||
locations_default(#20002,#10000,1,1,7,15)
|
||||
hasLocation(#20001,#20002)
|
||||
#20003=*
|
||||
stmts(#20003,2,#20001,0,"x1 ?? y1;")
|
||||
#20004=@"loc,{#10000},1,1,1,9"
|
||||
locations_default(#20004,#10000,1,1,1,9)
|
||||
hasLocation(#20003,#20004)
|
||||
stmtContainers(#20003,#20001)
|
||||
#20005=*
|
||||
exprs(#20005,107,#20003,0,"x1 ?? y1")
|
||||
#20006=@"loc,{#10000},1,1,1,8"
|
||||
locations_default(#20006,#10000,1,1,1,8)
|
||||
hasLocation(#20005,#20006)
|
||||
enclosingStmt(#20005,#20003)
|
||||
exprContainers(#20005,#20001)
|
||||
#20007=*
|
||||
exprs(#20007,79,#20005,0,"x1")
|
||||
#20008=@"loc,{#10000},1,1,1,2"
|
||||
locations_default(#20008,#10000,1,1,1,2)
|
||||
hasLocation(#20007,#20008)
|
||||
enclosingStmt(#20007,#20003)
|
||||
exprContainers(#20007,#20001)
|
||||
literals("x1","x1",#20007)
|
||||
#20009=@"var;{x1};{#20000}"
|
||||
variables(#20009,"x1",#20000)
|
||||
bind(#20007,#20009)
|
||||
#20010=*
|
||||
exprs(#20010,79,#20005,1,"y1")
|
||||
#20011=@"loc,{#10000},1,7,1,8"
|
||||
locations_default(#20011,#10000,1,7,1,8)
|
||||
hasLocation(#20010,#20011)
|
||||
enclosingStmt(#20010,#20003)
|
||||
exprContainers(#20010,#20001)
|
||||
literals("y1","y1",#20010)
|
||||
#20012=@"var;{y1};{#20000}"
|
||||
variables(#20012,"y1",#20000)
|
||||
bind(#20010,#20012)
|
||||
#20013=*
|
||||
stmts(#20013,2,#20001,1,"x2 || y2 ?? z2;")
|
||||
#20014=@"loc,{#10000},3,1,3,15"
|
||||
locations_default(#20014,#10000,3,1,3,15)
|
||||
hasLocation(#20013,#20014)
|
||||
stmtContainers(#20013,#20001)
|
||||
#20015=*
|
||||
exprs(#20015,107,#20013,0,"x2 || y2 ?? z2")
|
||||
#20016=@"loc,{#10000},3,1,3,14"
|
||||
locations_default(#20016,#10000,3,1,3,14)
|
||||
hasLocation(#20015,#20016)
|
||||
enclosingStmt(#20015,#20013)
|
||||
exprContainers(#20015,#20001)
|
||||
#20017=*
|
||||
exprs(#20017,45,#20015,0,"x2 || y2")
|
||||
#20018=@"loc,{#10000},3,1,3,8"
|
||||
locations_default(#20018,#10000,3,1,3,8)
|
||||
hasLocation(#20017,#20018)
|
||||
enclosingStmt(#20017,#20013)
|
||||
exprContainers(#20017,#20001)
|
||||
#20019=*
|
||||
exprs(#20019,79,#20017,0,"x2")
|
||||
#20020=@"loc,{#10000},3,1,3,2"
|
||||
locations_default(#20020,#10000,3,1,3,2)
|
||||
hasLocation(#20019,#20020)
|
||||
enclosingStmt(#20019,#20013)
|
||||
exprContainers(#20019,#20001)
|
||||
literals("x2","x2",#20019)
|
||||
#20021=@"var;{x2};{#20000}"
|
||||
variables(#20021,"x2",#20000)
|
||||
bind(#20019,#20021)
|
||||
#20022=*
|
||||
exprs(#20022,79,#20017,1,"y2")
|
||||
#20023=@"loc,{#10000},3,7,3,8"
|
||||
locations_default(#20023,#10000,3,7,3,8)
|
||||
hasLocation(#20022,#20023)
|
||||
enclosingStmt(#20022,#20013)
|
||||
exprContainers(#20022,#20001)
|
||||
literals("y2","y2",#20022)
|
||||
#20024=@"var;{y2};{#20000}"
|
||||
variables(#20024,"y2",#20000)
|
||||
bind(#20022,#20024)
|
||||
#20025=*
|
||||
exprs(#20025,79,#20015,1,"z2")
|
||||
#20026=@"loc,{#10000},3,13,3,14"
|
||||
locations_default(#20026,#10000,3,13,3,14)
|
||||
hasLocation(#20025,#20026)
|
||||
enclosingStmt(#20025,#20013)
|
||||
exprContainers(#20025,#20001)
|
||||
literals("z2","z2",#20025)
|
||||
#20027=@"var;{z2};{#20000}"
|
||||
variables(#20027,"z2",#20000)
|
||||
bind(#20025,#20027)
|
||||
#20028=*
|
||||
stmts(#20028,2,#20001,2,"x3 ?? y3 || z3;")
|
||||
#20029=@"loc,{#10000},4,1,4,15"
|
||||
locations_default(#20029,#10000,4,1,4,15)
|
||||
hasLocation(#20028,#20029)
|
||||
stmtContainers(#20028,#20001)
|
||||
#20030=*
|
||||
exprs(#20030,45,#20028,0,"x3 ?? y3 || z3")
|
||||
#20031=@"loc,{#10000},4,1,4,14"
|
||||
locations_default(#20031,#10000,4,1,4,14)
|
||||
hasLocation(#20030,#20031)
|
||||
enclosingStmt(#20030,#20028)
|
||||
exprContainers(#20030,#20001)
|
||||
#20032=*
|
||||
exprs(#20032,107,#20030,0,"x3 ?? y3")
|
||||
#20033=@"loc,{#10000},4,1,4,8"
|
||||
locations_default(#20033,#10000,4,1,4,8)
|
||||
hasLocation(#20032,#20033)
|
||||
enclosingStmt(#20032,#20028)
|
||||
exprContainers(#20032,#20001)
|
||||
#20034=*
|
||||
exprs(#20034,79,#20032,0,"x3")
|
||||
#20035=@"loc,{#10000},4,1,4,2"
|
||||
locations_default(#20035,#10000,4,1,4,2)
|
||||
hasLocation(#20034,#20035)
|
||||
enclosingStmt(#20034,#20028)
|
||||
exprContainers(#20034,#20001)
|
||||
literals("x3","x3",#20034)
|
||||
#20036=@"var;{x3};{#20000}"
|
||||
variables(#20036,"x3",#20000)
|
||||
bind(#20034,#20036)
|
||||
#20037=*
|
||||
exprs(#20037,79,#20032,1,"y3")
|
||||
#20038=@"loc,{#10000},4,7,4,8"
|
||||
locations_default(#20038,#10000,4,7,4,8)
|
||||
hasLocation(#20037,#20038)
|
||||
enclosingStmt(#20037,#20028)
|
||||
exprContainers(#20037,#20001)
|
||||
literals("y3","y3",#20037)
|
||||
#20039=@"var;{y3};{#20000}"
|
||||
variables(#20039,"y3",#20000)
|
||||
bind(#20037,#20039)
|
||||
#20040=*
|
||||
exprs(#20040,79,#20030,1,"z3")
|
||||
#20041=@"loc,{#10000},4,13,4,14"
|
||||
locations_default(#20041,#10000,4,13,4,14)
|
||||
hasLocation(#20040,#20041)
|
||||
enclosingStmt(#20040,#20028)
|
||||
exprContainers(#20040,#20001)
|
||||
literals("z3","z3",#20040)
|
||||
#20042=@"var;{z3};{#20000}"
|
||||
variables(#20042,"z3",#20000)
|
||||
bind(#20040,#20042)
|
||||
#20043=*
|
||||
stmts(#20043,2,#20001,3,"x4 && y4 ?? z4;")
|
||||
#20044=@"loc,{#10000},6,1,6,15"
|
||||
locations_default(#20044,#10000,6,1,6,15)
|
||||
hasLocation(#20043,#20044)
|
||||
stmtContainers(#20043,#20001)
|
||||
#20045=*
|
||||
exprs(#20045,107,#20043,0,"x4 && y4 ?? z4")
|
||||
#20046=@"loc,{#10000},6,1,6,14"
|
||||
locations_default(#20046,#10000,6,1,6,14)
|
||||
hasLocation(#20045,#20046)
|
||||
enclosingStmt(#20045,#20043)
|
||||
exprContainers(#20045,#20001)
|
||||
#20047=*
|
||||
exprs(#20047,44,#20045,0,"x4 && y4")
|
||||
#20048=@"loc,{#10000},6,1,6,8"
|
||||
locations_default(#20048,#10000,6,1,6,8)
|
||||
hasLocation(#20047,#20048)
|
||||
enclosingStmt(#20047,#20043)
|
||||
exprContainers(#20047,#20001)
|
||||
#20049=*
|
||||
exprs(#20049,79,#20047,0,"x4")
|
||||
#20050=@"loc,{#10000},6,1,6,2"
|
||||
locations_default(#20050,#10000,6,1,6,2)
|
||||
hasLocation(#20049,#20050)
|
||||
enclosingStmt(#20049,#20043)
|
||||
exprContainers(#20049,#20001)
|
||||
literals("x4","x4",#20049)
|
||||
#20051=@"var;{x4};{#20000}"
|
||||
variables(#20051,"x4",#20000)
|
||||
bind(#20049,#20051)
|
||||
#20052=*
|
||||
exprs(#20052,79,#20047,1,"y4")
|
||||
#20053=@"loc,{#10000},6,7,6,8"
|
||||
locations_default(#20053,#10000,6,7,6,8)
|
||||
hasLocation(#20052,#20053)
|
||||
enclosingStmt(#20052,#20043)
|
||||
exprContainers(#20052,#20001)
|
||||
literals("y4","y4",#20052)
|
||||
#20054=@"var;{y4};{#20000}"
|
||||
variables(#20054,"y4",#20000)
|
||||
bind(#20052,#20054)
|
||||
#20055=*
|
||||
exprs(#20055,79,#20045,1,"z4")
|
||||
#20056=@"loc,{#10000},6,13,6,14"
|
||||
locations_default(#20056,#10000,6,13,6,14)
|
||||
hasLocation(#20055,#20056)
|
||||
enclosingStmt(#20055,#20043)
|
||||
exprContainers(#20055,#20001)
|
||||
literals("z4","z4",#20055)
|
||||
#20057=@"var;{z4};{#20000}"
|
||||
variables(#20057,"z4",#20000)
|
||||
bind(#20055,#20057)
|
||||
#20058=*
|
||||
stmts(#20058,2,#20001,4,"x5 ?? y5 && z5;")
|
||||
#20059=@"loc,{#10000},7,1,7,15"
|
||||
locations_default(#20059,#10000,7,1,7,15)
|
||||
hasLocation(#20058,#20059)
|
||||
stmtContainers(#20058,#20001)
|
||||
#20060=*
|
||||
exprs(#20060,107,#20058,0,"x5 ?? y5 && z5")
|
||||
#20061=@"loc,{#10000},7,1,7,14"
|
||||
locations_default(#20061,#10000,7,1,7,14)
|
||||
hasLocation(#20060,#20061)
|
||||
enclosingStmt(#20060,#20058)
|
||||
exprContainers(#20060,#20001)
|
||||
#20062=*
|
||||
exprs(#20062,79,#20060,0,"x5")
|
||||
#20063=@"loc,{#10000},7,1,7,2"
|
||||
locations_default(#20063,#10000,7,1,7,2)
|
||||
hasLocation(#20062,#20063)
|
||||
enclosingStmt(#20062,#20058)
|
||||
exprContainers(#20062,#20001)
|
||||
literals("x5","x5",#20062)
|
||||
#20064=@"var;{x5};{#20000}"
|
||||
variables(#20064,"x5",#20000)
|
||||
bind(#20062,#20064)
|
||||
#20065=*
|
||||
exprs(#20065,44,#20060,1,"y5 && z5")
|
||||
#20066=@"loc,{#10000},7,7,7,14"
|
||||
locations_default(#20066,#10000,7,7,7,14)
|
||||
hasLocation(#20065,#20066)
|
||||
enclosingStmt(#20065,#20058)
|
||||
exprContainers(#20065,#20001)
|
||||
#20067=*
|
||||
exprs(#20067,79,#20065,0,"y5")
|
||||
#20068=@"loc,{#10000},7,7,7,8"
|
||||
locations_default(#20068,#10000,7,7,7,8)
|
||||
hasLocation(#20067,#20068)
|
||||
enclosingStmt(#20067,#20058)
|
||||
exprContainers(#20067,#20001)
|
||||
literals("y5","y5",#20067)
|
||||
#20069=@"var;{y5};{#20000}"
|
||||
variables(#20069,"y5",#20000)
|
||||
bind(#20067,#20069)
|
||||
#20070=*
|
||||
exprs(#20070,79,#20065,1,"z5")
|
||||
#20071=@"loc,{#10000},7,13,7,14"
|
||||
locations_default(#20071,#10000,7,13,7,14)
|
||||
hasLocation(#20070,#20071)
|
||||
enclosingStmt(#20070,#20058)
|
||||
exprContainers(#20070,#20001)
|
||||
literals("z5","z5",#20070)
|
||||
#20072=@"var;{z5};{#20000}"
|
||||
variables(#20072,"z5",#20000)
|
||||
bind(#20070,#20072)
|
||||
#20073=*
|
||||
lines(#20073,#20001,"x1 ?? y1;","
|
||||
")
|
||||
hasLocation(#20073,#20004)
|
||||
#20074=*
|
||||
lines(#20074,#20001,"","
|
||||
")
|
||||
#20075=@"loc,{#10000},2,1,2,0"
|
||||
locations_default(#20075,#10000,2,1,2,0)
|
||||
hasLocation(#20074,#20075)
|
||||
#20076=*
|
||||
lines(#20076,#20001,"x2 || y2 ?? z2;","
|
||||
")
|
||||
hasLocation(#20076,#20014)
|
||||
#20077=*
|
||||
lines(#20077,#20001,"x3 ?? y3 || z3;","
|
||||
")
|
||||
hasLocation(#20077,#20029)
|
||||
#20078=*
|
||||
lines(#20078,#20001,"","
|
||||
")
|
||||
#20079=@"loc,{#10000},5,1,5,0"
|
||||
locations_default(#20079,#10000,5,1,5,0)
|
||||
hasLocation(#20078,#20079)
|
||||
#20080=*
|
||||
lines(#20080,#20001,"x4 && y4 ?? z4;","
|
||||
")
|
||||
hasLocation(#20080,#20044)
|
||||
#20081=*
|
||||
lines(#20081,#20001,"x5 ?? y5 && z5;","")
|
||||
hasLocation(#20081,#20059)
|
||||
numlines(#20001,7,5,0)
|
||||
#20082=*
|
||||
tokeninfo(#20082,6,#20001,0,"x1")
|
||||
hasLocation(#20082,#20008)
|
||||
#20083=*
|
||||
tokeninfo(#20083,8,#20001,1,"??")
|
||||
#20084=@"loc,{#10000},1,4,1,5"
|
||||
locations_default(#20084,#10000,1,4,1,5)
|
||||
hasLocation(#20083,#20084)
|
||||
#20085=*
|
||||
tokeninfo(#20085,6,#20001,2,"y1")
|
||||
hasLocation(#20085,#20011)
|
||||
#20086=*
|
||||
tokeninfo(#20086,8,#20001,3,";")
|
||||
#20087=@"loc,{#10000},1,9,1,9"
|
||||
locations_default(#20087,#10000,1,9,1,9)
|
||||
hasLocation(#20086,#20087)
|
||||
#20088=*
|
||||
tokeninfo(#20088,6,#20001,4,"x2")
|
||||
hasLocation(#20088,#20020)
|
||||
#20089=*
|
||||
tokeninfo(#20089,8,#20001,5,"||")
|
||||
#20090=@"loc,{#10000},3,4,3,5"
|
||||
locations_default(#20090,#10000,3,4,3,5)
|
||||
hasLocation(#20089,#20090)
|
||||
#20091=*
|
||||
tokeninfo(#20091,6,#20001,6,"y2")
|
||||
hasLocation(#20091,#20023)
|
||||
#20092=*
|
||||
tokeninfo(#20092,8,#20001,7,"??")
|
||||
#20093=@"loc,{#10000},3,10,3,11"
|
||||
locations_default(#20093,#10000,3,10,3,11)
|
||||
hasLocation(#20092,#20093)
|
||||
#20094=*
|
||||
tokeninfo(#20094,6,#20001,8,"z2")
|
||||
hasLocation(#20094,#20026)
|
||||
#20095=*
|
||||
tokeninfo(#20095,8,#20001,9,";")
|
||||
#20096=@"loc,{#10000},3,15,3,15"
|
||||
locations_default(#20096,#10000,3,15,3,15)
|
||||
hasLocation(#20095,#20096)
|
||||
#20097=*
|
||||
tokeninfo(#20097,6,#20001,10,"x3")
|
||||
hasLocation(#20097,#20035)
|
||||
#20098=*
|
||||
tokeninfo(#20098,8,#20001,11,"??")
|
||||
#20099=@"loc,{#10000},4,4,4,5"
|
||||
locations_default(#20099,#10000,4,4,4,5)
|
||||
hasLocation(#20098,#20099)
|
||||
#20100=*
|
||||
tokeninfo(#20100,6,#20001,12,"y3")
|
||||
hasLocation(#20100,#20038)
|
||||
#20101=*
|
||||
tokeninfo(#20101,8,#20001,13,"||")
|
||||
#20102=@"loc,{#10000},4,10,4,11"
|
||||
locations_default(#20102,#10000,4,10,4,11)
|
||||
hasLocation(#20101,#20102)
|
||||
#20103=*
|
||||
tokeninfo(#20103,6,#20001,14,"z3")
|
||||
hasLocation(#20103,#20041)
|
||||
#20104=*
|
||||
tokeninfo(#20104,8,#20001,15,";")
|
||||
#20105=@"loc,{#10000},4,15,4,15"
|
||||
locations_default(#20105,#10000,4,15,4,15)
|
||||
hasLocation(#20104,#20105)
|
||||
#20106=*
|
||||
tokeninfo(#20106,6,#20001,16,"x4")
|
||||
hasLocation(#20106,#20050)
|
||||
#20107=*
|
||||
tokeninfo(#20107,8,#20001,17,"&&")
|
||||
#20108=@"loc,{#10000},6,4,6,5"
|
||||
locations_default(#20108,#10000,6,4,6,5)
|
||||
hasLocation(#20107,#20108)
|
||||
#20109=*
|
||||
tokeninfo(#20109,6,#20001,18,"y4")
|
||||
hasLocation(#20109,#20053)
|
||||
#20110=*
|
||||
tokeninfo(#20110,8,#20001,19,"??")
|
||||
#20111=@"loc,{#10000},6,10,6,11"
|
||||
locations_default(#20111,#10000,6,10,6,11)
|
||||
hasLocation(#20110,#20111)
|
||||
#20112=*
|
||||
tokeninfo(#20112,6,#20001,20,"z4")
|
||||
hasLocation(#20112,#20056)
|
||||
#20113=*
|
||||
tokeninfo(#20113,8,#20001,21,";")
|
||||
#20114=@"loc,{#10000},6,15,6,15"
|
||||
locations_default(#20114,#10000,6,15,6,15)
|
||||
hasLocation(#20113,#20114)
|
||||
#20115=*
|
||||
tokeninfo(#20115,6,#20001,22,"x5")
|
||||
hasLocation(#20115,#20063)
|
||||
#20116=*
|
||||
tokeninfo(#20116,8,#20001,23,"??")
|
||||
#20117=@"loc,{#10000},7,4,7,5"
|
||||
locations_default(#20117,#10000,7,4,7,5)
|
||||
hasLocation(#20116,#20117)
|
||||
#20118=*
|
||||
tokeninfo(#20118,6,#20001,24,"y5")
|
||||
hasLocation(#20118,#20068)
|
||||
#20119=*
|
||||
tokeninfo(#20119,8,#20001,25,"&&")
|
||||
#20120=@"loc,{#10000},7,10,7,11"
|
||||
locations_default(#20120,#10000,7,10,7,11)
|
||||
hasLocation(#20119,#20120)
|
||||
#20121=*
|
||||
tokeninfo(#20121,6,#20001,26,"z5")
|
||||
hasLocation(#20121,#20071)
|
||||
#20122=*
|
||||
tokeninfo(#20122,8,#20001,27,";")
|
||||
#20123=@"loc,{#10000},7,15,7,15"
|
||||
locations_default(#20123,#10000,7,15,7,15)
|
||||
hasLocation(#20122,#20123)
|
||||
#20124=*
|
||||
tokeninfo(#20124,0,#20001,28,"")
|
||||
#20125=@"loc,{#10000},7,16,7,15"
|
||||
locations_default(#20125,#10000,7,16,7,15)
|
||||
hasLocation(#20124,#20125)
|
||||
#20126=*
|
||||
entry_cfg_node(#20126,#20001)
|
||||
#20127=@"loc,{#10000},1,1,1,0"
|
||||
locations_default(#20127,#10000,1,1,1,0)
|
||||
hasLocation(#20126,#20127)
|
||||
#20128=*
|
||||
exit_cfg_node(#20128,#20001)
|
||||
hasLocation(#20128,#20125)
|
||||
successor(#20058,#20060)
|
||||
successor(#20060,#20062)
|
||||
successor(#20062,#20065)
|
||||
successor(#20062,#20128)
|
||||
successor(#20065,#20067)
|
||||
#20129=*
|
||||
guard_node(#20129,1,#20067)
|
||||
hasLocation(#20129,#20068)
|
||||
successor(#20129,#20070)
|
||||
#20130=*
|
||||
guard_node(#20130,0,#20067)
|
||||
hasLocation(#20130,#20068)
|
||||
successor(#20130,#20128)
|
||||
successor(#20067,#20129)
|
||||
successor(#20067,#20130)
|
||||
successor(#20070,#20128)
|
||||
successor(#20043,#20045)
|
||||
successor(#20045,#20047)
|
||||
successor(#20047,#20049)
|
||||
#20131=*
|
||||
guard_node(#20131,1,#20049)
|
||||
hasLocation(#20131,#20050)
|
||||
successor(#20131,#20052)
|
||||
#20132=*
|
||||
guard_node(#20132,0,#20049)
|
||||
hasLocation(#20132,#20050)
|
||||
successor(#20132,#20055)
|
||||
successor(#20132,#20058)
|
||||
successor(#20049,#20131)
|
||||
successor(#20049,#20132)
|
||||
successor(#20052,#20055)
|
||||
successor(#20052,#20058)
|
||||
successor(#20055,#20058)
|
||||
successor(#20028,#20030)
|
||||
successor(#20030,#20032)
|
||||
successor(#20032,#20034)
|
||||
successor(#20034,#20037)
|
||||
successor(#20034,#20043)
|
||||
successor(#20034,#20040)
|
||||
#20133=*
|
||||
guard_node(#20133,1,#20037)
|
||||
hasLocation(#20133,#20038)
|
||||
successor(#20133,#20043)
|
||||
#20134=*
|
||||
guard_node(#20134,0,#20037)
|
||||
hasLocation(#20134,#20038)
|
||||
successor(#20134,#20040)
|
||||
successor(#20037,#20133)
|
||||
successor(#20037,#20134)
|
||||
successor(#20040,#20043)
|
||||
successor(#20013,#20015)
|
||||
successor(#20015,#20017)
|
||||
successor(#20017,#20019)
|
||||
#20135=*
|
||||
guard_node(#20135,1,#20019)
|
||||
hasLocation(#20135,#20020)
|
||||
successor(#20135,#20025)
|
||||
successor(#20135,#20028)
|
||||
#20136=*
|
||||
guard_node(#20136,0,#20019)
|
||||
hasLocation(#20136,#20020)
|
||||
successor(#20136,#20022)
|
||||
successor(#20019,#20135)
|
||||
successor(#20019,#20136)
|
||||
successor(#20022,#20025)
|
||||
successor(#20022,#20028)
|
||||
successor(#20025,#20028)
|
||||
successor(#20003,#20005)
|
||||
successor(#20005,#20007)
|
||||
successor(#20007,#20010)
|
||||
successor(#20007,#20013)
|
||||
successor(#20010,#20013)
|
||||
successor(#20126,#20003)
|
||||
numlines(#10000,7,5,0)
|
||||
filetype(#10000,"javascript")
|
||||
@@ -1288,6 +1288,15 @@ class LogOrExpr extends @logorexpr, BinaryExpr {
|
||||
override ControlFlowNode getFirstControlFlowNode() { result = this }
|
||||
}
|
||||
|
||||
/** A nullish coalescing '??' expression. */
|
||||
class NullishCoalescingExpr extends @nullishcoalescingexpr, BinaryExpr {
|
||||
override string getOperator() {
|
||||
result = "??"
|
||||
}
|
||||
|
||||
override ControlFlowNode getFirstControlFlowNode() { result = this }
|
||||
}
|
||||
|
||||
/**
|
||||
* A logical binary expression, that is, either a logical
|
||||
* 'or' or a logical 'and' expression.
|
||||
@@ -1295,7 +1304,8 @@ class LogOrExpr extends @logorexpr, BinaryExpr {
|
||||
class LogicalBinaryExpr extends BinaryExpr {
|
||||
LogicalBinaryExpr() {
|
||||
this instanceof LogAndExpr or
|
||||
this instanceof LogOrExpr
|
||||
this instanceof LogOrExpr or
|
||||
this instanceof NullishCoalescingExpr
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -338,6 +338,7 @@ case @expr.kind of
|
||||
| 104 = @decorator_list
|
||||
| 105 = @non_null_assertion
|
||||
| 106 = @bigintliteral
|
||||
| 107 = @nullishcoalescingexpr
|
||||
;
|
||||
|
||||
@varaccess = @proper_varaccess | @export_varaccess;
|
||||
@@ -357,7 +358,7 @@ case @expr.kind of
|
||||
|
||||
@comparison = @equalitytest | @ltexpr | @leexpr | @gtexpr | @geexpr;
|
||||
|
||||
@binaryexpr = @comparison | @lshiftexpr | @rshiftexpr | @urshiftexpr | @addexpr | @subexpr | @mulexpr | @divexpr | @modexpr | @expexpr | @bitorexpr | @xorexpr | @bitandexpr | @inexpr | @instanceofexpr | @logandexpr | @logorexpr;
|
||||
@binaryexpr = @comparison | @lshiftexpr | @rshiftexpr | @urshiftexpr | @addexpr | @subexpr | @mulexpr | @divexpr | @modexpr | @expexpr | @bitorexpr | @xorexpr | @bitandexpr | @inexpr | @instanceofexpr | @logandexpr | @logorexpr | @nullishcoalescingexpr;
|
||||
|
||||
@assignment = @assignexpr | @assignaddexpr | @assignsubexpr | @assignmulexpr | @assigndivexpr | @assignmodexpr | @assignexpexpr | @assignlshiftexpr | @assignrshiftexpr | @assignurshiftexpr | @assignorexpr | @assignxorexpr | @assignandexpr;
|
||||
|
||||
@@ -1081,4 +1082,4 @@ xmllocations(
|
||||
|
||||
isOptionalChaining(int id: @optionalchainable ref);
|
||||
|
||||
/* Last updated 2018/10/22. */
|
||||
/* Last updated 2018/10/23. */
|
||||
|
||||
@@ -1370,6 +1370,10 @@
|
||||
<v>100</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@nullishcoalescingexpr</k>
|
||||
<v>100</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@xmldtd</k>
|
||||
<v>1</v>
|
||||
</e>
|
||||
@@ -1397,6 +1401,10 @@
|
||||
<k>@optionalchainable</k>
|
||||
<v>100</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@nullishcoalescingexpr</k>
|
||||
<v>100</v>
|
||||
</e>
|
||||
</typesizes>
|
||||
<stats>
|
||||
<relation>
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
| tst.js:4:5:4:12 | y | tst.js:12:6:12:6 | y |
|
||||
| tst.js:4:5:4:12 | y | tst.js:13:5:13:5 | y |
|
||||
| tst.js:4:5:4:12 | y | tst.js:14:9:14:9 | y |
|
||||
| tst.js:4:5:4:12 | y | tst.js:105:6:105:6 | y |
|
||||
| tst.js:4:9:4:12 | "hi" | tst.js:4:5:4:12 | y |
|
||||
| tst.js:9:2:9:2 | x | tst.js:9:1:9:3 | (x) |
|
||||
| tst.js:10:4:10:4 | y | tst.js:10:1:10:4 | x, y |
|
||||
@@ -59,6 +60,7 @@
|
||||
| tst.js:25:1:25:3 | x | tst.js:32:1:32:0 | x |
|
||||
| tst.js:25:1:25:3 | x | tst.js:57:7:57:7 | x |
|
||||
| tst.js:25:1:25:3 | x | tst.js:58:11:58:11 | x |
|
||||
| tst.js:25:1:25:3 | x | tst.js:105:1:105:1 | x |
|
||||
| tst.js:28:2:28:1 | x | tst.js:29:3:29:3 | x |
|
||||
| tst.js:28:2:29:3 | () =>\\n x | tst.js:28:1:30:1 | (() =>\\n ... ables\\n) |
|
||||
| tst.js:29:3:29:3 | x | tst.js:28:1:30:3 | (() =>\\n ... les\\n)() |
|
||||
@@ -117,6 +119,8 @@
|
||||
| tst.js:101:13:101:16 | rest | tst.js:101:3:101:16 | [ , z ] = rest |
|
||||
| tst.js:102:10:102:18 | x + y + z | tst.js:98:1:103:17 | (functi ... 3, 0 ]) |
|
||||
| tst.js:103:4:103:16 | [ 19, 23, 0 ] | tst.js:98:11:98:24 | [ x, ...rest ] |
|
||||
| tst.js:105:1:105:1 | x | tst.js:105:1:105:6 | x ?? y |
|
||||
| tst.js:105:6:105:6 | y | tst.js:105:1:105:6 | x ?? y |
|
||||
| tst.ts:1:1:1:1 | A | tst.ts:1:11:1:11 | A |
|
||||
| tst.ts:1:1:1:1 | A | tst.ts:7:1:7:0 | A |
|
||||
| tst.ts:1:1:5:1 | A | tst.ts:7:1:7:0 | A |
|
||||
|
||||
@@ -102,4 +102,5 @@ var vs2 = ( for (v of o) v ); // generator comprehensions are not analysed
|
||||
return x + y + z;
|
||||
})([ 19, 23, 0 ]);
|
||||
|
||||
x ?? y; // flow through short-circuiting operator
|
||||
// semmle-extractor-options: --experimental
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
| v1 | file://:0:0:0:0 | true |
|
||||
| v2 | file://:0:0:0:0 | false |
|
||||
| v2 | file://:0:0:0:0 | undefined |
|
||||
| v4 | file://:0:0:0:0 | false |
|
||||
| v4 | file://:0:0:0:0 | true |
|
||||
| v4 | file://:0:0:0:0 | undefined |
|
||||
| v5 | file://:0:0:0:0 | false |
|
||||
| v5 | file://:0:0:0:0 | true |
|
||||
| v5 | file://:0:0:0:0 | undefined |
|
||||
| v6 | file://:0:0:0:0 | false |
|
||||
| v6 | file://:0:0:0:0 | true |
|
||||
| v6 | file://:0:0:0:0 | undefined |
|
||||
| v7 | file://:0:0:0:0 | false |
|
||||
| v7 | file://:0:0:0:0 | true |
|
||||
| v7 | file://:0:0:0:0 | undefined |
|
||||
| v7 | tst.js:22:15:22:16 | object literal |
|
||||
| x | file://:0:0:0:0 | false |
|
||||
| x | file://:0:0:0:0 | true |
|
||||
| x | file://:0:0:0:0 | undefined |
|
||||
@@ -0,0 +1,5 @@
|
||||
import javascript
|
||||
|
||||
from Variable v, Expr e
|
||||
where e = v.getAnAssignedExpr()
|
||||
select v, e.analyze().getAValue()
|
||||
@@ -0,0 +1,24 @@
|
||||
(function() {
|
||||
var x = f()? undefined: f()? false: true;
|
||||
|
||||
if (x || false) {
|
||||
v1 = x;
|
||||
} else {
|
||||
v2 = x;
|
||||
}
|
||||
|
||||
if (x && false) {
|
||||
v3 = x;
|
||||
} else {
|
||||
v4 = x;
|
||||
}
|
||||
|
||||
if (x ?? false) {
|
||||
v5 = x;
|
||||
} else {
|
||||
v6 = x;
|
||||
}
|
||||
|
||||
v7 = x ?? {};
|
||||
});
|
||||
// semmle-extractor-options: --experimental
|
||||
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: 'introduce @nullishcoalescingexpr'
|
||||
compatibility: backwards
|
||||
Reference in New Issue
Block a user