{"id":50872175,"url":"https://github.com/epfl-systemf/lorikeet","last_synced_at":"2026-06-15T06:06:10.750Z","repository":{"id":358496498,"uuid":"1165736580","full_name":"epfl-systemf/lorikeet","owner":"epfl-systemf","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-17T16:16:04.000Z","size":238,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-17T18:38:46.060Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/epfl-systemf.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-24T13:45:19.000Z","updated_at":"2026-05-17T16:16:08.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/epfl-systemf/lorikeet","commit_stats":null,"previous_names":["epfl-systemf/lorikeet"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/epfl-systemf/lorikeet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epfl-systemf%2Florikeet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epfl-systemf%2Florikeet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epfl-systemf%2Florikeet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epfl-systemf%2Florikeet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/epfl-systemf","download_url":"https://codeload.github.com/epfl-systemf/lorikeet/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epfl-systemf%2Florikeet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34349972,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-15T02:00:07.085Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-15T06:06:08.951Z","updated_at":"2026-06-15T06:06:10.743Z","avatar_url":"https://github.com/epfl-systemf.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Lorikeet\n\nLorikeet is a Scalafix-based code quality feedback tool that lets you define custom rules using  query patterns and rewrite templates. It can be used for automated grading and feedback on student assignments, as well as a dev tool to simplify writing custom Scalafix rules.\n\nWriting rules requires no knowledge of Scala's AST or the Scalafix API, and allows you to express complex patterns and rewrites with a simple and intuitive syntax.\n\nThe included script [Check.scala](scripts/Check.scala) allows easily running a set of custom rules on a large number of student submissions, and provides detailed feedback and statistics on the results.\n\n## ️Supported Scala Versions\n\nLorikeet is designed to  work for Scala 3 codebases and rules, but it also supports Scala 2.13 on a best-effort basis.\n\nQuery patterns and rewrite templates are currently parsed as Scala 3 in priority, with Scala 2.13 as a fallback if parsing fails. The rules can be run on both Scala 3 and Scala 2.13 codebases, regardless of the version they are parsed with.\n\nNote that possible differences in AST structure may cause matching issues, and query patterns or rewrite templates that use syntax that is specific to Scala 3 will not be applicable to Scala 2.13 codebases.\n\n## Development\n\n### Run Tests\n\n```bash\nsbt \"tests / test\"\n```\n\n### Publish Locally\n\n```bash\nsbt \"lorikeet / publishLocal\"\n```\n\n## Usage\n\nThis section describes how to use Lorikeet:\n\n- To use it in your own project, see the [Using the MetaRule](#using-the-metarule) section below.\n- To grade student submissions, see the [Running a Check on Student Submissions](#running-a-check-on-student-submissions) section below.\n\nFor more details on how to write custom rules and the syntax of query patterns and rewrite templates, see the [Guide](GUIDE.md).\n\n### Using the MetaRule\n\n1. Publish the rule locally using the command above, or use the published version if available.\n2. Add sbt-scalafix and sbt-scalafmt to your `project/plugins.sbt` file:\n\n```scala\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalafix\" % \"0.14.4\")\naddSbtPlugin(\"org.scalameta\" % \"sbt-scalafmt\" % \"2.5.6\")\n```\n\n3. Add the rule as a dependency and semanticdb support to your `build.sbt` file:\n\n```scala\nsemanticdbEnabled := true\nsemanticdbVersion := scalafixSemanticdb.revision\n\nscalafixDependencies += \"ch.epfl.systemf\" % \"lorikeet_3\" % \"0.1.0-SNAPSHOT\"\n```\n\n4. Create a `.lorikeet.conf` file in the root of your project with your custom rule configuration (see the [Guide](GUIDE.md) for syntax and examples).\n\n5. Run Scalafix on your project, specifying the rule name:\n\n```bash\nsbt \"scalafix MetaRule\"\n```\n\n6. Optionally, if you need to test and modify your rules, disable scalafix caching in your `build.sbt` file:\n\n```scala\nscalafixCaching := false\n```\n\nThis is because sbt task caching will avoid rerunning a task that has already been run with the same arguments and scala input files, but changes to the custom rules configuration file `.lorikeet.conf` are not considered and would not trigger a re-run of scalafix.\n\n### Running a Check on Student Submissions\n\nSee script [Check.scala](scripts/Check.scala).\n\nThis script expects a submission directory with the following structure:\n\n```tree\nsubmission/\n├── SCIPER\n│   └── 0\n│       └── assignment.scala\n|   └── 1\n│       └── assignment.scala\n|   └── ...\n├── SCIPER\n│   └── 0\n│       └── assignment.scala\n|   └── ...\n└── ...\n```\n\nThe script also expects a `scaffold` directory containing the lab sbt project that has been\nconfigured to use the custom rules, as described above.\n\nTo use the `Check.scala` script, you also need to provide a `.scalafmt.conf` file in the root of your scaffold project. Scalafmt will be run before and after applying the rewrites to ensure proper formatting. A minimal configuration could be:\n\n```hocon\nversion = 3.9.9\nrunner.dialect = scala3\n```\n\nThe script will replace the `assignment.scala` file in the scaffold project with the ones from the submission, then compile and run scalafix check on it, collecting the results in a logs file.\n\nNote that submissions that do not compile will be reported as such but will not be checked with scalafix. This means it may be a good idea to remove `-Xfatal-warnings` or other such flags\nfrom the scaffold project.\n\nThe script output will be individual diffs for each submissions, as well as individual feedback (which rules matches, with their descriptions and where specifically in the code), and a summary at the end with statistics on how many submissions passed each rule.\n\nThe console output looks something like this:\n\n```text\nDiffs directory: ~evaluating/grading_diffs_2026.01.01_14.26.00\nLint reports directory: ~/evaluating/grading_reports_2026.01.01_14.26.00\n\nStarting grading process...\n\n-\u003e ⚠️  ISSUES:  359355 / 0 -\u003e Var Usage (1), If Simplification (12)\n-\u003e ⚠️  ISSUES:  361678 / 0 -\u003e If Simplification (12)\n-\u003e ⚠️  ISSUES:  356669 / 0 -\u003e Var Usage (5)\n-\u003e ⚠️  ISSUES:  380092 / 0 -\u003e If Simplification (5)\n-\u003e ✅ SUCCESS: 377073 / 0\n-\u003e ⚠️  ISSUES:  378842 / 2 -\u003e Var Usage (4), If Simplification (2)\n-\u003e ⚠️  ISSUES:  372197 / 0 -\u003e Var Usage (3), If Simplification (4)\n-\u003e ⚠️  ISSUES:  344921 / 0 -\u003e If Simplification (5)\n-\u003e ⚠️  ISSUES:  363557 / 0 -\u003e Var Usage (12)\n.....\n\n--- SUMMARY ---\nTotal submissions: 421\nSubmissions with missing file: 0\nSubmissions with compile errors: 1\nSubmissions failing check: 378\n\n--- STATISTICS ---\nSubmissions with Matches:\n  If Simplification: 267\n  Var Usage: 135\nTotal Rule Matches:\n  If Simplification: 2609\n  Var Usage: 752\n\nGrading complete.\n```\n\nSee the configuration options at the top of the script.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fepfl-systemf%2Florikeet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fepfl-systemf%2Florikeet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fepfl-systemf%2Florikeet/lists"}