Skip to content

Commit

Permalink
feat: embed the plc json into the source (PLC-lang#1079)
Browse files Browse the repository at this point in the history
The PLC Json schema is now part of the source.
It can be printed using plc config schema
  • Loading branch information
ghaith authored Jan 31, 2024
1 parent 0ae4811 commit 7e2e61a
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 35 deletions.
31 changes: 30 additions & 1 deletion compiler/plc_driver/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,33 @@ pub enum SubCommands {
)]
build_config: Option<String>,
},

/// Prints out various configuration options
Config {
#[clap(
name = "config-format",
group = "config",
default_value = "json",
help = "Format of the configuration file, if supported"
)]
format: ConfigFormat,

#[clap(subcommand)]
option: ConfigOption,
},
}

#[derive(Copy, Clone, PartialEq, Eq, Debug, Subcommand)]
pub enum ConfigOption {
#[clap(help = "Prints the plc.json schema used for validation")]
Schema,
}

impl SubCommands {
pub fn get_build_configuration(&self) -> Option<&str> {
let (SubCommands::Build { build_config, .. } | SubCommands::Check { build_config }) = self;
let (SubCommands::Build { build_config, .. } | SubCommands::Check { build_config }) = self else {
return None;
};
build_config.as_deref()
}
}
Expand Down Expand Up @@ -319,6 +341,13 @@ impl CompileParameters {
_ => None,
}
}

pub fn get_config_options(&self) -> Option<(ConfigOption, ConfigFormat)> {
let Some(SubCommands::Config { format, option }) = &self.commands else {
return None
};
Some((*option, *format))
}
}

#[cfg(test)]
Expand Down
17 changes: 17 additions & 0 deletions compiler/plc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ impl Display for CompileError {
pub fn compile<T: AsRef<str> + AsRef<OsStr> + Debug>(args: &[T]) -> Result<()> {
//Parse the arguments
let compile_parameters = CompileParameters::parse(args)?;
if let Some((options, format)) = compile_parameters.get_config_options() {
return print_config_options(options, format);
}
let project = get_project(&compile_parameters)?;
let output_format = compile_parameters.output_format().unwrap_or_else(|| project.get_output_format());
let location = project.get_location().map(|it| it.to_path_buf());
Expand Down Expand Up @@ -205,6 +208,20 @@ pub fn compile<T: AsRef<str> + AsRef<OsStr> + Debug>(args: &[T]) -> Result<()> {
Ok(())
}

fn print_config_options(
option: cli::ConfigOption,
_format: plc::ConfigFormat,
) -> std::result::Result<(), anyhow::Error> {
match option {
cli::ConfigOption::Schema => {
let schema = include_str!("../../plc_project/schema/plc-json.schema");
println!("{schema}");
}
};

Ok(())
}

/// Parses and annotates a given project. Can be used in tests or api calls
pub fn parse_and_annotate<T: SourceContainer>(
name: &str,
Expand Down
36 changes: 2 additions & 34 deletions compiler/plc_project/src/build_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,41 +84,9 @@ impl ProjectConfig {
Ok(project)
}

fn get_schema() -> Result<PathBuf> {
let current_exe_dir =
std::env::current_exe()?.parent().map(|it| it.to_path_buf()).unwrap_or_default();
let schema_dir = current_exe_dir.join("schema");
#[cfg(feature = "integration")]
//Fallback to the build location
let schema_dir = if !&schema_dir.exists() {
let project_dir: PathBuf = env!("CARGO_MANIFEST_DIR").into();
project_dir.join("schema")
} else {
schema_dir
};
let path = schema_dir.join("plc-json.schema");
if !path.exists() {
Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
format!("{}: File not found", path.to_string_lossy()),
)
.into())
} else {
Ok(path)
}
}

fn validate(&self) -> Result<()> {
let schema_path = match Self::get_schema() {
Ok(path) => path,
Err(error) => {
eprintln!("Could not find schema, validation skipped. Original error: {error:?}");
//Skip validation but do not fail
return Ok(());
}
};
let schema = fs::read_to_string(schema_path).map_err(Diagnostic::from)?;
let schema_obj = serde_json::from_str(&schema).expect("A valid schema");
let schema = include_str!("../schema/plc-json.schema");
let schema_obj = serde_json::from_str(schema).expect("A valid schema");
let compiled = JSONSchema::compile(&schema_obj).expect("A valid schema");
let instance = json!(self);
compiled.validate(&instance).map_err(|errors| {
Expand Down

0 comments on commit 7e2e61a

Please sign in to comment.