Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions change-notes/1.19/analysis-javascript.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
| User-controlled bypass of security check | Fewer results | This rule no longer flags conditions that guard early returns. The precision of this rule has been revised to "medium". Results are no longer shown on LGTM by default. |
| Whitespace contradicts operator precedence | Fewer false-positive results | This rule no longer flags operators with asymmetric whitespace. |
| Unused import | Fewer false-positive results | This rule no longer flags imports used by the `transform-react-jsx` Babel plugin. |
| Self assignment | Fewer false-positive results | This rule now ignores self-assignments preceded by a JSDoc comment with a `@type` tag. |

## Changes to QL libraries

Expand Down
9 changes: 8 additions & 1 deletion javascript/ql/src/Expressions/Clones.qll
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,14 @@ class SelfAssignment extends StructurallyCompared {
}

override Expr candidate() {
result = getParent().(AssignExpr).getRhs()
result = getAssignment().getRhs()
}

/**
* Gets the enclosing assignment.
*/
AssignExpr getAssignment() {
result.getLhs() = this
}
}

Expand Down
5 changes: 5 additions & 0 deletions javascript/ql/src/Expressions/SelfAssignment.qhelp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ Assigning a variable to itself typically indicates a mistake such as a missing
Carefully inspect the assignment to check for misspellings or missing qualifiers.
</p>

<p>
If the self-assignment is intentional and is needed for documentation or optimization purposes,
add a JSDoc comment with a <tt>@type</tt> tag. This will indicate the self-assignment is intentional.
</p>

</recommendation>
<example>

Expand Down
6 changes: 4 additions & 2 deletions javascript/ql/src/Expressions/SelfAssignment.ql
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,7 @@ where e.same(_) and
propName = any(AccessorMethodDeclaration amd).getName()
) and
// exclude DOM properties
not isDOMProperty(e.(PropAccess).getPropertyName())
select e.getParent(), "This expression assigns " + dsc + " to itself."
not isDOMProperty(e.(PropAccess).getPropertyName()) and
// exclude self-assignments that have been inserted to satisfy the TypeScript JS-checker
not e.getAssignment().getParent().(ExprStmt).getDocumentation().getATag().getTitle() = "type"
select e.getParent(), "This expression assigns " + dsc + " to itself."
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
| jsdoc.js:9:5:9:19 | this.y = this.y | This expression assigns property y to itself. |
| jsdoc.js:11:5:11:23 | this.arg = this.arg | This expression assigns property arg to itself. |
| tst.js:5:2:5:14 | width = width | This expression assigns variable width to itself. |
| tst.js:24:1:24:19 | array[1] = array[1] | This expression assigns element 1 to itself. |
| tst.js:27:1:27:9 | o.x = o.x | This expression assigns property x to itself. |
15 changes: 15 additions & 0 deletions javascript/ql/test/query-tests/Expressions/SelfAssignment/jsdoc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class C extends Q {
constructor(arg) {
/**
* Something.
* @type {string | undefined}
*/
this.x = this.x; // OK - documentation

this.y = this.y; // NOT OK

this.arg = this.arg; // NOT OK
}
}

// semmle-extractor-options: --experimental