mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-28 12:55:05 +00:00
ty_ide: improve completions by using scopes
Previously, completions were based on just returning every identifier parsed in the current Python file. In this commit, we change it to identify an expression under the cursor and then return all symbols available to the scope containing that expression. This is still returning too much, and also, in some cases, not enough. Namely, it doesn't really take the specific context into account other than scope. But this does improve on the status quo. For example: def foo(): ... def bar(): def fast(): ... def foofoo(): ... f<CURSOR> When asking for completions here, the LSP will no longer include `fast` as a possible completion in this context. Ref https://github.com/astral-sh/ty/issues/86
This commit is contained in:
parent
a827b16ebd
commit
33ed502edb
3 changed files with 893 additions and 22 deletions
|
@ -1,7 +1,7 @@
|
|||
use ruff_db::files::{File, FilePath};
|
||||
use ruff_db::source::line_index;
|
||||
use ruff_python_ast as ast;
|
||||
use ruff_python_ast::{Expr, ExprRef};
|
||||
use ruff_python_ast::{Expr, ExprRef, name::Name};
|
||||
use ruff_source_file::LineIndex;
|
||||
|
||||
use crate::Db;
|
||||
|
@ -9,6 +9,7 @@ use crate::module_name::ModuleName;
|
|||
use crate::module_resolver::{Module, resolve_module};
|
||||
use crate::semantic_index::ast_ids::HasScopedExpressionId;
|
||||
use crate::semantic_index::semantic_index;
|
||||
use crate::semantic_index::symbol::FileScopeId;
|
||||
use crate::types::{Type, binding_type, infer_scope_types};
|
||||
|
||||
pub struct SemanticModel<'db> {
|
||||
|
@ -38,6 +39,32 @@ impl<'db> SemanticModel<'db> {
|
|||
pub fn resolve_module(&self, module_name: &ModuleName) -> Option<Module> {
|
||||
resolve_module(self.db, module_name)
|
||||
}
|
||||
|
||||
/// Returns completions for symbols available in the scope containing the
|
||||
/// given expression.
|
||||
///
|
||||
/// If a scope could not be determined, then completions for the global
|
||||
/// scope of this model's `File` are returned.
|
||||
pub fn completions(&self, node: ast::AnyNodeRef<'_>) -> Vec<Name> {
|
||||
let index = semantic_index(self.db, self.file);
|
||||
let file_scope = match node {
|
||||
ast::AnyNodeRef::Identifier(identifier) => index.expression_scope_id(identifier),
|
||||
node => match node.as_expr_ref() {
|
||||
// If we couldn't identify a specific
|
||||
// expression that we're in, then just
|
||||
// fall back to the global scope.
|
||||
None => FileScopeId::global(),
|
||||
Some(expr) => index.expression_scope_id(expr),
|
||||
},
|
||||
};
|
||||
let mut symbols = vec![];
|
||||
for (file_scope, _) in index.ancestor_scopes(file_scope) {
|
||||
for symbol in index.symbol_table(file_scope).symbols() {
|
||||
symbols.push(symbol.name().clone());
|
||||
}
|
||||
}
|
||||
symbols
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HasType {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue