Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strict mode: fail on unused imports [PR] #4377

Merged
merged 2 commits into from Mar 11, 2022

Conversation

damienjburks
Copy link
Contributor

@damienjburks damienjburks commented Feb 23, 2022

Fixes #4354

Copy link
Contributor

@srenatus srenatus left a comment

Choose a reason for hiding this comment

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

😃 Thanks for picking this up! Welcome to compiler land 🎉

This is definitely going in a good direction. I've added a few comments inline, please let me know if you'd like me to add more detail to them.

ast/compile.go Show resolved Hide resolved
ast/compile.go Outdated
Comment on lines 1370 to 1369
if strings.Contains(r1.Body.String(), imp.String()[6:]) || strings.Contains(r1.Body.String(), name.String()) {
processedImports[name.String()] = imp.String()
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Oh that's an interesting approach. Took me a moment to understand 😃

I think we'd be better off using one of the Walk* methods here (ast.WalkTerms or ast.WalkExprs or whatever fits); because right now, this check is prone to false positives:

package p

import data.foo.bar as bar

r {
  input.bar == 2
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm making those requested changes, but I have a question for you. When you say it's a false positive, for this case, that means that we should be checking for if it is an exact match or the postfix of the variable is equivalent to the input?

For example,

input.bar == 2 -> OK
hello.bar == 2 -> OK
hello.wut == 2 -> import data.foo.bar as bar unused.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry if false positive was a the wrong word -- I mean that when the compiler runs this stage, it should be clear if we're using the import, unambiguously. So, neither input.bar nor hello.bar should not make the compiler think that import data.foo.bar as bar (or a plain import data.foo.bar) was used.

I often find myself adding log.Printf("%s: %v", s.name, c.Modules) to this function to figure out what the compiler does in rewriting. With a module like the example, we'll find

2022/02/28 08:25:43 CheckDuplicateImports: map[p.rego:package p

import data.foo.bar as bar

r = true { equal(input.bar, 2) }]
2022/02/28 08:25:43 CheckKeywordOverrides: map[p.rego:package p

import data.foo.bar as bar

r = true { equal(input.bar, 2) }]
2022/02/28 08:25:43 ResolveRefs: map[p.rego:package p

r = true { equal(input.bar, 2) }]

So ResolveRefs has removed the import, and didn't otherwise change the module.

With a positive example,

package p

import data.foo.bar

r {
  input.bar == bar
}

we get this:

2022/02/28 08:27:29 CheckDuplicateImports: map[q.rego:package p

import data.foo.bar

r = true { equal(input.bar, bar) }]
2022/02/28 08:27:29 CheckKeywordOverrides: map[q.rego:package p

import data.foo.bar

r = true { equal(input.bar, bar) }]
2022/02/28 08:27:29 ResolveRefs: map[q.rego:package p

r = true { equal(input.bar, data.foo.bar) }]

So we should be able to find unused imports by

  • for all imports
    • take the ref of the import (qualified name won't matter because it's been rewritten already)
    • check if the ref is used in the body
    • fail if it isn't

This is merely a sketch, and there may be better ways to approach finding unused imports here.

Concretely, I think what I've outlined would fail with this example:

package p
import data.foo # unused
r { data.foo == 10 }

because at the stage we'd check for used imports, the import would already have been removed, but it didn't actually resolve any ref.

This makes me think that perhaps finding unused imports should be a stage that closely mirrors what ResolveRefs does, instead of running after ResolveRefs. What do you think?

(Btw these would all make decent test cases when you get to adding a few test cases. Personally, I prefer to start with them, because it gives me some assurance when expanding the functionality that previous wins aren't lost again 😅)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For sure. I understand your concept. I uploaded some new code that is passing all of the test cases I could come up with. Please check it out and let me know what you think.

@anderseknert
Copy link
Member

I'll leave the review in @srenatus capable hands, but just one thing I noticed - could you change "Addresses" to "Fixes" in the commit message? That'll make the script that builds the release notes pick it up automatically later :)

Copy link
Contributor

@srenatus srenatus left a comment

Choose a reason for hiding this comment

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

Thanks for working on this! This is a good step into the right direction, please see my inline comments. 😃

ast/compile.go Outdated Show resolved Hide resolved
@srenatus
Copy link
Contributor

srenatus commented Mar 1, 2022

If you get around to it, adding a row to the strict-mode docs would be great, too: https://github.com/open-policy-agent/opa/blob/main/docs/content/strict.md#strict-mode-constraints-and-checks

@damienjburks
Copy link
Contributor Author

damienjburks commented Mar 8, 2022

@srenatus I've added those changes to the documentation. Please check when you have time. Everything seems to be working now.

@anderseknert
Copy link
Member

@damienjburks awesome work on this!

Could you please rebase from the latest main, and fix the merge conflict that seems to be there?

@damienjburks damienjburks force-pushed the issue-4354 branch 2 times, most recently from 651fd17 to 32d75ba Compare March 9, 2022 03:25
@damienjburks
Copy link
Contributor Author

@anderseknert rebased and fixed issues with broken test cases. Please review and let me know if there are any more changes I should make.

@anderseknert
Copy link
Member

Thanks Damien!

It still looks like there's some changes in your PR that shouldn't be there (i.e. the change to philosophy.md). From your checked out fork, something like this should do the trick:

git checkout main
git remote add upstream https://github.com/open-policy-agent/opa.git
git pull upstream main
git checkout issue-4354
git rebase main
git push --force

author Itay Shakury <itay@itaysk.com> 1646501263 +0200
committer Damien Burks <damien@damienjburks.com> 1646794189 -0600

docs: add missing title to annotations index (open-policy-agent#4406)

Signed-off-by: Itay Shakury <itay@itaysk.com>

Update philosophy.md (open-policy-agent#4412)

I am suggesting this change to fix grammatical errors which will increase readability for consumers of the OPA Philosophy document.

---

1. I noticed there is a missing word ("be") in the OPA Document Model section, just above the table that summarizes the different models for loading base documents into OPA. This change adds the omitted word.

2. I've also made a change to the first note at the bottom of the page ([1]). "However" is used as a conjunctive adverb, I've updated the sentence's punctuation to reflect this.

3. Lastly, I've made a punctuation change to note number three at the bottom of the page ([3])  to increase readability.

Signed-off-by: Arthur Jones <arthur.h.jones3@gmail.com>

Co-authored-by: Stephan Renatus <stephan.renatus@gmail.com>

docs: mention who created OPA and who owns it (open-policy-agent#4414)

These are two common questions that come up and we do not mention this
anywhere else in the docs.

Signed-off-by: Torin Sandall <torinsandall@gmail.com>

committing latest changes

Signed-off-by: Damien Burks <damien@damienjburks.com>

committing latest changes to unsued imports function

Signed-off-by: Damien Burks <damien@damienjburks.com>

removing print statements and adding more test cases

Signed-off-by: Damien Burks <damien@damienjburks.com>

server: exposing disableInlining option via Compile API (open-policy-agent#4378)

This change enables consumers of Compile API to specify packages
those should not be inlined in partial evaluation response.

Fixes: open-policy-agent#4357

Signed-off-by: skosunda <skosunda@adobe.com>

docs: Update Envoy primer to use variables instead of objects

Previously, the Envoy primer provided samples of policies for
status-code, body, and headers that explicitly returned an object
in individual rules instead of the more common and recommended
approach of using separate variables for each concern.

This change replaces those sample policies with ones that use
variables for each of allow, status_code, headers, body,
and it adds a section on the output expected by Envoy,
where we include the snippet combining those variables into
the JSON object expected by Envoy.

Signed-off-by: Tim Hinrichs <tim@styra.com>

make: Disable WASM by default on darwin/arm64 (open-policy-agent#4382)

Signed-off-by: Anders Eknert <anders@eknert.com>

docs: Update Istio tutorial to expose application to outside traffic (open-policy-agent#4384)

Signed-off-by: Ashutosh Narkar <anarkar4387@gmail.com>

fixing linting issues

Signed-off-by: Damien Burks <damien@damienjburks.com>

committing latest changes for PR

Signed-off-by: Damien Burks <damien@damienjburks.com>

adding info to strict.md

adding switch statement for 'in' operator

adding additional case to if statement

finalizing changes for broken test cases

Signed-off-by: Damien Burks <damien@damienjburks.com>
@damienjburks
Copy link
Contributor Author

@anderseknert just made those changes and pushed the latest code. Thanks for the guidance.

@srenatus
Copy link
Contributor

I'll merge this, I've got some touch-ups that I'll open a PR for in a bit. Thanks again for picking this up and contributing @damienjburks 👏 🎉

@srenatus srenatus merged commit 785f742 into open-policy-agent:main Mar 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Strict mode: fail on unused imports
4 participants