Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: auto-import for sway #5174

Merged
merged 36 commits into from
Oct 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
2519221
Checkpoint
sdankel Sep 27, 2023
6e1eea7
recursive submodules
sdankel Sep 30, 2023
58dd12d
fix consts
sdankel Oct 2, 2023
3a27ad6
traits
sdankel Oct 2, 2023
09757d7
fix typo
sdankel Oct 2, 2023
30494e5
sort imports
sdankel Oct 5, 2023
fb63523
Merge branch 'master' into sophie/importCodeAction
sdankel Oct 5, 2023
b4f62e7
cargo fmt
sdankel Oct 5, 2023
340ebf7
pass span as option
sdankel Oct 9, 2023
1725b71
Pass by reference
sdankel Oct 9, 2023
3682dc9
Merge branch 'master' into sophie/importCodeAction
sdankel Oct 9, 2023
645e4ca
Revert test
sdankel Oct 9, 2023
b303ad9
add typed include_statement
sdankel Oct 10, 2023
57c3ae6
Clean up
sdankel Oct 11, 2023
dd19808
Merge branch 'master' into sophie/importCodeAction
sdankel Oct 11, 2023
600177f
clippy
sdankel Oct 11, 2023
30fb1fd
integ tests
sdankel Oct 11, 2023
3674594
test progress
sdankel Oct 12, 2023
2aa72de
Unit tests
sdankel Oct 13, 2023
c15d514
Update comments
sdankel Oct 13, 2023
406a0ad
fix tests
sdankel Oct 13, 2023
aa7a0bb
toml sorting
sdankel Oct 13, 2023
7cb62d2
Merge branch 'master' into sophie/importCodeAction
sdankel Oct 13, 2023
6331a9c
Merge branch 'master' into sophie/importCodeAction
sdankel Oct 13, 2023
b2cf178
feedback
sdankel Oct 13, 2023
1351f44
feedback
sdankel Oct 16, 2023
2959326
Merge branch 'master' into sophie/importCodeAction
sdankel Oct 16, 2023
8110a56
cargo fmt
sdankel Oct 16, 2023
9fe1bc7
Merge branch 'master' into sophie/importCodeAction
sdankel Oct 17, 2023
2d8e1fd
remove newline after group statement
sdankel Oct 17, 2023
9c26840
cargo fmt
sdankel Oct 17, 2023
05a32a7
Merge branch 'master' into sophie/importCodeAction
sdankel Oct 18, 2023
ca40994
Merge branch 'master' into sophie/importCodeAction
sdankel Oct 19, 2023
4d846ea
array instead of vec for submodules
sdankel Oct 19, 2023
2f1de38
Merge branch 'master' into sophie/importCodeAction
sdankel Oct 20, 2023
25a40f2
Merge branch 'master' into sophie/importCodeAction
sdankel Oct 20, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions Cargo.lock

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

13 changes: 13 additions & 0 deletions sway-ast/src/item/item_use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,16 @@ pub enum UseTree {
spans: Box<[Span]>,
},
}

impl Spanned for UseTree {
fn span(&self) -> Span {
match self {
UseTree::Group { imports } => imports.span(),
UseTree::Name { name } => name.span(),
UseTree::Rename { name, alias, .. } => Span::join(name.span(), alias.span()),
UseTree::Glob { star_token } => star_token.span(),
UseTree::Path { prefix, suffix, .. } => Span::join(prefix.span(), suffix.span()),
UseTree::Error { spans } => Span::join_all(spans.to_vec().clone()),
}
}
}
34 changes: 32 additions & 2 deletions sway-core/src/language/call_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ pub struct CallPath<T = Ident> {
pub suffix: T,
// If `is_absolute` is true, then this call path is an absolute path from
// the project root namespace. If not, then it is relative to the current namespace.
pub(crate) is_absolute: bool,
pub is_absolute: bool,
}

impl std::convert::From<Ident> for CallPath {
Expand Down Expand Up @@ -258,6 +258,19 @@ impl CallPath {
}
}

/// Removes the first prefix. Does nothing if prefixes are empty.
pub fn lshift(&self) -> CallPath {
if self.prefixes.is_empty() {
self.clone()
} else {
CallPath {
prefixes: self.prefixes[1..self.prefixes.len()].to_vec(),
suffix: self.suffix.clone(),
is_absolute: self.is_absolute,
}
}
}

pub fn as_vec_string(&self) -> Vec<String> {
self.prefixes
.iter()
Expand All @@ -266,7 +279,7 @@ impl CallPath {
.collect::<Vec<_>>()
}

/// Convert a given `CallPath` to an symbol to a full `CallPath` from the root of the project
/// Convert a given [CallPath] to an symbol to a full [CallPath] from the root of the project
/// in which the symbol is declared. For example, given a path `pkga::SOME_CONST` where `pkga`
/// is an _internal_ library of a package named `my_project`, the corresponding call path is
/// `my_project::pkga::SOME_CONST`.
Expand Down Expand Up @@ -353,4 +366,21 @@ impl CallPath {
}
}
}

