tree update!
This commit is contained in:
parent
26b6056dbc
commit
5f86f4cee7
18 changed files with 431 additions and 179 deletions
|
@ -4,7 +4,7 @@ use anyhow::Context;
|
|||
use treehouse_format::ast::Branch;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
use crate::state::{FileId, Treehouse};
|
||||
use crate::state::{FileId, Source, Treehouse};
|
||||
|
||||
use super::{
|
||||
parse::{self, parse_toml_with_diagnostics, parse_tree_with_diagnostics},
|
||||
|
@ -106,7 +106,7 @@ pub fn fix_file(
|
|||
file_id: FileId,
|
||||
) -> Result<String, parse::ErrorsEmitted> {
|
||||
parse_tree_with_diagnostics(treehouse, file_id).map(|roots| {
|
||||
let mut source = treehouse.source(file_id).to_owned();
|
||||
let mut source = treehouse.source(file_id).input().to_owned();
|
||||
let mut state = State::default();
|
||||
|
||||
for branch in &roots.branches {
|
||||
|
@ -130,14 +130,14 @@ pub fn fix_file_cli(fix_args: FixArgs) -> anyhow::Result<()> {
|
|||
let file = std::fs::read_to_string(&fix_args.file).context("cannot read file to fix")?;
|
||||
|
||||
let mut treehouse = Treehouse::new();
|
||||
let file_id = treehouse.add_file(utf8_filename, None, file);
|
||||
let file_id = treehouse.add_file(utf8_filename, Source::Other(file));
|
||||
|
||||
if let Ok(fixed) = fix_file(&mut treehouse, file_id) {
|
||||
if fix_args.apply {
|
||||
// Try to write the backup first. If writing that fails, bail out without overwriting
|
||||
// the source file.
|
||||
if let Some(backup_path) = fix_args.backup {
|
||||
std::fs::write(backup_path, treehouse.source(file_id))
|
||||
std::fs::write(backup_path, treehouse.source(file_id).input())
|
||||
.context("cannot write backup; original file will not be overwritten")?;
|
||||
}
|
||||
std::fs::write(&fix_args.file, fixed).context("cannot overwrite original file")?;
|
||||
|
@ -160,10 +160,10 @@ pub fn fix_all_cli(fix_all_args: FixAllArgs, paths: &Paths<'_>) -> anyhow::Resul
|
|||
let utf8_filename = entry.path().to_string_lossy();
|
||||
|
||||
let mut treehouse = Treehouse::new();
|
||||
let file_id = treehouse.add_file(utf8_filename.into_owned(), None, file);
|
||||
let file_id = treehouse.add_file(utf8_filename.into_owned(), Source::Other(file));
|
||||
|
||||
if let Ok(fixed) = fix_file(&mut treehouse, file_id) {
|
||||
if fixed != treehouse.source(file_id) {
|
||||
if fixed != treehouse.source(file_id).input() {
|
||||
if fix_all_args.apply {
|
||||
println!("fixing: {:?}", entry.path());
|
||||
std::fs::write(entry.path(), fixed).with_context(|| {
|
||||
|
|
|
@ -5,17 +5,14 @@ use std::{
|
|||
};
|
||||
|
||||
use anyhow::{bail, Context};
|
||||
use axum::Router;
|
||||
use codespan_reporting::{
|
||||
diagnostic::{Diagnostic, Label, LabelStyle, Severity},
|
||||
files::Files as _,
|
||||
};
|
||||
use copy_dir::copy_dir;
|
||||
use handlebars::Handlebars;
|
||||
use log::{debug, info};
|
||||
use log::{debug, error, info};
|
||||
use serde::Serialize;
|
||||
use tower_http::services::ServeDir;
|
||||
use tower_livereload::LiveReloadLayer;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
use crate::{
|
||||
|
@ -26,6 +23,7 @@ use crate::{
|
|||
navmap::{build_navigation_map, NavigationMap},
|
||||
tree::branches_to_html,
|
||||
},
|
||||
state::Source,
|
||||
tree::SemaRoots,
|
||||
};
|
||||
|
||||
|
@ -63,7 +61,8 @@ impl Generator {
|
|||
) -> anyhow::Result<FileId> {
|
||||
let source = std::fs::read_to_string(path)
|
||||
.with_context(|| format!("cannot read template file {path:?}"))?;
|
||||
let file_id = treehouse.add_file(path.to_string_lossy().into_owned(), None, source);
|
||||
let file_id =
|
||||
treehouse.add_file(path.to_string_lossy().into_owned(), Source::Other(source));
|
||||
let source = treehouse.source(file_id);
|
||||
if let Err(error) = handlebars.register_template_string(name, source) {
|
||||
Self::wrangle_handlebars_error_into_diagnostic(
|
||||
|
@ -136,9 +135,17 @@ impl Generator {
|
|||
continue;
|
||||
}
|
||||
};
|
||||
let tree_path = tree_path.with_extension("").to_string_lossy().replace('\\', "/");
|
||||
let file_id =
|
||||
treehouse.add_file(utf8_filename.into_owned(), Some(tree_path.clone()), source);
|
||||
let tree_path = tree_path
|
||||
.with_extension("")
|
||||
.to_string_lossy()
|
||||
.replace('\\', "/");
|
||||
let file_id = treehouse.add_file(
|
||||
utf8_filename.into_owned(),
|
||||
Source::Tree {
|
||||
input: source,
|
||||
tree_path: tree_path.clone(),
|
||||
},
|
||||
);
|
||||
|
||||
if let Ok(roots) = parse_tree_with_diagnostics(&mut treehouse, file_id) {
|
||||
let roots = SemaRoots::from_roots(&mut treehouse, file_id, roots);
|
||||
|
@ -186,20 +193,30 @@ impl Generator {
|
|||
parsed_tree.file_id,
|
||||
&roots.branches,
|
||||
);
|
||||
treehouse.roots.insert(parsed_tree.tree_path, roots);
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct Page {
|
||||
pub title: String,
|
||||
pub breadcrumbs: String,
|
||||
pub tree: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct TemplateData<'a> {
|
||||
pub config: &'a Config,
|
||||
pub breadcrumbs: String,
|
||||
pub tree: String,
|
||||
pub page: Page,
|
||||
}
|
||||
let template_data = TemplateData {
|
||||
config,
|
||||
breadcrumbs,
|
||||
tree,
|
||||
page: Page {
|
||||
title: roots.attributes.title.clone(),
|
||||
breadcrumbs,
|
||||
tree,
|
||||
},
|
||||
};
|
||||
|
||||
treehouse.roots.insert(parsed_tree.tree_path, roots);
|
||||
|
||||
let templated_html = match handlebars.render("tree", &template_data) {
|
||||
Ok(html) => html,
|
||||
Err(error) => {
|
||||
|
@ -227,7 +244,7 @@ impl Generator {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn regenerate(paths: &Paths<'_>) -> anyhow::Result<()> {
|
||||
pub fn generate(paths: &Paths<'_>) -> anyhow::Result<Treehouse> {
|
||||
let start = Instant::now();
|
||||
|
||||
info!("loading config");
|
||||
|
@ -268,26 +285,19 @@ pub fn regenerate(paths: &Paths<'_>) -> anyhow::Result<()> {
|
|||
let duration = start.elapsed();
|
||||
info!("generation done in {duration:?}");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn regenerate_or_report_error(paths: &Paths<'_>) {
|
||||
info!("regenerating site content");
|
||||
|
||||
match regenerate(paths) {
|
||||
Ok(_) => (),
|
||||
Err(error) => eprintln!("error: {error:?}"),
|
||||
if !treehouse.has_errors() {
|
||||
Ok(treehouse)
|
||||
} else {
|
||||
bail!("generation errors occurred; diagnostics were emitted with detailed descriptions");
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn web_server(port: u16) -> anyhow::Result<()> {
|
||||
let app = Router::new().nest_service("/", ServeDir::new("target/site"));
|
||||
pub fn regenerate_or_report_error(paths: &Paths<'_>) -> anyhow::Result<Treehouse> {
|
||||
info!("regenerating site content");
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
let app = app.layer(LiveReloadLayer::new());
|
||||
|
||||
info!("serving on port {port}");
|
||||
Ok(axum::Server::bind(&([0, 0, 0, 0], port).into())
|
||||
.serve(app.into_make_service())
|
||||
.await?)
|
||||
let result = generate(paths);
|
||||
if let Err(e) = &result {
|
||||
error!("{e:?}");
|
||||
}
|
||||
result
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
pub mod fix;
|
||||
pub mod generate;
|
||||
mod parse;
|
||||
pub mod serve;
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
|
@ -24,14 +25,21 @@ pub enum Command {
|
|||
///
|
||||
/// By default only prints which files would be changed. To apply the changes, use `--apply`.
|
||||
FixAll(#[clap(flatten)] FixAllArgs),
|
||||
|
||||
/// `generate` and start a treehouse server.
|
||||
///
|
||||
/// The server uses the generated files and provides extra functionality on top, handling
|
||||
Serve {
|
||||
#[clap(flatten)]
|
||||
generate: GenerateArgs,
|
||||
|
||||
#[clap(flatten)]
|
||||
serve: ServeArgs,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Args)]
|
||||
pub struct GenerateArgs {
|
||||
/// Start a web server serving the static files on the given port. Useful with `cargo watch`.
|
||||
#[clap(short, long)]
|
||||
pub serve: Option<u16>,
|
||||
}
|
||||
pub struct GenerateArgs {}
|
||||
|
||||
#[derive(Args)]
|
||||
pub struct FixArgs {
|
||||
|
@ -57,6 +65,13 @@ pub struct FixAllArgs {
|
|||
pub apply: bool,
|
||||
}
|
||||
|
||||
#[derive(Args)]
|
||||
pub struct ServeArgs {
|
||||
/// The port under which to serve the treehouse.
|
||||
#[clap(short, long, default_value_t = 8080)]
|
||||
pub port: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Paths<'a> {
|
||||
pub target_dir: &'a Path,
|
||||
|
|
|
@ -11,7 +11,7 @@ pub fn parse_tree_with_diagnostics(
|
|||
treehouse: &mut Treehouse,
|
||||
file_id: FileId,
|
||||
) -> Result<Roots, ErrorsEmitted> {
|
||||
let input = treehouse.source(file_id);
|
||||
let input = &treehouse.source(file_id).input();
|
||||
Roots::parse(&mut treehouse_format::pull::Parser { input, position: 0 }).map_err(|error| {
|
||||
treehouse.diagnostics.push(Diagnostic {
|
||||
severity: Severity::Error,
|
||||
|
@ -34,7 +34,7 @@ pub fn parse_toml_with_diagnostics(
|
|||
file_id: FileId,
|
||||
range: Range<usize>,
|
||||
) -> Result<toml_edit::Document, ErrorsEmitted> {
|
||||
let input = &treehouse.source(file_id)[range.clone()];
|
||||
let input = &treehouse.source(file_id).input()[range.clone()];
|
||||
toml_edit::Document::from_str(input).map_err(|error| {
|
||||
treehouse
|
||||
.diagnostics
|
||||
|
|
86
crates/treehouse/src/cli/serve.rs
Normal file
86
crates/treehouse/src/cli/serve.rs
Normal file
|
@ -0,0 +1,86 @@
|
|||
use std::{path::PathBuf, sync::Arc};
|
||||
|
||||
use anyhow::Context;
|
||||
use axum::{
|
||||
extract::{RawQuery, State},
|
||||
response::Html,
|
||||
routing::get,
|
||||
Router,
|
||||
};
|
||||
use log::{error, info};
|
||||
use pulldown_cmark::escape::escape_html;
|
||||
use tower_http::services::ServeDir;
|
||||
|
||||
use crate::state::{Source, Treehouse};
|
||||
|
||||
use super::Paths;
|
||||
|
||||
struct SystemPages {
|
||||
four_oh_four: String,
|
||||
b_docs: String,
|
||||
}
|
||||
|
||||
struct Server {
|
||||
treehouse: Treehouse,
|
||||
target_dir: PathBuf,
|
||||
system_pages: SystemPages,
|
||||
}
|
||||
|
||||
pub async fn serve(treehouse: Treehouse, paths: &Paths<'_>, port: u16) -> anyhow::Result<()> {
|
||||
let app = Router::new()
|
||||
.nest_service("/", ServeDir::new(paths.target_dir))
|
||||
.route("/b", get(branch))
|
||||
.with_state(Arc::new(Server {
|
||||
treehouse,
|
||||
target_dir: paths.target_dir.to_owned(),
|
||||
system_pages: SystemPages {
|
||||
four_oh_four: std::fs::read_to_string(paths.target_dir.join("_treehouse/404.html"))
|
||||
.context("cannot read 404 page")?,
|
||||
b_docs: std::fs::read_to_string(paths.target_dir.join("_treehouse/b.html"))
|
||||
.context("cannot read /b documentation page")?,
|
||||
},
|
||||
}));
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
let app = app.layer(tower_livereload::LiveReloadLayer::new());
|
||||
|
||||
info!("serving on port {port}");
|
||||
Ok(axum::Server::bind(&([0, 0, 0, 0], port).into())
|
||||
.serve(app.into_make_service())
|
||||
.await?)
|
||||
}
|
||||
|
||||
async fn branch(RawQuery(named_id): RawQuery, State(state): State<Arc<Server>>) -> Html<String> {
|
||||
if let Some(named_id) = named_id {
|
||||
if let Some(&branch_id) = state.treehouse.branches_by_named_id.get(&named_id) {
|
||||
let branch = state.treehouse.tree.branch(branch_id);
|
||||
if let Source::Tree { input, tree_path } = state.treehouse.source(branch.file_id) {
|
||||
let file_path = state.target_dir.join(format!("{tree_path}.html"));
|
||||
match std::fs::read_to_string(&file_path) {
|
||||
Ok(content) => {
|
||||
let branch_markdown_content = input[branch.content.clone()].trim();
|
||||
let mut per_page_metadata =
|
||||
String::from("<meta property=\"og:description\" content=\"");
|
||||
escape_html(&mut per_page_metadata, branch_markdown_content).unwrap();
|
||||
per_page_metadata.push_str("\">");
|
||||
|
||||
const PER_PAGE_METADATA_REPLACEMENT_STRING: &str = "<!-- treehouse-ca37057a-cff5-45b3-8415-3b02dbf6c799-per-branch-metadata -->";
|
||||
return Html(content.replacen(
|
||||
PER_PAGE_METADATA_REPLACEMENT_STRING,
|
||||
&per_page_metadata,
|
||||
// Replace one under the assumption that it appears in all pages.
|
||||
1,
|
||||
));
|
||||
}
|
||||
Err(e) => {
|
||||
error!("error while reading file {file_path:?}: {e:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Html(state.system_pages.four_oh_four.clone())
|
||||
} else {
|
||||
Html(state.system_pages.b_docs.clone())
|
||||
}
|
||||
}
|
|
@ -61,7 +61,7 @@ pub fn branch_to_html(
|
|||
s.push_str("<div>");
|
||||
}
|
||||
|
||||
let raw_block_content = &source[branch.content.clone()];
|
||||
let raw_block_content = &source.input()[branch.content.clone()];
|
||||
let mut unindented_block_content = String::with_capacity(raw_block_content.len());
|
||||
for line in raw_block_content.lines() {
|
||||
// Bit of a jank way to remove at most branch.indent_level spaces from the front.
|
||||
|
@ -93,7 +93,11 @@ pub fn branch_to_html(
|
|||
.get(linked)
|
||||
.map(|&branch_id| {
|
||||
(
|
||||
format!("#{}", treehouse.tree.branch(branch_id).html_id).into(),
|
||||
format!(
|
||||
"/b?{}",
|
||||
treehouse.tree.branch(branch_id).attributes.id
|
||||
)
|
||||
.into(),
|
||||
"".into(),
|
||||
)
|
||||
}),
|
||||
|
@ -144,8 +148,8 @@ pub fn branch_to_html(
|
|||
|
||||
write!(
|
||||
s,
|
||||
"<a class=\"icon icon-permalink\" href=\"#{}\" title=\"permalink\"></a>",
|
||||
EscapeAttribute(&branch.html_id)
|
||||
"<a class=\"icon icon-permalink\" href=\"/b?{}\" title=\"permalink\"></a>",
|
||||
EscapeAttribute(&branch.attributes.id)
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
|
|
@ -3,10 +3,11 @@ use std::path::Path;
|
|||
use clap::Parser;
|
||||
use cli::{
|
||||
fix::{fix_all_cli, fix_file_cli},
|
||||
generate::{self, regenerate_or_report_error},
|
||||
generate::regenerate_or_report_error,
|
||||
serve::serve,
|
||||
Command, Paths, ProgramArgs,
|
||||
};
|
||||
use log::{error, info};
|
||||
use log::{error, info, warn};
|
||||
|
||||
mod cli;
|
||||
mod config;
|
||||
|
@ -30,14 +31,17 @@ async fn fallible_main() -> anyhow::Result<()> {
|
|||
};
|
||||
|
||||
match args.command {
|
||||
Command::Generate(regenerate_args) => {
|
||||
Command::Generate(_generate_args) => {
|
||||
info!("regenerating using directories: {paths:#?}");
|
||||
|
||||
regenerate_or_report_error(&paths);
|
||||
|
||||
if let Some(port) = regenerate_args.serve {
|
||||
generate::web_server(port).await?;
|
||||
}
|
||||
regenerate_or_report_error(&paths)?;
|
||||
warn!("`generate` is for debugging only and the files cannot be fully served using a static file server; use `treehouse serve` if you wish to start a treehouse server");
|
||||
}
|
||||
Command::Serve {
|
||||
generate: _,
|
||||
serve: serve_args,
|
||||
} => {
|
||||
let treehouse = regenerate_or_report_error(&paths)?;
|
||||
serve(treehouse, &paths, serve_args.port).await?;
|
||||
}
|
||||
|
||||
Command::Fix(fix_args) => fix_file_cli(fix_args)?,
|
||||
|
|
|
@ -10,7 +10,28 @@ use ulid::Ulid;
|
|||
|
||||
use crate::tree::{SemaBranchId, SemaRoots, SemaTree};
|
||||
|
||||
pub type Files = SimpleFiles<String, String>;
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Source {
|
||||
Tree { input: String, tree_path: String },
|
||||
Other(String),
|
||||
}
|
||||
|
||||
impl Source {
|
||||
pub fn input(&self) -> &str {
|
||||
match &self {
|
||||
Source::Tree { input, .. } => input,
|
||||
Source::Other(source) => source,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for Source {
|
||||
fn as_ref(&self) -> &str {
|
||||
self.input()
|
||||
}
|
||||
}
|
||||
|
||||
pub type Files = SimpleFiles<String, Source>;
|
||||
pub type FileId = <Files as codespan_reporting::files::Files<'static>>::FileId;
|
||||
|
||||
/// Treehouse compilation context.
|
||||
|
@ -22,19 +43,9 @@ pub struct Treehouse {
|
|||
pub branches_by_named_id: HashMap<String, SemaBranchId>,
|
||||
pub roots: HashMap<String, SemaRoots>,
|
||||
|
||||
// Bit of a hack because I don't wanna write my own `Files`.
|
||||
tree_paths: Vec<Option<String>>,
|
||||
|
||||
missingno_generator: ulid::Generator,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct BranchRef {
|
||||
pub html_id: String,
|
||||
pub file_id: FileId,
|
||||
pub kind_span: Range<usize>,
|
||||
}
|
||||
|
||||
impl Treehouse {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
|
@ -45,25 +56,16 @@ impl Treehouse {
|
|||
branches_by_named_id: HashMap::new(),
|
||||
roots: HashMap::new(),
|
||||
|
||||
tree_paths: vec![],
|
||||
|
||||
missingno_generator: ulid::Generator::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_file(
|
||||
&mut self,
|
||||
filename: String,
|
||||
tree_path: Option<String>,
|
||||
source: String,
|
||||
) -> FileId {
|
||||
let id = self.files.add(filename, source);
|
||||
self.tree_paths.push(tree_path);
|
||||
id
|
||||
pub fn add_file(&mut self, filename: String, source: Source) -> FileId {
|
||||
self.files.add(filename, source)
|
||||
}
|
||||
|
||||
/// Get the source code of a file, assuming it was previously registered.
|
||||
pub fn source(&self, file_id: FileId) -> &str {
|
||||
pub fn source(&self, file_id: FileId) -> &Source {
|
||||
self.files
|
||||
.get(file_id)
|
||||
.expect("file should have been registered previously")
|
||||
|
@ -79,7 +81,10 @@ impl Treehouse {
|
|||
}
|
||||
|
||||
pub fn tree_path(&self, file_id: FileId) -> Option<&str> {
|
||||
self.tree_paths[file_id].as_deref()
|
||||
match self.source(file_id) {
|
||||
Source::Tree { tree_path, .. } => Some(tree_path),
|
||||
Source::Other(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn report_diagnostics(&self) -> anyhow::Result<()> {
|
||||
|
@ -98,6 +103,12 @@ impl Treehouse {
|
|||
.generate()
|
||||
.expect("just how much disk space do you have?")
|
||||
}
|
||||
|
||||
pub fn has_errors(&self) -> bool {
|
||||
self.diagnostics
|
||||
.iter()
|
||||
.any(|diagnostic| diagnostic.severity == Severity::Error)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TomlError {
|
||||
|
|
|
@ -1,5 +1,15 @@
|
|||
use serde::Deserialize;
|
||||
|
||||
/// Top-level `%%` root attributes.
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize)]
|
||||
pub struct RootAttributes {
|
||||
/// Title of the generated .html page.
|
||||
///
|
||||
/// The page's tree path is used if empty.
|
||||
#[serde(default)]
|
||||
pub title: String,
|
||||
}
|
||||
|
||||
/// Branch attributes.
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize)]
|
||||
pub struct Attributes {
|
||||
|
|
|
@ -9,10 +9,12 @@ use treehouse_format::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
state::{toml_error_to_diagnostic, FileId, TomlError, Treehouse},
|
||||
state::{toml_error_to_diagnostic, FileId, Source, TomlError, Treehouse},
|
||||
tree::attributes::{Attributes, Content},
|
||||
};
|
||||
|
||||
use self::attributes::RootAttributes;
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct SemaTree {
|
||||
branches: Vec<SemaBranch>,
|
||||
|
@ -35,12 +37,14 @@ impl SemaTree {
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SemaRoots {
|
||||
pub attributes: RootAttributes,
|
||||
pub branches: Vec<SemaBranchId>,
|
||||
}
|
||||
|
||||
impl SemaRoots {
|
||||
pub fn from_roots(treehouse: &mut Treehouse, file_id: FileId, roots: Roots) -> Self {
|
||||
Self {
|
||||
attributes: Self::parse_attributes(treehouse, file_id, &roots),
|
||||
branches: roots
|
||||
.branches
|
||||
.into_iter()
|
||||
|
@ -48,6 +52,44 @@ impl SemaRoots {
|
|||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_attributes(
|
||||
treehouse: &mut Treehouse,
|
||||
file_id: FileId,
|
||||
roots: &Roots,
|
||||
) -> RootAttributes {
|
||||
let source = treehouse.source(file_id);
|
||||
|
||||
let mut successfully_parsed = true;
|
||||
let mut attributes = if let Some(attributes) = &roots.attributes {
|
||||
toml_edit::de::from_str(&source.input()[attributes.data.clone()]).unwrap_or_else(
|
||||
|error| {
|
||||
treehouse
|
||||
.diagnostics
|
||||
.push(toml_error_to_diagnostic(TomlError {
|
||||
message: error.message().to_owned(),
|
||||
span: error.span(),
|
||||
file_id,
|
||||
input_range: attributes.data.clone(),
|
||||
}));
|
||||
successfully_parsed = false;
|
||||
RootAttributes::default()
|
||||
},
|
||||
)
|
||||
} else {
|
||||
RootAttributes::default()
|
||||
};
|
||||
let successfully_parsed = successfully_parsed;
|
||||
|
||||
if successfully_parsed && attributes.title.is_empty() {
|
||||
attributes.title = match treehouse.source(file_id) {
|
||||
Source::Tree { tree_path, .. } => tree_path.clone(),
|
||||
_ => panic!("parse_attributes called for a non-.tree file"),
|
||||
}
|
||||
}
|
||||
|
||||
attributes
|
||||
}
|
||||
}
|
||||
|
||||
/// Analyzed branch.
|
||||
|
@ -132,18 +174,20 @@ impl SemaBranch {
|
|||
|
||||
let mut successfully_parsed = true;
|
||||
let mut attributes = if let Some(attributes) = &branch.attributes {
|
||||
toml_edit::de::from_str(&source[attributes.data.clone()]).unwrap_or_else(|error| {
|
||||
treehouse
|
||||
.diagnostics
|
||||
.push(toml_error_to_diagnostic(TomlError {
|
||||
message: error.message().to_owned(),
|
||||
span: error.span(),
|
||||
file_id,
|
||||
input_range: attributes.data.clone(),
|
||||
}));
|
||||
successfully_parsed = false;
|
||||
Attributes::default()
|
||||
})
|
||||
toml_edit::de::from_str(&source.input()[attributes.data.clone()]).unwrap_or_else(
|
||||
|error| {
|
||||
treehouse
|
||||
.diagnostics
|
||||
.push(toml_error_to_diagnostic(TomlError {
|
||||
message: error.message().to_owned(),
|
||||
span: error.span(),
|
||||
file_id,
|
||||
input_range: attributes.data.clone(),
|
||||
}));
|
||||
successfully_parsed = false;
|
||||
Attributes::default()
|
||||
},
|
||||
)
|
||||
} else {
|
||||
Attributes::default()
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue