Skip to content

Python: modernise variables queries#2540

Merged
tausbn merged 17 commits intogithub:masterfrom
RasmusWL:python-modernise-variables-queries
Jan 10, 2020
Merged

Python: modernise variables queries#2540
tausbn merged 17 commits intogithub:masterfrom
RasmusWL:python-modernise-variables-queries

Conversation

@RasmusWL
Copy link
Copy Markdown
Member

Some of these changes would only fix 1 line, so I have bundled them all together.

Wanted to make a draft PR so tests can run to verify I didn't miss something 😉

@RasmusWL RasmusWL force-pushed the python-modernise-variables-queries branch from 0908e4e to 3908994 Compare December 19, 2019 11:56
@RasmusWL RasmusWL marked this pull request as ready for review December 19, 2019 11:56
@RasmusWL RasmusWL requested a review from a team as a code owner December 19, 2019 11:56
Copy link
Copy Markdown
Contributor

@tausbn tausbn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A large variety of comments, but otherwise looking good!

// Escapes if used out side of for loop or is a lambda in a comprehension
(
exists(Expr e, For forloop | forloop = loop and e.refersTo(_, _, capturing) | not forloop.contains(e))
exists(Expr e, For forloop | forloop = loop and e.pointsTo(_, _, capturing) | not forloop.contains(e))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if forloop = loop is a holdover from back when there was no syntax for casting. I think writing loop.(For).contains(e) and eliminating the For forloop part of the exists would be better.

exists(Object::builtin(l.getId()))
exists(Builtin::builtin(l.getId()))
) and
scope instanceof Function and
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we could simply change Scope to Function in the definition of the scope parameter?

Copy link
Copy Markdown
Member Author

@RasmusWL RasmusWL Dec 20, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm starting to wonder if the restriction of scope to Function makes sense?

Looking at the original code

predicate shadows(Name d, string name, Scope scope, int line) {
    exists(LocalVariable l | d.defines(l) and scope instanceof Function and
           l.getId() = name and
           exists(Object::builtin(l.getId()))
    ) and
    d.getScope() = scope and
    d.getLocation().getStartLine() = line and
    not white_list(name) and
    not optimizing_parameter(d)
}

it might simply have been an oversigt? What do you think? (that is, do we not care about shadowing a builting when you are making a global variable?)

Comment thread python/ql/src/Variables/ShadowGlobal.ql Outdated

predicate shadows(Name d, GlobalVariable g, Scope scope, int line) {
exists(LocalVariable l | d.defines(l) and l.getId() = g.getId() and
scope instanceof Function and g.getScope() = scope.getScope() and
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, scope instanceof Function can be moved to the scope parameter declaration, methinks.

Comment thread python/ql/src/Variables/ShadowGlobal.ql Outdated
d.defines(l) and
l.getId() = g.getId() and
scope instanceof Function and
g.getScope() = scope.getScope() and
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line and the two that follow should probably be moved outside the exists (since they don't relate to the bound variable l.)

f.refersTo(call) and
call.(CallNode).getFunction().refersTo(range)
f.pointsTo(call) and
call.getACall().getFunction().pointsTo(range)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems a bit overwrought. Would f = range.getACall() not suffice?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I found it very strange and just kept it as is. tests passes with f = range.getACall() so that's very good!

exists(Module m |
m = this.getSourceModule() |
not exists(Call modify, Attribute attr, GlobalVariable all |
modify.getScope() = m and modify.getFunc() = attr and
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just do modify.getScope() = this.getSourceModule() and then you don't need the existentially quantified variable m at all!

exists(ModuleValue imported |
imported.importedAs(imp.getImportedModuleName()) |
not imported.exportsComplete()
not imported.hasCompleteExportInfo()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can combine these two exists and push the disjunction inside. Also, wouldn't imported.isAbsent() imply not imported.hasCompleteExportInfo() anyway?

@RasmusWL
Copy link
Copy Markdown
Member Author

I realized there were quite a few files in Variables/ I didn't touch, but wanted to autoformat them as well. So I squashed the autoformat commits. I like this better 👍

Tests were failing since the ClassValue::nameError() didn't give any results -- I had used Builtin::special("NameError") instead of the correct Builtin::builtin("NameError").

I have not forgotten about all your suggestions, will fix them 👍

@RasmusWL RasmusWL force-pushed the python-modernise-variables-queries branch from 3908994 to b8a9a35 Compare December 20, 2019 14:11
Original code:

exists(Expr e, For forloop | forloop = loop and e.pointsTo(_, _, capturing) |
    not loop.contains(e)
)

The new version will preserve the same semantics. The problem with the first
rewrite was that `not loop.(For).somethingMore` would hold for any AstNode that
was not a For
@RasmusWL RasmusWL requested a review from tausbn January 10, 2020 13:01
@tausbn tausbn merged commit cfb84be into github:master Jan 10, 2020
@RasmusWL RasmusWL deleted the python-modernise-variables-queries branch January 10, 2020 14:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants