diff --git a/.gitignore b/.gitignore index eb941c1cec9..f4c05b5167b 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,8 @@ Cargo.lock # These are backup files generated by rustfmt **/*.rs.bk + +# Ignore Typescript files +out +node_modules +.vscode-test \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 44a01a37e8f..466f1bcd430 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,4 @@ [workspace] -members = ["core_lang", "forc", "test_suite"] +members = ["core_lang", "forc", "test_suite", "fume-server"] diff --git a/LICENSE b/LICENSE index 261eeb9e9f8..f49a4e16e68 100644 --- a/LICENSE +++ b/LICENSE @@ -198,4 +198,4 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and - limitations under the License. + limitations under the License. \ No newline at end of file diff --git a/core_lang/src/ident.rs b/core_lang/src/ident.rs index 7850570749a..e485492d5ab 100644 --- a/core_lang/src/ident.rs +++ b/core_lang/src/ident.rs @@ -5,12 +5,12 @@ use pest::Span; use std::hash::{Hash, Hasher}; #[derive(Debug, Clone)] pub struct Ident<'sc> { - pub(crate) primary_name: &'sc str, + pub primary_name: &'sc str, // sub-names are the stuff after periods // like x.test.thing.method() // `test`, `thing`, and `method` are sub-names // the primary name is `x` - pub(crate) span: Span<'sc>, + pub span: Span<'sc>, } // custom implementation of Hash so that namespacing isn't reliant on the span itself, which will diff --git a/core_lang/src/lib.rs b/core_lang/src/lib.rs index fc3eea0bd9f..a89d01c32bb 100644 --- a/core_lang/src/lib.rs +++ b/core_lang/src/lib.rs @@ -11,7 +11,7 @@ mod parse_tree; mod parser; mod semantic_analysis; -use crate::parse_tree::*; +pub use crate::parse_tree::*; use crate::parser::{HllParser, Rule}; use crate::{asm_generation::compile_ast_to_asm, error::*}; pub use asm_generation::{AbstractInstructionSet, FinalizedAsm, HllAsmSet}; @@ -20,10 +20,9 @@ use pest::iterators::Pair; use pest::Parser; use semantic_analysis::{TreeType, TypedParseTree}; use std::collections::HashMap; - pub(crate) mod types; pub(crate) mod utils; -pub(crate) use crate::parse_tree::{Expression, UseStatement, WhileLoop}; +pub use crate::parse_tree::{Declaration, Expression, UseStatement, WhileLoop}; pub use error::{CompileError, CompileResult, CompileWarning}; pub use ident::Ident; @@ -59,18 +58,18 @@ pub struct ParseTree<'sc> { /// In a typical programming language, you might have a single root node for your syntax tree. /// In this language however, we want to expose multiple public functions at the root /// level so the tree is multi-root. - root_nodes: Vec>, - span: Span<'sc>, + pub root_nodes: Vec>, + pub span: Span<'sc>, } #[derive(Debug, Clone)] -struct AstNode<'sc> { - content: AstNodeContent<'sc>, - span: Span<'sc>, +pub struct AstNode<'sc> { + pub content: AstNodeContent<'sc>, + pub span: Span<'sc>, } #[derive(Debug, Clone)] -pub(crate) enum AstNodeContent<'sc> { +pub enum AstNodeContent<'sc> { UseStatement(UseStatement<'sc>), ReturnStatement(ReturnStatement<'sc>), Declaration(Declaration<'sc>), diff --git a/core_lang/src/parse_tree/call_path.rs b/core_lang/src/parse_tree/call_path.rs index e46de7f7055..57a5583b9be 100644 --- a/core_lang/src/parse_tree/call_path.rs +++ b/core_lang/src/parse_tree/call_path.rs @@ -7,8 +7,8 @@ use pest::Span; /// in the expression `a::b::c()`, `a` and `b` are the prefixes and `c` is the suffix. #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct CallPath<'sc> { - pub(crate) prefixes: Vec>, - pub(crate) suffix: Ident<'sc>, + pub prefixes: Vec>, + pub suffix: Ident<'sc>, } impl<'sc> std::convert::From> for CallPath<'sc> { diff --git a/core_lang/src/parse_tree/code_block.rs b/core_lang/src/parse_tree/code_block.rs index 27f65c549b7..73985c5f3d8 100644 --- a/core_lang/src/parse_tree/code_block.rs +++ b/core_lang/src/parse_tree/code_block.rs @@ -10,8 +10,8 @@ use pest::Span; use std::collections::HashMap; #[derive(Debug, Clone)] -pub(crate) struct CodeBlock<'sc> { - pub(crate) contents: Vec>, +pub struct CodeBlock<'sc> { + pub contents: Vec>, pub(crate) scope: HashMap<&'sc str, Declaration<'sc>>, pub(crate) whole_block_span: Span<'sc>, } diff --git a/core_lang/src/parse_tree/declaration/enum_declaration.rs b/core_lang/src/parse_tree/declaration/enum_declaration.rs index 861e221a0c7..cffaf687f15 100644 --- a/core_lang/src/parse_tree/declaration/enum_declaration.rs +++ b/core_lang/src/parse_tree/declaration/enum_declaration.rs @@ -11,7 +11,7 @@ use pest::iterators::Pair; use pest::Span; #[derive(Debug, Clone)] pub struct EnumDeclaration<'sc> { - pub(crate) name: Ident<'sc>, + pub name: Ident<'sc>, pub(crate) type_parameters: Vec>, pub(crate) variants: Vec>, pub(crate) span: Span<'sc>, diff --git a/core_lang/src/parse_tree/declaration/function_declaration.rs b/core_lang/src/parse_tree/declaration/function_declaration.rs index 8a541106aa6..9612157838e 100644 --- a/core_lang/src/parse_tree/declaration/function_declaration.rs +++ b/core_lang/src/parse_tree/declaration/function_declaration.rs @@ -22,10 +22,10 @@ impl Visibility { } #[derive(Debug, Clone)] -pub(crate) struct FunctionDeclaration<'sc> { - pub(crate) name: Ident<'sc>, +pub struct FunctionDeclaration<'sc> { + pub name: Ident<'sc>, pub(crate) visibility: Visibility, - pub(crate) body: CodeBlock<'sc>, + pub body: CodeBlock<'sc>, pub(crate) parameters: Vec>, pub(crate) span: pest::Span<'sc>, pub(crate) return_type: TypeInfo<'sc>, diff --git a/core_lang/src/parse_tree/declaration/impl_trait.rs b/core_lang/src/parse_tree/declaration/impl_trait.rs index b4362196d65..320e03b11b6 100644 --- a/core_lang/src/parse_tree/declaration/impl_trait.rs +++ b/core_lang/src/parse_tree/declaration/impl_trait.rs @@ -5,7 +5,7 @@ use pest::iterators::Pair; use pest::Span; #[derive(Debug, Clone)] -pub(crate) struct ImplTrait<'sc> { +pub struct ImplTrait<'sc> { pub(crate) trait_name: CallPath<'sc>, pub(crate) type_implementing_for: TypeInfo<'sc>, pub(crate) type_arguments: Vec>, @@ -18,7 +18,7 @@ pub(crate) struct ImplTrait<'sc> { /// An impl of methods without a trait /// like `impl MyType { fn foo { .. } }` #[derive(Debug, Clone)] -pub(crate) struct ImplSelf<'sc> { +pub struct ImplSelf<'sc> { pub(crate) type_implementing_for: TypeInfo<'sc>, pub(crate) type_arguments: Vec>, pub(crate) functions: Vec>, diff --git a/core_lang/src/parse_tree/declaration/mod.rs b/core_lang/src/parse_tree/declaration/mod.rs index 991d41a602d..cb370d6cf1c 100644 --- a/core_lang/src/parse_tree/declaration/mod.rs +++ b/core_lang/src/parse_tree/declaration/mod.rs @@ -14,7 +14,7 @@ pub(crate) use reassignment::*; pub(crate) use struct_declaration::*; pub(crate) use trait_declaration::*; pub(crate) use type_parameter::*; -pub(crate) use variable_declaration::*; +pub use variable_declaration::*; use crate::error::*; use crate::parse_tree::Expression; @@ -24,7 +24,7 @@ use crate::Ident; use pest::iterators::Pair; #[derive(Debug, Clone)] -pub(crate) enum Declaration<'sc> { +pub enum Declaration<'sc> { VariableDeclaration(VariableDeclaration<'sc>), FunctionDeclaration(FunctionDeclaration<'sc>), TraitDeclaration(TraitDeclaration<'sc>), diff --git a/core_lang/src/parse_tree/declaration/reassignment.rs b/core_lang/src/parse_tree/declaration/reassignment.rs index 209012d082b..31c28e9a2af 100644 --- a/core_lang/src/parse_tree/declaration/reassignment.rs +++ b/core_lang/src/parse_tree/declaration/reassignment.rs @@ -6,11 +6,11 @@ use pest::iterators::Pair; use pest::Span; #[derive(Debug, Clone)] -pub(crate) struct Reassignment<'sc> { +pub struct Reassignment<'sc> { // the thing being reassigned - pub(crate) lhs: Ident<'sc>, + pub lhs: Ident<'sc>, // the expression that is being assigned to the lhs - pub(crate) rhs: Expression<'sc>, + pub rhs: Expression<'sc>, pub(crate) span: Span<'sc>, } diff --git a/core_lang/src/parse_tree/declaration/struct_declaration.rs b/core_lang/src/parse_tree/declaration/struct_declaration.rs index 5b9fe428c0a..9563c2b1c4f 100644 --- a/core_lang/src/parse_tree/declaration/struct_declaration.rs +++ b/core_lang/src/parse_tree/declaration/struct_declaration.rs @@ -11,7 +11,7 @@ use super::Visibility; #[derive(Debug, Clone)] pub struct StructDeclaration<'sc> { - pub(crate) name: Ident<'sc>, + pub name: Ident<'sc>, pub(crate) fields: Vec>, pub(crate) type_parameters: Vec>, pub(crate) visibility: Visibility, diff --git a/core_lang/src/parse_tree/declaration/trait_declaration.rs b/core_lang/src/parse_tree/declaration/trait_declaration.rs index 21c6e59b91a..fb06656b851 100644 --- a/core_lang/src/parse_tree/declaration/trait_declaration.rs +++ b/core_lang/src/parse_tree/declaration/trait_declaration.rs @@ -9,8 +9,8 @@ use pest::iterators::Pair; use pest::Span; #[derive(Debug, Clone)] -pub(crate) struct TraitDeclaration<'sc> { - pub(crate) name: Ident<'sc>, +pub struct TraitDeclaration<'sc> { + pub name: Ident<'sc>, pub(crate) interface_surface: Vec>, pub(crate) methods: Vec>, pub(crate) type_parameters: Vec>, diff --git a/core_lang/src/parse_tree/declaration/variable_declaration.rs b/core_lang/src/parse_tree/declaration/variable_declaration.rs index c74a6c4ae4f..099d32c7d39 100644 --- a/core_lang/src/parse_tree/declaration/variable_declaration.rs +++ b/core_lang/src/parse_tree/declaration/variable_declaration.rs @@ -2,9 +2,9 @@ use crate::parse_tree::Expression; use crate::{types::TypeInfo, Ident}; #[derive(Debug, Clone)] -pub(crate) struct VariableDeclaration<'sc> { - pub(crate) name: Ident<'sc>, - pub(crate) type_ascription: Option>, - pub(crate) body: Expression<'sc>, // will be codeblock variant - pub(crate) is_mutable: bool, +pub struct VariableDeclaration<'sc> { + pub name: Ident<'sc>, + pub type_ascription: Option>, + pub body: Expression<'sc>, // will be codeblock variant + pub is_mutable: bool, } diff --git a/core_lang/src/parse_tree/expression/asm.rs b/core_lang/src/parse_tree/expression/asm.rs index 5f8767b6bf8..0e7d29f8c55 100644 --- a/core_lang/src/parse_tree/expression/asm.rs +++ b/core_lang/src/parse_tree/expression/asm.rs @@ -9,7 +9,7 @@ use super::Expression; use crate::types::IntegerBits; #[derive(Debug, Clone)] -pub(crate) struct AsmExpression<'sc> { +pub struct AsmExpression<'sc> { pub(crate) registers: Vec>, pub(crate) body: Vec>, pub(crate) returns: Option<(AsmRegister, Span<'sc>)>, diff --git a/core_lang/src/parse_tree/expression/mod.rs b/core_lang/src/parse_tree/expression/mod.rs index 8b9489a8318..8c973049a29 100644 --- a/core_lang/src/parse_tree/expression/mod.rs +++ b/core_lang/src/parse_tree/expression/mod.rs @@ -12,7 +12,7 @@ use crate::utils::join_spans; pub(crate) use asm::*; #[derive(Debug, Clone)] -pub(crate) enum Expression<'sc> { +pub enum Expression<'sc> { Literal { value: Literal<'sc>, span: Span<'sc>, @@ -110,7 +110,7 @@ pub(crate) enum Expression<'sc> { } #[derive(Debug, Clone)] -pub(crate) struct StructExpressionField<'sc> { +pub struct StructExpressionField<'sc> { pub(crate) name: Ident<'sc>, pub(crate) value: Expression<'sc>, pub(crate) span: Span<'sc>, @@ -633,7 +633,7 @@ impl<'sc> Expression<'sc> { } #[derive(Debug, Clone)] -pub(crate) struct MatchBranch<'sc> { +pub struct MatchBranch<'sc> { pub(crate) condition: MatchCondition<'sc>, pub(crate) result: Expression<'sc>, pub(crate) span: Span<'sc>, @@ -727,7 +727,7 @@ impl<'sc> MatchBranch<'sc> { } #[derive(Clone, Debug)] -pub(crate) enum UnaryOp { +pub enum UnaryOp { Not, Ref, Deref, diff --git a/core_lang/src/parse_tree/literal.rs b/core_lang/src/parse_tree/literal.rs index 87c6b8ff24a..10f161baebb 100644 --- a/core_lang/src/parse_tree/literal.rs +++ b/core_lang/src/parse_tree/literal.rs @@ -6,7 +6,7 @@ use pest::Span; use std::convert::TryInto; #[derive(Debug, Clone, Eq, PartialEq)] -pub(crate) enum Literal<'sc> { +pub enum Literal<'sc> { U8(u8), U16(u16), U32(u32), diff --git a/core_lang/src/parse_tree/mod.rs b/core_lang/src/parse_tree/mod.rs index 142cc841a73..f455208f728 100644 --- a/core_lang/src/parse_tree/mod.rs +++ b/core_lang/src/parse_tree/mod.rs @@ -7,11 +7,11 @@ mod return_statement; mod use_statement; mod while_loop; -pub(crate) use call_path::*; -pub(crate) use code_block::*; -pub(crate) use declaration::*; -pub(crate) use expression::*; -pub(crate) use literal::Literal; -pub(crate) use return_statement::*; -pub(crate) use use_statement::{ImportType, UseStatement}; -pub(crate) use while_loop::WhileLoop; +pub use call_path::*; +pub use code_block::*; +pub use declaration::*; +pub use expression::*; +pub use literal::Literal; +pub use return_statement::*; +pub use use_statement::{ImportType, UseStatement}; +pub use while_loop::WhileLoop; diff --git a/core_lang/src/parse_tree/return_statement.rs b/core_lang/src/parse_tree/return_statement.rs index 009a9731b05..68a019a7bb8 100644 --- a/core_lang/src/parse_tree/return_statement.rs +++ b/core_lang/src/parse_tree/return_statement.rs @@ -4,7 +4,7 @@ use crate::{CompileResult, Expression}; use pest::iterators::Pair; #[derive(Debug, Clone)] -pub(crate) struct ReturnStatement<'sc> { +pub struct ReturnStatement<'sc> { pub(crate) expr: Expression<'sc>, } diff --git a/core_lang/src/parse_tree/use_statement.rs b/core_lang/src/parse_tree/use_statement.rs index 29a23bddfe8..c6a163edc8c 100644 --- a/core_lang/src/parse_tree/use_statement.rs +++ b/core_lang/src/parse_tree/use_statement.rs @@ -4,13 +4,13 @@ use crate::Rule; use pest::iterators::Pair; #[derive(Debug, Clone)] -pub(crate) enum ImportType<'sc> { +pub enum ImportType<'sc> { Star, Item(Ident<'sc>), } #[derive(Debug, Clone)] -pub(crate) struct UseStatement<'sc> { +pub struct UseStatement<'sc> { pub(crate) call_path: Vec>, pub(crate) import_type: ImportType<'sc>, } diff --git a/core_lang/src/parse_tree/while_loop.rs b/core_lang/src/parse_tree/while_loop.rs index 436e816d525..c916ff0edb2 100644 --- a/core_lang/src/parse_tree/while_loop.rs +++ b/core_lang/src/parse_tree/while_loop.rs @@ -6,7 +6,7 @@ use crate::{ use pest::iterators::Pair; #[derive(Debug, Clone)] -pub(crate) struct WhileLoop<'sc> { +pub struct WhileLoop<'sc> { pub(crate) condition: Expression<'sc>, pub(crate) body: CodeBlock<'sc>, } diff --git a/forc/Cargo.toml b/forc/Cargo.toml index 917c1ea7b0b..637401ae789 100644 --- a/forc/Cargo.toml +++ b/forc/Cargo.toml @@ -1,20 +1,19 @@ [package] -name = "forc" -version = "0.1.0" authors = ["Alex Hansen "] edition = "2018" +name = "forc" rust = "1.50" - +version = "0.1.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -core_lang = { path = "../core_lang" } -structopt = "0.3" +core_lang = {path = "../core_lang"} +line-col = "0.2" +pest = "2.1" +serde = {version = "1.0", features = ["derive"]} source-span = "2.4" -termcolor = "1.1" -line-col = "0.2" -toml = "0.5" -serde = { version = "1.0", features = ["derive"] } -whoami = "1.1" -pest = "2.1" +structopt = "0.3" +termcolor = "1.1" +toml = "0.5" +whoami = "1.1" diff --git a/forc/src/cli/commands/analysis.rs b/forc/src/cli/commands/analysis.rs new file mode 100644 index 00000000000..6c10e5b90b9 --- /dev/null +++ b/forc/src/cli/commands/analysis.rs @@ -0,0 +1,8 @@ +use structopt::{self, StructOpt}; + +#[derive(Debug, StructOpt)] +pub(crate) struct Command {} + +pub(crate) fn exec(command: Command) -> Result<(), String> { + todo!() +} diff --git a/forc/src/cli/commands/benchmark.rs b/forc/src/cli/commands/benchmark.rs new file mode 100644 index 00000000000..6c10e5b90b9 --- /dev/null +++ b/forc/src/cli/commands/benchmark.rs @@ -0,0 +1,8 @@ +use structopt::{self, StructOpt}; + +#[derive(Debug, StructOpt)] +pub(crate) struct Command {} + +pub(crate) fn exec(command: Command) -> Result<(), String> { + todo!() +} diff --git a/forc/src/cli/commands/build.rs b/forc/src/cli/commands/build.rs new file mode 100644 index 00000000000..2c74d4e3e17 --- /dev/null +++ b/forc/src/cli/commands/build.rs @@ -0,0 +1,12 @@ +use structopt::{self, StructOpt}; + +use crate::ops::forc_build; +#[derive(Debug, StructOpt)] +pub(crate) struct Command { + #[structopt(short = "p")] + pub path: Option, +} + +pub(crate) fn exec(command: Command) -> Result<(), String> { + forc_build::build(command.path) +} diff --git a/forc/src/cli/commands/coverage.rs b/forc/src/cli/commands/coverage.rs new file mode 100644 index 00000000000..6c10e5b90b9 --- /dev/null +++ b/forc/src/cli/commands/coverage.rs @@ -0,0 +1,8 @@ +use structopt::{self, StructOpt}; + +#[derive(Debug, StructOpt)] +pub(crate) struct Command {} + +pub(crate) fn exec(command: Command) -> Result<(), String> { + todo!() +} diff --git a/forc/src/cli/commands/deploy.rs b/forc/src/cli/commands/deploy.rs new file mode 100644 index 00000000000..6c10e5b90b9 --- /dev/null +++ b/forc/src/cli/commands/deploy.rs @@ -0,0 +1,8 @@ +use structopt::{self, StructOpt}; + +#[derive(Debug, StructOpt)] +pub(crate) struct Command {} + +pub(crate) fn exec(command: Command) -> Result<(), String> { + todo!() +} diff --git a/forc/src/cli/commands/init.rs b/forc/src/cli/commands/init.rs new file mode 100644 index 00000000000..c63b142a2f9 --- /dev/null +++ b/forc/src/cli/commands/init.rs @@ -0,0 +1,13 @@ +use structopt::{self, StructOpt}; + +use crate::ops::forc_init; +#[derive(Debug, StructOpt)] +pub(crate) struct Command { + #[structopt(name = "init")] + project_name: String, +} + +pub(crate) fn exec(command: Command) -> Result<(), String> { + let project_name = command.project_name; + forc_init::init_new_project(project_name).map_err(|e| e.to_string()) +} diff --git a/forc/src/cli/commands/mod.rs b/forc/src/cli/commands/mod.rs new file mode 100644 index 00000000000..db1e7969252 --- /dev/null +++ b/forc/src/cli/commands/mod.rs @@ -0,0 +1,9 @@ +pub mod analysis; +pub mod benchmark; +pub mod build; +pub mod coverage; +pub mod deploy; +pub mod init; +pub mod publish; +pub mod serve; +pub mod test; diff --git a/forc/src/cli/commands/publish.rs b/forc/src/cli/commands/publish.rs new file mode 100644 index 00000000000..6c10e5b90b9 --- /dev/null +++ b/forc/src/cli/commands/publish.rs @@ -0,0 +1,8 @@ +use structopt::{self, StructOpt}; + +#[derive(Debug, StructOpt)] +pub(crate) struct Command {} + +pub(crate) fn exec(command: Command) -> Result<(), String> { + todo!() +} diff --git a/forc/src/cli/commands/serve.rs b/forc/src/cli/commands/serve.rs new file mode 100644 index 00000000000..6c10e5b90b9 --- /dev/null +++ b/forc/src/cli/commands/serve.rs @@ -0,0 +1,8 @@ +use structopt::{self, StructOpt}; + +#[derive(Debug, StructOpt)] +pub(crate) struct Command {} + +pub(crate) fn exec(command: Command) -> Result<(), String> { + todo!() +} diff --git a/forc/src/cli/commands/test.rs b/forc/src/cli/commands/test.rs new file mode 100644 index 00000000000..6c10e5b90b9 --- /dev/null +++ b/forc/src/cli/commands/test.rs @@ -0,0 +1,8 @@ +use structopt::{self, StructOpt}; + +#[derive(Debug, StructOpt)] +pub(crate) struct Command {} + +pub(crate) fn exec(command: Command) -> Result<(), String> { + todo!() +} diff --git a/forc/src/cli/mod.rs b/forc/src/cli/mod.rs index 1a28fb6cfef..a32576f94ca 100644 --- a/forc/src/cli/mod.rs +++ b/forc/src/cli/mod.rs @@ -1,36 +1,58 @@ use structopt::StructOpt; -mod build; -pub use build::*; -mod init; +mod commands; +use self::commands::{analysis, benchmark, build, coverage, deploy, init, publish, serve, test}; + +use analysis::Command as AnalysisCommand; +use benchmark::Command as BenchmarkCommand; +use build::Command as BuildCommand; +use coverage::Command as CoverageCommand; +use deploy::Command as DeployCommand; +use init::Command as InitCommand; +use publish::Command as PublishCommand; +use serve::Command as ServeCommand; +use test::Command as TestCommand; #[derive(Debug, StructOpt)] #[structopt(name = "forc", about = "Fuel HLL Orchestrator")] struct Opt { /// the command to run #[structopt(subcommand)] - command: Command, + command: Forc, } #[derive(Debug, StructOpt)] -enum Command { - #[structopt(name = "init")] - Init { project_name: String }, - #[structopt(name = "build")] - Build { - #[structopt(short = "p")] - path: Option, - }, +enum Forc { + Analysis(AnalysisCommand), + Benchmark(BenchmarkCommand), + Build(BuildCommand), + Coverage(CoverageCommand), + Deploy(DeployCommand), + Init(InitCommand), + Publish(PublishCommand), + Serve(ServeCommand), + Test(TestCommand), } pub(crate) fn run_cli() -> Result<(), String> { let opt = Opt::from_args(); match opt.command { - Command::Init { project_name } => { - init::init_new_project(project_name).map_err(|e| e.to_string()) - } - Command::Build { path } => build::build(path), + Forc::Analysis(command) => analysis::exec(command), + Forc::Benchmark(command) => benchmark::exec(command), + Forc::Build(command) => build::exec(command), + Forc::Coverage(command) => coverage::exec(command), + Forc::Deploy(command) => deploy::exec(command), + Forc::Init(command) => init::exec(command), + Forc::Publish(command) => publish::exec(command), + Forc::Serve(command) => serve::exec(command), + Forc::Test(command) => test::exec(command), }?; + /* + let content = fs::read_to_string(opt.input.clone())?; + + let res = compile(&content); + + */ Ok(()) } diff --git a/forc/src/lib.rs b/forc/src/lib.rs index 79ba70f812e..566abb97ef8 100644 --- a/forc/src/lib.rs +++ b/forc/src/lib.rs @@ -1,8 +1,6 @@ #![allow(dead_code)] mod cli; -mod constants; -mod defaults; -mod manifest; +pub mod ops; +mod utils; -pub use cli::*; -pub use constants::*; +pub use utils::constants::*; diff --git a/forc/src/main.rs b/forc/src/main.rs index 26a23017216..056202ad1a3 100644 --- a/forc/src/main.rs +++ b/forc/src/main.rs @@ -1,7 +1,7 @@ +#![allow(warnings)] mod cli; -mod constants; -mod defaults; -mod manifest; +mod ops; +mod utils; fn main() -> Result<(), Box> { match cli::run_cli() { diff --git a/forc/src/cli/build.rs b/forc/src/ops/forc_build.rs similarity index 98% rename from forc/src/cli/build.rs rename to forc/src/ops/forc_build.rs index 1745a47c1d2..23734d5b778 100644 --- a/forc/src/cli/build.rs +++ b/forc/src/ops/forc_build.rs @@ -6,7 +6,7 @@ use source_span::{ use std::io::{self, Write}; use termcolor::{BufferWriter, Color as TermColor, ColorChoice, ColorSpec, WriteColor}; -use crate::manifest::{Dependency, DependencyDetails, Manifest}; +use crate::utils::manifest::{Dependency, DependencyDetails, Manifest}; use core_lang::{CompilationResult, LibraryExports, Namespace}; use std::{fs, path::PathBuf}; @@ -54,7 +54,7 @@ fn find_manifest_dir(starter_path: &PathBuf) -> Option { let mut path = fs::canonicalize(starter_path.clone()).ok()?; let empty_path = PathBuf::from("/"); while path != empty_path { - path.push(crate::constants::MANIFEST_FILE_NAME); + path.push(crate::utils::constants::MANIFEST_FILE_NAME); if path.exists() { path.pop(); return Some(path); @@ -126,7 +126,7 @@ fn compile_dependency_lib<'source, 'manifest>( fn read_manifest(manifest_dir: &PathBuf) -> Result { let manifest_path = { let mut man = manifest_dir.clone(); - man.push(crate::constants::MANIFEST_FILE_NAME); + man.push(crate::utils::constants::MANIFEST_FILE_NAME); man }; let manifest_path_str = format!("{:?}", manifest_path); @@ -197,6 +197,7 @@ fn compile_library<'source, 'manifest>( } } } + fn compile<'source, 'manifest>( source: &'source str, proj_name: &str, diff --git a/forc/src/cli/init.rs b/forc/src/ops/forc_init.rs similarity index 66% rename from forc/src/cli/init.rs rename to forc/src/ops/forc_init.rs index 43e4a386aa3..89b76876b40 100644 --- a/forc/src/cli/init.rs +++ b/forc/src/ops/forc_init.rs @@ -1,3 +1,4 @@ +use crate::utils::{constants, defaults}; use std::fs; pub(crate) fn init_new_project(project_name: String) -> Result<(), Box> { @@ -6,14 +7,14 @@ pub(crate) fn init_new_project(project_name: String) -> Result<(), Box(&crate::defaults::default_manifest("test_proj".into())).unwrap() + toml::from_str::(&super::defaults::default_manifest("test_proj".into())).unwrap() ) } diff --git a/forc/src/utils/mod.rs b/forc/src/utils/mod.rs new file mode 100644 index 00000000000..b437263adad --- /dev/null +++ b/forc/src/utils/mod.rs @@ -0,0 +1,3 @@ +pub mod constants; +pub mod defaults; +pub mod manifest; diff --git a/fume-server/Cargo.toml b/fume-server/Cargo.toml new file mode 100644 index 00000000000..59e30e84a2f --- /dev/null +++ b/fume-server/Cargo.toml @@ -0,0 +1,19 @@ +[package] +authors = ["leviathan88 "] +edition = "2018" +name = "fume-server" +version = "0.1.0" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +core_lang = {path = "../core_lang"} +dashmap = "4.0.2" +lspower = "1.0.0" +pest = "2.0" +ropey = "1.2" +serde_json = "1.0.60" +tokio = {version = "1.3", features = ["io-std", "io-util", "macros", "net", "rt-multi-thread", "sync", "time"]} + +[profile.dev] +debug = 2 diff --git a/fume-server/src/capabilities/completion.rs b/fume-server/src/capabilities/completion.rs new file mode 100644 index 00000000000..6b1052de142 --- /dev/null +++ b/fume-server/src/capabilities/completion.rs @@ -0,0 +1,51 @@ +use crate::core::{ + session::Session, + token::{ContentType, DeclarationType, Token}, +}; +use lspower::lsp::{CompletionItem, CompletionItemKind, CompletionParams, CompletionResponse}; +use std::sync::Arc; + +pub fn get_completion( + session: Arc, + params: CompletionParams, +) -> Option { + let url = params.text_document_position.text_document.uri; + + match session.get_completion_items(&url) { + Some(items) => Some(CompletionResponse::Array(items)), + _ => None, + } +} + +pub fn to_completion_items(tokens: &Vec) -> Vec { + let mut completion_items = vec![]; + + for token in tokens { + if token.is_initial_declaration() { + let item = CompletionItem { + label: token.name.clone(), + kind: get_kind(&token.content_type), + ..Default::default() + }; + completion_items.push(item); + } + } + + completion_items +} + +fn get_kind(content_type: &ContentType) -> Option { + if let ContentType::Declaration(dec) = content_type { + match dec { + DeclarationType::Enum => Some(CompletionItemKind::Enum), + DeclarationType::Function => Some(CompletionItemKind::Function), + DeclarationType::Library => Some(CompletionItemKind::Module), + DeclarationType::Struct => Some(CompletionItemKind::Struct), + DeclarationType::Variable => Some(CompletionItemKind::Variable), + DeclarationType::Trait => Some(CompletionItemKind::Interface), + _ => None, + } + } else { + None + } +} diff --git a/fume-server/src/capabilities/diagnostic.rs b/fume-server/src/capabilities/diagnostic.rs new file mode 100644 index 00000000000..9fa6a30057e --- /dev/null +++ b/fume-server/src/capabilities/diagnostic.rs @@ -0,0 +1,60 @@ +use lsp::{Diagnostic, DiagnosticSeverity, Position, Range}; +use lspower::lsp::{self}; + +use core_lang::{CompileError, CompileWarning}; + +pub fn get_diagnostics( + warnings: Vec, + errors: Vec, +) -> Vec { + let errors: Vec = errors + .iter() + .map(|error| { + let range = get_range(&WarningOrError::Error(error)); + Diagnostic { + range, + severity: Some(DiagnosticSeverity::Error), + message: error.to_friendly_error_string(), + ..Default::default() + } + }) + .collect(); + + let warnings: Vec = warnings + .iter() + .map(|warning| { + let range = get_range(&WarningOrError::Warning(warning)); + Diagnostic { + range, + severity: Some(DiagnosticSeverity::Warning), + message: warning.to_friendly_warning_string(), + ..Default::default() + } + }) + .collect(); + + vec![warnings, errors].into_iter().flatten().collect() +} + +fn get_range<'s>(warning_or_error: &WarningOrError<'s>) -> Range { + let (start, end) = match warning_or_error { + WarningOrError::Error(error) => error.line_col(), + WarningOrError::Warning(warning) => warning.line_col(), + }; + + let start_line = start.line as u32 - 1; + let start_character = start.col as u32; + + let end_line = end.line as u32 - 1; + let end_character = end.col as u32; + + Range { + start: Position::new(start_line, start_character), + end: Position::new(end_line, end_character), + } +} + +enum WarningOrError<'s> { + Warning(&'s CompileWarning<'s>), + Error(&'s CompileError<'s>), +} diff --git a/fume-server/src/capabilities/document_symbol.rs b/fume-server/src/capabilities/document_symbol.rs new file mode 100644 index 00000000000..90922fb5a53 --- /dev/null +++ b/fume-server/src/capabilities/document_symbol.rs @@ -0,0 +1,53 @@ +use std::sync::Arc; + +use lspower::lsp::{DocumentSymbolResponse, Location, SymbolInformation, SymbolKind, Url}; + +use crate::core::{ + session::Session, + token::{ContentType, DeclarationType, Token}, +}; + +pub fn document_symbol(session: Arc, url: Url) -> Option { + match session.get_symbol_information(&url) { + Some(symbols) => Some(DocumentSymbolResponse::Flat(symbols)), + _ => None, + } +} + +pub fn to_symbol_information(tokens: &Vec, url: Url) -> Vec { + let mut symbols: Vec = vec![]; + + for token in tokens { + let symbol = create_symbol_info(token, url.clone()); + symbols.push(symbol) + } + + symbols +} + +fn create_symbol_info(token: &Token, url: Url) -> SymbolInformation { + SymbolInformation { + name: token.name.clone(), + kind: get_kind(&token.content_type), + location: Location::new(url, token.range), + tags: None, + container_name: None, + deprecated: None, + } +} + +fn get_kind(content_type: &ContentType) -> SymbolKind { + if let ContentType::Declaration(dec) = content_type { + match dec { + DeclarationType::Enum => SymbolKind::Enum, + DeclarationType::Function => SymbolKind::Function, + DeclarationType::Library => SymbolKind::Module, + DeclarationType::Struct => SymbolKind::Struct, + DeclarationType::Variable => SymbolKind::Variable, + DeclarationType::Trait => SymbolKind::Interface, + _ => SymbolKind::Unknown, + } + } else { + SymbolKind::Unknown + } +} diff --git a/fume-server/src/capabilities/go_to.rs b/fume-server/src/capabilities/go_to.rs new file mode 100644 index 00000000000..eddf3941482 --- /dev/null +++ b/fume-server/src/capabilities/go_to.rs @@ -0,0 +1,18 @@ +use std::sync::Arc; + +use crate::core::{session::Session, token::Token}; +use lspower::lsp::{GotoDefinitionParams, GotoDefinitionResponse, Location, Url}; + +pub fn go_to_definition( + session: Arc, + params: GotoDefinitionParams, +) -> Option { + let url = params.text_document_position_params.text_document.uri; + let position = params.text_document_position_params.position; + + session.get_token_definition_response(url, position) +} + +pub fn to_definition_response(url: Url, token: &Token) -> GotoDefinitionResponse { + GotoDefinitionResponse::Scalar(Location::new(url, token.range)) +} diff --git a/fume-server/src/capabilities/highlight.rs b/fume-server/src/capabilities/highlight.rs new file mode 100644 index 00000000000..d782dbf5eaa --- /dev/null +++ b/fume-server/src/capabilities/highlight.rs @@ -0,0 +1,21 @@ +use crate::core::session::Session; +use lspower::lsp::{DocumentHighlight, DocumentHighlightParams}; +use std::sync::Arc; + +pub fn get_highlights( + session: Arc, + params: DocumentHighlightParams, +) -> Option> { + let url = params.text_document_position_params.text_document.uri; + let position = params.text_document_position_params.position; + + match session.get_token_ranges(&url, position) { + Some(ranges) => Some( + ranges + .into_iter() + .map(|range| DocumentHighlight { range, kind: None }) + .collect(), + ), + _ => None, + } +} diff --git a/fume-server/src/capabilities/hover.rs b/fume-server/src/capabilities/hover.rs new file mode 100644 index 00000000000..742a0ba667b --- /dev/null +++ b/fume-server/src/capabilities/hover.rs @@ -0,0 +1,21 @@ +use std::sync::Arc; + +use crate::core::{session::Session, token::Token}; +use lspower::lsp::{Hover, HoverContents, HoverParams, MarkupContent, MarkupKind}; + +pub fn get_hover_data(session: Arc, params: HoverParams) -> Option { + let position = params.text_document_position_params.position; + let url = ¶ms.text_document_position_params.text_document.uri; + + session.get_token_hover_content(url, position) +} + +pub fn to_hover_content(token: &Token) -> Hover { + Hover { + contents: HoverContents::Markup(MarkupContent { + value: format!("{:?} : {}", token.content_type, token.name), + kind: MarkupKind::PlainText, + }), + range: Some(token.range), + } +} diff --git a/fume-server/src/capabilities/mod.rs b/fume-server/src/capabilities/mod.rs new file mode 100644 index 00000000000..c1dd0f27505 --- /dev/null +++ b/fume-server/src/capabilities/mod.rs @@ -0,0 +1,8 @@ +pub mod completion; +pub mod diagnostic; +pub mod document_symbol; +pub mod go_to; +pub mod highlight; +pub mod hover; +pub mod semantic_tokens; +pub mod text_sync; diff --git a/fume-server/src/capabilities/semantic_tokens.rs b/fume-server/src/capabilities/semantic_tokens.rs new file mode 100644 index 00000000000..58a1fad9de5 --- /dev/null +++ b/fume-server/src/capabilities/semantic_tokens.rs @@ -0,0 +1,148 @@ +use crate::core::{ + session::Session, + token::{ContentType, DeclarationType, Token}, +}; +use lspower::lsp::{ + SemanticToken, SemanticTokenModifier, SemanticTokenType, SemanticTokens, + SemanticTokensFullOptions, SemanticTokensLegend, SemanticTokensOptions, SemanticTokensParams, + SemanticTokensResult, SemanticTokensServerCapabilities, +}; +use std::sync::Arc; + +// https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L71 +pub fn get_semantic_tokens_full( + session: Arc, + params: SemanticTokensParams, +) -> Option { + let url = params.text_document.uri; + + match session.get_semantic_tokens(&url) { + Some(semantic_tokens) => { + if semantic_tokens.is_empty() { + return None; + } + + Some(SemanticTokensResult::Tokens(SemanticTokens { + result_id: None, + data: semantic_tokens, + })) + } + _ => None, + } +} + +pub fn to_semantic_tokes(tokens: &Vec) -> Vec { + if tokens.is_empty() { + return vec![]; + } + + let mut semantic_tokens: Vec = vec![create_semantic_token(&tokens[0], None)]; + + for i in 1..tokens.len() { + let semantic_token = create_semantic_token(&tokens[i], Some(&tokens[i - 1])); + semantic_tokens.push(semantic_token); + } + + semantic_tokens +} + +fn create_semantic_token(next_token: &Token, prev_token: Option<&Token>) -> SemanticToken { + // TODO - improve with modifiers + let token_modifiers_bitset = 0; + let token_type = get_type(&next_token.content_type); + let length = next_token.length; + + let next_token_start_char = next_token.range.start.character; + + let (delta_line, delta_start) = if let Some(prev_token) = prev_token { + let delta_start = if next_token.line_start == prev_token.line_start { + next_token_start_char - prev_token.range.start.character + } else { + next_token_start_char + }; + (next_token.line_start - prev_token.line_start, delta_start) + } else { + (next_token.line_start, next_token_start_char) + }; + + SemanticToken { + token_modifiers_bitset, + token_type, + length, + delta_line, + delta_start, + } +} + +// these values should reflect indexes in `token_types` +static FUNCTION: u32 = 1; +static LIBRARY: u32 = 3; +static VARIABLE: u32 = 9; +static ENUM: u32 = 10; +static STRUCT: u32 = 11; +static TRAIT: u32 = 12; + +fn get_type(content_type: &ContentType) -> u32 { + if let ContentType::Declaration(dec) = content_type { + match dec { + DeclarationType::Function => FUNCTION, + DeclarationType::Library => LIBRARY, + DeclarationType::Variable => VARIABLE, + DeclarationType::Enum => ENUM, + DeclarationType::Struct => STRUCT, + DeclarationType::Trait => TRAIT, + _ => VARIABLE, + } + } else { + // currently we return `variable` type as default + VARIABLE + } +} + +pub fn get_semantic_tokens() -> Option { + let token_types = vec![ + SemanticTokenType::CLASS, // 0 + SemanticTokenType::FUNCTION, // 1 + SemanticTokenType::KEYWORD, // 2 + SemanticTokenType::NAMESPACE, // 3 + SemanticTokenType::OPERATOR, // 4 + SemanticTokenType::PARAMETER, // 5 + SemanticTokenType::STRING, // 6 + SemanticTokenType::TYPE, // 7 + SemanticTokenType::TYPE_PARAMETER, // 8 + SemanticTokenType::VARIABLE, // 9 + SemanticTokenType::ENUM, // 10 + SemanticTokenType::STRUCT, // 11 + SemanticTokenType::INTERFACE, // 12 + ]; + + let token_modifiers: Vec = vec![ + // declaration of symbols + SemanticTokenModifier::DECLARATION, + // definition of symbols as in header files + SemanticTokenModifier::DEFINITION, + SemanticTokenModifier::READONLY, + SemanticTokenModifier::STATIC, + // for variable references where the variable is assigned to + SemanticTokenModifier::MODIFICATION, + SemanticTokenModifier::DOCUMENTATION, + // for symbols that are part of stdlib + SemanticTokenModifier::DEFAULT_LIBRARY, + ]; + + let legend = SemanticTokensLegend { + token_types, + token_modifiers, + }; + + let options = SemanticTokensOptions { + legend, + range: None, + full: Some(SemanticTokensFullOptions::Bool(true)), + ..Default::default() + }; + + Some(SemanticTokensServerCapabilities::SemanticTokensOptions( + options, + )) +} diff --git a/fume-server/src/capabilities/text_sync.rs b/fume-server/src/capabilities/text_sync.rs new file mode 100644 index 00000000000..365aa93c6e4 --- /dev/null +++ b/fume-server/src/capabilities/text_sync.rs @@ -0,0 +1,65 @@ +use std::sync::Arc; + +use lspower::lsp::{ + Diagnostic, DidChangeTextDocumentParams, DidCloseTextDocumentParams, DidOpenTextDocumentParams, + DidSaveTextDocumentParams, +}; + +use crate::core::{ + document::{DocumentError, TextDocument}, + session::Session, +}; + +pub fn handle_open_file( + session: Arc, + params: &DidOpenTextDocumentParams, +) -> Option> { + if let Ok(_) = session.store_document(¶ms.text_document) { + match session.parse_document(¶ms.text_document.uri) { + Ok(diagnostics) => { + if diagnostics.is_empty() { + None + } else { + Some(diagnostics) + } + } + Err(DocumentError::FailedToParse(diagnostics)) => Some(diagnostics), + _ => None, + } + } else { + None + } +} + +pub fn handle_change_file( + session: Arc, + params: DidChangeTextDocumentParams, +) -> Result<(), DocumentError> { + session.update_text_document(¶ms.text_document.uri, params.content_changes) +} + +pub fn handle_save_file( + session: Arc, + params: &DidSaveTextDocumentParams, +) -> Option> { + match session.parse_document(¶ms.text_document.uri) { + Ok(diagnostics) => { + if diagnostics.is_empty() { + None + } else { + Some(diagnostics) + } + } + Err(DocumentError::FailedToParse(diagnostics)) => Some(diagnostics), + _ => None, + } +} + +pub fn handle_close_file( + session: Arc, + params: DidCloseTextDocumentParams, +) -> Result { + // TODO + // should we remove the document after closing ? + session.remove_document(¶ms.text_document.uri) +} diff --git a/fume-server/src/core/document.rs b/fume-server/src/core/document.rs new file mode 100644 index 00000000000..637bbc00bb4 --- /dev/null +++ b/fume-server/src/core/document.rs @@ -0,0 +1,269 @@ +use std::collections::HashMap; + +use core_lang::{parse, CompileResult}; +use lspower::lsp::{Diagnostic, Position, Range, TextDocumentContentChangeEvent, TextDocumentItem}; + +use ropey::Rope; + +use crate::{ + capabilities, + core::token::{traverse_node, DeclarationType}, +}; + +use super::token::{ContentType, Token}; + +#[derive(Debug)] +pub struct TextDocument { + language_id: String, + version: i32, + uri: String, + content: Rope, + text: String, + tokens: Vec, + lines: HashMap>, + values: HashMap>, +} + +impl TextDocument { + pub fn new(item: &TextDocumentItem) -> Self { + Self { + language_id: item.language_id.clone(), + version: item.version, + uri: item.uri.to_string(), + content: Rope::from_str(&item.text), + text: item.text.clone(), + tokens: vec![], + lines: HashMap::new(), + values: HashMap::new(), + } + } + + pub fn get_token_at_position(&self, position: Position) -> Option<&Token> { + let line = position.line; + + if let Some(indices) = self.lines.get(&line) { + for index in indices { + let token = &self.tokens[*index]; + if token.is_within_character_range(position.character) { + return Some(token); + } + } + } + + None + } + + pub fn get_all_tokens_by_single_name(&self, name: &str) -> Option> { + if let Some(indices) = self.values.get(name) { + let tokens = indices.iter().map(|index| &self.tokens[*index]).collect(); + Some(tokens) + } else { + None + } + } + + pub fn get_declared_token(&self, name: &str) -> Option<&Token> { + if let Some(indices) = self.values.get(name) { + for index in indices { + let token = &self.tokens[*index]; + if token.is_initial_declaration() { + return Some(token); + } + } + } + None + } + + pub fn get_tokens(&self) -> &Vec { + &self.tokens + } + + pub fn parse(&mut self) -> Result, DocumentError> { + self.sync_text_with_content(); + self.clear_tokens(); + self.clear_hash_maps(); + + match self.parse_tokens_from_text() { + Ok((tokens, diagnostics)) => { + self.store_tokens(tokens); + Ok(diagnostics) + } + Err(diagnostics) => Err(DocumentError::FailedToParse(diagnostics)), + } + } + + pub fn apply_change(&mut self, change: &TextDocumentContentChangeEvent) { + let edit = self.build_edit(change); + + self.content.remove(edit.start_index..edit.end_index); + self.content.insert(edit.start_index, edit.change_text); + } +} + +// private methods +impl TextDocument { + fn parse_tokens_from_text(&self) -> Result<(Vec, Vec), Vec> { + match parse(&self.text) { + CompileResult::Err { warnings, errors } => { + Err(capabilities::diagnostic::get_diagnostics(warnings, errors)) + } + CompileResult::Ok { + value, + warnings, + errors, + } => { + let mut tokens = vec![]; + + for (ident, parse_tree) in value.library_exports { + // TODO + // Is library name necessary to store for the LSP? + let token = Token::from_ident( + ident, + ContentType::Declaration(DeclarationType::Library), + ); + tokens.push(token); + for node in parse_tree.root_nodes { + traverse_node(node, &mut tokens); + } + } + + if let Some(script) = value.script_ast { + for node in script.root_nodes { + traverse_node(node, &mut tokens); + } + } + + if let Some(contract) = value.contract_ast { + for node in contract.root_nodes { + traverse_node(node, &mut tokens); + } + } + + if let Some(predicate) = value.predicate_ast { + for node in predicate.root_nodes { + traverse_node(node, &mut tokens); + } + } + + Ok(( + tokens, + capabilities::diagnostic::get_diagnostics(warnings, errors), + )) + } + } + } + + fn store_tokens(&mut self, tokens: Vec) { + self.tokens = Vec::with_capacity(tokens.len()); + + for (index, token) in tokens.into_iter().enumerate() { + let line = token.get_line_start(); + let token_name = token.name.clone(); + + // insert to tokens + self.tokens.push(token); + + // insert index into hashmap for lines + match self.lines.get_mut(&line) { + Some(v) => { + v.push(index); + } + None => { + self.lines.insert(line, vec![index]); + } + } + + // insert index into hashmap for names + match self.values.get_mut(&token_name) { + Some(v) => { + v.push(index); + } + None => { + self.values.insert(token_name, vec![index]); + } + } + } + } + + fn sync_text_with_content(&mut self) { + self.text = self.content.to_string(); + } + + fn clear_hash_maps(&mut self) { + self.lines = HashMap::new(); + self.values = HashMap::new(); + } + + fn clear_tokens(&mut self) { + self.tokens = vec![]; + } + + fn build_edit<'change>( + &self, + change: &'change TextDocumentContentChangeEvent, + ) -> EditText<'change> { + let change_text = change.text.as_str(); + let text_bytes = change_text.as_bytes(); + let text_end_byte_index = text_bytes.len(); + + let range = match change.range { + Some(range) => range, + None => { + let start = self.byte_to_position(0); + let end = self.byte_to_position(text_end_byte_index); + Range { start, end } + } + }; + + let start_index = self.position_to_index(range.start); + let end_index = self.position_to_index(range.end); + + EditText { + start_index, + end_index, + change_text, + } + } + + fn byte_to_position(&self, byte_index: usize) -> Position { + let line_index = self.content.byte_to_line(byte_index); + + let line_utf16_cu_index = { + let char_index = self.content.line_to_char(line_index); + self.content.char_to_utf16_cu(char_index) + }; + + let character_utf16_cu_index = { + let char_index = self.content.byte_to_char(byte_index); + self.content.char_to_utf16_cu(char_index) + }; + + let character = character_utf16_cu_index - line_utf16_cu_index; + + Position::new(line_index as u32, character as u32) + } + + fn position_to_index(&self, position: Position) -> usize { + let row_index = position.line as usize; + let column_index = position.character as usize; + + let row_char_index = self.content.line_to_char(row_index); + let column_char_index = self.content.utf16_cu_to_char(column_index); + + row_char_index + column_char_index + } +} + +#[derive(Debug)] +struct EditText<'text> { + start_index: usize, + end_index: usize, + change_text: &'text str, +} + +#[derive(Debug)] +pub enum DocumentError { + FailedToParse(Vec), + DocumentNotFound, + DocumentAlreadyStored, +} diff --git a/fume-server/src/core/mod.rs b/fume-server/src/core/mod.rs new file mode 100644 index 00000000000..e060ccf9eb0 --- /dev/null +++ b/fume-server/src/core/mod.rs @@ -0,0 +1,3 @@ +pub mod document; +pub mod session; +pub mod token; diff --git a/fume-server/src/core/session.rs b/fume-server/src/core/session.rs new file mode 100644 index 00000000000..77c9e9cea05 --- /dev/null +++ b/fume-server/src/core/session.rs @@ -0,0 +1,145 @@ +use dashmap::DashMap; +use lspower::lsp::{ + CompletionItem, Diagnostic, GotoDefinitionResponse, Hover, Position, Range, SemanticToken, + SymbolInformation, TextDocumentContentChangeEvent, TextDocumentItem, Url, +}; + +use crate::capabilities; + +use super::document::{DocumentError, TextDocument}; + +#[derive(Debug)] +pub struct Session { + documents: DashMap, +} + +impl Session { + pub fn new() -> Self { + Session { + documents: DashMap::new(), + } + } + + // Document + pub fn store_document(&self, document: &TextDocumentItem) -> Result<(), DocumentError> { + let text_document = TextDocument::new(document); + let url = document.uri.clone(); + + match self.documents.insert(url, text_document) { + None => Ok(()), + _ => Err(DocumentError::DocumentAlreadyStored), + } + } + + pub fn remove_document(&self, uri: &Url) -> Result { + match self.documents.remove(uri) { + Some((_, text_document)) => Ok(text_document), + None => Err(DocumentError::DocumentNotFound), + } + } + + pub fn parse_document(&self, url: &Url) -> Result, DocumentError> { + match self.documents.get_mut(&url) { + Some(ref mut document) => document.parse(), + _ => Err(DocumentError::DocumentNotFound), + } + } + + pub fn update_text_document( + &self, + uri: &Url, + changes: Vec, + ) -> Result<(), DocumentError> { + match self.documents.get_mut(&uri) { + Some(ref mut document) => { + changes.iter().for_each(|change| { + document.apply_change(change); + }); + Ok(()) + } + _ => Err(DocumentError::DocumentNotFound), + } + } + + // Token + pub fn get_token_ranges(&self, url: &Url, position: Position) -> Option> { + if let Some(document) = self.documents.get(url) { + if let Some(token) = document.get_token_at_position(position) { + let result = document + .get_all_tokens_by_single_name(&token.name) + .unwrap() + .iter() + .map(|token| token.range) + .collect(); + + return Some(result); + } + } + + None + } + + pub fn get_token_hover_content(&self, url: &Url, position: Position) -> Option { + if let Some(document) = self.documents.get(url) { + if let Some(token) = document.get_token_at_position(position) { + return Some(capabilities::hover::to_hover_content(token)); + } + } + + None + } + + pub fn get_token_definition_response( + &self, + url: Url, + position: Position, + ) -> Option { + if let Some(document) = self.documents.get(&url) { + if let Some(token) = document.get_token_at_position(position) { + if token.is_initial_declaration() { + return Some(capabilities::go_to::to_definition_response(url, token)); + } else { + if let Some(other_token) = document.get_declared_token(&token.name) { + return Some(capabilities::go_to::to_definition_response( + url, + other_token, + )); + } + } + } + } + + None + } + + pub fn get_completion_items(&self, url: &Url) -> Option> { + if let Some(document) = self.documents.get(url) { + return Some(capabilities::completion::to_completion_items( + document.get_tokens(), + )); + } + + None + } + + pub fn get_semantic_tokens(&self, url: &Url) -> Option> { + if let Some(document) = self.documents.get(url) { + return Some(capabilities::semantic_tokens::to_semantic_tokes( + document.get_tokens(), + )); + } + + None + } + + pub fn get_symbol_information(&self, url: &Url) -> Option> { + if let Some(document) = self.documents.get(url) { + return Some(capabilities::document_symbol::to_symbol_information( + document.get_tokens(), + url.clone(), + )); + } + + None + } +} diff --git a/fume-server/src/core/token.rs b/fume-server/src/core/token.rs new file mode 100644 index 00000000000..b8ff8182a9b --- /dev/null +++ b/fume-server/src/core/token.rs @@ -0,0 +1,194 @@ +use core_lang::{ + AstNode, AstNodeContent, Declaration, Expression, Ident, Span, VariableDeclaration, +}; +use lspower::lsp::{Position, Range}; + +#[derive(Debug, Clone)] +pub struct Token { + pub range: Range, + pub content_type: ContentType, + pub name: String, + pub line_start: u32, + pub length: u32, +} + +impl Token { + pub fn new(span: Span, name: String, content_type: ContentType) -> Self { + let range = get_range_from_span(&span); + + Self { + range, + name, + content_type, + line_start: range.start.line, + length: range.end.character - range.start.character + 1, + } + } + + pub fn is_within_character_range(&self, character: u32) -> bool { + let range = self.range; + character >= range.start.character && character <= range.end.character + } + + pub fn get_line_start(&self) -> u32 { + self.line_start + } + + pub fn from_variable(variable: &VariableDeclaration) -> Self { + let ident = &variable.name; + let span = ident.span.clone(); + let name = ident.primary_name; + // todo + // we could add type of variable as well? from type_ascription: TypeInfo field + Token::new( + span, + name.into(), + ContentType::Declaration(DeclarationType::Variable), + ) + } + + pub fn from_ident(ident: Ident, content_type: ContentType) -> Self { + Token::new(ident.span.clone(), ident.primary_name.into(), content_type) + } + + pub fn is_initial_declaration(&self) -> bool { + if let ContentType::Declaration(ref dec) = self.content_type { + if &DeclarationType::Reassignment == dec { + return false; + } + return true; + } + + false + } +} + +pub fn traverse_node(node: AstNode, tokens: &mut Vec) { + match node.content { + AstNodeContent::Declaration(dec) => handle_declaration(dec, tokens), + AstNodeContent::Expression(exp) => handle_expression(exp, tokens), + // TODO + // handle other content types + _ => {} + }; +} + +fn handle_declaration(declaration: Declaration, tokens: &mut Vec) { + match declaration { + Declaration::VariableDeclaration(variable) => { + tokens.push(Token::from_variable(&variable)); + handle_expression(variable.body, tokens); + } + Declaration::FunctionDeclaration(func) => { + let ident = func.name; + let token = + Token::from_ident(ident, ContentType::Declaration(DeclarationType::Function)); + tokens.push(token); + + for node in func.body.contents { + traverse_node(node, tokens); + } + } + Declaration::Reassignment(reassignment) => { + let ident = reassignment.lhs; + let token = Token::from_ident( + ident, + ContentType::Declaration(DeclarationType::Reassignment), + ); + tokens.push(token); + + handle_expression(reassignment.rhs, tokens); + } + + Declaration::TraitDeclaration(trait_dec) => { + let ident = trait_dec.name; + let token = Token::from_ident(ident, ContentType::Declaration(DeclarationType::Trait)); + tokens.push(token); + + // todo + // traverse methods: Vec> field as well ? + } + Declaration::StructDeclaration(struct_dec) => { + let ident = struct_dec.name; + let token = Token::from_ident(ident, ContentType::Declaration(DeclarationType::Struct)); + tokens.push(token); + } + Declaration::EnumDeclaration(enum_dec) => { + let ident = enum_dec.name; + let token = Token::from_ident(ident, ContentType::Declaration(DeclarationType::Enum)); + tokens.push(token); + } + _ => {} + }; +} + +fn handle_expression(exp: Expression, tokens: &mut Vec) { + match exp { + Expression::CodeBlock { + span: _span, + contents, + } => { + let nodes = contents.contents; + + for node in nodes { + traverse_node(node, tokens); + } + } + Expression::FunctionApplication { + name, + span: _span, + arguments: _arguments, + } => { + let ident = name.suffix; + let token = Token::from_ident( + ident, + ContentType::Expression(ExpressionType::FunctionApplication), + ); + tokens.push(token); + + // TODO + // perform a for/in on arguments ? + } + // TODO + // handle other expressions + _ => {} + } +} + +fn get_range_from_span(span: &Span) -> Range { + let start = span.start_pos().line_col(); + let end = span.end_pos().line_col(); + + let start_line = start.0 as u32 - 1; + let start_character = start.1 as u32 - 1; + + let end_line = end.0 as u32 - 1; + let end_character = end.1 as u32 - 2; + + Range { + start: Position::new(start_line, start_character), + end: Position::new(end_line, end_character), + } +} + +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum DeclarationType { + Library, + Variable, + Function, + Reassignment, + Enum, + Trait, + Struct, +} + +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum ExpressionType { + FunctionApplication, +} + +#[derive(Debug, Clone, PartialEq)] +pub enum ContentType { + Declaration(DeclarationType), + Expression(ExpressionType), +} diff --git a/fume-server/src/main.rs b/fume-server/src/main.rs new file mode 100644 index 00000000000..75282e58b90 --- /dev/null +++ b/fume-server/src/main.rs @@ -0,0 +1,18 @@ +use lspower::{LspService, Server}; + +mod capabilities; +mod core; +mod server; +use server::Backend; + +#[tokio::main] +async fn main() { + let stdin = tokio::io::stdin(); + let stdout = tokio::io::stdout(); + + let (service, messages) = LspService::new(|client| Backend::new(client)); + Server::new(stdin, stdout) + .interleave(messages) + .serve(service) + .await; +} diff --git a/fume-server/src/server.rs b/fume-server/src/server.rs new file mode 100644 index 00000000000..210d921b830 --- /dev/null +++ b/fume-server/src/server.rs @@ -0,0 +1,165 @@ +use lspower::{ + jsonrpc, + lsp::{self}, + Client, LanguageServer, +}; +use std::sync::Arc; + +use lsp::{ + CompletionParams, CompletionResponse, Hover, HoverParams, HoverProviderCapability, + InitializeParams, InitializeResult, MessageType, OneOf, +}; + +use crate::capabilities; +use crate::core::session::Session; + +#[derive(Debug)] +pub struct Backend { + pub client: Client, + session: Arc, +} + +impl Backend { + pub fn new(client: Client) -> Self { + let session = Arc::new(Session::new()); + Backend { client, session } + } + + async fn log_info_message(&self, message: &str) { + self.client.log_message(MessageType::Info, message).await; + } +} + +#[lspower::async_trait] +impl LanguageServer for Backend { + async fn initialize(&self, _params: InitializeParams) -> jsonrpc::Result { + self.client + .log_message(MessageType::Info, "Initializing the Server") + .await; + + Ok(lsp::InitializeResult { + server_info: None, + capabilities: lsp::ServerCapabilities { + text_document_sync: Some(lsp::TextDocumentSyncCapability::Kind( + lsp::TextDocumentSyncKind::Incremental, + )), + definition_provider: Some(lsp::OneOf::Left(true)), + semantic_tokens_provider: capabilities::semantic_tokens::get_semantic_tokens(), + document_symbol_provider: Some(lsp::OneOf::Left(true)), + hover_provider: Some(HoverProviderCapability::Simple(true)), + completion_provider: Some(lsp::CompletionOptions { + resolve_provider: Some(false), + trigger_characters: None, + ..Default::default() + }), + execute_command_provider: Some(lsp::ExecuteCommandOptions { + commands: vec![], + ..Default::default() + }), + document_highlight_provider: Some(OneOf::Left(true)), + ..lsp::ServerCapabilities::default() + }, + }) + } + + // LSP-Server Lifecycle + async fn initialized(&self, _: lsp::InitializedParams) { + self.log_info_message("Server initialized").await; + } + + async fn shutdown(&self) -> jsonrpc::Result<()> { + self.log_info_message("Shutting the server").await; + Ok(()) + } + + // Document Handlers + async fn did_open(&self, params: lsp::DidOpenTextDocumentParams) { + if let Some(diagnostics) = + capabilities::text_sync::handle_open_file(self.session.clone(), ¶ms) + { + self.client + .publish_diagnostics(params.text_document.uri, diagnostics, None) + .await; + } + } + + async fn did_change(&self, params: lsp::DidChangeTextDocumentParams) { + let _ = capabilities::text_sync::handle_change_file(self.session.clone(), params); + } + + async fn did_save(&self, params: lsp::DidSaveTextDocumentParams) { + let url = params.text_document.uri.clone(); + self.client.publish_diagnostics(url, vec![], None).await; + + if let Some(diagnostics) = + capabilities::text_sync::handle_save_file(self.session.clone(), ¶ms) + { + self.client + .publish_diagnostics(params.text_document.uri, diagnostics, None) + .await; + } + } + + async fn did_close(&self, params: lsp::DidCloseTextDocumentParams) { + let _ = capabilities::text_sync::handle_close_file(self.session.clone(), params); + } + + async fn hover(&self, params: HoverParams) -> jsonrpc::Result> { + Ok(capabilities::hover::get_hover_data( + self.session.clone(), + params, + )) + } + + async fn completion( + &self, + params: CompletionParams, + ) -> jsonrpc::Result> { + // TODO + // here we would also need to provide a list of builtin methods not just the ones from the document + Ok(capabilities::completion::get_completion( + self.session.clone(), + params, + )) + } + + async fn document_symbol( + &self, + params: lsp::DocumentSymbolParams, + ) -> jsonrpc::Result> { + Ok(capabilities::document_symbol::document_symbol( + self.session.clone(), + params.text_document.uri, + )) + } + + async fn semantic_tokens_full( + &self, + params: lsp::SemanticTokensParams, + ) -> jsonrpc::Result> { + Ok(capabilities::semantic_tokens::get_semantic_tokens_full( + self.session.clone(), + params, + )) + } + + async fn document_highlight( + &self, + params: lsp::DocumentHighlightParams, + ) -> jsonrpc::Result>> { + Ok(capabilities::highlight::get_highlights( + self.session.clone(), + params, + )) + } + + async fn goto_definition( + &self, + params: lsp::GotoDefinitionParams, + ) -> jsonrpc::Result> { + Ok(capabilities::go_to::go_to_definition( + self.session.clone(), + params, + )) + } +} diff --git a/test_suite/src/basic_compilation_tests/harness.rs b/test_suite/src/basic_compilation_tests/harness.rs index ab0844aa686..a55384e43ec 100644 --- a/test_suite/src/basic_compilation_tests/harness.rs +++ b/test_suite/src/basic_compilation_tests/harness.rs @@ -5,7 +5,7 @@ use forc; pub(crate) fn should_compile(file_name: &str) -> bool { println!("Compiling {}", file_name); let manifest_dir = env!("CARGO_MANIFEST_DIR"); - let res = forc::build(Some(format!( + let res = forc::ops::forc_build::build(Some(format!( "{}/src/basic_compilation_tests/test_programs/{}", manifest_dir, file_name ))); diff --git a/vscode-plugin/.gitattributes b/vscode-plugin/.gitattributes new file mode 100644 index 00000000000..13bc9c2eed6 --- /dev/null +++ b/vscode-plugin/.gitattributes @@ -0,0 +1,3 @@ +# Set default behavior to automatically normalize line endings. +* text=auto + diff --git a/vscode-plugin/.vscode/launch.json b/vscode-plugin/.vscode/launch.json new file mode 100644 index 00000000000..779faa294a3 --- /dev/null +++ b/vscode-plugin/.vscode/launch.json @@ -0,0 +1,43 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "attach", + "name": "Fume Server", + "program": "${workspaceFolder}/../target/debug/fume-server", + "targetCreateCommands": [ + "target create ${workspaceFolder}/../target/debug/fume-server" + ], + "processCreateCommands": [ + "settings set target.run-args value1 value2 value3", + "process launch" + ] + }, + { + "type": "extensionHost", + "request": "launch", + "name": "Launch Client", + "runtimeExecutable": "${execPath}", + "args": [ + "--extensionDevelopmentPath=${workspaceRoot}" + ], + "outFiles": [ + "${workspaceRoot}/client/out/**/*.js" + ], + "preLaunchTask": { + "type": "npm", + "script": "watch" + } + }, + ], + "compounds": [ + { + "name": "Client + Server", + "configurations": [ + "Launch Client", + "Fume Server" + ] + } + ] +} \ No newline at end of file diff --git a/vscode-plugin/.vscode/tasks.json b/vscode-plugin/.vscode/tasks.json new file mode 100644 index 00000000000..5efd8048880 --- /dev/null +++ b/vscode-plugin/.vscode/tasks.json @@ -0,0 +1,33 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "compile", + "group": "build", + "presentation": { + "panel": "dedicated", + "reveal": "never" + }, + "problemMatcher": [ + "$tsc" + ] + }, + { + "type": "npm", + "script": "watch", + "isBackground": true, + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "panel": "dedicated", + "reveal": "never" + }, + "problemMatcher": [ + "$tsc-watch" + ] + } + ] +} \ No newline at end of file diff --git a/vscode-plugin/.vscodeignore b/vscode-plugin/.vscodeignore new file mode 100644 index 00000000000..f369b5e55b6 --- /dev/null +++ b/vscode-plugin/.vscodeignore @@ -0,0 +1,4 @@ +.vscode/** +.vscode-test/** +.gitignore +vsc-extension-quickstart.md diff --git a/vscode-plugin/CHANGELOG.md b/vscode-plugin/CHANGELOG.md new file mode 100644 index 00000000000..946c421c17c --- /dev/null +++ b/vscode-plugin/CHANGELOG.md @@ -0,0 +1,9 @@ +# Change Log + +All notable changes to the "vscode-fume" extension will be documented in this file. + +Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. + +## [Unreleased] + +- Initial release \ No newline at end of file diff --git a/vscode-plugin/README.md b/vscode-plugin/README.md new file mode 100644 index 00000000000..b71f6f3b23a --- /dev/null +++ b/vscode-plugin/README.md @@ -0,0 +1,18 @@ +# vscode-fume README + +### When does the vscode-plugin get activated? +Currently it gets activated once you open a file with ".fm" extension. +### Testing as a real installed Extension +* To start using your extension with Visual Studio Code copy vscode-plugin into the `/.vscode/extensions` folder and restart Code. +* Copy /fume-server folder as well in order that the vscode-plugin can start the LSP Server once it is activated. + +### Testing in Debug mode +* In order to start the Debug mode, open `vscode-plugin` in VSCode, make sure that it's opened as root/main workspace - in order to avoid any problems. +* Make sure that in `Run and Debug` Tab that "Launch Client" is selected - press F5 and new VSCode Debug Window will be opened. +* Within that Window open a .fm file like "main.fm" - which will activate Fume-server, which currently needs to be in the same root folder as vscode-plugin. + +### Testing in Debug mode with the attached Server +* (This is only needed if you are developing the Server.) +* Install this extension -> [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb) +* Repeat the steps outlined in "Testing in Debug mode", then go back `Run and Debug` Tab, from the dropdown menu +choose "Fume Server" which will attach the server in the debug mode as well. diff --git a/vscode-plugin/client/src/extension.ts b/vscode-plugin/client/src/extension.ts new file mode 100644 index 00000000000..0ff70f0a51d --- /dev/null +++ b/vscode-plugin/client/src/extension.ts @@ -0,0 +1,83 @@ +import { workspace, ExtensionContext, ExtensionMode } from 'vscode' + +import { + Executable, + LanguageClient, + LanguageClientOptions, + ServerOptions, + TransportKind +} from 'vscode-languageclient/node' + +let client: LanguageClient + +export function activate(context: ExtensionContext) { + client = new LanguageClient( + 'fume-server', + 'Fume', + getServerOptions(context), + getClientOptions() + ) + + // Start the client. This will also launch the server + console.log("Starting Client and Server") + client.start() + + client.onReady().then(_ => { + console.log("Client has Connected to the Server successfully!") + }) +} + +export function deactivate(): Thenable | undefined { + if (!client) { + return undefined + } + return client.stop() +} + + +function getServerOptions(context: ExtensionContext): ServerOptions { + const serverPath = context.asAbsolutePath('../fume-server') + + const serverExecutable: Executable = { + command: 'cargo run', + options: { + cwd: serverPath, + shell: true, + } + } + + const serverOptions: ServerOptions = { + run: serverExecutable, + debug: serverExecutable, + transport: TransportKind.stdio, + } + + switch (context.extensionMode) { + case ExtensionMode.Development: + case ExtensionMode.Test: + return serverOptions + + default: + throw new Error("Production Mode not available at the moment!") + } +} + +function getClientOptions(): LanguageClientOptions { + // Options to control the language client + const clientOptions: LanguageClientOptions = { + // Register the server for plain text documents + documentSelector: [ + { scheme: 'file', language: 'fume' }, + { scheme: 'untitled', language: 'fume' }, + ], + synchronize: { + // Notify the server about file changes to '.fm files contained in the workspace + fileEvents: [ + workspace.createFileSystemWatcher('**/.fm'), + workspace.createFileSystemWatcher("**/*.fm"), + ] + } + } + + return clientOptions +} \ No newline at end of file diff --git a/vscode-plugin/client/tsconfig.json b/vscode-plugin/client/tsconfig.json new file mode 100644 index 00000000000..c526fc9c6ae --- /dev/null +++ b/vscode-plugin/client/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es2019", + "lib": ["ES2019"], + "outDir": "out", + "rootDir": "src", + "sourceMap": true + }, + "include": ["src"], + "exclude": ["node_modules", ".vscode-test"] +} diff --git a/vscode-plugin/language-configuration.json b/vscode-plugin/language-configuration.json new file mode 100644 index 00000000000..8f162a0c45f --- /dev/null +++ b/vscode-plugin/language-configuration.json @@ -0,0 +1,30 @@ +{ + "comments": { + // symbol used for single line comment. Remove this entry if your language does not support line comments + "lineComment": "//", + // symbols used for start and end a block comment. Remove this entry if your language does not support block comments + "blockComment": [ "/*", "*/" ] + }, + // symbols used as brackets + "brackets": [ + ["{", "}"], + ["[", "]"], + ["(", ")"] + ], + // symbols that are auto closed when typing + "autoClosingPairs": [ + ["{", "}"], + ["[", "]"], + ["(", ")"], + ["\"", "\""], + ["'", "'"] + ], + // symbols that can be used to surround a selection + "surroundingPairs": [ + ["{", "}"], + ["[", "]"], + ["(", ")"], + ["\"", "\""], + ["'", "'"] + ] +} \ No newline at end of file diff --git a/vscode-plugin/package-lock.json b/vscode-plugin/package-lock.json new file mode 100644 index 00000000000..ca8d360069e --- /dev/null +++ b/vscode-plugin/package-lock.json @@ -0,0 +1,1990 @@ +{ + "name": "vscode-fume", + "version": "0.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", + "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, + "@eslint/eslintrc": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", + "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + } + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", + "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.4", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", + "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", + "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.4", + "fastq": "^1.6.0" + } + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", + "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==", + "dev": true + }, + "@types/mocha": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.2.tgz", + "integrity": "sha512-Lwh0lzzqT5Pqh6z61P3c3P5nm6fzQK/MMHl9UKeneAeInVflBSz1O2EkX6gM6xfJd7FBXBY5purtLx7fUiZ7Hw==", + "dev": true + }, + "@types/node": { + "version": "12.20.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.11.tgz", + "integrity": "sha512-gema+apZ6qLQK7k7F0dGkGCWQYsL0qqKORWOQO6tq46q+x+1C0vbOiOqOwRVlh4RAdbQwV/j/ryr3u5NOG1fPQ==", + "dev": true + }, + "@types/vscode": { + "version": "1.55.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.55.0.tgz", + "integrity": "sha512-49hysH7jneTQoSC8TWbAi7nKK9Lc5osQNjmDHVosrcU8o3jecD9GrK0Qyul8q4aGPSXRfNGqIp9CBdb13akETg==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.22.0.tgz", + "integrity": "sha512-U8SP9VOs275iDXaL08Ln1Fa/wLXfj5aTr/1c0t0j6CdbOnxh+TruXu1p4I0NAvdPBQgoPjHsgKn28mOi0FzfoA==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "4.22.0", + "@typescript-eslint/scope-manager": "4.22.0", + "debug": "^4.1.1", + "functional-red-black-tree": "^1.0.1", + "lodash": "^4.17.15", + "regexpp": "^3.0.0", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + } + }, + "@typescript-eslint/experimental-utils": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.22.0.tgz", + "integrity": "sha512-xJXHHl6TuAxB5AWiVrGhvbGL8/hbiCQ8FiWwObO3r0fnvBdrbWEDy1hlvGQOAWc6qsCWuWMKdVWlLAEMpxnddg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/scope-manager": "4.22.0", + "@typescript-eslint/types": "4.22.0", + "@typescript-eslint/typescript-estree": "4.22.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + } + }, + "@typescript-eslint/parser": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.22.0.tgz", + "integrity": "sha512-z/bGdBJJZJN76nvAY9DkJANYgK3nlRstRRi74WHm3jjgf2I8AglrSY+6l7ogxOmn55YJ6oKZCLLy+6PW70z15Q==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "4.22.0", + "@typescript-eslint/types": "4.22.0", + "@typescript-eslint/typescript-estree": "4.22.0", + "debug": "^4.1.1" + } + }, + "@typescript-eslint/scope-manager": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.22.0.tgz", + "integrity": "sha512-OcCO7LTdk6ukawUM40wo61WdeoA7NM/zaoq1/2cs13M7GyiF+T4rxuA4xM+6LeHWjWbss7hkGXjFDRcKD4O04Q==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.22.0", + "@typescript-eslint/visitor-keys": "4.22.0" + } + }, + "@typescript-eslint/types": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.22.0.tgz", + "integrity": "sha512-sW/BiXmmyMqDPO2kpOhSy2Py5w6KvRRsKZnV0c4+0nr4GIcedJwXAq+RHNK4lLVEZAJYFltnnk1tJSlbeS9lYA==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.22.0.tgz", + "integrity": "sha512-TkIFeu5JEeSs5ze/4NID+PIcVjgoU3cUQUIZnH3Sb1cEn1lBo7StSV5bwPuJQuoxKXlzAObjYTilOEKRuhR5yg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.22.0", + "@typescript-eslint/visitor-keys": "4.22.0", + "debug": "^4.1.1", + "globby": "^11.0.1", + "is-glob": "^4.0.1", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.22.0.tgz", + "integrity": "sha512-nnMu4F+s4o0sll6cBSsTeVsT4cwxB7zECK3dFxzEjPBii9xLpq4yqqsy/FU5zMfan6G60DKZSCXAa3sHJZrcYw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.22.0", + "eslint-visitor-keys": "^2.0.0" + } + }, + "@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "big-integer": { + "version": "1.6.48", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", + "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==", + "dev": true + }, + "binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", + "dev": true, + "requires": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + } + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "buffer-indexof-polyfill": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", + "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", + "dev": true + }, + "buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", + "dev": true + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true + }, + "chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", + "dev": true, + "requires": { + "traverse": ">=0.3.0 <0.4" + } + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.3.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.25.0.tgz", + "integrity": "sha512-TVpSovpvCNpLURIScDRB6g5CYu/ZFq9GfX2hLNIV4dSBKxIWojeDODvYl3t0k0VtMxYeR8OXPCFE5+oHMlGfhw==", + "dev": true, + "requires": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash": "^4.17.21", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.4", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + } + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", + "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "dev": true + }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-glob": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", + "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fastq": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", + "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", + "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.8.0.tgz", + "integrity": "sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + }, + "dependencies": { + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, + "globby": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", + "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "dev": true + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "listenercount": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", + "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", + "dev": true + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "dev": true + }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, + "log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "mocha": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.2.tgz", + "integrity": "sha512-UdmISwr/5w+uXLPKspgoV7/RXZwKRTiTjJ2/AC5ZiEztIoOYdfKb19+9jNmEInzx5pBsCyJQzarAxqIGBNYJhg==", + "dev": true, + "requires": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.1", + "debug": "4.3.1", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.6", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.0.0", + "log-symbols": "4.0.0", + "minimatch": "3.0.4", + "ms": "2.1.3", + "nanoid": "3.1.20", + "serialize-javascript": "5.0.1", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "wide-align": "1.1.3", + "workerpool": "6.1.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "js-yaml": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", + "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "nanoid": { + "version": "3.1.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", + "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "picomatch": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", + "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.6.0.tgz", + "integrity": "sha512-iZMtp5tUvcnAdtHpZTWLPF0M7AgiQsURR2DwmxnJwSy8I3+cY+ozzVvYha3BOLG2TB+L0CqjIz+91htuj6yCXg==", + "dev": true, + "requires": { + "ajv": "^8.0.1", + "lodash.clonedeep": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.2.0.tgz", + "integrity": "sha512-WSNGFuyWd//XO8n/m/EaOlNLtO0yL8EXT/74LqT4khdhpZjP7lkj/kT5uwRmGitKEVp/Oj7ZUHeGfPtgHhQ5CA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", + "dev": true + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "typescript": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", + "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", + "dev": true + }, + "unzipper": { + "version": "0.10.11", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", + "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", + "dev": true, + "requires": { + "big-integer": "^1.6.17", + "binary": "~0.3.0", + "bluebird": "~3.4.1", + "buffer-indexof-polyfill": "~1.0.0", + "duplexer2": "~0.1.4", + "fstream": "^1.0.12", + "graceful-fs": "^4.2.2", + "listenercount": "~1.0.1", + "readable-stream": "~2.3.6", + "setimmediate": "~1.0.4" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "vscode-jsonrpc": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz", + "integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==" + }, + "vscode-languageclient": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.0.0.tgz", + "integrity": "sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg==", + "requires": { + "minimatch": "^3.0.4", + "semver": "^7.3.4", + "vscode-languageserver-protocol": "3.16.0" + } + }, + "vscode-languageserver-protocol": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz", + "integrity": "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==", + "requires": { + "vscode-jsonrpc": "6.0.0", + "vscode-languageserver-types": "3.16.0" + } + }, + "vscode-languageserver-types": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", + "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==" + }, + "vscode-test": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.5.2.tgz", + "integrity": "sha512-x9PVfKxF6EInH9iSFGQi0V8H5zIW1fC7RAer6yNQR6sy3WyOwlWkuT3I+wf75xW/cO53hxMi1aj/EvqQfDFOAg==", + "dev": true, + "requires": { + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "rimraf": "^3.0.2", + "unzipper": "^0.10.11" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "workerpool": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", + "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true + }, + "yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "requires": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + } + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} diff --git a/vscode-plugin/package.json b/vscode-plugin/package.json new file mode 100644 index 00000000000..c0fb8eb3d44 --- /dev/null +++ b/vscode-plugin/package.json @@ -0,0 +1,67 @@ +{ + "name": "vscode-fume", + "displayName": "vscode-fume", + "description": "Fume language VSCode extension", + "version": "0.0.1", + "scripts": { + "vscode:prepublish": "npm run compile", + "compile": "tsc -b", + "watch": "tsc -b -w", + "test": "sh ./scripts/e2e.sh" + }, + "engines": { + "vscode": "^1.55.0" + }, + "categories": [ + "Programming Languages", + "Extension Packs", + "Snippets", + "Themes" + ], + "main": "./client/out/extension", + "activationEvents": [ + "onLanguage:fume" + ], + "contributes": { + "languages": [ + { + "id": "fume", + "aliases": [ + "Fume", + "fume" + ], + "extensions": [ + ".fm" + ], + "configuration": "./language-configuration.json" + } + ], + "snippets": [ + { + "language": "fume", + "path": "./snippets/fume.json" + } + ], + "grammars": [ + { + "language": "fume", + "scopeName": "source.fume", + "path": "./syntaxes/fume.tmLanguage.json" + } + ] + }, + "dependencies": { + "vscode-languageclient": "^7.0.0" + }, + "devDependencies": { + "@types/vscode": "^1.52.0", + "vscode-test": "^1.3.0", + "@types/mocha": "^8.2.2", + "@types/node": "^12.12.0", + "@typescript-eslint/eslint-plugin": "^4.21.0", + "@typescript-eslint/parser": "^4.21.0", + "eslint": "^7.23.0", + "mocha": "^8.3.2", + "typescript": "^4.2.3" + } +} diff --git a/vscode-plugin/scripts/e2e.sh b/vscode-plugin/scripts/e2e.sh new file mode 100644 index 00000000000..860c62ef8c3 --- /dev/null +++ b/vscode-plugin/scripts/e2e.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +export CODE_TESTS_PATH="$(pwd)/client/out/test" +export CODE_TESTS_WORKSPACE="$(pwd)/client/testFixture" + +node "$(pwd)/client/out/test/runTest" \ No newline at end of file diff --git a/vscode-plugin/snippets/fume.json b/vscode-plugin/snippets/fume.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/vscode-plugin/syntaxes/fume.tmLanguage.json b/vscode-plugin/syntaxes/fume.tmLanguage.json new file mode 100644 index 00000000000..1914536847a --- /dev/null +++ b/vscode-plugin/syntaxes/fume.tmLanguage.json @@ -0,0 +1,400 @@ +{ + "name": "fume", + "scopeName": "source.fume", + "patterns": [ + { + "comment": "Implementation", + "begin": "\\b(impl)\\b", + "end": "\\{", + "beginCaptures": { + "1": { + "name": "storage.type.fume" + } + }, + "patterns": [ + { + "include": "#block_comment" + }, + { + "include": "#line_comment" + }, + { + "include": "#sigils" + }, + { + "include": "#mut" + }, + { + "include": "#core_types" + }, + { + "include": "#type_params" + }, + { + "include": "#where" + }, + { + "name": "storage.type.fume", + "match": "\\bfor\\b" + }, + { + "include": "#type" + } + ] + }, + { + "include": "#block_doc_comment" + }, + { + "include": "#block_comment" + }, + { + "include": "#line_doc_comment" + }, + { + "include": "#line_comment" + }, + { + "comment": "Integer literal (decimal)", + "name": "constant.numeric.integer.fume", + "match": "\\b[0-9][0-9_]*([u](8|16|32|64|128))?\\b" + }, + { + "comment": "Integer literal (hexadecimal)", + "name": "constant.numeric.integer.hexadecimal.fume", + "match": "\\b0x[a-fA-F0-9_]+([u](8|16|32|64|128))?\\b" + }, + { + "comment": "Integer literal (binary)", + "name": "constant.numeric.integer.binary.fume", + "match": "\\b0b[01_]+([u](8|16|32|64|128))?\\b" + }, + { + "comment": "Boolean constant", + "name": "constant.language.boolean.fume", + "match": "\\b(true|false)\\b" + }, + { + "comment": "Control keyword", + "name": "keyword.control.fume", + "match": "\\b(else|if|for|match|return|while)\\b" + }, + { + "comment": "Keyword", + "name": "keyword.other.fume", + "match": "\\b(deref|let|ref|use|asm)\\b" + }, + { + "include": "#sigils" + }, + { + "include": "#self" + }, + { + "include": "#mut" + }, + { + "include": "#impl" + }, + { + "include": "#pub" + }, + { + "comment": "Miscellaneous operator", + "name": "keyword.operator.misc.fume", + "match": "(=>|::|->\\?)" + }, + { + "comment": "Comparison operator", + "name": "keyword.operator.comparison.fume", + "match": "(&&|\\|\\||==|!=)" + }, + { + "comment": "Assignment operator", + "name": "keyword.operator.assignment.fume", + "match": "(\\+=|-=|/=|\\*=|%=|\\^=|&=|\\|=|<<=|>>=|=)" + }, + { + "comment": "Arithmetic operator", + "name": "keyword.operator.arithmetic.fume", + "match": "(!|\\+|-|/|\\*|%|\\^|&|\\||<<|>>)" + }, + { + "comment": "Comparison operator (second group because of regex precedence)", + "name": "keyword.operator.comparison.fume", + "match": "(<=|>=|<|>)" + }, + { + "include": "#core_types" + }, + { + "comment": "Function call", + "match": "\\b([A-Za-z][A-Za-z0-9_]*|_[A-Za-z0-9_]+)\\s*\\(", + "captures": { + "1": { + "name": "entity.name.function.fume" + } + } + }, + { + "comment": "Function call with type parameters", + "begin": "\\b([A-Za-z][A-Za-z0-9_]*|_[A-Za-z0-9_]+)\\s*(::)(?=\\s*<.*>\\s*\\()", + "end": "\\(", + "captures": { + "1": { + "name": "entity.name.function.fume" + }, + "2": { + "name": "keyword.operator.misc.fume" + } + }, + "patterns": [ + { + "include": "#type_params" + } + ] + }, + { + "comment": "Function definition", + "begin": "\\b(fn)\\s+([A-Za-z][A-Za-z0-9_]*|_[A-Za-z0-9_]+)", + "end": "[\\{;]", + "beginCaptures": { + "1": { + "name": "keyword.other.fn.fume" + }, + "2": { + "name": "entity.name.function.fume" + } + }, + "patterns": [ + { + "include": "#block_comment" + }, + { + "include": "#line_comment" + }, + { + "include": "#sigils" + }, + { + "include": "#self" + }, + { + "include": "#mut" + }, + { + "include": "#impl" + }, + { + "include": "#core_types" + }, + { + "include": "#type_params" + }, + { + "include": "#where" + }, + { + "comment": "Function arguments", + "match": "\bfn\b", + "name": "keyword.other.fn.fume" + } + ] + }, + { + "comment": "Top level declaration", + "begin": "\\b(library|contract|script|predicate)\\s+([a-zA-Z_][a-zA-Z0-9_]*)", + "end": "[\\{\\(;]", + "beginCaptures": { + "1": { + "name": "storage.type.fume" + }, + "2": { + "name": "entity.name.type.fume" + } + }, + "patterns": [ + { + "include": "#block_comment" + }, + { + "include": "#line_comment" + }, + { + "include": "#impl" + }, + { + "include": "#type_params" + }, + { + "include": "#core_types" + }, + { + "include": "#pub" + }, + { + "include": "#where" + } + ] + }, + { + "comment": "Type declaration", + "begin": "\\b(enum|struct|trait)\\s+([a-zA-Z_][a-zA-Z0-9_]*)", + "end": "[\\{\\(;]", + "beginCaptures": { + "1": { + "name": "storage.type.fume" + }, + "2": { + "name": "entity.name.type.fume" + } + }, + "patterns": [ + { + "include": "#block_comment" + }, + { + "include": "#line_comment" + }, + { + "include": "#type_params" + }, + { + "include": "#core_types" + }, + { + "include": "#pub" + }, + { + "include": "#where" + } + ] + } + ], + "repository": { + "block_doc_comment": { + "comment": "Block documentation comment", + "name": "comment.block.documentation.fume", + "begin": "/\\*[\\*!](?![\\*/])", + "end": "\\*/", + "patterns": [ + { + "include": "#block_doc_comment" + }, + { + "include": "#block_comment" + } + ] + }, + "block_comment": { + "comment": "Block comment", + "name": "comment.block.fume", + "begin": "/\\*", + "end": "\\*/", + "patterns": [ + { + "include": "#block_doc_comment" + }, + { + "include": "#block_comment" + } + ] + }, + "line_doc_comment": { + "comment": "Single-line documentation comment", + "name": "comment.line.documentation.fume", + "begin": "//[!/](?=[^/])", + "end": "$" + }, + "line_comment": { + "comment": "Single-line comment", + "name": "comment.line.double-slash.fume", + "begin": "//", + "end": "$" + }, + "escaped_character": { + "name": "constant.character.escape.fume", + "match": "\\\\(x[0-9A-Fa-f]{2}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)" + }, + "string_literal": { + "comment": "Double-quote string literal", + "name": "string.quoted.double.fume", + "begin": "b?\"", + "end": "\"", + "patterns": [ + { + "include": "#escaped_character" + } + ] + }, + "sigils": { + "comment": "Sigil", + "name": "keyword.operator.sigil.fume", + "match": "[&*](?=[a-zA-Z0-9_\\(\\[\\|\\\"]+)" + }, + "self": { + "comment": "Self variable", + "name": "variable.language.fume", + "match": "\\bself\\b" + }, + "mut": { + "comment": "Mutable storage modifier", + "name": "storage.modifier.mut.fume", + "match": "\\bmut\\b" + }, + "impl": { + "comment": "Existential type modifier", + "name": "storage.modifier.impl.fume", + "match": "\\bimpl\\b" + }, + "pub": { + "comment": "Visibility modifier", + "name": "storage.modifier.visibility.fume", + "match": "\\bpub\\b" + }, + "where": { + "comment": "Generic where clause", + "name": "keyword.other.where.fume", + "match": "\\bwhere\\b" + }, + "core_types": { + "comment": "Built-in/core type", + "name": "support.type.primitive.fume", + "match": "\\b(bool|char|u8|u16|u32|u64|u128|string|Self)\\b" + }, + "type": { + "comment": "A type", + "name": "entity.name.type.fume", + "match": "\\b([A-Za-z][_A-Za-z0-9]*|_[_A-Za-z0-9]+)\\b" + }, + "type_params": { + "comment": "Type parameters", + "name": "meta.type_params.fume", + "begin": "<(?![=<])", + "end": "(?", + "patterns": [ + { + "include": "#block_comment" + }, + { + "include": "#line_comment" + }, + { + "include": "#sigils" + }, + { + "include": "#mut" + }, + { + "include": "#impl" + }, + { + "include": "#core_types" + }, + { + "include": "#type_params" + } + ] + } + } +} \ No newline at end of file diff --git a/vscode-plugin/tsconfig.json b/vscode-plugin/tsconfig.json new file mode 100644 index 00000000000..63fb7c8c56e --- /dev/null +++ b/vscode-plugin/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es2019", + "lib": ["ES2019"], + "outDir": "out", + "rootDir": "src", + "sourceMap": true + }, + "include": [ + "src" + ], + "exclude": [ + "node_modules", + ".vscode-test" + ], + "references": [ + { "path": "./client" }, + ] +} \ No newline at end of file