-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
efbf7b1
commit d4dd96d
Showing
9 changed files
with
193 additions
and
15 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
use std::fmt::Formatter; | ||
use std::ops::Deref; | ||
use std::sync::Arc; | ||
|
||
use ruff_python_ast::{ModModule, PySourceType}; | ||
use ruff_python_parser::{parse_unchecked_source, Parsed}; | ||
|
||
use crate::source::source_text; | ||
use crate::vfs::{VfsFile, VfsPath}; | ||
use crate::Db; | ||
|
||
/// Returns the parsed AST of `file`, including its token stream. | ||
/// | ||
/// The query uses Ruff's error-resilient parser. That means that the parser always succeeds to produce a | ||
/// AST even if the file contains syntax errors. The parse errors | ||
/// are then accessible through [`Parsed::errors`]. | ||
/// | ||
/// The query is only cached when the [`source_text()`] hasn't changed. This is because | ||
/// comparing two ASTs is a non-trivial operation and every offset change is directly | ||
/// reflected in the changed AST offsets. | ||
/// The other reason is that Ruff's AST doesn't implement `Eq` which Sala requires | ||
/// for determining if a query result is unchanged. | ||
#[salsa::tracked(return_ref, no_eq)] | ||
pub fn parsed_module(db: &dyn Db, file: VfsFile) -> ParsedModule { | ||
let source = source_text(db, file); | ||
let path = file.path(db); | ||
|
||
let ty = match path { | ||
VfsPath::FileSystem(path) => path | ||
.extension() | ||
.map_or(PySourceType::Python, PySourceType::from_extension), | ||
VfsPath::Vendored(_) => PySourceType::Stub, | ||
}; | ||
|
||
ParsedModule { | ||
inner: Arc::new(parse_unchecked_source(&source, ty)), | ||
} | ||
} | ||
|
||
/// Cheap cloneable wrapper around the parsed module. | ||
#[derive(Clone, PartialEq)] | ||
pub struct ParsedModule { | ||
inner: Arc<Parsed<ModModule>>, | ||
} | ||
|
||
impl ParsedModule { | ||
/// Consumes `self` and returns the Arc storing the parsed module. | ||
pub fn into_arc(self) -> Arc<Parsed<ModModule>> { | ||
self.inner | ||
} | ||
} | ||
|
||
impl Deref for ParsedModule { | ||
type Target = Parsed<ModModule>; | ||
|
||
fn deref(&self) -> &Self::Target { | ||
&self.inner | ||
} | ||
} | ||
|
||
impl std::fmt::Debug for ParsedModule { | ||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||
f.debug_tuple("ParsedModule").field(&self.inner).finish() | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use crate::file_system::FileSystemPath; | ||
use crate::parsed::parsed_module; | ||
use crate::tests::TestDb; | ||
use crate::vfs::VendoredPath; | ||
use crate::Db; | ||
|
||
#[test] | ||
fn python_file() { | ||
let mut db = TestDb::new(); | ||
let path = FileSystemPath::new("test.py"); | ||
|
||
db.file_system_mut().write_file(path, "x = 10".to_string()); | ||
|
||
let file = db.file(path); | ||
|
||
let parsed = parsed_module(&db, file); | ||
|
||
assert!(parsed.is_valid()); | ||
} | ||
|
||
#[test] | ||
fn python_ipynb_file() { | ||
let mut db = TestDb::new(); | ||
let path = FileSystemPath::new("test.ipynb"); | ||
|
||
db.file_system_mut() | ||
.write_file(path, "%timeit a = b".to_string()); | ||
|
||
let file = db.file(path); | ||
|
||
let parsed = parsed_module(&db, file); | ||
|
||
assert!(parsed.is_valid()); | ||
} | ||
|
||
#[test] | ||
fn vendored_file() { | ||
let mut db = TestDb::new(); | ||
db.vfs_mut().stub_vendored([( | ||
"path.pyi", | ||
r#" | ||
import sys | ||
if sys.platform == "win32": | ||
from ntpath import * | ||
from ntpath import __all__ as __all__ | ||
else: | ||
from posixpath import * | ||
from posixpath import __all__ as __all__"#, | ||
)]); | ||
|
||
let file = db.vendored_file(VendoredPath::new("path.pyi")).unwrap(); | ||
|
||
let parsed = parsed_module(&db, file); | ||
|
||
assert!(parsed.is_valid()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters