Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add 'compile_only' flag for lint check #737

Merged
merged 1 commit into from
Oct 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions kclvm/api/src/capi_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,15 @@ fn test_c_api_lint_path() {
);
}

#[test]
fn test_c_api_call_exec_program_with_compile_only() {
test_c_api_paniced::<ExecProgramArgs>(
"KclvmService.ExecProgram",
"exec-program-with-compile-only.json",
"exec-program-with-compile-only.response.panic",
);
}

#[test]
fn test_c_api_validate_code() {
test_c_api_without_wrapper::<ValidateCodeArgs, ValidateCodeResult>(
Expand Down Expand Up @@ -149,3 +158,47 @@ where
kclvm_service_free_string(result_ptr);
}
}

fn test_c_api_paniced<A>(svc_name: &str, input: &str, output: &str)
where
A: Message + DeserializeOwned,
{
let _test_lock = TEST_MUTEX.lock().unwrap();
let serv = kclvm_service_new(0);

let input_path = Path::new(TEST_DATA_PATH).join(input);
let input = fs::read_to_string(&input_path)
.unwrap_or_else(|_| panic!("Something went wrong reading {}", input_path.display()));
let args = unsafe {
CString::from_vec_unchecked(serde_json::from_str::<A>(&input).unwrap().encode_to_vec())
};
let call = CString::new(svc_name).unwrap();
let prev_hook = std::panic::take_hook();
// disable print panic info
std::panic::set_hook(Box::new(|_info| {}));
let result = std::panic::catch_unwind(|| {
kclvm_service_call(serv, call.as_ptr(), args.as_ptr()) as *mut i8
});
std::panic::set_hook(prev_hook);
match result {
Ok(result_ptr) => {
let result = unsafe { CStr::from_ptr(result_ptr) };
let except_result_path = Path::new(TEST_DATA_PATH).join(output);
let except_result_panic_msg =
fs::read_to_string(&except_result_path).unwrap_or_else(|_| {
panic!(
"Something went wrong reading {}",
except_result_path.display()
)
});
assert!(result.to_string_lossy().contains(&except_result_panic_msg));
unsafe {
kclvm_service_delete(serv);
kclvm_service_free_string(result_ptr);
}
}
Err(_) => {
panic!("unreachable code")
}
}
}
17 changes: 17 additions & 0 deletions kclvm/api/src/testdata/exec-program-with-compile-only.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"work_dir" : "./src/testdata",
"k_filename_list":[
"test-lint-import.k"
],
"compile_only": true,
"external_pkgs": [
{
"pkg_name": "external",
"pkg_path": "./src/testdata_external/external"
},
{
"pkg_name": "external_1",
"pkg_path": "./src/testdata_external/external_1"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Module 'external' imported but unused
4 changes: 4 additions & 0 deletions kclvm/api/src/testdata/test-lint-import.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import external as ext
import external_1 as ext_1

a1 = ext_1.a
18 changes: 15 additions & 3 deletions kclvm/runner/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ use kclvm_error::{Diagnostic, Handler};
use kclvm_parser::{load_program, ParseSession};
use kclvm_query::apply_overrides;
use kclvm_runtime::{PanicInfo, PlanOptions, ValueRef};
use kclvm_sema::resolver::{resolve_program, scope::ProgramScope};
use kclvm_sema::resolver::{
resolve_program, resolve_program_with_opts, scope::ProgramScope, Options,
};
use linker::Command;
pub use runner::ExecProgramArgs;
use runner::{ExecProgramResult, KclvmRunner, KclvmRunnerOptions};
Expand Down Expand Up @@ -192,9 +194,18 @@ pub fn execute(
mut program: Program,
args: &ExecProgramArgs,
) -> Result<String, String> {
// If the user only wants to compile the kcl program, the following code will only resolve ast.
if args.compile_only {
let mut resolve_opts = Options::default();
resolve_opts.merge_program = false;
// Resolve ast
let scope = resolve_program_with_opts(&mut program, resolve_opts);
emit_compile_diag_to_string(sess, &scope, args.compile_only)?;
return Ok("".to_string());
}
// Resolve ast
let scope = resolve_program(&mut program);
emit_compile_diag_to_string(sess, &scope)?;
emit_compile_diag_to_string(sess, &scope, false)?;

// Create a temp entry file and the temp dir will be delete automatically
let temp_dir = tempdir().map_err(|e| e.to_string())?;
Expand Down Expand Up @@ -303,13 +314,14 @@ fn temp_file(dir: &str) -> Result<String> {
fn emit_compile_diag_to_string(
sess: Arc<ParseSession>,
scope: &ProgramScope,
include_warnings: bool,
) -> Result<(), String> {
let mut res_str = sess
.1
.borrow_mut()
.emit_to_string()
.map_err(|err| err.to_string())?;
let sema_err = scope.emit_diagnostics_to_string(sess.0.clone());
let sema_err = scope.emit_diagnostics_to_string(sess.0.clone(), include_warnings);
if sema_err.is_err() {
#[cfg(not(target_os = "windows"))]
res_str.push_str("\n");
Expand Down
2 changes: 2 additions & 0 deletions kclvm/runner/src/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ pub struct ExecProgramArgs {
pub sort_keys: bool,
/// Whether including schema type in JSON/YAML result
pub include_schema_type_path: bool,
// Whether to compile only.
pub compile_only: bool,
// plugin_agent is the address of plugin.
#[serde(skip)]
pub plugin_agent: u64,
Expand Down
2 changes: 1 addition & 1 deletion kclvm/runner/src/test_datas/exec_prog_args/default.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"work_dir":null,"k_filename_list":[],"external_pkgs":[],"k_code_list":[],"args":[],"overrides":[],"disable_yaml_result":false,"print_override_ast":false,"strict_range_check":false,"disable_none":false,"verbose":0,"debug":0,"sort_keys":false,"include_schema_type_path":false}
{"work_dir":null,"k_filename_list":[],"external_pkgs":[],"k_code_list":[],"args":[],"overrides":[],"disable_yaml_result":false,"print_override_ast":false,"strict_range_check":false,"disable_none":false,"verbose":0,"debug":0,"sort_keys":false,"include_schema_type_path":false,"compile_only":false}
2 changes: 1 addition & 1 deletion kclvm/runner/src/test_datas/settings_file/settings.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"work_dir":null,"k_filename_list":["../main.k","./before/base.k","./main.k","./sub/sub.k"],"external_pkgs":[],"k_code_list":[],"args":[{"name":"app-name","value":"\"kclvm\""},{"name":"image","value":"\"kclvm:v0.0.1\""}],"overrides":[],"disable_yaml_result":false,"print_override_ast":false,"strict_range_check":false,"disable_none":false,"verbose":0,"debug":0,"sort_keys":false,"include_schema_type_path":false}
{"work_dir":null,"k_filename_list":["../main.k","./before/base.k","./main.k","./sub/sub.k"],"external_pkgs":[],"k_code_list":[],"args":[{"name":"app-name","value":"\"kclvm\""},{"name":"image","value":"\"kclvm:v0.0.1\""}],"overrides":[],"disable_yaml_result":false,"print_override_ast":false,"strict_range_check":false,"disable_none":false,"verbose":0,"debug":0,"sort_keys":false,"include_schema_type_path":false,"compile_only":false}
9 changes: 8 additions & 1 deletion kclvm/sema/src/resolver/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,13 +297,20 @@ impl ProgramScope {
}

/// Return diagnostic pretty string but do not abort if the session exists any diagnostic.
pub fn emit_diagnostics_to_string(&self, sess: Arc<Session>) -> Result<(), String> {
pub fn emit_diagnostics_to_string(
&self,
sess: Arc<Session>,
include_warning: bool,
) -> Result<(), String> {
let emit_error = || -> anyhow::Result<()> {
// Add resolve errors into the session
for diag in &self.handler.diagnostics {
if matches!(diag.level, Level::Error) {
sess.add_err(diag.clone())?;
}
if include_warning && matches!(diag.level, Level::Warning) {
sess.add_err(diag.clone())?;
}
}
// If has syntax and resolve errors, return its string format.
if sess.diag_handler.has_errors()? {
Expand Down
3 changes: 3 additions & 0 deletions kclvm/spec/gpyrpc/gpyrpc.proto
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ message ExecProgram_Args {

// Whether including schema type in JSON/YAML result
bool include_schema_type_path = 14;

// Whether only compiling the program
bool compile_only = 15;
}

message ExecProgram_Result {
Expand Down
Loading