Skip to content

Commit

Permalink
switch from tree-sitter to regex
Browse files Browse the repository at this point in the history
  • Loading branch information
BrianHicks committed Nov 19, 2020
1 parent 6990b59 commit cee73f0
Show file tree
Hide file tree
Showing 65 changed files with 48 additions and 56,986 deletions.
34 changes: 2 additions & 32 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Expand Up @@ -11,12 +11,12 @@ anyhow = "1.0"
clap = "3.0.0-beta.2"
crossbeam = "0.8"
ignore = "0.4"
lazy_static = "1.4"
pathdiff = "0.1"
regex = "1.0"
serde = {version = "1.0", features = ["derive"]}
serde_json = "1.0"
thiserror = "1.0"
toml = "0.5"
tree-sitter = "0.17"

[build-dependencies]
cc = "*"
21 changes: 0 additions & 21 deletions build.rs

This file was deleted.

5 changes: 1 addition & 4 deletions default.nix
Expand Up @@ -3,8 +3,5 @@
let
naersk = pkgs.callPackage sources.naersk { };
gitignore = import sources.gitignore { };
in naersk.buildPackage {
src = gitignore.gitignoreSource ./.;
buildInputs = if pkgs.stdenv.isDarwin then [ pkgs.xcbuild ] else [ ];
}
in naersk.buildPackage (gitignore.gitignoreSource ./.)

1 change: 0 additions & 1 deletion script/update-subtrees.sh
@@ -1,5 +1,4 @@
#!/usr/bin/env bash
set -euo pipefail

git subtree pull --squash --prefix vendor/tree-sitter-elm https://github.com/Razzeee/tree-sitter-elm master
git subtree pull --squash --prefix vendor/elm-spa-example https://github.com/rtfeldman/elm-spa-example master
107 changes: 38 additions & 69 deletions src/importfinder.rs
@@ -1,11 +1,11 @@
use anyhow::{anyhow, bail, Context, Result};
use anyhow::{bail, Context, Result};
use crossbeam::channel;
use lazy_static::lazy_static;
use regex::Regex;
use serde::Serialize;
use std::collections::{BTreeMap, BTreeSet};
use std::fs;
use std::path::PathBuf;
use thiserror::Error;

static IMPORT_QUERY: &str = "(import_clause (import) (upper_case_qid)@import)";

