Git Product home page Git Product logo

rust-analyzer's Introduction

rust-analyzer

Not to be confused with the rust-analyzer of the Rust project!

rust-analyzer is a static analysis utility that is used for the automatic mentoring of exercise solutions of Exercism's Rust track. Please find general documentation about Exercism's language analyzers here.

Supported exercises

Usage

The utility can be used on the local machine. It accepts two required parameters:

  • --path (-p) - path to the solution directory.
  • --slug (-s) - the slug of the exercise that is being analyzed.

For example:

rust-analyzer -p ~/solution-238382y7sds7fsadfasj23j/ -s reverse-string

In the context of the automatic mentoring the utility is invoked inside the Docker container via the bin/analyze.sh script.

Building

Using Cargo

You should have the latest stable version of Rust installed on you machine. Then from the project root run:

cargo build

To run the utility using Cargo execute the following command:

cargo run -- -s exercise_slug -p /path/to/the/solution/directory

To run tests use the following command:

cargo test

Using Docker

Simply run the following script to run the tests in docker:

./bin/run-tests-in-docker.sh

rust-analyzer's People

Contributors

efx avatar erikschierboom avatar exercism-bot avatar gilescope avatar harrisonmc555 avatar ihid avatar kytrinyx avatar petertseng avatar senekor avatar zapanton avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

rust-analyzer's Issues

reverse-string: lints do not check for conditional compilation

As an example, my solution resulted in the comment "Consider expanding the solution to pass the feature-gated test_grapheme_clusters test case..."

#[cfg(feature = "grapheme")]
use unicode_segmentation::UnicodeSegmentation;

#[cfg(not(feature = "grapheme"))]
pub fn reverse(input: &str) -> String {
    input.chars().rev().collect()
}

#[cfg(feature = "grapheme")]
pub fn reverse(input: &str) -> String {
    input.graphemes(true).rev().collect()
}

I assume the #[cfg()] blocks are tripping it up. I'm afraid I don't have a suggestion for fixing this but I'm sure it's an interesting challenge for someone to tackle at some point :)

reverse-string: Refactor the lints.rs module

The current implementation of the lint functions in the lints.rs module consists of a great number of the deeply nested if let statements with the intermediate logic inside the condition blocks.

Some block could not be avoided, since the dyn keyword inside the pattern matches is not stable yet, but even without it there is a lot of repetitive and hard to maintain code, which potentially can migrate to the other exercise analyzers.

So it would be great to see if the code could be somehow refactored for better readability/maintainability.

suggest: refactor analyzer for greater flexibility

The analyzer currently matches full ASTs:

if let Some(output) = PREPARED_SOLUTION_OUTPUTS
.iter()
.find(|prepared_output| {
syn::parse_str::<File>(prepared_output.solution).unwrap() == *solution_ast
})
.map(|prepared_output| prepared_output.output)
.cloned()
{
output
} else {
AnalysisOutput::new(AnalysisStatus::ReferToMentor, vec![])
},

This works, but is inflexible: it is currently impossible to suggest both implementing the bonus test and also removing use statements. We could refactor for greater flexibility by writing this more like a linter.

Detailed proposal:

  1. Add a static LINTS: Vec<dyn Fn(&File, &mut AnalysisOutput) -> Result<()>>

  2. Populate this list with functions which look for particular features of the input file. For example:

    • one might look for the presence of use statements, and add a suggestion that those aren't necessary in Rust 2018
    • one might look for the absence of use of the unicode_segmentation crate, and suggest that this would be an easy way to implement the bonus feature
    • one might compare the body of the reverse function (ignoring the variable name) with the ideal output, and approve if it is optimal

    These functions have the option to return an error, aborting the parse, but generally they should be OK.

  3. Refactor the main Analyze implementation such that by default, it has a basic "refer to mentor" output. Every lint in the LINTS list is run, possibly modifying the output. If any lint returns an Err, the break out of the lints iteration and return an appropriate error.

  4. Once every lint has run, simply return the fully-mutated AnalysisOutput.

  5. Remove most of the existing PreparedOutput stuff, which should no longer be needed or used.

I believe that this architecture would be sufficient to close #5.

Automated Analysis showing up blank (for Rust)

This is on a mentoring request, but I have also seen this when I am doing exercises myself.

image

The specific mentoring request is for gigasecond, and the code from the mentoring request is:

use time::PrimitiveDateTime as DateTime;
use time::Duration as Duration;

// Returns a DateTime one billion seconds after start.
pub fn after(start: DateTime) -> DateTime {
    start + Duration::seconds(1000000000)
}

Running this crate locally on that code gives:

{
  "status": "refer_to_mentor",
  "comments": [
    "The solution could not be parsed."
  ]
}

But I do not know if that is what the live site is giving.

Expand the 'reverse-string' analyzer

The current version of the reverse-string analyzer does a very primitive version of the analysis - read the solution AST and compare it with a bunch of prepared ASTs to give a approve_as_optimal or approve_with_comment status.

The prepared ASTs can be viewed in the reverse-string README.

The following work should be done:

  • Make the AST analysis more thorough
  • Expand the approve solution list
  • Make the analyzer return the disapprove status

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.