Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ac23f15

Browse files
committed
Refactored ut_annotation_parser API to use ut_annotations collection as output results.
Reworked `ut_suite_manager` to operate on sorted collection for building ut_suite and it's tests. Adjusted `test_annotation_parser` to cover the refactoring.
1 parent 13703fa commit ac23f15

10 files changed

Lines changed: 716 additions & 833 deletions

File tree

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
create type ut_annotation as object(
2+
position number(5,0),
3+
name varchar2(1000),
4+
text varchar2(4000),
5+
subobject_name varchar2(250)
6+
)
7+
/
8+

source/core/annotations/ut_annotation_parser.pkb

Lines changed: 57 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,14 @@ create or replace package body ut_annotation_parser as
3939
,modifier => 'n');
4040
end;
4141

42-
function get_annotations(a_source varchar2, a_comments tt_comment_list) return tt_annotations is
43-
l_loop_index pls_integer := 1;
44-
l_comment_index pls_integer;
45-
l_comment varchar2(32767);
46-
l_annotation_str varchar2(32767);
47-
l_annotation_text varchar2(32767);
48-
l_annotation_name varchar2(1000);
49-
l_annotation t_annotation;
50-
l_annotations_list tt_annotations;
42+
function get_annotations(a_source varchar2, a_comments tt_comment_list, a_subobject_name varchar2 := null) return ut_annotations is
43+
l_loop_index pls_integer := 1;
44+
l_annotation_index pls_integer;
45+
l_comment varchar2(32767);
46+
l_annotation_str varchar2(32767);
47+
l_annotation_text varchar2(32767);
48+
l_annotation_name varchar2(1000);
49+
l_annotations ut_annotations := ut_annotations();
5150
begin
5251
-- loop while there are unprocessed comment blocks
5352
while 0 != nvl(regexp_instr(srcstr => a_source
@@ -57,13 +56,13 @@ create or replace package body ut_annotation_parser as
5756
,0) loop
5857

5958
-- define index of the comment block and get it's content from cache
60-
l_comment_index := to_number(regexp_substr(a_source
59+
l_annotation_index := to_number(regexp_substr(a_source
6160
,c_comment_replacer_regex_ptrn
6261
,1
6362
,l_loop_index
6463
,subexpression => 1));
6564

66-
l_comment := a_comments(l_comment_index);
65+
l_comment := a_comments( l_annotation_index );
6766

6867
-- strip everything except the annotation itself (spaces and others)
6968
l_annotation_str := regexp_substr(l_comment, c_annotation_pattern, 1, 1, modifier => 'i');
@@ -76,38 +75,39 @@ create or replace package body ut_annotation_parser as
7675
,subexpression => 1));
7776
l_annotation_text := trim(regexp_substr(l_annotation_str, '\((.*?)\)\s*$', subexpression => 1));
7877

79-
l_annotation.text := l_annotation_text;
80-
l_annotations_list(l_annotation_name) := l_annotation;
78+
l_annotations.extend;
79+
l_annotations( l_annotations.last) :=
80+
ut_annotation(l_annotation_index, l_annotation_name, l_annotation_text, a_subobject_name);
8181
end if;
8282
l_loop_index := l_loop_index + 1;
8383
end loop;
84-
85-
return l_annotations_list;
84+
return l_annotations;
8685

8786
end get_annotations;
8887

89-
function get_package_annotations(a_source clob, a_comments tt_comment_list) return tt_annotations is
88+
function get_package_annotations(a_source clob, a_comments tt_comment_list) return ut_annotations is
9089
l_package_comments varchar2(32767);
90+
l_annotations ut_annotations := ut_annotations();
9191
begin
9292
l_package_comments := regexp_substr(srcstr => a_source
9393
,pattern => '^\s*(CREATE\s+(OR\s+REPLACE)?(\s+(NON)?EDITIONABLE)?\s+)?PACKAGE\s[^;]*?(\s+(AS|IS)\s+)((.*?{COMMENT#\d+}\s?)+)'
9494
,modifier => 'i'
9595
,subexpression => 7);
9696

9797
-- parsing for package annotations
98-
return
99-
case when l_package_comments is not null then
100-
get_annotations(l_package_comments, a_comments)
101-
end;
98+
if l_package_comments is not null then
99+
l_annotations := get_annotations(l_package_comments, a_comments);
100+
end if;
101+
102+
return l_annotations;
102103
end;
103104

104-
function get_procedure_list(a_source clob, a_comments tt_comment_list) return tt_procedure_list is
105+
function get_procedure_list(a_source clob, a_comments tt_comment_list) return ut_annotations is
105106
l_proc_comments varchar2(32767);
106107
l_proc_name t_annotation_name;
107108
l_annot_proc_ind number;
108109
l_annot_proc_block varchar2(32767);
109-
l_procedure_annotations tt_procedure_annotations;
110-
l_procedure_list tt_procedure_list;
110+
l_annotations ut_annotations := ut_annotations();
111111
begin
112112
-- loop through procedures and functions of the package and get all the comment blocks just before it's declaration
113113
l_annot_proc_ind := 1;
@@ -139,18 +139,16 @@ create or replace package body ut_annotation_parser as
139139
,subexpression => 5));
140140

