mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 15:21:12 +00:00
Implement [more] app header formatting
Also, refactor out a utility method to format a Collection. This method can currently replace some of the formatting done in module headers - but the goal is eventually to be able to replace the code in fmt_list as well, such that there is 'one true way' to format collections.
This commit is contained in:
parent
f02ed47f31
commit
24f7692a73
9 changed files with 322 additions and 137 deletions
|
@ -1,7 +1,13 @@
|
|||
use crate::spaces::{fmt_spaces, INDENT};
|
||||
use crate::annotation::Formattable;
|
||||
use crate::collection::{fmt_collection, CollectionConfig};
|
||||
use crate::expr::fmt_str_literal;
|
||||
use crate::spaces::{fmt_default_spaces, fmt_spaces, INDENT};
|
||||
use bumpalo::collections::String;
|
||||
use roc_parse::ast::{Collection, Module};
|
||||
use roc_parse::header::{AppHeader, ExposesEntry, ImportsEntry, InterfaceHeader, PlatformHeader};
|
||||
use roc_parse::header::{
|
||||
AppHeader, ExposesEntry, ImportsEntry, InterfaceHeader, PackageEntry, PackageOrPath,
|
||||
PlatformHeader, To,
|
||||
};
|
||||
use roc_region::all::Located;
|
||||
|
||||
pub fn fmt_module<'a>(buf: &mut String<'a>, module: &'a Module<'a>) {
|
||||
|
@ -24,46 +30,19 @@ pub fn fmt_interface_header<'a>(buf: &mut String<'a>, header: &'a InterfaceHeade
|
|||
buf.push_str("interface");
|
||||
|
||||
// module name
|
||||
if header.after_interface_keyword.is_empty() {
|
||||
buf.push(' ');
|
||||
} else {
|
||||
fmt_spaces(buf, header.after_interface_keyword.iter(), indent);
|
||||
}
|
||||
|
||||
fmt_default_spaces(buf, header.after_interface_keyword, " ", indent);
|
||||
buf.push_str(header.name.value.as_str());
|
||||
|
||||
// exposes
|
||||
if header.before_exposes.is_empty() {
|
||||
buf.push(' ');
|
||||
} else {
|
||||
fmt_spaces(buf, header.before_exposes.iter(), indent);
|
||||
}
|
||||
|
||||
fmt_default_spaces(buf, header.before_exposes, " ", indent);
|
||||
buf.push_str("exposes");
|
||||
|
||||
if header.after_exposes.is_empty() {
|
||||
buf.push(' ');
|
||||
} else {
|
||||
fmt_spaces(buf, header.after_exposes.iter(), indent);
|
||||
}
|
||||
|
||||
fmt_default_spaces(buf, header.after_exposes, " ", indent);
|
||||
fmt_exposes(buf, &header.exposes, indent);
|
||||
|
||||
// imports
|
||||
if header.before_imports.is_empty() {
|
||||
buf.push(' ');
|
||||
} else {
|
||||
fmt_spaces(buf, header.before_imports.iter(), indent);
|
||||
}
|
||||
|
||||
fmt_default_spaces(buf, header.before_imports, " ", indent);
|
||||
buf.push_str("imports");
|
||||
|
||||
if header.after_imports.is_empty() {
|
||||
buf.push(' ');
|
||||
} else {
|
||||
fmt_spaces(buf, header.after_imports.iter(), indent);
|
||||
}
|
||||
|
||||
fmt_default_spaces(buf, header.after_imports, " ", indent);
|
||||
fmt_imports(buf, header.imports, indent);
|
||||
}
|
||||
|
||||
|
@ -72,12 +51,30 @@ pub fn fmt_app_header<'a>(buf: &mut String<'a>, header: &'a AppHeader<'a>) {
|
|||
|
||||
buf.push_str("app");
|
||||
|
||||
// imports
|
||||
buf.push_str("imports");
|
||||
fmt_default_spaces(buf, header.after_app_keyword, " ", indent);
|
||||
fmt_str_literal(buf, header.name.value, indent);
|
||||
|
||||
fmt_spaces(buf, header.before_imports.iter(), indent);
|
||||
// packages
|
||||
fmt_default_spaces(buf, header.before_packages, " ", indent);
|
||||
buf.push_str("packages");
|
||||
fmt_default_spaces(buf, header.after_packages, " ", indent);
|
||||
fmt_packages(buf, header.packages, indent);
|
||||
|
||||
// imports
|
||||
fmt_default_spaces(buf, header.before_imports, " ", indent);
|
||||
buf.push_str("imports");
|
||||
fmt_default_spaces(buf, header.after_imports, " ", indent);
|
||||
fmt_imports(buf, header.imports, indent);
|
||||
fmt_spaces(buf, header.after_imports.iter(), indent);
|
||||
|
||||
// provides
|
||||
fmt_default_spaces(buf, header.before_provides, " ", indent);
|
||||
buf.push_str("provides");
|
||||
fmt_default_spaces(buf, header.after_provides, " ", indent);
|
||||
fmt_provides(buf, header.provides, indent);
|
||||
fmt_default_spaces(buf, header.before_to, " ", indent);
|
||||
buf.push_str("to");
|
||||
fmt_default_spaces(buf, header.after_to, " ", indent);
|
||||
fmt_to(buf, header.to.value, indent);
|
||||
}
|
||||
|
||||
pub fn fmt_platform_header<'a>(_buf: &mut String<'a>, _header: &'a PlatformHeader<'a>) {
|
||||
|
@ -89,25 +86,42 @@ fn fmt_imports<'a>(
|
|||
loc_entries: Collection<'a, Located<ImportsEntry<'a>>>,
|
||||
indent: u16,
|
||||
) {
|
||||
buf.push('[');
|
||||
fmt_collection(
|
||||
buf,
|
||||
loc_entries,
|
||||
indent,
|
||||
CollectionConfig {
|
||||
begin: '[',
|
||||
end: ']',
|
||||
delimiter: ',',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if !loc_entries.is_empty() {
|
||||
buf.push(' ');
|
||||
}
|
||||
fn fmt_provides<'a>(
|
||||
buf: &mut String<'a>,
|
||||
loc_entries: Collection<'a, Located<ExposesEntry<'a, &'a str>>>,
|
||||
indent: u16,
|
||||
) {
|
||||
fmt_collection(
|
||||
buf,
|
||||
loc_entries,
|
||||
indent,
|
||||
CollectionConfig {
|
||||
begin: '[',
|
||||
end: ']',
|
||||
delimiter: ',',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
for (index, loc_entry) in loc_entries.iter().enumerate() {
|
||||
if index > 0 {
|
||||
buf.push_str(", ");
|
||||
fn fmt_to<'a>(buf: &mut String<'a>, to: To<'a>, indent: u16) {
|
||||
match to {
|
||||
To::ExistingPackage(name) => {
|
||||
buf.push_str(name);
|
||||
}
|
||||
|
||||
fmt_imports_entry(buf, &loc_entry.value, indent);
|
||||
To::NewPackage(package_or_path) => fmt_package_or_path(buf, &package_or_path, indent),
|
||||
}
|
||||
|
||||
if !loc_entries.is_empty() {
|
||||
buf.push(' ');
|
||||
}
|
||||
|
||||
buf.push(']');
|
||||
}
|
||||
|
||||
fn fmt_exposes<'a>(
|
||||
|
@ -115,28 +129,29 @@ fn fmt_exposes<'a>(
|
|||
loc_entries: &'a Collection<'a, Located<ExposesEntry<'a, &'a str>>>,
|
||||
indent: u16,
|
||||
) {
|
||||
buf.push('[');
|
||||
|
||||
if !loc_entries.is_empty() {
|
||||
buf.push(' ');
|
||||
}
|
||||
|
||||
for (index, loc_entry) in loc_entries.iter().enumerate() {
|
||||
if index > 0 {
|
||||
buf.push_str(", ");
|
||||
}
|
||||
|
||||
fmt_exposes_entry(buf, &loc_entry.value, indent);
|
||||
}
|
||||
|
||||
if !loc_entries.is_empty() {
|
||||
buf.push(' ');
|
||||
}
|
||||
|
||||
buf.push(']');
|
||||
fmt_collection(
|
||||
buf,
|
||||
*loc_entries,
|
||||
indent,
|
||||
CollectionConfig {
|
||||
begin: '[',
|
||||
end: ']',
|
||||
delimiter: ',',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn fmt_exposes_entry<'a>(buf: &mut String<'a>, entry: &'a ExposesEntry<'a, &'a str>, indent: u16) {
|
||||
impl<'a> Formattable<'a> for ExposesEntry<'a, &'a str> {
|
||||
fn is_multiline(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn format(&self, buf: &mut String<'a>, indent: u16) {
|
||||
fmt_exposes_entry(buf, self, indent);
|
||||
}
|
||||
}
|
||||
|
||||
fn fmt_exposes_entry<'a>(buf: &mut String<'a>, entry: &ExposesEntry<'a, &'a str>, indent: u16) {
|
||||
use roc_parse::header::ExposesEntry::*;
|
||||
|
||||
match entry {
|
||||
|
@ -153,7 +168,76 @@ fn fmt_exposes_entry<'a>(buf: &mut String<'a>, entry: &'a ExposesEntry<'a, &'a s
|
|||
}
|
||||
}
|
||||
|
||||
fn fmt_imports_entry<'a>(buf: &mut String<'a>, entry: &'a ImportsEntry<'a>, indent: u16) {
|
||||
fn fmt_packages<'a>(
|
||||
buf: &mut String<'a>,
|
||||
loc_entries: Collection<'a, Located<PackageEntry<'a>>>,
|
||||
indent: u16,
|
||||
) {
|
||||
fmt_collection(
|
||||
buf,
|
||||
loc_entries,
|
||||
indent,
|
||||
CollectionConfig {
|
||||
begin: '{',
|
||||
end: '}',
|
||||
delimiter: ',',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
impl<'a> Formattable<'a> for PackageEntry<'a> {
|
||||
fn is_multiline(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn format(&self, buf: &mut String<'a>, indent: u16) {
|
||||
fmt_packages_entry(buf, self, indent);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Formattable<'a> for ImportsEntry<'a> {
|
||||
fn is_multiline(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn format(&self, buf: &mut String<'a>, indent: u16) {
|
||||
fmt_imports_entry(buf, self, indent);
|
||||
}
|
||||
}
|
||||
fn fmt_packages_entry<'a>(buf: &mut String<'a>, entry: &PackageEntry<'a>, indent: u16) {
|
||||
use PackageEntry::*;
|
||||
match entry {
|
||||
Entry {
|
||||
shorthand,
|
||||
spaces_after_shorthand,
|
||||
package_or_path,
|
||||
} => {
|
||||
buf.push_str(shorthand);
|
||||
buf.push(':');
|
||||
fmt_default_spaces(buf, spaces_after_shorthand, " ", indent);
|
||||
fmt_package_or_path(buf, &package_or_path.value, indent);
|
||||
}
|
||||
SpaceBefore(sub_entry, spaces) => {
|
||||
fmt_spaces(buf, spaces.iter(), indent);
|
||||
fmt_packages_entry(buf, sub_entry, indent);
|
||||
}
|
||||
SpaceAfter(sub_entry, spaces) => {
|
||||
fmt_packages_entry(buf, sub_entry, indent);
|
||||
fmt_spaces(buf, spaces.iter(), indent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fmt_package_or_path<'a>(buf: &mut String<'a>, package_or_path: &PackageOrPath<'a>, indent: u16) {
|
||||
match package_or_path {
|
||||
PackageOrPath::Package(_name, _version) => {
|
||||
todo!("format package");
|
||||
}
|
||||
PackageOrPath::Path(str_literal) => fmt_str_literal(buf, *str_literal, indent),
|
||||
}
|
||||
}
|
||||
|
||||
fn fmt_imports_entry<'a>(buf: &mut String<'a>, entry: &ImportsEntry<'a>, indent: u16) {
|
||||
use roc_parse::header::ImportsEntry::*;
|
||||
|
||||
match entry {
|
||||
|
@ -161,17 +245,18 @@ fn fmt_imports_entry<'a>(buf: &mut String<'a>, entry: &'a ImportsEntry<'a>, inde
|
|||
buf.push_str(module.as_str());
|
||||
|
||||
if !loc_exposes_entries.is_empty() {
|
||||
buf.push_str(".{ ");
|
||||
buf.push('.');
|
||||
|
||||
for (index, loc_entry) in loc_exposes_entries.iter().enumerate() {
|
||||
if index > 0 {
|
||||
buf.push_str(", ");
|
||||
}
|
||||
|
||||
fmt_exposes_entry(buf, &loc_entry.value, indent);
|
||||
}
|
||||
|
||||
buf.push_str(" }");
|
||||
fmt_collection(
|
||||
buf,
|
||||
*loc_exposes_entries,
|
||||
indent,
|
||||
CollectionConfig {
|
||||
begin: '{',
|
||||
end: '}',
|
||||
delimiter: ',',
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue