Initial SFERA platform baseline
This commit is contained in:
@@ -0,0 +1,290 @@
|
||||
pub mod calls;
|
||||
pub mod keywords;
|
||||
pub mod models;
|
||||
pub mod parser;
|
||||
pub mod queries;
|
||||
pub mod writes;
|
||||
|
||||
use crate::calls::extract_calls;
|
||||
use crate::models::ParsedSemanticUnit;
|
||||
use crate::parser::extract_procedures;
|
||||
use crate::queries::extract_queries;
|
||||
use crate::writes::extract_writes;
|
||||
|
||||
pub fn parse_module(source_path: &str, source: &str) -> ParsedSemanticUnit {
|
||||
ParsedSemanticUnit {
|
||||
source_path: source_path.to_string(),
|
||||
procedures: extract_procedures(source),
|
||||
calls: extract_calls(source),
|
||||
queries: extract_queries(source),
|
||||
writes: extract_writes(source),
|
||||
diagnostics: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::parse_module;
|
||||
|
||||
#[test]
|
||||
fn parses_procedure_calls_query_and_write() {
|
||||
let source = r#"
|
||||
Процедура Проведение()
|
||||
ПроверитьОстатки();
|
||||
Движения.ОстаткиТоваров.Записать();
|
||||
КонецПроцедуры
|
||||
|
||||
Процедура ПроверитьОстатки()
|
||||
Запрос = Новый Запрос;
|
||||
Запрос.Текст =
|
||||
"ВЫБРАТЬ
|
||||
Остатки.Номенклатура
|
||||
ИЗ
|
||||
РегистрНакопления.ОстаткиТоваров КАК Остатки";
|
||||
КонецПроцедуры
|
||||
"#;
|
||||
let unit = parse_module("module.bsl", source);
|
||||
assert_eq!(unit.procedures.len(), 2);
|
||||
assert_eq!(unit.calls.len(), 1);
|
||||
assert_eq!(unit.queries.len(), 1);
|
||||
assert_eq!(unit.writes.len(), 1);
|
||||
assert_eq!(unit.calls[0].caller, "Проведение");
|
||||
assert_eq!(unit.calls[0].callee, "ПроверитьОстатки");
|
||||
assert_eq!(unit.writes[0].target, "ОстаткиТоваров");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_english_function_query_call_and_write() {
|
||||
let source = r#"
|
||||
Procedure Posting()
|
||||
CheckStock(); // inline comment
|
||||
Movements.StockBalance.Write();
|
||||
EndProcedure
|
||||
|
||||
Function CheckStock()
|
||||
Query = New Query;
|
||||
Query.Text =
|
||||
"SELECT
|
||||
Stock.Item
|
||||
FROM
|
||||
AccumulationRegister.StockBalance AS Stock";
|
||||
EndFunction
|
||||
"#;
|
||||
let unit = parse_module("module.bsl", source);
|
||||
|
||||
assert_eq!(unit.procedures.len(), 2);
|
||||
assert!(unit.procedures[1].is_function);
|
||||
assert_eq!(unit.calls.len(), 1);
|
||||
assert_eq!(unit.calls[0].callee, "CheckStock");
|
||||
assert_eq!(unit.queries.len(), 1);
|
||||
assert_eq!(
|
||||
unit.queries[0].tables,
|
||||
vec!["AccumulationRegister.StockBalance"]
|
||||
);
|
||||
assert!(!unit.queries[0].query_text.ends_with('"'));
|
||||
assert_eq!(unit.writes.len(), 1);
|
||||
assert_eq!(unit.writes[0].target, "StockBalance");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_mixed_russian_and_english_keywords_in_one_module() {
|
||||
let source = r#"
|
||||
Procedure Posting()
|
||||
ПроверитьОстатки();
|
||||
Movements.StockBalance.Write();
|
||||
EndProcedure
|
||||
|
||||
Процедура ПроверитьОстатки()
|
||||
Query = New Query;
|
||||
Query.Text =
|
||||
"SELECT
|
||||
Stock.Item
|
||||
FROM
|
||||
AccumulationRegister.StockBalance AS Stock";
|
||||
КонецПроцедуры
|
||||
"#;
|
||||
let unit = parse_module("module.bsl", source);
|
||||
|
||||
assert_eq!(unit.procedures.len(), 2);
|
||||
assert_eq!(unit.procedures[0].name, "Posting");
|
||||
assert_eq!(unit.procedures[1].name, "ПроверитьОстатки");
|
||||
assert_eq!(unit.calls.len(), 1);
|
||||
assert_eq!(unit.calls[0].caller, "Posting");
|
||||
assert_eq!(unit.calls[0].callee, "ПроверитьОстатки");
|
||||
assert_eq!(unit.queries.len(), 1);
|
||||
assert_eq!(
|
||||
unit.queries[0].tables,
|
||||
vec!["AccumulationRegister.StockBalance"]
|
||||
);
|
||||
assert_eq!(unit.writes.len(), 1);
|
||||
assert_eq!(unit.writes[0].target, "StockBalance");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_inline_query_assignment_with_pipe_prefixed_lines() {
|
||||
let source = r#"
|
||||
Процедура ПолучитьТовары()
|
||||
Запрос = Новый Запрос;
|
||||
Запрос.Текст = "ВЫБРАТЬ
|
||||
|Товары.Ссылка
|
||||
|ИЗ
|
||||
|Справочник.Номенклатура КАК Товары";
|
||||
КонецПроцедуры
|
||||
"#;
|
||||
let unit = parse_module("module.bsl", source);
|
||||
|
||||
assert_eq!(unit.queries.len(), 1);
|
||||
assert_eq!(unit.queries[0].tables, vec!["Справочник.Номенклатура"]);
|
||||
assert!(unit.queries[0].query_text.starts_with("ВЫБРАТЬ"));
|
||||
assert!(!unit.queries[0].query_text.contains("|ИЗ"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_query_from_and_table_on_same_line() {
|
||||
let source = r#"
|
||||
Процедура ПолучитьКонтрагентов()
|
||||
Запрос = Новый Запрос;
|
||||
Запрос.Текст = "ВЫБРАТЬ
|
||||
|Контрагенты.Ссылка
|
||||
|ИЗ Справочник.Контрагенты КАК Контрагенты";
|
||||
КонецПроцедуры
|
||||
"#;
|
||||
let unit = parse_module("module.bsl", source);
|
||||
|
||||
assert_eq!(unit.queries.len(), 1);
|
||||
assert_eq!(unit.queries[0].tables, vec!["Справочник.Контрагенты"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_assignment_function_calls() {
|
||||
let source = r#"
|
||||
Процедура Проведение()
|
||||
МожноПроводить = ПроверитьОстатки();
|
||||
КонецПроцедуры
|
||||
|
||||
Функция ПроверитьОстатки()
|
||||
Возврат Истина;
|
||||
КонецФункции
|
||||
"#;
|
||||
let unit = parse_module("module.bsl", source);
|
||||
|
||||
assert_eq!(unit.calls.len(), 1);
|
||||
assert_eq!(unit.calls[0].caller, "Проведение");
|
||||
assert_eq!(unit.calls[0].callee, "ПроверитьОстатки");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_condition_function_calls() {
|
||||
let source = r#"
|
||||
Процедура Проведение()
|
||||
Если ПроверитьОстатки() Тогда
|
||||
Движения.ОстаткиТоваров.Записать();
|
||||
КонецЕсли;
|
||||
КонецПроцедуры
|
||||
|
||||
Функция ПроверитьОстатки()
|
||||
Возврат Истина;
|
||||
КонецФункции
|
||||
"#;
|
||||
let unit = parse_module("module.bsl", source);
|
||||
|
||||
assert_eq!(unit.calls.len(), 1);
|
||||
assert_eq!(unit.calls[0].caller, "Проведение");
|
||||
assert_eq!(unit.calls[0].callee, "ПроверитьОстатки");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_join_tables_from_query_text() {
|
||||
let source = r#"
|
||||
Процедура ПолучитьЗаказы()
|
||||
Запрос = Новый Запрос;
|
||||
Запрос.Текст = "ВЫБРАТЬ
|
||||
|Заказы.Ссылка,
|
||||
|Контрагенты.Наименование
|
||||
|ИЗ Документ.ЗаказПокупателя КАК Заказы
|
||||
|ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты
|
||||
|ПО Заказы.Контрагент = Контрагенты.Ссылка";
|
||||
КонецПроцедуры
|
||||
"#;
|
||||
let unit = parse_module("module.bsl", source);
|
||||
|
||||
assert_eq!(
|
||||
unit.queries[0].tables,
|
||||
vec!["Документ.ЗаказПокупателя", "Справочник.Контрагенты"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_object_write_targets_from_create_assignments() {
|
||||
let source = r#"
|
||||
Процедура СоздатьНоменклатуру()
|
||||
Элемент = Справочники.Номенклатура.СоздатьЭлемент();
|
||||
Элемент.Записать();
|
||||
КонецПроцедуры
|
||||
|
||||
Procedure CreateOrder()
|
||||
Order = Documents.CustomerOrder.CreateDocument();
|
||||
Order.Write();
|
||||
EndProcedure
|
||||
"#;
|
||||
let unit = parse_module("module.bsl", source);
|
||||
|
||||
assert_eq!(unit.writes.len(), 2);
|
||||
assert_eq!(unit.writes[0].target, "Справочник.Номенклатура");
|
||||
assert_eq!(unit.writes[0].write_type, "OBJECT_WRITE");
|
||||
assert_eq!(unit.writes[1].target, "Документ.CustomerOrder");
|
||||
assert_eq!(unit.writes[1].write_type, "OBJECT_WRITE");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_recordset_write_targets_from_create_assignments() {
|
||||
let source = r#"
|
||||
Процедура ЗаписатьЦены()
|
||||
Набор = РегистрыСведений.Цены.СоздатьНаборЗаписей();
|
||||
Набор.Записать();
|
||||
КонецПроцедуры
|
||||
|
||||
Procedure WriteBalances()
|
||||
Records = AccumulationRegisters.StockBalance.CreateRecordSet();
|
||||
Records.Write();
|
||||
EndProcedure
|
||||
"#;
|
||||
let unit = parse_module("module.bsl", source);
|
||||
|
||||
assert_eq!(unit.writes.len(), 2);
|
||||
assert_eq!(unit.writes[0].target, "РегистрСведений.Цены");
|
||||
assert_eq!(unit.writes[0].write_type, "REGISTER_WRITE");
|
||||
assert_eq!(unit.writes[1].target, "РегистрНакопления.StockBalance");
|
||||
assert_eq!(unit.writes[1].write_type, "REGISTER_WRITE");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_calls_and_writes_inside_control_flow_blocks() {
|
||||
let source = r#"
|
||||
Процедура Проведение()
|
||||
Для Каждого Строка Из Товары Цикл
|
||||
ПроверитьСтроку(Строка);
|
||||
КонецЦикла;
|
||||
|
||||
Попытка
|
||||
Движения.ОстаткиТоваров.Записать();
|
||||
Исключение
|
||||
СообщитьОбОшибке();
|
||||
КонецПопытки;
|
||||
КонецПроцедуры
|
||||
|
||||
Процедура ПроверитьСтроку(Строка)
|
||||
КонецПроцедуры
|
||||
|
||||
Процедура СообщитьОбОшибке()
|
||||
КонецПроцедуры
|
||||
"#;
|
||||
let unit = parse_module("module.bsl", source);
|
||||
|
||||
assert_eq!(unit.calls.len(), 2);
|
||||
assert_eq!(unit.calls[0].callee, "ПроверитьСтроку");
|
||||
assert_eq!(unit.calls[1].callee, "СообщитьОбОшибке");
|
||||
assert_eq!(unit.writes.len(), 1);
|
||||
assert_eq!(unit.writes[0].target, "ОстаткиТоваров");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user