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

External lint api #1

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

External lint api #1

wants to merge 2 commits into from

Conversation

HKalbasi
Copy link
Owner

cc @xFrednet

This is just a proof of concept and many things are done poorly.

Actually running it requires a clone of rust_linting repo as a sibling directory of this repo.

@HKalbasi HKalbasi closed this Sep 10, 2022
@HKalbasi HKalbasi reopened this Sep 10, 2022
@xFrednet
Copy link

It seems like the needed code is actually quite reasonable. I'll have a closer look over the week or the latest on the weekend. Thank you for putting this together ❤️

Have you already noticed some parts of the API design which doesn't work too well for RA?

I saw some allocations, which are never cleaned up. I thought about limiting the lifetime of expressions and nodes to not be the full 'ast 🤔

Copy link
Owner Author

@HKalbasi HKalbasi left a comment

Choose a reason for hiding this comment

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

Have you already noticed some parts of the API design which doesn't work too well for RA?

It was better than what I expected. I added some comments on code about things that can be better.

I saw some allocations, which are never cleaned up. I thought about limiting the lifetime of expressions and nodes to not be the full 'ast thinking

I think it is just a bumpalo away, and no change is needed in linter_api.

node: &SourceFile,
config: &DiagnosticsConfig,
) {
std::env::set_var("LINTER_LINT_CRATES", &config.external_lints);
Copy link
Owner Author

Choose a reason for hiding this comment

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

Here I should add an env variable manually, which is not very ideal. I think an api which get string directly in addition to new_from_env helps.

Choose a reason for hiding this comment

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

Agreed, I only added one interface, while figuring out how lint crates should be loaded. After an evaluation and the conclusion that dynamic libraries will be the way, at least for the start. It's safe to add such a function. A PR which adds that would be highly appreciated, but an issue would also already be helpful 🙃

struct A { a: &'static str }

mod foo {
static X: u32 = 5;
Copy link
Owner Author

Choose a reason for hiding this comment

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

This one is not linted, which I think is because process_krate doesn't check nested items.

Choose a reason for hiding this comment

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

Interesting, I believe that modules are not fully visited. In general, there are many items missing. Thank you for the report


impl<'ast> DriverContext<'ast> for RADriver<'ast> {
fn emit_lint(
&self,
Copy link
Owner Author

Choose a reason for hiding this comment

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

Is it intentionally &self? By changing it to &mut self I can drop those RefCell fields in RADriver.

Choose a reason for hiding this comment

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

Good question, this is mostly the result of evolving source code. Just using &self was also inspired by rustc way to implement these traits.

The main question here is how concurrency should be handled. By only using &self the adapter passes responsibility to the driver. The driver could potentially check multiple crates at once. On the other hand, we could just use RefCell in the adapter itself 🤔

crate_id: CrateId,
) -> Option<ItemType<'ast>> {
let cx = &driver.ast_context.get().unwrap();
let item_id = ItemId::new(crate_id, driver.id_map.borrow().len() as u32);
Copy link
Owner Author

Choose a reason for hiding this comment

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

At ast level r-a doesn't have id for items, so I made it in this way. Is it possible / better to use &'ast Item instead of ItemId?

Choose a reason for hiding this comment

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

What does ra use to identify items then?

I changed the ItemId to just be a u64 which can be used by the driver however they want. In theory, a pointer address can also be stored in it. The problem with this solution, is that it requires the item to already be created, which goes a bit against lazy evaluation, which was also wished for if I'm correct.

@xFrednet
Copy link

Have you already noticed some parts of the API design which doesn't work too well for RA?

It was better than what I expected. I added some comments on code about things that can be better.

Awesome, this has already helped me a lot!

I saw some allocations, which are never cleaned up. I thought about limiting the lifetime of expressions and nodes to not be the full 'ast thinking

I think it is just a bumpalo away, and no change is needed in linter_api.

When will we then clear the memory, though 🤔. The current setup basically expects that any object with the 'ast lifetime, will be available, until a lint crate is unloaded. However, this guarantee will leak memory for RA. That's actually a good insight 🙃

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.

None yet

2 participants