Skip to content

Commit

Permalink
cherry-picks for Scarb help. (#7090)
Browse files Browse the repository at this point in the history
  • Loading branch information
orizi authored Jan 15, 2025
2 parents 13bec09 + fa0a148 commit 3180b36
Show file tree
Hide file tree
Showing 17 changed files with 3,170 additions and 121 deletions.
17 changes: 6 additions & 11 deletions crates/cairo-lang-defs/src/patcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,13 +268,8 @@ impl<'a> PatchBuilder<'a> {
/// Builds the resulting code and code mappings.
pub fn build(mut self) -> (String, Vec<CodeMapping>) {
// Adds the mapping to the original node from all code not previously mapped.
self.code_mappings.push(CodeMapping {
span: TextSpan {
start: TextOffset::default(),
end: TextOffset::default().add_width(TextWidth::from_str(&self.code)),
},
origin: self.origin,
});
self.code_mappings
.push(CodeMapping { span: TextSpan::from_str(&self.code), origin: self.origin });
(self.code, self.code_mappings)
}

Expand Down Expand Up @@ -320,7 +315,7 @@ impl<'a> PatchBuilder<'a> {
}

pub fn add_node(&mut self, node: SyntaxNode) {
let start = TextOffset::default().add_width(TextWidth::from_str(&self.code));
let start = TextOffset::from_str(&self.code);
let orig_span = node.span(self.db);
self.code_mappings.push(CodeMapping {
span: TextSpan { start, end: start.add_width(orig_span.width()) },
Expand All @@ -330,9 +325,9 @@ impl<'a> PatchBuilder<'a> {
}

fn add_mapped(&mut self, node: RewriteNode, origin: TextSpan) {
let start = TextOffset::default().add_width(TextWidth::from_str(&self.code));
let start = TextOffset::from_str(&self.code);
self.add_modified(node);
let end = TextOffset::default().add_width(TextWidth::from_str(&self.code));
let end = TextOffset::from_str(&self.code);
self.code_mappings
.push(CodeMapping { span: TextSpan { start, end }, origin: CodeOrigin::Span(origin) });
}
Expand All @@ -344,7 +339,7 @@ impl<'a> PatchBuilder<'a> {
let origin_span = TextSpan { start: orig_start, end: orig_end };

let text = node.get_text_of_span(self.db, origin_span);
let start = TextOffset::default().add_width(TextWidth::from_str(&self.code));
let start = TextOffset::from_str(&self.code);

self.code += &text;

Expand Down
4 changes: 2 additions & 2 deletions crates/cairo-lang-diagnostics/src/diagnostics_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ impl DiagnosticEntry for SimpleDiag {
DiagnosticLocation {
file_id: self.file_id,
span: TextSpan {
start: TextOffset::default().add_width(TextWidth::new_for_testing(0)),
end: TextOffset::default().add_width(TextWidth::new_for_testing(6)),
start: TextOffset::START,
end: TextWidth::new_for_testing(6).as_offset(),
},
}
}
Expand Down
7 changes: 3 additions & 4 deletions crates/cairo-lang-doc/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ use cairo_lang_semantic::items::functions::GenericFunctionId;
use cairo_lang_semantic::resolve::{AsSegments, ResolvedGenericItem, Resolver};
use cairo_lang_syntax::node::ast::{Expr, ExprPath, ItemModule};
use cairo_lang_syntax::node::helpers::GetIdentifier;
use cairo_lang_syntax::node::kind::SyntaxKind;
use cairo_lang_syntax::node::{SyntaxNode, TypedSyntaxNode};
use cairo_lang_utils::Intern;
use pulldown_cmark::{
Expand Down Expand Up @@ -230,9 +229,9 @@ impl<'a> DocumentationCommentParser<'a> {
// Get the stack (bottom-up) of submodule names in the file containing the node, in the main
// module, that lead to the node.
iter::successors(node.parent(), SyntaxNode::parent)
.filter(|node| node.kind(syntax_db) == SyntaxKind::ItemModule)
.map(|node| {
ItemModule::from_syntax_node(syntax_db, node)
.filter_map(|node| ItemModule::cast(syntax_db, node))
.map(|item_module| {
item_module
.stable_ptr()
.name_green(syntax_db)
.identifier(syntax_db)
Expand Down
4 changes: 2 additions & 2 deletions crates/cairo-lang-filesystem/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,8 @@ fn file_content(db: &dyn FilesGroup, file: FileId) -> Option<Arc<str>> {
}
fn file_summary(db: &dyn FilesGroup, file: FileId) -> Option<Arc<FileSummary>> {
let content = db.file_content(file)?;
let mut line_offsets = vec![TextOffset::default()];
let mut offset = TextOffset::default();
let mut line_offsets = vec![TextOffset::START];
let mut offset = TextOffset::START;
for ch in content.chars() {
offset = offset.add_width(TextWidth::from_char(ch));
if ch == '\n' {
Expand Down
29 changes: 29 additions & 0 deletions crates/cairo-lang-filesystem/src/span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ mod test;
)]
pub struct TextWidth(u32);
impl TextWidth {
pub const ZERO: Self = Self(0);

pub fn from_char(c: char) -> Self {
Self(c.len_utf8() as u32)
}
Expand All @@ -27,9 +29,24 @@ impl TextWidth {
pub fn new_for_testing(value: u32) -> Self {
Self(value)
}
/// Creates a `TextWidth` at the given index of a string.
///
/// The index is required to be a char boundary.
/// This function runs a debug assertion to verify this,
/// while retains performance on release builds.
pub fn at(s: &str, index: usize) -> Self {
debug_assert!(
s.is_char_boundary(index),
"cannot create a TextWidth outside of a char boundary"
);
Self(index as u32)
}
pub fn as_u32(self) -> u32 {
self.0
}
pub fn as_offset(self) -> TextOffset {
TextOffset(self)
}
}
impl Add for TextWidth {
type Output = Self;
Expand Down Expand Up @@ -57,6 +74,13 @@ impl Sum for TextWidth {
)]
pub struct TextOffset(TextWidth);
impl TextOffset {
pub const START: Self = Self(TextWidth::ZERO);

/// Creates a `TextOffset` at the end of a given string.
#[allow(clippy::should_implement_trait)]
pub fn from_str(content: &str) -> Self {
Self(TextWidth::from_str(content))
}
pub fn add_width(self, width: TextWidth) -> Self {
TextOffset(self.0 + width)
}
Expand Down Expand Up @@ -87,6 +111,11 @@ pub struct TextSpan {
pub end: TextOffset,
}
impl TextSpan {
/// Creates a `TextSpan` for the entirety of a given string.
#[allow(clippy::should_implement_trait)]
pub fn from_str(content: &str) -> Self {
Self { start: TextOffset::START, end: TextOffset::from_str(content) }
}
pub fn width(self) -> TextWidth {
self.end - self.start
}
Expand Down
11 changes: 4 additions & 7 deletions crates/cairo-lang-formatter/src/formatter_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1088,13 +1088,10 @@ impl<'a> FormatterImpl<'a> {
/// Returns whether the node has only whitespace trivia.
fn has_only_whitespace_trivia(&self, node: &SyntaxNode) -> bool {
node.descendants(self.db).all(|descendant| {
if descendant.kind(self.db) == SyntaxKind::Trivia {
ast::Trivia::from_syntax_node(self.db, descendant)
.elements(self.db)
.into_iter()
.all(|element| {
matches!(element, ast::Trivium::Whitespace(_) | ast::Trivium::Newline(_))
})
if let Some(trivia) = ast::Trivia::cast(self.db, descendant) {
trivia.elements(self.db).into_iter().all(|element| {
matches!(element, ast::Trivium::Whitespace(_) | ast::Trivium::Newline(_))
})
} else {
true
}
Expand Down
9 changes: 2 additions & 7 deletions crates/cairo-lang-parser/src/db_test.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
use std::path::PathBuf;

use cairo_lang_filesystem::ids::FileId;
use cairo_lang_filesystem::span::{TextOffset, TextSpan, TextWidth};
use cairo_lang_filesystem::span::TextSpan;
use cairo_lang_syntax::node::ast::{
ModuleItemList, SyntaxFile, TerminalEndOfFile, TokenEndOfFile, Trivia,
};
use cairo_lang_syntax::node::db::SyntaxGroup;
use cairo_lang_syntax::node::{SyntaxNode, Terminal, Token as SyntaxToken, TypedSyntaxNode};
use cairo_lang_utils::Upcast;
use indoc::indoc;
use num_traits::ToPrimitive;
use pretty_assertions::assert_eq;
use smol_str::SmolStr;
use test_log::test;
Expand Down Expand Up @@ -96,11 +95,7 @@ fn test_token_stream_expr_parser() {
let token_stream = MockTokenStream {
tokens: vec![MockToken {
content: expr_code.to_string(),
span: TextSpan {
start: TextOffset::default(),
end: TextOffset::default()
.add_width(TextWidth::new_for_testing(expr_code.len().to_u32().unwrap())),
},
span: TextSpan::from_str(expr_code),
}],
content_string: expr_code.to_string(),
};
Expand Down
4 changes: 2 additions & 2 deletions crates/cairo-lang-parser/src/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ impl<'a> Lexer<'a> {
Lexer {
db,
text,
previous_position: TextOffset::default(),
current_position: TextOffset::default(),
previous_position: TextOffset::START,
current_position: TextOffset::START,
done: false,
}
}
Expand Down
8 changes: 3 additions & 5 deletions crates/cairo-lang-plugins/src/plugins/generate_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use cairo_lang_defs::plugin::{
use cairo_lang_syntax::attribute::structured::{AttributeArgVariant, AttributeStructurize};
use cairo_lang_syntax::node::db::SyntaxGroup;
use cairo_lang_syntax::node::helpers::{BodyItems, GenericParamEx, QueryAttrs};
use cairo_lang_syntax::node::kind::SyntaxKind;
use cairo_lang_syntax::node::{Terminal, TypedSyntaxNode, ast};

#[derive(Debug, Default)]
Expand Down Expand Up @@ -159,10 +158,7 @@ fn generate_trait_for_impl(db: &dyn SyntaxGroup, impl_ast: ast::ItemImpl) -> Plu
for node in
db.get_children(signature.parameters(db).node.clone()).iter().cloned()
{
if node.kind(db) != SyntaxKind::Param {
builder.add_node(node);
} else {
let param = ast::Param::from_syntax_node(db, node);
if let Some(param) = ast::Param::cast(db, node.clone()) {
for modifier in param.modifiers(db).elements(db) {
// `mut` modifiers are only relevant for impls, not traits.
if !matches!(modifier, ast::Modifier::Mut(_)) {
Expand All @@ -171,6 +167,8 @@ fn generate_trait_for_impl(db: &dyn SyntaxGroup, impl_ast: ast::ItemImpl) -> Plu
}
builder.add_node(param.name(db).as_syntax_node());
builder.add_node(param.type_clause(db).as_syntax_node());
} else {
builder.add_node(node);
}
}
let rparen = signature.rparen(db);
Expand Down
7 changes: 2 additions & 5 deletions crates/cairo-lang-plugins/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use cairo_lang_filesystem::db::{
use cairo_lang_filesystem::ids::{
CodeMapping, CodeOrigin, CrateId, Directory, FileLongId, VirtualFile,
};
use cairo_lang_filesystem::span::{TextOffset, TextSpan, TextWidth};
use cairo_lang_filesystem::span::TextSpan;
use cairo_lang_parser::db::ParserDatabase;
use cairo_lang_syntax::node::db::{SyntaxDatabase, SyntaxGroup};
use cairo_lang_syntax::node::helpers::QueryAttrs;
Expand Down Expand Up @@ -160,10 +160,7 @@ impl MacroPlugin for DoubleIndirectionPlugin {
let orig_span = node.span(db);
let code_mappings = |content: &str| {
vec![CodeMapping {
span: TextSpan {
start: TextOffset::default(),
end: TextOffset::default().add_width(TextWidth::from_str(content)),
},
span: TextSpan::from_str(content),
origin: CodeOrigin::Start(orig_span.start),
}]
};
Expand Down
7 changes: 2 additions & 5 deletions crates/cairo-lang-semantic/src/inline_macros/consteval_int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use cairo_lang_defs::plugin::{
PluginGeneratedFile,
};
use cairo_lang_filesystem::ids::{CodeMapping, CodeOrigin};
use cairo_lang_filesystem::span::{TextOffset, TextSpan, TextWidth};
use cairo_lang_filesystem::span::TextSpan;
use cairo_lang_syntax::node::db::SyntaxGroup;
use cairo_lang_syntax::node::{TypedStablePtr, TypedSyntaxNode, ast};
use indoc::indoc;
Expand Down Expand Up @@ -45,10 +45,7 @@ impl InlineMacroExprPlugin for ConstevalIntMacro {
InlinePluginResult {
code: code.map(|x| {
let content = x.to_string();
let span = TextSpan {
start: TextOffset::default(),
end: TextOffset::default().add_width(TextWidth::from_str(&content)),
};
let span = TextSpan::from_str(&content);
PluginGeneratedFile {
name: "consteval_int_inline_macro".into(),
content,
Expand Down
6 changes: 2 additions & 4 deletions crates/cairo-lang-starknet/src/plugin/starknet_module/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ use cairo_lang_plugins::plugins::HasItemsInCfgEx;
use cairo_lang_syntax::node::ast::MaybeModuleBody;
use cairo_lang_syntax::node::db::SyntaxGroup;
use cairo_lang_syntax::node::helpers::{BodyItems, QueryAttrs};
use cairo_lang_syntax::node::kind::SyntaxKind;
use cairo_lang_syntax::node::{SyntaxNode, Terminal, TypedSyntaxNode, ast};
use cairo_lang_utils::{extract_matches, require};
use cairo_lang_utils::extract_matches;

use self::component::generate_component_specific_code;
use self::contract::generate_contract_specific_code;
Expand Down Expand Up @@ -244,8 +243,7 @@ fn grand_grand_parent_starknet_module(
// Get the containing module node. The parent is the item list, the grand parent is the module
// body, and the grand grand parent is the module.
let module_node = item_node.parent()?.parent()?.parent()?;
require(module_node.kind(db) == SyntaxKind::ItemModule)?;
let module_ast = ast::ItemModule::from_syntax_node(db, module_node);
let module_ast = ast::ItemModule::cast(db, module_node)?;
let (module_kind, attr) = StarknetModuleKind::from_module(db, &module_ast)?;
Some((module_ast, module_kind, attr))
}
Expand Down
7 changes: 3 additions & 4 deletions crates/cairo-lang-starknet/src/plugin/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use cairo_lang_defs::ids::ModuleId;
use cairo_lang_diagnostics::DiagnosticLocation;
use cairo_lang_filesystem::db::FilesGroup;
use cairo_lang_filesystem::ids::FileLongId;
use cairo_lang_filesystem::span::{TextOffset, TextSpan, TextWidth};
use cairo_lang_filesystem::span::TextSpan;
use cairo_lang_plugins::test_utils::expand_module_text;
use cairo_lang_semantic::test_utils::setup_test_module;
use cairo_lang_test_utils::parse_test_file::{TestFileRunner, TestRunnerResult};
Expand Down Expand Up @@ -49,9 +49,8 @@ impl TestFileRunner for ExpandContractTestRunner {

for file_id in files {
let content = db.file_content(file_id).unwrap();
let start = TextOffset::default();
let end = start.add_width(TextWidth::from_str(&content));
let content_location = DiagnosticLocation { file_id, span: TextSpan { start, end } };
let content_location =
DiagnosticLocation { file_id, span: TextSpan::from_str(&content) };
let original_location = content_location.user_location(db.upcast());
let origin = (content_location != original_location)
.then(|| format!("{:?}\n", original_location.debug(db.upcast())))
Expand Down
32 changes: 32 additions & 0 deletions crates/cairo-lang-syntax-codegen/src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,13 @@ fn gen_common_list_code(name: &str, green_name: &str, ptr_name: &str) -> rust::T
fn from_syntax_node(db: &dyn SyntaxGroup, node: SyntaxNode) -> Self {
Self(ElementList::new(node))
}
fn cast(db: &dyn SyntaxGroup, node: SyntaxNode) -> Option<Self> {
if node.kind(db) == SyntaxKind::$name {
Some(Self(ElementList::new(node)))
} else {
None
}
}
fn as_syntax_node(&self) -> SyntaxNode {
self.node.clone()
}
Expand All @@ -390,6 +397,7 @@ fn gen_enum_code(
let green_name = format!("{name}Green");
let mut enum_body = quote! {};
let mut from_node_body = quote! {};
let mut cast_body = quote! {};
let mut ptr_conversions = quote! {};
let mut green_conversions = quote! {};
for variant in &variants {
Expand All @@ -402,6 +410,9 @@ fn gen_enum_code(
from_node_body.extend(quote! {
SyntaxKind::$k => $(&name)::$n($k::from_syntax_node(db, node)),
});
cast_body.extend(quote! {
SyntaxKind::$k => Some($(&name)::$n($k::from_syntax_node(db, node))),
});
let variant_ptr = format!("{k}Ptr");
ptr_conversions.extend(quote! {
impl From<$(&variant_ptr)> for $(&ptr_name) {
Expand Down Expand Up @@ -469,6 +480,13 @@ fn gen_enum_code(
$[str]($[const](&name))),
}
}
fn cast(db: &dyn SyntaxGroup, node: SyntaxNode) -> Option<Self> {
let kind = node.kind(db);
match kind {
$cast_body
_ => None,
}
}
fn as_syntax_node(&self) -> SyntaxNode {
match self {
$(for v in &variants => $(&name)::$(&v.name)(x) => x.as_syntax_node(),)
Expand Down Expand Up @@ -556,6 +574,12 @@ fn gen_token_code(name: String) -> rust::Tokens {
),
}
}
fn cast(db: &dyn SyntaxGroup, node: SyntaxNode) -> Option<Self> {
match node.0.green.lookup_intern(db).details {
GreenNodeDetails::Token(_) => Some(Self { node }),
GreenNodeDetails::Node { .. } => None,
}
}
fn as_syntax_node(&self) -> SyntaxNode {
self.node.clone()
}
Expand Down Expand Up @@ -706,6 +730,14 @@ fn gen_struct_code(name: String, members: Vec<Member>, is_terminal: bool) -> rus
let children = db.get_children(node.clone());
Self { node, children }
}
fn cast(db: &dyn SyntaxGroup, node: SyntaxNode) -> Option<Self> {
let kind = node.kind(db);
if kind == SyntaxKind::$(&name) {
Some(Self::from_syntax_node(db, node))
} else {
None
}
}
fn as_syntax_node(&self) -> SyntaxNode {
self.node.clone()
}
Expand Down
Loading

0 comments on commit 3180b36

Please sign in to comment.