@@ -39,6 +39,43 @@ create or replace package body ut_annotation_parser as
3939 ,modifier => 'n');
4040 end;
4141
42+ procedure add_annotation(
43+ a_annotations in out nocopy ut_annotations,
44+ a_position positiven,
45+ a_comment varchar2,
46+ a_subobject_name varchar2 := null
47+ ) is
48+ l_annotation_str varchar2(32767);
49+ l_annotation_text varchar2(32767);
50+ l_annotation_name varchar2(1000);
51+ begin
52+ -- strip everything except the annotation itself (spaces and others)
53+ l_annotation_str := regexp_substr(a_comment, c_annotation_pattern, 1, 1, modifier => 'i');
54+ if l_annotation_str is not null then
55+
56+ -- get the annotation name and it's parameters if present
57+ l_annotation_name := lower(regexp_substr(l_annotation_str
58+ ,'%(' || c_regexp_identifier || ')'
59+ ,modifier => 'i'
60+ ,subexpression => 1));
61+ l_annotation_text := trim(regexp_substr(l_annotation_str, '\((.*?)\)\s*$', subexpression => 1));
62+
63+ a_annotations.extend;
64+ a_annotations( a_annotations.last) :=
65+ ut_annotation(a_position, l_annotation_name, l_annotation_text, a_subobject_name);
66+ end if;
67+ end;
68+
69+ procedure delete_processed_comments( a_comments in out nocopy tt_comment_list, a_annotations ut_annotations ) is
70+ l_loop_index pls_integer := 1;
71+ begin
72+ l_loop_index := a_annotations.first;
73+ while l_loop_index is not null loop
74+ a_comments.delete( a_annotations(l_loop_index).position );
75+ l_loop_index := a_annotations.next( l_loop_index );
76+ end loop;
77+ end;
78+
4279 procedure add_annotations(
4380 a_annotations in out nocopy ut_annotations,
4481 a_source varchar2,
@@ -47,10 +84,6 @@ create or replace package body ut_annotation_parser as
4784 ) is
4885 l_loop_index pls_integer := 1;
4986 l_annotation_index pls_integer;
50- l_comment varchar2(32767);
51- l_annotation_str varchar2(32767);
52- l_annotation_text varchar2(32767);
53- l_annotation_name varchar2(1000);
5487 begin
5588 -- loop while there are unprocessed comment blocks
5689 while 0 != nvl(regexp_instr(srcstr => a_source
@@ -60,49 +93,14 @@ create or replace package body ut_annotation_parser as
6093 ,0) loop
6194
6295 -- define index of the comment block and get it's content from cache
63- l_annotation_index := to_number(regexp_substr(a_source
64- ,c_comment_replacer_regex_ptrn
65- ,1
66- ,l_loop_index
67- ,subexpression => 1));
68-
69- l_comment := a_comments( l_annotation_index );
70-
71- -- strip everything except the annotation itself (spaces and others)
72- l_annotation_str := regexp_substr(l_comment, c_annotation_pattern, 1, 1, modifier => 'i');
73- if l_annotation_str is not null then
74-
75- -- get the annotation name and it's parameters if present
76- l_annotation_name := lower(regexp_substr(l_annotation_str
77- ,'%(' || c_regexp_identifier || ')'
78- ,modifier => 'i'
79- ,subexpression => 1));
80- l_annotation_text := trim(regexp_substr(l_annotation_str, '\((.*?)\)\s*$', subexpression => 1));
81-
82- a_annotations.extend;
83- a_annotations( a_annotations.last) :=
84- ut_annotation(l_annotation_index, l_annotation_name, l_annotation_text, a_subobject_name);
85- end if;
96+ l_annotation_index := regexp_substr( a_source ,c_comment_replacer_regex_ptrn ,1 ,l_loop_index ,subexpression => 1);
97+ add_annotation( a_annotations, l_annotation_index, a_comments( l_annotation_index ), a_subobject_name );
8698 l_loop_index := l_loop_index + 1;
8799 end loop;
88100
89101 end add_annotations;
90102
91- procedure add_package_annotations(a_annotations in out nocopy ut_annotations, a_source clob, a_comments tt_comment_list) is
92- l_package_comments varchar2(32767);
93- begin
94- l_package_comments := regexp_substr(srcstr => a_source
95- ,pattern => '^\s*(CREATE\s+(OR\s+REPLACE)?(\s+(NON)?EDITIONABLE)?\s+)?PACKAGE\s[^;]*?(\s+(AS|IS)\s+)((.*?{COMMENT#\d+}\s?)+)'
96- ,modifier => 'i'
97- ,subexpression => 7);
98-
99- -- parsing for package annotations
100- if l_package_comments is not null then
101- add_annotations(a_annotations, l_package_comments, a_comments);
102- end if;
103- end add_package_annotations;
104-
105- procedure add_procedure_annotations(a_annotations in out nocopy ut_annotations, a_source clob, a_comments tt_comment_list) is
103+ procedure add_procedure_annotations(a_annotations in out nocopy ut_annotations, a_source clob, a_comments in out nocopy tt_comment_list) is
106104 l_proc_comments varchar2(32767);
107105 l_proc_name varchar2(250);
108106 l_annot_proc_ind number;
@@ -119,7 +117,7 @@ create or replace package body ut_annotation_parser as
119117 ,position => l_annot_proc_ind);
120118 exit when l_annot_proc_ind = 0;
121119
122- --get the annotataions with procedure name
120+ --get the annotations with procedure name
123121 l_annot_proc_block := regexp_substr(srcstr => a_source
124122 ,pattern => c_annotation_block_pattern
125123 ,position => l_annot_proc_ind
@@ -140,7 +138,6 @@ create or replace package body ut_annotation_parser as
140138 -- parse the comment block for the syntactically correct annotations and store them as an array
141139 add_annotations(a_annotations, l_proc_comments, a_comments, l_proc_name);
142140
143- --l_annot_proc_ind := l_annot_proc_ind + length(l_annot_proc_block);
144141 l_annot_proc_ind := regexp_instr(srcstr => a_source
145142 ,pattern => ';'
146143 ,occurrence => 1
@@ -203,6 +200,7 @@ create or replace package body ut_annotation_parser as
203200 l_comments tt_comment_list;
204201 l_annotations ut_annotations := ut_annotations();
205202 l_result ut_annotations;
203+ l_comment_index positive;
206204 begin
207205
208206 l_source := delete_multiline_comments(l_source);
@@ -211,15 +209,20 @@ create or replace package body ut_annotation_parser as
211209 -- this call modifies l_source
212210 l_comments := extract_and_replace_comments(l_source);
213211
214- add_package_annotations(l_annotations, l_source, l_comments);
215212 add_procedure_annotations(l_annotations, l_source, l_comments);
216213
214+ delete_processed_comments(l_comments, l_annotations);
215+
216+ --at this point, only the comments not related to procedures are left, so we process them all as top-level
217+ l_comment_index := l_comments.first;
218+ while l_comment_index is not null loop
219+ add_annotation( l_annotations, l_comment_index, l_comments( l_comment_index ) );
220+ l_comment_index := l_comments.next(l_comment_index);
221+ end loop;
217222
218223 dbms_lob.freetemporary(l_source);
219- select value(x)
220- bulk collect into l_result
221- from table(l_annotations) x
222- order by x.position;
224+
225+ select value(x) bulk collect into l_result from table(l_annotations) x order by x.position;
223226
224227 -- printing out parsed structure for debugging
225228 $if $$ut_trace $then
0 commit comments