/// Convert a given [CallPath] into a call path suitable for a `use` statement.
///
/// For example, given a path `pkga::SOME_CONST` where `pkga` is an _internal_ library of a package named
/// `my_project`, the corresponding call path is `pkga::SOME_CONST`.
///
/// Paths to _external_ libraries such `std::lib1::lib2::my_obj` are left unchanged.
pub fn to_import_path(&self, namespace: &Namespace) -> CallPath {
let converted = self.to_fullpath(namespace);

if let Some(first) = converted.prefixes.first() {
if namespace.root().name == Some(first.clone()) {
return converted.lshift();
}
}
converted
}
}
14 changes: 14 additions & 0 deletions sway-core/src/language/lexed/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use crate::language::ModName;
pub use program::LexedProgram;
use sway_ast::Module;

use super::{HasModule, HasSubmodules};

/// A module and its submodules in the form of a tree.
#[derive(Debug, Clone)]
pub struct LexedModule {
Expand All @@ -20,3 +22,15 @@ pub struct LexedModule {
pub struct LexedSubmodule {
pub module: LexedModule,
}

impl HasModule<LexedModule> for LexedSubmodule {
fn module(&self) -> &LexedModule {
&self.module
}
}

impl HasSubmodules<LexedSubmodule> for LexedModule {
fn submodules(&self) -> &[(ModName, LexedSubmodule)] {
&self.submodules
}
}
69 changes: 69 additions & 0 deletions sway-core/src/language/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,72 @@ use sway_types::Ident;
/// If an alias was given to the `mod`, this will be the alias. If not, this is the submodule's
/// library name.
pub type ModName = Ident;

pub trait HasModule<T>
where
T: HasSubmodules<Self>,
Self: Sized,
{
/// Returns the module of this submodule.
fn module(&self) -> &T;
}

pub trait HasSubmodules<E>
where
E: HasModule<Self>,
Self: Sized,
{
/// Returns the submodules of this module.
fn submodules(&self) -> &[(ModName, E)];

/// An iterator yielding all submodules recursively, depth-first.
fn submodules_recursive(&self) -> SubmodulesRecursive<Self, E> {
SubmodulesRecursive {
_module_type: std::marker::PhantomData,
submods: self.submodules().iter(),
current: None,
}
}
}

type NamedSubmodule<E> = (ModName, E);
type SubmoduleItem<'module, T, E> = (
&'module NamedSubmodule<E>,
Box<SubmodulesRecursive<'module, T, E>>,
);

/// Iterator type for iterating over submodules.
///
/// Used rather than `impl Iterator` to enable recursive submodule iteration.
pub struct SubmodulesRecursive<'module, T, E> {
_module_type: std::marker::PhantomData<T>,
submods: std::slice::Iter<'module, NamedSubmodule<E>>,
current: Option<SubmoduleItem<'module, T, E>>,
}

impl<'module, T, E> Iterator for SubmodulesRecursive<'module, T, E>
where
T: HasSubmodules<E> + 'module,
E: HasModule<T>,
{
type Item = &'module (ModName, E);
fn next(&mut self) -> Option<Self::Item> {
loop {
self.current = match self.current.take() {
None => match self.submods.next() {
None => return None,
Some(submod) => {
Some((submod, Box::new(submod.1.module().submodules_recursive())))
}
},
Some((submod, mut submods)) => match submods.next() {
Some(next) => {
self.current = Some((submod, submods));
return Some(next);
}
None => return Some(submod),
},
}
}
}
}
9 changes: 6 additions & 3 deletions sway-core/src/language/parsed/include_statement.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use sway_types::span::Span;
use sway_types::{span::Span, Ident};

use crate::language::Visibility;

#[derive(Clone, Debug)]
pub struct IncludeStatement {
// this span may be used for errors in the future, although it is not right now.
pub(crate) _span: Span,
pub(crate) _mod_name_span: Span,
pub span: Span,
pub mod_name: Ident,
pub visibility: Visibility,
}
2 changes: 1 addition & 1 deletion sway-core/src/language/parsed/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ mod use_statement;
pub use code_block::*;
pub use declaration::*;
pub use expression::*;
pub(crate) use include_statement::IncludeStatement;
pub use include_statement::IncludeStatement;
pub use module::{ParseModule, ParseSubmodule};
pub use program::{ParseProgram, TreeType};
pub use return_statement::*;
Expand Down
14 changes: 13 additions & 1 deletion sway-core/src/language/parsed/module.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
language::{ModName, Visibility},
language::{HasModule, HasSubmodules, ModName, Visibility},
transform,
};

Expand Down Expand Up @@ -33,3 +33,15 @@ pub struct ParseSubmodule {
pub mod_name_span: Span,
pub visibility: Visibility,
}

impl HasModule<ParseModule> for ParseSubmodule {
fn module(&self) -> &ParseModule {
&self.module
}
}

impl HasSubmodules<ParseSubmodule> for ParseModule {
fn submodules(&self) -> &[(ModName, ParseSubmodule)] {
&self.submodules
}
}
1 change: 1 addition & 0 deletions sway-core/src/language/parsed/use_statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub enum ImportType {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct UseStatement {
pub call_path: Vec<Ident>,
pub span: Span,
pub import_type: ImportType,
// If `is_absolute` is true, then this use statement is an absolute path from
// the project root namespace. If not, then it is relative to the current namespace.
Expand Down
5 changes: 4 additions & 1 deletion sway-core/src/language/ty/declaration/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::{
use sha2::{Digest, Sha256};
use sway_error::handler::{ErrorEmitted, Handler};

use crate::semantic_analysis::type_check_context::MonomorphizeHelper;
use crate::{language::CallPath, semantic_analysis::type_check_context::MonomorphizeHelper};

use crate::{
decl_engine::*,
Expand All @@ -31,6 +31,7 @@ pub struct TyFunctionDecl {
pub parameters: Vec<TyFunctionParameter>,
pub implementing_type: Option<TyDecl>,
pub span: Span,
pub call_path: CallPath,
pub attributes: transform::AttributesMap,
pub type_parameters: Vec<TypeParameter>,
pub return_type: TypeArgument,
Expand Down Expand Up @@ -91,6 +92,7 @@ impl HashWithEngines for TyFunctionDecl {
purity,
// these fields are not hashed because they aren't relevant/a
// reliable source of obj v. obj distinction
call_path: _,
span: _,
attributes: _,
implementing_type: _,
Expand Down Expand Up @@ -234,6 +236,7 @@ impl TyFunctionDecl {
},
implementing_type: None,
span,
call_path: CallPath::from(Ident::dummy()),
attributes: Default::default(),
is_contract_call: false,
parameters: Default::default(),
Expand Down
4 changes: 3 additions & 1 deletion sway-core/src/language/ty/declaration/trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
DeclRefTraitType, ReplaceFunctionImplementingType,
},
engine_threading::*,
language::{parsed, Visibility},
language::{parsed, CallPath, Visibility},
semantic_analysis::{
type_check_context::MonomorphizeHelper, TypeCheckAnalysis, TypeCheckAnalysisContext,
TypeCheckFinalization, TypeCheckFinalizationContext,
Expand All @@ -30,6 +30,7 @@ pub struct TyTraitDecl {
pub supertraits: Vec<parsed::Supertrait>,
pub visibility: Visibility,
pub attributes: transform::AttributesMap,
pub call_path: CallPath,
IGI-111 marked this conversation as resolved.
Show resolved Hide resolved
pub span: Span,
}

Expand Down Expand Up @@ -85,6 +86,7 @@ impl HashWithEngines for TyTraitDecl {
// reliable source of obj v. obj distinction
attributes: _,
span: _,
call_path: _,
} = self;
name.hash(state);
type_parameters.hash(state, engines);
Expand Down
9 changes: 8 additions & 1 deletion sway-core/src/language/ty/declaration/type_alias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ use std::hash::{Hash, Hasher};

use sway_types::{Ident, Named, Span, Spanned};

use crate::{engine_threading::*, language::Visibility, transform, type_system::*};
use crate::{
engine_threading::*,
language::{CallPath, Visibility},
transform,
type_system::*,
};

#[derive(Clone, Debug)]
pub struct TyTypeAliasDecl {
pub name: Ident,
pub call_path: CallPath,
pub attributes: transform::AttributesMap,
pub ty: TypeArgument,
pub visibility: Visibility,
Expand Down Expand Up @@ -36,6 +42,7 @@ impl HashWithEngines for TyTypeAliasDecl {
visibility,
// these fields are not hashed because they aren't relevant/a
// reliable source of obj v. obj distinction
call_path: _,
span: _,
attributes: _,
} = self;
Expand Down
14 changes: 13 additions & 1 deletion sway-core/src/language/ty/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use sway_types::Span;

use crate::{
decl_engine::{DeclEngine, DeclRef, DeclRefFunction},
language::ty::*,
language::ModName,
language::{ty::*, HasModule, HasSubmodules},
semantic_analysis::namespace,
transform::{self, AllowDeprecatedState},
Engines,
Expand Down Expand Up @@ -110,3 +110,15 @@ impl<'module> Iterator for SubmodulesRecursive<'module> {
}
}
}

impl HasModule<TyModule> for TySubmodule {
fn module(&self) -> &TyModule {
&self.module
}
}

impl HasSubmodules<TySubmodule> for TyModule {
fn submodules(&self) -> &[(ModName, TySubmodule)] {
&self.submodules
}
}
Loading
Loading