Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ members = [
"core_lang",
"core-types",
"forc",
"formatter",
"sway-server",
"test_suite"
]
11 changes: 6 additions & 5 deletions forc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,18 @@ version = "0.1.0"

[dependencies]
core_lang = {path = "../core_lang"}
fuel-tx = { git = "ssh://git@github.com/FuelLabs/fuel-tx.git" }
fuel-vm = { git = "ssh://git@github.com/FuelLabs/fuel-vm.git" }
formatter = {path = "../formatter"}
fuel-tx = {git = "ssh://git@github.com/FuelLabs/fuel-tx.git"}
fuel-vm = {git = "ssh://git@github.com/FuelLabs/fuel-vm.git"}
hex = "0.4.3"
line-col = "0.2"
#pest = "2.1"
pest = { git = "https://github.com/sezna/pest.git" , rev = "8aa58791f759daf4caee26e8560e862df5a6afb7" }
fuel-asm = {git = "ssh://git@github.com/FuelLabs/fuel-asm.git"}
pest = {git = "https://github.com/sezna/pest.git", rev = "8aa58791f759daf4caee26e8560e862df5a6afb7"}
serde = {version = "1.0", features = ["derive"]}
source-span = "2.4"
structopt = "0.3"
term-table = "1.3"
termcolor = "1.1"
toml = "0.5"
whoami = "1.1"
fuel-asm = { git = "ssh://git@github.com/FuelLabs/fuel-asm.git" }
term-table = "1.3"
16 changes: 16 additions & 0 deletions forc/src/cli/commands/format.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use structopt::{self, StructOpt};

use crate::ops::forc_fmt;

#[derive(Debug, StructOpt)]
pub struct Command {
#[structopt(short, long)]
pub check: bool,
}

pub(crate) fn exec(command: Command) -> Result<(), String> {
match forc_fmt::format(command) {
Err(e) => Err(e.message),
_ => Ok(()),
}
}
1 change: 1 addition & 0 deletions forc/src/cli/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub mod benchmark;
pub mod build;
pub mod coverage;
pub mod deploy;
pub mod format;
pub mod init;
pub mod mvprun;
pub mod parse_bytecode;
Expand Down
9 changes: 7 additions & 2 deletions forc/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ use structopt::StructOpt;

mod commands;
use self::commands::{
analysis, benchmark, build, coverage, deploy, init, mvprun, parse_bytecode, publish, serve,
test,
analysis, benchmark, build, coverage, deploy, format, init, mvprun, parse_bytecode, publish,
serve, test,
};

use analysis::Command as AnalysisCommand;
use benchmark::Command as BenchmarkCommand;
pub use build::Command as BuildCommand;
use coverage::Command as CoverageCommand;
use deploy::Command as DeployCommand;
pub use format::Command as FormatCommand;
use init::Command as InitCommand;
use mvprun::Command as MvprunCommand;
use parse_bytecode::Command as ParseBytecodeCommand;
Expand All @@ -32,6 +33,9 @@ enum Forc {
Benchmark(BenchmarkCommand),
Build(BuildCommand),
Coverage(CoverageCommand),

#[structopt(name = "fmt")]
Format(FormatCommand),
Deploy(DeployCommand),
Init(InitCommand),
Mvprun(MvprunCommand),
Expand All @@ -48,6 +52,7 @@ pub(crate) fn run_cli() -> Result<(), String> {
Forc::Benchmark(command) => benchmark::exec(command),
Forc::Build(command) => build::exec(command),
Forc::Coverage(command) => coverage::exec(command),
Forc::Format(command) => format::exec(command),
Forc::Deploy(command) => deploy::exec(command),
Forc::Init(command) => init::exec(command),
Forc::Mvprun(command) => mvprun::exec(command),
Expand Down
19 changes: 1 addition & 18 deletions forc/src/ops/forc_build.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::cli::BuildCommand;
use crate::{cli::BuildCommand, utils::helpers::find_manifest_dir};
use line_col::LineColLookup;
use source_span::{
fmt::{Color, Formatter, Style},
Expand Down Expand Up @@ -74,23 +74,6 @@ pub fn build(command: BuildCommand) -> Result<Vec<u8>, String> {
Ok(main)
}

/// Continually go up in the file tree until a manifest (Forc.toml) is found.
fn find_manifest_dir(starter_path: &PathBuf) -> Option<PathBuf> {
let mut path = fs::canonicalize(starter_path.clone()).ok()?;
let empty_path = PathBuf::from("/");
while path != empty_path {
path.push(crate::utils::constants::MANIFEST_FILE_NAME);
if path.exists() {
path.pop();
return Some(path);
} else {
path.pop();
path.pop();
}
}
None
}

/// Takes a dependency and returns a namespace of exported things from that dependency
/// trait implementations are included as well
fn compile_dependency_lib<'source, 'manifest>(
Expand Down
126 changes: 126 additions & 0 deletions forc/src/ops/forc_fmt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
use crate::{
cli::FormatCommand,
utils::{constants::SWAY_EXTENSION, helpers::find_manifest_dir},
};
use formatter::get_formatted_data;
use std::{
ffi::OsStr,
fmt, fs, io,
path::{Path, PathBuf},
};

pub fn format(command: FormatCommand) -> Result<(), FormatError> {
let curr_dir = std::env::current_dir()?;

match find_manifest_dir(&curr_dir) {
Some(path) => {
let files = get_sway_files(path)?;
let mut files_to_be_formatted = vec![];

for file in files {
if let Ok(file_content) = fs::read_to_string(&file) {
match core_lang::parse(&file_content) {
core_lang::CompileResult::Ok {
value: _,
warnings: _,
errors: _,
} => {
if command.check {
if file_should_change(&file_content) {
files_to_be_formatted.push(format!("{:?}", file))
}
} else {
format_sway_file(&file_content, &file)?;
}
}
_ => {}
}
}
}

if command.check {
if files_to_be_formatted.is_empty() {
// All files are formatted, exit cleanly
std::process::exit(0);
} else {
for file in files_to_be_formatted {
eprintln!("{}", file);
}
// One or more files are not formatted, exit with error
std::process::exit(1);
}
}

Ok(())
}
_ => Err("Manifest file does not exist".into()),
}
}

fn get_sway_files(path: PathBuf) -> Result<Vec<PathBuf>, FormatError> {
let mut files = vec![];
let mut dir_entries = vec![path];

while let Some(entry) = dir_entries.pop() {
for inner_entry in fs::read_dir(entry)? {
if let Ok(entry) = inner_entry {
let path = entry.path();
if path.is_dir() {
dir_entries.push(path);
} else {
if is_sway_file(&path) {
files.push(path)
}
}
}
}
}

Ok(files)
}

fn file_should_change(file_content: &str) -> bool {
// todo: get tab_size from Manifest file
let (_, formatted_content) = get_formatted_data(file_content, 4);
let should_change = file_content != &formatted_content;
should_change
}

fn format_sway_file(file_content: &str, file: &PathBuf) -> Result<(), FormatError> {
// todo: get tab_size from Manifest file
let (_, formatted_content) = get_formatted_data(file_content, 4);
fs::write(file, formatted_content)?;

Ok(())
}

fn is_sway_file(file: &Path) -> bool {
let res = file.extension();
Some(OsStr::new(SWAY_EXTENSION)) == res
}

pub struct FormatError {
pub message: String,
}

impl fmt::Display for FormatError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "{}", self)
}
}

impl From<&str> for FormatError {
fn from(s: &str) -> Self {
FormatError {
message: s.to_string(),
}
}
}

impl From<io::Error> for FormatError {
fn from(e: io::Error) -> Self {
FormatError {
message: e.to_string(),
}
}
}
1 change: 1 addition & 0 deletions forc/src/ops/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod forc_build;
pub mod forc_fmt;
pub mod forc_init;
1 change: 1 addition & 0 deletions forc/src/utils/constants.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub const MANIFEST_FILE_NAME: &'static str = "Forc.toml";
pub const SWAY_EXTENSION: &'static str = "sw";
18 changes: 18 additions & 0 deletions forc/src/utils/helpers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use std::path::PathBuf;

// Continually go up in the file tree until a manifest (Forc.toml) is found.
pub fn find_manifest_dir(starter_path: &PathBuf) -> Option<PathBuf> {
let mut path = std::fs::canonicalize(starter_path.clone()).ok()?;
let empty_path = PathBuf::from("/");
while path != empty_path {
path.push(crate::utils::constants::MANIFEST_FILE_NAME);
if path.exists() {
path.pop();
return Some(path);
} else {
path.pop();
path.pop();
}
}
None
}
1 change: 1 addition & 0 deletions forc/src/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod constants;
pub mod defaults;
pub mod helpers;
pub mod manifest;
7 changes: 7 additions & 0 deletions formatter/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
authors = ["leviathan88 <elvisdedic@outlook.com>"]
edition = "2018"
name = "formatter"
version = "0.1.0"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ use std::{
str::Chars,
};

use lspower::lsp::{Position, Range, TextEdit};

use super::parse_helpers::{clean_all_incoming_whitespace, is_comment};
use super::{
code_line::CodeLine,
Expand All @@ -30,27 +28,17 @@ impl CodeBuilder {
}
}

pub fn to_text_edit(&mut self, text_lines_count: usize) -> Vec<TextEdit> {
let line_end = std::cmp::max(self.edits.len(), text_lines_count) as u32;

pub fn get_final_edits(mut self) -> (usize, String) {
// add new line at the end if needed
if let Some(code_line) = self.edits.last() {
if !code_line.is_empty() {
self.edits.push(CodeLine::empty_line())
}
}

let main_edit = TextEdit {
range: Range::new(Position::new(0, 0), Position::new(line_end as u32, 0)),
new_text: self
.edits
.iter()
.map(|code_line| code_line.text.clone())
.collect::<Vec<String>>()
.join("\n"),
};
let num_of_lines = self.edits.len();

vec![main_edit]
(num_of_lines, self.to_string())
}

/// formats line of code and adds it to Vec<CodeLine>
Expand Down Expand Up @@ -131,6 +119,14 @@ impl CodeBuilder {
self.add_line(code_line);
}

fn to_string(&mut self) -> String {
self.edits
.iter()
.map(|code_line| code_line.text.clone())
.collect::<Vec<String>>()
.join("\n")
}

/// if previous line is not completed get it, otherwise start a new one
fn get_unfinished_code_line_or_new(&mut self) -> CodeLine {
match self.edits.last() {
Expand Down
14 changes: 14 additions & 0 deletions formatter/src/formatter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use super::code_builder::CodeBuilder;

/// returns number of lines and formatted text
pub fn get_formatted_data(file: &str, tab_size: u32) -> (usize, String) {
let mut code_builder = CodeBuilder::new(tab_size);
let lines: Vec<&str> = file.split("\n").collect();

// todo: handle lengthy lines of code
for line in lines {
code_builder.format_and_add(line);
}

code_builder.get_final_edits()
}
6 changes: 6 additions & 0 deletions formatter/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
mod code_builder;
mod code_line;
mod formatter;
mod parse_helpers;

pub use crate::formatter::get_formatted_data;
Loading