141141
-- parse the comment block for the syntactically correct annotations and store them as an array
142-
l_procedure_annotations.name := l_proc_name;
143-
l_procedure_annotations.annotations := get_annotations(l_proc_comments, a_comments);
144-
145-
l_procedure_list(l_procedure_list.count+1) := l_procedure_annotations;
142+
l_annotations := l_annotations multiset union all get_annotations(l_proc_comments, a_comments, l_proc_name);
146143

147144
--l_annot_proc_ind := l_annot_proc_ind + length(l_annot_proc_block);
148145
l_annot_proc_ind := regexp_instr(srcstr => a_source
149146
,pattern => ';'
150147
,occurrence => 1
151148
,position => l_annot_proc_ind + length(l_annot_proc_block));
152149
end loop;
153-
return l_procedure_list;
150+
151+
return l_annotations;
154152
end;
155153

156154
function extract_and_replace_comments(a_source in out nocopy clob) return tt_comment_list is
@@ -199,62 +197,21 @@ create or replace package body ut_annotation_parser as
199197
return l_comments;
200198
end extract_and_replace_comments;
201199

202-
-- $if $$ut_trace $then
203-
-- procedure print_parse_results(a_annotated_pkg typ_annotated_package) is
204-
-- l_name t_annotation_name := a_annotated_pkg.package_annotations.first;
205-
-- l_proc_name t_annotation_name;
206-
-- begin
207-
-- dbms_output.put_line('Annotations count: ' || a_annotated_pkg.package_annotations.count);
208-
--
209-
-- while l_name is not null loop
210-
-- dbms_output.put_line(' @' || l_name);
211-
-- if a_annotated_pkg.package_annotations(l_name).count > 0 then
212-
-- dbms_output.put_line(' Parameters:');
213-
--
214-
-- for j in 1 .. a_annotated_pkg.package_annotations(l_name).count loop
215-
-- dbms_output.put_line(' ' || nvl(a_annotated_pkg.package_annotations(l_name)(j).key, '<Anonymous>') || ' = ' ||
216-
-- nvl(a_annotated_pkg.package_annotations(l_name)(j).val, 'NULL'));
217-
-- end loop;
218-
-- else
219-
-- dbms_output.put_line(' No parameters.');
220-
-- end if;
221-
--
222-
-- l_name := a_annotated_pkg.package_annotations.next(l_name);
223-
--
224-
-- end loop;
225-
--
226-
-- dbms_output.put_line('Procedures count: ' || a_annotated_pkg.procedure_annotations.count);
227-
--
228-
-- for i in 1 .. a_annotated_pkg.procedure_annotations.count loop
229-
-- l_proc_name := a_annotated_pkg.procedure_annotations(i).name;
230-
-- dbms_output.put_line(rpad('-', 80, '-'));
231-
-- dbms_output.put_line(' Procedure: ' || l_proc_name);
232-
-- dbms_output.put_line(' Annotations count: ' || a_annotated_pkg.procedure_annotations(i).annotations.count);
233-
-- l_name := a_annotated_pkg.procedure_annotations(i).annotations.first;
234-
-- while l_name is not null loop
235-
-- dbms_output.put_line(' @' || l_name);
236-
-- if a_annotated_pkg.procedure_annotations(i).annotations(l_name).count > 0 then
237-
-- dbms_output.put_line(' Parameters:');
238-
-- for j in 1 .. a_annotated_pkg.procedure_annotations(i).annotations(l_name).count loop
239-
-- dbms_output.put_line(' ' ||
240-
-- nvl(a_annotated_pkg.procedure_annotations(i).annotations(l_name)(j).key, '<Anonymous>') ||
241-
-- ' = ' || nvl(a_annotated_pkg.procedure_annotations(i).annotations(l_name)(j).val, 'NULL'));
242-
-- end loop;
243-
-- else
244-
-- dbms_output.put_line(' No parameters.');
245-
-- end if;
246-
--
247-
-- l_name := a_annotated_pkg.procedure_annotations(i).annotations.next(l_name);
248-
-- end loop;
249-
-- end loop;
250-
--
251-
-- end print_parse_results;
252-
-- $end
253-
254-
function parse_package_annotations(a_source clob) return typ_annotated_package is
200+
$if $$ut_trace $then
201+
procedure print_parse_results(a_annotations ut_annotations) is
202+
begin
203+
dbms_output.put_line('Annotations count: ' || a_annotations.count);
204+
for i in 1 .. a_annotations.count loop
205+
dbms_output.put_line(xmltype(a_annotations(i)).getclobval());
206+
end loop;
207+
end print_parse_results;
208+
$end
209+
210+
function parse_package_annotations(a_source clob) return ut_annotations is
255211
l_source clob := a_source;
256212
l_comments tt_comment_list;
257-
l_annotated_pkg typ_annotated_package;
213+
l_annotations ut_annotations;
214+
l_result ut_annotations;
258215
begin
259216