pub struct ImportFinder {
roots: BTreeSet<PathBuf>,
Expand Down Expand Up @@ -38,10 +38,6 @@ impl ImportFinder {
.context("could not build extensions to scan for")?;
builder.types(types);

let query = tree_sitter::Query::new(get_language(), IMPORT_QUERY)
.map_err(TreeSitterError::QueryError)
.context("could not instantiate the import query")?;

let mut out: BTreeMap<String, BTreeSet<FoundImport>> = BTreeMap::new();

let (parent_results_sender, results_receiver) = channel::unbounded();
Expand All @@ -51,10 +47,6 @@ impl ImportFinder {
let results_sender = parent_results_sender.clone();
let error_sender = parent_error_sender.clone();

let mut parser = get_parser().unwrap();

let query = &query;

Box::new(move |maybe_dir_entry| {
let dir_entry = match maybe_dir_entry.context("could not read an entry from a root")
{
Expand All @@ -71,7 +63,18 @@ impl ImportFinder {
return ignore::WalkState::Continue;
}

let source = match fs::read(dir_entry.path()).context("could not read an Elm file")
let source_bytes =
match fs::read(dir_entry.path()).context("could not read an Elm file") {
Ok(s) => s,
Err(err) => {
#[allow(unused_must_use)]
let _ = error_sender.send(err);
return ignore::WalkState::Quit;
}
};

let source = match std::str::from_utf8(&source_bytes)
.context("could not read the source as utf8")
{
Ok(s) => s,
Err(err) => {
Expand All @@ -81,42 +84,31 @@ impl ImportFinder {
}
};

let parsed = match parser.parse(&source, None) {
Some(p) => p,
None => {
#[allow(unused_must_use)]
let _ = error_sender
.send(anyhow!("could not parse {:}", dir_entry.path().display()));
return ignore::WalkState::Quit;
}
};

let mut cursor = tree_sitter::QueryCursor::new();
lazy_static! {
// TODO: maybe faster to use `([^ ]+)` for the match
static ref IMPORT_RE: Regex = Regex::new(r"^import +([A-Z][A-Za-z0-9_\.]*)").unwrap();
}

for match_ in cursor.matches(&query, parsed.root_node(), |_| []) {
for capture in match_.captures {
let import = match capture
.node
.utf8_text(&source)
.context("could not convert a match to a source string")
{
Ok(i) => i,
#[allow(unused_must_use)]
Err(err) => {
error_sender.send(err);
return ignore::WalkState::Quit;
}
};
// perf idea; keep track of if we've finished the import list and
// bail on any further lines once we get there. Since imports
// are forbidden after the block at the top of the module, we
// shouldn't miss anything by skipping the rest of the lines
// in each file!

for (line_number, line) in source.lines().enumerate() {
if let Some(import_module) = IMPORT_RE.captures(line).and_then(|m| m.get(1)) {
if let Err(err) = results_sender.send(FoundImport {
import: import.to_string(),
path: dir_entry.path().to_path_buf(),
position: capture.node.start_position(),
import: import_module.as_str().to_string(),
position: Position {
row: line_number + 1,
column: import_module.start(),
},
}) {
#[allow(unused_must_use)]
let _ = error_sender.send(err.into());
return ignore::WalkState::Quit;
};
}
}
}

Expand Down Expand Up @@ -157,34 +149,11 @@ impl ImportFinder {
pub struct FoundImport {
pub import: String,
pub path: PathBuf,
pub position: tree_sitter::Point,
}

// tree sitter

extern "C" {
fn tree_sitter_elm() -> tree_sitter::Language;
}

fn get_language() -> tree_sitter::Language {
unsafe { tree_sitter_elm() }
}

fn get_parser() -> Result<tree_sitter::Parser, TreeSitterError> {
let mut parser = tree_sitter::Parser::new();

parser
.set_language(get_language())
.map_err(TreeSitterError::LanguageError)?;

Ok(parser)
pub position: Position,
}

#[derive(Debug, Error)]
enum TreeSitterError {
#[error("language error: {0}")]
LanguageError(tree_sitter::LanguageError),

#[error("query error: {0:?}")]
QueryError(tree_sitter::QueryError),
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize)]
pub struct Position {
pub row: usize,
pub column: usize,
}
32 changes: 5 additions & 27 deletions src/store.rs
@@ -1,6 +1,5 @@
use anyhow::{anyhow, Context, Result};
use serde::ser::SerializeStruct;
use serde::{Deserialize, Serialize, Serializer};
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, BTreeSet};
use std::fmt::{self, Display};
use std::fs;
Expand Down Expand Up @@ -183,7 +182,7 @@ impl Store {
.map(|found| found.path.to_owned())
.collect::<BTreeSet<PathBuf>>();

let mut to_positions: BTreeMap<&PathBuf, tree_sitter::Point> = BTreeMap::new();
let mut to_positions: BTreeMap<&PathBuf, importfinder::Position> = BTreeMap::new();

for import in found_imports.iter() {
to_positions.insert(&import.path, import.position);
Expand All @@ -192,7 +191,7 @@ impl Store {
for file in new_usages.difference(&existing.usages) {
out.push(CheckResult {
file: file.to_path_buf(),
position: to_positions.get(file).map(|p| Point(*p)),
position: to_positions.get(file).copied(),
import: import.to_string(),
error_location: ErrorLocation::InElmSource {
hint: existing.hint.as_ref(),
Expand Down Expand Up @@ -230,32 +229,11 @@ impl Store {
#[derive(Debug, Serialize)]
pub struct CheckResult<'a> {
file: PathBuf,
position: Option<Point>,
position: Option<importfinder::Position>,
import: String,
error_location: ErrorLocation<'a>,
}

#[derive(Debug)]
pub struct Point(tree_sitter::Point);

impl Serialize for Point {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("Color", 2)?;
state.serialize_field("row", &self.0.row)?;
state.serialize_field("column", &self.0.column)?;
state.end()
}
}

impl Display for Point {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:{}", self.0.row, self.0.column)
}
}

#[derive(Debug, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
enum ErrorLocation<'a> {
Expand All @@ -279,7 +257,7 @@ impl Display for CheckResult<'_> {
};

let position_string = match &self.position {
Some(position) => format!(":{}", position),
Some(position) => format!(":{}:{}", position.row, position.column),
None => String::new(),
};

Expand Down
17 changes: 0 additions & 17 deletions vendor/tree-sitter-elm/.editorconfig

This file was deleted.

1 change: 0 additions & 1 deletion vendor/tree-sitter-elm/.gitattributes

This file was deleted.

1 change: 0 additions & 1 deletion vendor/tree-sitter-elm/.github/FUNDING.yml

This file was deleted.

30 changes: 0 additions & 30 deletions vendor/tree-sitter-elm/.github/workflows/test-full.yml

This file was deleted.

0 comments on commit cee73f0

Please sign in to comment.