Add unknown ranges and open object values
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
use decodal::{
|
||||
Engine, HostEnvironment, HostValue, ImportLoader, LoadedImport, Result, RuntimeValue,
|
||||
Engine, HostEnvironment, ImportLoader, LoadedImport, Result, Value, runtime::RuntimeValue,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
@@ -116,12 +116,12 @@ pub(crate) fn complete<E: HostEnvironment>(
|
||||
let mut loader = environment.create_loader();
|
||||
let loaded = loader.load(Some(key), specifier)?;
|
||||
detail = match &loaded {
|
||||
LoadedImport::Source(source) => source.name.clone(),
|
||||
LoadedImport::Value(value) => value.key.clone(),
|
||||
LoadedImport::Source { name, .. } => name.clone(),
|
||||
LoadedImport::Value { key, .. } => key.clone(),
|
||||
};
|
||||
fields = match loaded {
|
||||
LoadedImport::Source(source) => collect_fields(&tokenize(&source.source)),
|
||||
LoadedImport::Value(value) => fields_from_host_value(&value.value),
|
||||
LoadedImport::Source { source, .. } => collect_fields(&tokenize(&source)),
|
||||
LoadedImport::Value { value, .. } => fields_from_value(&value),
|
||||
};
|
||||
} else if let Some(local) = local_fields.get(root) {
|
||||
fields = local.clone();
|
||||
@@ -229,6 +229,7 @@ fn builtin_items() -> Vec<CompletionItem> {
|
||||
("Int", CompletionKind::Type, "integer constraint", 5),
|
||||
("Float", CompletionKind::Type, "float constraint", 5),
|
||||
("Bool", CompletionKind::Type, "boolean constraint", 5),
|
||||
("Unknown", CompletionKind::Type, "unknown top range", 5),
|
||||
]
|
||||
.into_iter()
|
||||
.map(|(label, kind, detail, priority)| CompletionItem {
|
||||
@@ -267,24 +268,24 @@ fn fields_from_runtime<L: ImportLoader>(
|
||||
Ok(tree)
|
||||
}
|
||||
|
||||
fn fields_from_host_value(value: &HostValue) -> FieldTree {
|
||||
fn fields_from_value(value: &Value) -> FieldTree {
|
||||
match value {
|
||||
HostValue::Object(fields) => fields
|
||||
Value::Object { fields, .. } => fields
|
||||
.iter()
|
||||
.map(|field| (field.name.clone(), fields_from_host_value(&field.value)))
|
||||
.map(|field| (field.name.clone(), fields_from_value(&field.value)))
|
||||
.collect(),
|
||||
HostValue::ArrayConstraint {
|
||||
Value::ArrayRange {
|
||||
default: Some(value),
|
||||
..
|
||||
}
|
||||
| HostValue::MapConstraint {
|
||||
| Value::MapRange {
|
||||
default: Some(value),
|
||||
..
|
||||
}
|
||||
| HostValue::Abstract {
|
||||
| Value::Range {
|
||||
default: Some(value),
|
||||
..
|
||||
} => fields_from_host_value(value),
|
||||
} => fields_from_value(value),
|
||||
_ => FieldTree::new(),
|
||||
}
|
||||
}
|
||||
@@ -688,7 +689,7 @@ mod tests {
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use decodal::{
|
||||
Diagnostic, DiagnosticKind, EmptyLoader, HostValue, ImportCandidate, LoadedImport, Span,
|
||||
Diagnostic, DiagnosticKind, EmptyLoader, ImportCandidate, LoadedImport, Span, Value,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
@@ -708,15 +709,15 @@ mod tests {
|
||||
if specifier == "./post.md" {
|
||||
return Ok(LoadedImport::value(
|
||||
"post.md",
|
||||
HostValue::object([
|
||||
Value::object([
|
||||
(
|
||||
"frontmatter",
|
||||
HostValue::object([
|
||||
("title", HostValue::string("Hello")),
|
||||
("draft", HostValue::bool(false)),
|
||||
Value::object([
|
||||
("title", Value::string("Hello")),
|
||||
("draft", Value::bool(false)),
|
||||
]),
|
||||
),
|
||||
("body", HostValue::string("# Hello")),
|
||||
("body", Value::string("# Hello")),
|
||||
]),
|
||||
));
|
||||
}
|
||||
@@ -758,12 +759,9 @@ mod tests {
|
||||
fn configure_engine(&self, engine: &mut Engine<Self::Loader>) -> Result<()> {
|
||||
engine.bind_global(
|
||||
"App",
|
||||
HostValue::object([(
|
||||
Value::object([(
|
||||
"config",
|
||||
HostValue::object([
|
||||
("enabled", HostValue::bool_type()),
|
||||
("port", HostValue::int_type()),
|
||||
]),
|
||||
Value::object([("enabled", Value::bool_type()), ("port", Value::int_type())]),
|
||||
)]),
|
||||
)?;
|
||||
Ok(())
|
||||
@@ -854,6 +852,7 @@ mod tests {
|
||||
.unwrap();
|
||||
let labels = labels(result);
|
||||
assert!(labels.contains(&"String".into()));
|
||||
assert!(labels.contains(&"Unknown".into()));
|
||||
assert!(labels.contains(&"service".into()));
|
||||
assert!(labels.contains(&"value".into()));
|
||||
assert!(labels.contains(&"App".into()));
|
||||
@@ -881,6 +880,10 @@ mod tests {
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
assert!(labels(result).contains(&"String".into()));
|
||||
let result = complete(&EmptyEnvironment, "main.dcdl", "Unk", 3, false)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
assert!(labels(result).contains(&"Unknown".into()));
|
||||
}
|
||||
|
||||
struct EmptyEnvironment;
|
||||
|
||||
@@ -92,7 +92,7 @@ impl SemanticAnalysis {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use decodal::{
|
||||
Data, Diagnostic, DiagnosticKind, Engine, HostValue, ImportLoader, LoadedImport, Span,
|
||||
Data, Diagnostic, DiagnosticKind, Engine, ImportLoader, LoadedImport, Span, Value,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
@@ -100,11 +100,11 @@ mod tests {
|
||||
const ROOT: &str = r#"Post & import "./post.md""#;
|
||||
|
||||
struct ContentEnvironment {
|
||||
draft: HostValue,
|
||||
draft: Value,
|
||||
}
|
||||
|
||||
struct ContentLoader {
|
||||
draft: HostValue,
|
||||
draft: Value,
|
||||
}
|
||||
|
||||
impl ImportLoader for ContentLoader {
|
||||
@@ -122,15 +122,15 @@ mod tests {
|
||||
}
|
||||
Ok(LoadedImport::value(
|
||||
"content/post.md",
|
||||
HostValue::object([
|
||||
Value::object([
|
||||
(
|
||||
"frontmatter",
|
||||
HostValue::object([
|
||||
("title", HostValue::string("Hello")),
|
||||
Value::object([
|
||||
("title", Value::string("Hello")),
|
||||
("draft", self.draft.clone()),
|
||||
]),
|
||||
),
|
||||
("body", HostValue::string("# Hello")),
|
||||
("body", Value::string("# Hello")),
|
||||
]),
|
||||
))
|
||||
}
|
||||
@@ -148,15 +148,15 @@ mod tests {
|
||||
fn configure_engine(&self, engine: &mut Engine<Self::Loader>) -> decodal::Result<()> {
|
||||
engine.bind_global(
|
||||
"Post",
|
||||
HostValue::object([
|
||||
Value::object([
|
||||
(
|
||||
"frontmatter",
|
||||
HostValue::object([
|
||||
("title", HostValue::string_type()),
|
||||
("draft", HostValue::bool_type()),
|
||||
Value::object([
|
||||
("title", Value::string_type()),
|
||||
("draft", Value::bool_type()),
|
||||
]),
|
||||
),
|
||||
("body", HostValue::string_type()),
|
||||
("body", Value::string_type()),
|
||||
]),
|
||||
)?;
|
||||
Ok(())
|
||||
@@ -173,7 +173,7 @@ mod tests {
|
||||
#[test]
|
||||
fn injected_environment_matches_direct_evaluation() {
|
||||
let environment = ContentEnvironment {
|
||||
draft: HostValue::bool(false),
|
||||
draft: Value::bool(false),
|
||||
};
|
||||
let direct = evaluate_direct(&environment).unwrap();
|
||||
let service = LanguageService::new(&environment);
|
||||
@@ -186,7 +186,7 @@ mod tests {
|
||||
#[test]
|
||||
fn injected_environment_preserves_import_diagnostics() {
|
||||
let service = LanguageService::new(ContentEnvironment {
|
||||
draft: HostValue::string("maybe"),
|
||||
draft: Value::string("maybe"),
|
||||
});
|
||||
let analysis = service.analyze("main.dcdl", "main.dcdl", ROOT);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user