use crate::language::Token;
use crate::parsers::SyntaxKind;
use super::Parser;
impl Parser<'_> {
pub(super) fn parse_property_statement(&mut self) {
self.parsing_header = false;
self.builder
.start_node(SyntaxKind::PropertyStatement.to_raw());
self.consume_whitespace();
if self.at_token(Token::PublicKeyword)
|| self.at_token(Token::PrivateKeyword)
|| self.at_token(Token::FriendKeyword)
{
self.consume_token();
self.consume_whitespace();
}
if self.at_token(Token::StaticKeyword) {
self.consume_token();
self.consume_whitespace();
}
self.consume_token();
self.consume_whitespace();
if self.at_token(Token::GetKeyword)
|| self.at_token(Token::LetKeyword)
|| self.at_token(Token::SetKeyword)
{
self.consume_token();
}
self.consume_whitespace();
if self.at_token(Token::Identifier) {
self.consume_token();
} else if self.at_keyword() {
self.consume_token_as_identifier();
}
self.consume_whitespace();
if self.at_token(Token::LeftParenthesis) {
self.parse_parameter_list();
}
self.consume_until_after(Token::Newline);
self.parse_statement_list(|parser| {
parser.at_token(Token::EndKeyword)
&& parser.peek_next_keyword() == Some(Token::PropertyKeyword)
});
if self.at_token(Token::EndKeyword) {
self.consume_token();
self.consume_whitespace();
self.consume_token();
self.consume_until_after(Token::Newline);
}
self.builder.finish_node(); }
}
#[cfg(test)]
mod tests {
use crate::*;
#[test]
fn property_get_simple() {
let source = r"
Property Get Name() As String
Name = m_name
End Property
";
let (cst_opt, _failures) = ConcreteSyntaxTree::from_text("test.bas", source).unpack();
let cst = cst_opt.expect("CST should be parsed");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../../snapshots/parsers/cst/property_statements");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!(tree);
}
#[test]
fn property_let_simple() {
let source = r"
Property Let Name(ByVal newName As String)
m_name = newName
End Property
";
let (cst_opt, _failures) = ConcreteSyntaxTree::from_text("test.bas", source).unpack();
let cst = cst_opt.expect("CST should be parsed");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../../snapshots/parsers/cst/property_statements");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!(tree);
}
#[test]
fn property_set_simple() {
let source = r"
Property Set Container(glistNN As gList)
Set glistN = glistNN
End Property
";
let (cst_opt, _failures) = ConcreteSyntaxTree::from_text("test.bas", source).unpack();
let cst = cst_opt.expect("CST should be parsed");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../../snapshots/parsers/cst/property_statements");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!(tree);
}
#[test]
fn property_set_with_object() {
let source = r"
Property Set Callback(ByRef newObj As InterPress)
Set mCallback = newObj
End Property
";
let (cst_opt, _failures) = ConcreteSyntaxTree::from_text("test.bas", source).unpack();
let cst = cst_opt.expect("CST should be parsed");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../../snapshots/parsers/cst/property_statements");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!(tree);
}
#[test]
fn property_get_public() {
let source = r"
Public Property Get Value() As Long
Value = m_value
End Property
";
let (cst_opt, _failures) = ConcreteSyntaxTree::from_text("test.bas", source).unpack();
let cst = cst_opt.expect("CST should be parsed");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../../snapshots/parsers/cst/property_statements");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!(tree);
}
#[test]
fn property_let_private() {
let source = r"
Private Property Let Count(ByVal newCount As Integer)
m_count = newCount
End Property
";
let (cst_opt, _failures) = ConcreteSyntaxTree::from_text("test.bas", source).unpack();
let cst = cst_opt.expect("CST should be parsed");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../../snapshots/parsers/cst/property_statements");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!(tree);
}
#[test]
fn property_set_friend() {
let source = r"
Friend Property Set objref(RHS As Object)
Set m_objref = RHS
End Property
";
let (cst_opt, _failures) = ConcreteSyntaxTree::from_text("test.bas", source).unpack();
let cst = cst_opt.expect("CST should be parsed");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../../snapshots/parsers/cst/property_statements");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!(tree);
}
#[test]
fn property_get_with_parameters() {
let source = r"
Public Property Get Item(index As Long) As Variant
Item = m_items(index)
End Property
";
let (cst_opt, _failures) = ConcreteSyntaxTree::from_text("test.bas", source).unpack();
let cst = cst_opt.expect("CST should be parsed");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../../snapshots/parsers/cst/property_statements");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!(tree);
}
#[test]
fn property_set_with_index_parameter() {
let source = r"
Public Property Set item(curitem As Long, item As Variant)
Set m_items(curitem) = item
End Property
";
let (cst_opt, _failures) = ConcreteSyntaxTree::from_text("test.bas", source).unpack();
let cst = cst_opt.expect("CST should be parsed");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../../snapshots/parsers/cst/property_statements");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!(tree);
}
#[test]
fn property_get_with_if_statement() {
let source = r"
Public Property Get CustomColor(i As Integer) As Long
If fNotFirst = False Then InitColors
If i >= 0 And i <= 15 Then
CustomColor = alCustom(i)
Else
CustomColor = -1
End If
End Property
";
let (cst_opt, _failures) = ConcreteSyntaxTree::from_text("test.bas", source).unpack();
let cst = cst_opt.expect("CST should be parsed");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../../snapshots/parsers/cst/property_statements");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!(tree);
}
#[test]
fn property_let_with_if_statement() {
let source = r"
Public Property Let CustomColor(i As Integer, iValue As Long)
If fNotFirst = False Then InitColors
If i >= 0 And i <= 15 Then
alCustom(i) = iValue
End If
End Property
";
let (cst_opt, _failures) = ConcreteSyntaxTree::from_text("test.bas", source).unpack();
let cst = cst_opt.expect("CST should be parsed");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../../snapshots/parsers/cst/property_statements");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!(tree);
}
#[test]
fn property_get_no_parameters() {
let source = r"
Property Get APIReturn() As Long
APIReturn = m_lApiReturn
End Property
";
let (cst_opt, _failures) = ConcreteSyntaxTree::from_text("test.bas", source).unpack();
let cst = cst_opt.expect("CST should be parsed");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../../snapshots/parsers/cst/property_statements");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!(tree);
}
#[test]
fn property_set_preserves_whitespace() {
let source = r"
Property Set Container ( glistNN As gList )
Set glistN = glistNN
End Property
";
let (cst_opt, _failures) = ConcreteSyntaxTree::from_text("test.bas", source).unpack();
let cst = cst_opt.expect("CST should be parsed");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../../snapshots/parsers/cst/property_statements");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!(tree);
}
#[test]
fn multiple_properties_in_class() {
let source = r"
Private m_name As String
Private m_value As Long
Public Property Get Name() As String
Name = m_name
End Property
Public Property Let Name(ByVal newName As String)
m_name = newName
End Property
Public Property Get Value() As Long
Value = m_value
End Property
Public Property Let Value(ByVal newValue As Long)
m_value = newValue
End Property
";
let (cst_opt, _failures) = ConcreteSyntaxTree::from_text("test.bas", source).unpack();
let cst = cst_opt.expect("CST should be parsed");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../../snapshots/parsers/cst/property_statements");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!(tree);
}
#[test]
fn property_get_returns_object() {
let source = r"
Property Get Callback() As InterPress
Set Callback = mCallback
End Property
";
let (cst_opt, _failures) = ConcreteSyntaxTree::from_text("test.bas", source).unpack();
let cst = cst_opt.expect("CST should be parsed");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../../snapshots/parsers/cst/property_statements");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!(tree);
}
#[test]
fn property_with_exit_property() {
let source = r#"
Property Get Test() As String
If m_value = "" Then Exit Property
Test = m_value
End Property
"#;
let (cst_opt, _failures) = ConcreteSyntaxTree::from_text("test.bas", source).unpack();
let cst = cst_opt.expect("CST should be parsed");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../../snapshots/parsers/cst/property_statements");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!(tree);
}
#[test]
fn property_static() {
let source = r"
Public Static Property Get Counter() As Long
Static count As Long
count = count + 1
Counter = count
End Property
";
let (cst_opt, _failures) = ConcreteSyntaxTree::from_text("test.bas", source).unpack();
let cst = cst_opt.expect("CST should be parsed");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../../snapshots/parsers/cst/property_statements");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!(tree);
}
#[test]
fn property_let_with_multiple_statements() {
let source = r#"
Public Property Let Caption(myCap As String)
mCaptext = myCap
If Not glistN Is Nothing Then
If glistN.CenterText Then
glistN.list(0) = mCaptext
Else
glistN.list(0) = " " + mCaptext
End If
glistN.ShowMe
End If
End Property
"#;
let (cst_opt, _failures) = ConcreteSyntaxTree::from_text("test.bas", source).unpack();
let cst = cst_opt.expect("CST should be parsed");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../../snapshots/parsers/cst/property_statements");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!(tree);
}
}