Skip to content

Commit

Permalink
Fixed typo in elseifdef formatting.
Browse files Browse the repository at this point in the history
  • Loading branch information
cgagner committed Apr 16, 2024
1 parent 8cc8d30 commit 00071c2
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 15 deletions.
74 changes: 74 additions & 0 deletions moos-ivp-language-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# MOOS-IvP Language Server

## Features

The MOOS-IvP Language Server *will* support a number of different file
formats that are used in MOOS-IvP Projects. Mainly, they *will* support
MOOS Mission files, IvP Behavior files, and NSPlug template files.

### NSPlug
* Semantic Highlighting
* Keywords: Coloring keywords when used in the appropriate context. For
example, only color `#define` directive if it is at the start of the
line, but not if it appears in a quote.
* Include Paths: The `#include` directive is followed by a path to a file
to be included. This is colorized like a quote/string.
* Include Tags: The `#include` directive has an option `<some_tag>` token
that can appear at the end of the line. This relatively new feature will
only include lines from the specified filed between the `some_tag` tag
and the next tag (or end of the file).
* Primitives: NSPlug treats all values as strings. However, we thought it
would be nice to colorize values based on their type. The language
server currently supports floats, integers, booleans, and quotes.
* Diagnostics
* Errors:
- Unknown directives: NSPlug has only a handful of supported directives
(E.G. `#include`, `#define`, `#ifdef`). An error will be displayed if
an unknown directive appears in the file. For example, if you have a
typo like `#fidef` or `#inlcude`.
- Invalid `#ifdef` or `#ifndef` directives: These directive must have a
corresponding `#endif`. Additionally, there must be an `#ifdef` before
there is an `#elseifdef` and `#ifndef` does not support an
`#elseifndef`.Also, `#ifndef` directives do not support conjunctive
(logical-And) or disjunctive (logical-Or) operators. At least one error
message will be displayed if the parser detects an invalid structure.
In the case of a missing `#endif` two error messages will be displayed:
one at the end if the file and one at the outer most `#ifdef`.
- TODO: Combining conjunctive and disjunctive in the same condition.
NSPLug will display a warning by default and will fail in strict mode
if it detects invalid conditions. The language server will treat these
as errors.
* Warnings:
- TODO: Undefined Variable: NSPlug will display a warning if a variable
is not defined and will fail if running in strict mode. However, since
many NSPlug variables are defined launch scripts, the language server
will only ever treat these as warnings.
- TODO: Display a warning if an `#include` directive has a path that
does not exist. This cannot be treated as an error because NSPlug
has the ability to take in a list of directories (using the `--path=`
argument) to search for files. That list of directories is typically
set in a launch script that the language server does not have knowledge
about.
* Document Links:
* Include Paths: The `#include` directive is followed by a path to a file
to be included. If the path exists, the language server will make a
document link so you can `<Control>-Click` on the link to open the
document. This currently only works if the language server has access
to the local file system.
* Completion:
* Directives: If the `#` character is type at the start of the line, the
language server will provide completion for the available NSPLug
directives. For `#ifdef` and `#ifndef`, if completion is selected, the
matching `#endif` will automatically be inserted on the line below.
* TODO: Include Path: After the `#include` directive, if a users requests
completion, the language server will provide a list of files relative
to the current file. This currently only work if the language server has
access to the local file system.
* TODO: Variables: If the `$(` or `%(` strings are typed, the language
server will provide a list of variables defined in the current
mission/workspace along with the closing `)` if needed.


## TODO

1. Work on CI/CD, packaging, and releases.
4 changes: 2 additions & 2 deletions moos-ivp-language-server/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use lsp_types::{
DocumentLink, FoldingRange, FormattingOptions, InlayHint, SemanticToken, SemanticTokenModifier,
SemanticTokens, TextEdit, Url,
};
use moos_parser::{lexers::TokenMap, nsplug::tree::FormatOptions};
use moos_parser::{lexers::TokenMap, nsplug::tree::ENDIF_STR};
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, sync::Arc};

Expand Down Expand Up @@ -409,7 +409,7 @@ impl<'a> Document<'a> {
""
};

let endif_text = format!("{indent}#endif\n");
let endif_text = format!("{indent}{ENDIF_STR}\n");

let ifdef_completion = CompletionItem {
label: "ifdef ".to_string(),
Expand Down
3 changes: 2 additions & 1 deletion moos-ivp-language-server/src/parsers/nsplug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use moos_parser::{
tree::{
FormatOptions, IfDefBranch, IfNotDefBranch, IncludePath, IncludeTag, Line, Lines,
MacroCondition, MacroDefinition, MacroType, Quote, Values, Variable, VariableStrings,
ENDIF_STR,
},
},
ParseError, PlugParser,
Expand Down Expand Up @@ -106,7 +107,7 @@ pub fn parse(document: &mut Document) {
let d = new_error_diagnostic(
&error.loc_start,
&error.loc_end,
format!("Missing #endif"),
format!("Missing {ENDIF_STR}"),
);
document.diagnostics.push(d);
}
Expand Down
32 changes: 20 additions & 12 deletions moos-parser/src/nsplug/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ use crate::lexers::TokenRange;
use crate::vec_wrapper;
use crate::TreeNode;

pub const DEFINE_STR: &str = "#define";
pub const INCLUDE_STR: &str = "#include";
pub const IFDEF_STR: &str = "#ifdef";
pub const IFNDEF_STR: &str = "#ifndef";
pub const ELSEIFDEF_STR: &str = "#elseifdef";
pub const ELSE_STR: &str = "#else";
pub const ENDIF_STR: &str = "#endif";

#[cfg(feature = "lsp-types")]
fn create_text_edit(
new_text: String,
Expand Down Expand Up @@ -591,17 +599,17 @@ impl<'input> ToString for MacroType<'input> {
definition,
range: _,
} => {
format!("#define {}", definition.to_string())
format!("{DEFINE_STR} {}", definition.to_string())
}
MacroType::Include {
path,
tag,
range: _,
} => {
if let Some(tag) = tag {
format!("#include {} {}", path.to_string(), tag.to_string())
format!("{INCLUDE_STR} {} {}", path.to_string(), tag.to_string())
} else {
format!("#include {}", path.to_string())
format!("{INCLUDE_STR} {}", path.to_string())
}
}
MacroType::IfDef {
Expand All @@ -611,15 +619,15 @@ impl<'input> ToString for MacroType<'input> {
range: _,
} => {
// TODO: Need to recursively print the branch and lines
format!("#ifdef {}", condition.to_string())
format!("{IFDEF_STR} {}", condition.to_string())
}
MacroType::IfNotDef {
clauses,
branch: _,
body: _,
range: _,
} => {
let rtn = "#ifndef".to_string();
let rtn = IFNDEF_STR.to_string();
clauses
.iter()
.fold(rtn, |acc, v| acc + " " + v.to_string().as_str())
Expand Down Expand Up @@ -866,7 +874,7 @@ impl<'input> IfDefBranch<'input> {
.flat_map(|line| line.format(format_options, level + 1)),
);

let new_text = "#endif".to_string();
let new_text = ENDIF_STR.to_string();
if new_indent != *endif_indent
|| start_index != endif_macro_range.start
|| (start_index + new_text.len() as u32) != *endif_line_end_index
Expand Down Expand Up @@ -923,10 +931,10 @@ impl<'input> ToString for IfDefBranch<'input> {
fn to_string(&self) -> String {
match self {
IfDefBranch::ElseIfDef { condition, .. } => {
format!("#elsifdef {}", condition.to_string())
format!("{ELSEIFDEF_STR} {}", condition.to_string())
}
IfDefBranch::Else { .. } => "#else".to_string(),
IfDefBranch::EndIf { .. } => "#endif".to_string(),
IfDefBranch::Else { .. } => ELSE_STR.to_string(),
IfDefBranch::EndIf { .. } => ENDIF_STR.to_string(),
}
}
}
Expand Down Expand Up @@ -1036,7 +1044,7 @@ impl<'input> IfNotDefBranch<'input> {
.flat_map(|line| line.format(format_options, level + 1)),
);

let new_text = "#endif".to_string();
let new_text = ENDIF_STR.to_string();
if new_indent != *endif_indent
|| start_index != endif_macro_range.start
|| (start_index + new_text.len() as u32) != *endif_line_end_index
Expand Down Expand Up @@ -1090,8 +1098,8 @@ impl<'input> TreeNode for IfNotDefBranch<'input> {
impl<'input> ToString for IfNotDefBranch<'input> {
fn to_string(&self) -> String {
match self {
IfNotDefBranch::Else { .. } => "#else".to_string(),
IfNotDefBranch::EndIf { .. } => "#endif".to_string(),
IfNotDefBranch::Else { .. } => ELSE_STR.to_string(),
IfNotDefBranch::EndIf { .. } => ENDIF_STR.to_string(),
}
}
}
Expand Down

0 comments on commit 00071c2

Please sign in to comment.