Split up nu-protocol/src/engine/engine_state.rs (#10368)

Factor the big parts into separate files:
- `state_delta.rs`
- `state_working_set.rs`
- smaller `usage.rs`

This required adjusting the visibility of several parts.
Makes `StateDelta` transparent for the module.
Trying to reduce visibility in some other places
This commit is contained in:
Stefan Holderbach 2023-09-21 22:53:36 +02:00 committed by GitHub
parent 1c677c9577
commit ef7ade59f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 1284 additions and 1261 deletions

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,9 @@ mod engine_state;
mod overlay;
mod pattern_match;
mod stack;
mod state_delta;
mod state_working_set;
mod usage;
pub use call_info::*;
pub use capture_block::*;
@ -13,3 +16,5 @@ pub use engine_state::*;
pub use overlay::*;
pub use pattern_match::*;
pub use stack::*;
pub use state_delta::*;
pub use state_working_set::*;

View File

@ -0,0 +1,127 @@
use super::{usage::Usage, Command, EngineState, OverlayFrame, ScopeFrame, VirtualPath};
use crate::ast::Block;
use crate::{Module, Variable};
/// A delta (or change set) between the current global state and a possible future global state. Deltas
/// can be applied to the global state to update it to contain both previous state and the state held
/// within the delta.
pub struct StateDelta {
pub(super) files: Vec<(String, usize, usize)>,
pub(crate) file_contents: Vec<(Vec<u8>, usize, usize)>,
pub(super) virtual_paths: Vec<(String, VirtualPath)>,
pub(super) vars: Vec<Variable>, // indexed by VarId
pub(super) decls: Vec<Box<dyn Command>>, // indexed by DeclId
pub blocks: Vec<Block>, // indexed by BlockId
pub(super) modules: Vec<Module>, // indexed by ModuleId
pub(super) usage: Usage,
pub scope: Vec<ScopeFrame>,
#[cfg(feature = "plugin")]
pub(super) plugins_changed: bool, // marks whether plugin file should be updated
}
impl StateDelta {
pub fn new(engine_state: &EngineState) -> Self {
let last_overlay = engine_state.last_overlay(&[]);
let scope_frame = ScopeFrame::with_empty_overlay(
engine_state.last_overlay_name(&[]).to_owned(),
last_overlay.origin,
last_overlay.prefixed,
);
StateDelta {
files: vec![],
file_contents: vec![],
virtual_paths: vec![],
vars: vec![],
decls: vec![],
blocks: vec![],
modules: vec![],
scope: vec![scope_frame],
usage: Usage::new(),
#[cfg(feature = "plugin")]
plugins_changed: false,
}
}
pub fn num_files(&self) -> usize {
self.files.len()
}
pub fn num_virtual_paths(&self) -> usize {
self.virtual_paths.len()
}
pub fn num_decls(&self) -> usize {
self.decls.len()
}
pub fn num_blocks(&self) -> usize {
self.blocks.len()
}
pub fn num_modules(&self) -> usize {
self.modules.len()
}
pub fn last_scope_frame_mut(&mut self) -> &mut ScopeFrame {
self.scope
.last_mut()
.expect("internal error: missing required scope frame")
}
pub fn last_scope_frame(&self) -> &ScopeFrame {
self.scope
.last()
.expect("internal error: missing required scope frame")
}
pub fn last_overlay_mut(&mut self) -> Option<&mut OverlayFrame> {
let last_scope = self
.scope
.last_mut()
.expect("internal error: missing required scope frame");
if let Some(last_overlay_id) = last_scope.active_overlays.last() {
Some(
&mut last_scope
.overlays
.get_mut(*last_overlay_id)
.expect("internal error: missing required overlay")
.1,
)
} else {
None
}
}
pub fn last_overlay(&self) -> Option<&OverlayFrame> {
let last_scope = self
.scope
.last()
.expect("internal error: missing required scope frame");
if let Some(last_overlay_id) = last_scope.active_overlays.last() {
Some(
&last_scope
.overlays
.get(*last_overlay_id)
.expect("internal error: missing required overlay")
.1,
)
} else {
None
}
}
pub fn enter_scope(&mut self) {
self.scope.push(ScopeFrame::new());
}
pub fn exit_scope(&mut self) {
self.scope.pop();
}
pub fn get_file_contents(&self) -> &[(Vec<u8>, usize, usize)] {
&self.file_contents
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,89 @@
use crate::{ModuleId, Span};
use std::collections::HashMap;
/// Organizes usage messages for various primitives
#[derive(Debug, Clone)]
pub(super) struct Usage {
// TODO: Move decl usages here
module_comments: HashMap<ModuleId, Vec<Span>>,
}
impl Usage {
pub fn new() -> Self {
Usage {
module_comments: HashMap::new(),
}
}
pub fn add_module_comments(&mut self, module_id: ModuleId, comments: Vec<Span>) {
self.module_comments.insert(module_id, comments);
}
pub fn get_module_comments(&self, module_id: ModuleId) -> Option<&[Span]> {
self.module_comments.get(&module_id).map(|v| v.as_ref())
}
/// Overwrite own values with the other
pub fn merge_with(&mut self, other: Usage) {
self.module_comments.extend(other.module_comments);
}
}
impl Default for Usage {
fn default() -> Self {
Self::new()
}
}
pub(super) fn build_usage(comment_lines: &[&[u8]]) -> (String, String) {
let mut usage = String::new();
let mut num_spaces = 0;
let mut first = true;
// Use the comments to build the usage
for contents in comment_lines {
let comment_line = if first {
// Count the number of spaces still at the front, skipping the '#'
let mut pos = 1;
while pos < contents.len() {
if let Some(b' ') = contents.get(pos) {
// continue
} else {
break;
}
pos += 1;
}
num_spaces = pos;
first = false;
String::from_utf8_lossy(&contents[pos..]).to_string()
} else {
let mut pos = 1;
while pos < contents.len() && pos < num_spaces {
if let Some(b' ') = contents.get(pos) {
// continue
} else {
break;
}
pos += 1;
}
String::from_utf8_lossy(&contents[pos..]).to_string()
};
if !usage.is_empty() {
usage.push('\n');
}
usage.push_str(&comment_line);
}
if let Some((brief_usage, extra_usage)) = usage.split_once("\n\n") {
(brief_usage.to_string(), extra_usage.to_string())
} else {
(usage, String::default())
}
}