260217
l_source := delete_multiline_comments(l_source);
@@ -263,53 +220,37 @@ create or replace package body ut_annotation_parser as
263220
-- this call modifies l_source
264221
l_comments := extract_and_replace_comments(l_source);
265222

266-
l_annotated_pkg.package_annotations := get_package_annotations(l_source, l_comments);
267-
268-
l_annotated_pkg.procedure_annotations := get_procedure_list(l_source, l_comments);
269-
270-
-- -- printing out parsed structure for debugging
271-
-- $if $$ut_trace $then
272-
-- print_parse_results(l_annotated_pkg);
273-
-- $end
223+
l_annotations :=
224+
get_package_annotations(l_source, l_comments)
225+
multiset union all get_procedure_list(l_source, l_comments);
274226

275227
dbms_lob.freetemporary(l_source);
276-
return l_annotated_pkg;
228+
select value(x)
229+
bulk collect into l_result
230+
from table(l_annotations) x
231+
order by x.position;
232+
233+
-- printing out parsed structure for debugging
234+
$if $$ut_trace $then
235+
print_parse_results(l_result);
236+
$end
237+
return l_result;
277238
end parse_package_annotations;
278239

279240
------------------------------
280241
--public definitions
281242

282-
function get_package_annotations(a_owner_name varchar2, a_name varchar2) return typ_annotated_package is
243+
function get_package_annotations(a_owner_name varchar2, a_name varchar2) return ut_annotations is
283244
l_source clob;
284245
ex_package_is_wrapped exception;
285246
pragma exception_init(ex_package_is_wrapped, -24241);
286247
begin
287-
288-
-- TODO: Add cache of annotations. Cache invalidation should be based on DDL timestamp.
289-
-- Cache garbage collection should be executed once in a while to remove annotations cache for packages that were dropped.
290-
291-
begin
292-
l_source := ut_metadata.get_package_spec_source(a_owner_name, a_name);
293-
exception
294-
when ex_package_is_wrapped then
295-
null;
296-
end;
297-
298-
if l_source is null or sys.dbms_lob.getlength(l_source)=0 then
299-
return null;
300-
else
301-
return parse_package_annotations(l_source);
302-
end if;
248+
return parse_package_annotations(ut_metadata.get_package_spec_source(a_owner_name, a_name));
249+
exception
250+
when ex_package_is_wrapped then
251+
return ut_annotations();
303252
end;
304253

305-
-- function get_annotation_param(a_param_list tt_annotation_params, a_def_index pls_integer) return varchar2 is
306-
-- l_result varchar2(32767);
307-
-- begin
308-
-- if a_param_list.exists(a_def_index) then
309-
-- l_result := a_param_list(a_def_index).val;
310-
-- end if;
311-
-- return l_result;
312-
-- end get_annotation_param;
313254

314255
-- parse the annotation parameters and return as key-value pair array
315256
function parse_annotation_params(a_annotation_text varchar2) return tt_annotation_params is

source/core/annotations/ut_annotation_parser.pks

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -46,53 +46,19 @@ create or replace package ut_annotation_parser authid current_user as
4646
*/
4747
type tt_annotation_params is table of typ_annotation_param index by pls_integer;
4848

49-
type t_annotation is record(
50-
text varchar2(4000)
51-
);
52-
53-
/*
54-
type: tt_annotations
55-
a list of tt_annotation_params index by the annotation name
56-
*/
57-
type tt_annotations is table of t_annotation index by t_annotation_name;
58-
59-
/*
60-
type: tt_procedure_annotations
61-
a list of tt_annotations index by the procedure name
62-
*/
63-
type tt_procedure_annotations is record(name t_procedure_name, annotations tt_annotations);
64-
65-
type tt_procedure_list is table of tt_procedure_annotations index by pls_integer;
66-
67-
/*
68-
type: typ_annotated_package
69-
a structure containing a list of package level annotations and a list of procedure level annotations
70-
71-
*/
72-
type typ_annotated_package is record(
73-
procedure_annotations tt_procedure_list
74-
,package_annotations tt_annotations);
75-
7649
/*
7750
INTERNAL USE ONLY
7851
*/
79-
function parse_package_annotations(a_source clob) return typ_annotated_package;
52+
function parse_package_annotations(a_source clob) return ut_annotations;
8053

8154
/*
8255
function: get_package_annotations
8356

8457
get annotations for specified package specification and return its annotated schema
8558
*/
86-
function get_package_annotations(a_owner_name varchar2, a_name varchar2) return typ_annotated_package;
59+
function get_package_annotations(a_owner_name varchar2, a_name varchar2) return ut_annotations;
8760

8861

89-
/*
90-
function: get_annotation_param
91-
92-
get annotation parameter on a specified index position
93-
*/
94-
-- function get_annotation_param(a_param_list tt_annotation_params, a_def_index pls_integer) return varchar2;
95-
9662
/*
9763
function: parse_annotation_params
9864

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
create type ut_annotations as table of ut_annotation
2+
/

source/core/types/ut_test.tpb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ create or replace type body ut_test as
3333
return;
3434
end;
3535

36+
member procedure set_beforeeach(self in out nocopy ut_test, a_before_each_proc_name varchar2) is
37+
begin
38+
self.before_each := ut_executable(self, a_before_each_proc_name, ut_utils.gc_before_each);
39+
end;
40+
member procedure set_aftereach(self in out nocopy ut_test, a_after_each_proc_name varchar2) is
41+
begin
42+
self.after_each := ut_executable(self, a_after_each_proc_name, ut_utils.gc_after_each);
43+
end;
3644
member function is_valid(self in out nocopy ut_test) return boolean is
3745
l_is_valid boolean;
3846
begin

source/core/types/ut_test.tps

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ create or replace type ut_test under ut_suite_item (
5252
a_after_test_proc_name varchar2 := null, a_after_each_proc_name varchar2 := null
5353
) return self as result,
5454
member function is_valid(self in out nocopy ut_test) return boolean,
55+
member procedure set_beforeeach(self in out nocopy ut_test, a_before_each_proc_name varchar2),
56+
member procedure set_aftereach(self in out nocopy ut_test, a_after_each_proc_name varchar2),
5557
overriding member function do_execute(self in out nocopy ut_test, a_listener in out nocopy ut_event_listener_base) return boolean,
5658
overriding member procedure calc_execution_result(self in out nocopy ut_test),
5759
overriding member procedure mark_as_errored(self in out nocopy ut_test, a_listener in out nocopy ut_event_listener_base, a_error_stack_trace varchar2),

0 commit comments

Comments
 (0)