/[eiffelstudio]/branches/Eiffel_57_docking/Src/Eiffel/interface/new_graphical/case_tool/helper/class_text_modifier.e
ViewVC logotype

Contents of /branches/Eiffel_57_docking/Src/Eiffel/interface/new_graphical/case_tool/helper/class_text_modifier.e

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62171 - (show annotations)
Tue Aug 1 01:27:17 2006 UTC (13 years, 4 months ago) by larryl
File size: 38685 byte(s)
First commit docking tabbed Eiffel Studio.
1 indexing
2 description: "[
3 Associated with a class, can modify certain elements of that class text.
4
5 In order to add a feature with the wizard, call `new_feature'.
6 `new_query' does the same but no procedure can be created with the wizard.
7
8 Call `prepare_for_modification' first, which ensures that the
9 text is be managed which is a precondition for the other features.
10
11 Now check the flag `valid_syntax'. If it is `False' we cannot do
12 a modification because the syntax for the class is currently invalid.
13
14 When done modifying, call `commit_modification'.
15 ]"
16 legal: "See notice at end of class."
17 status: "See notice at end of class."
18 date: "$Date$"
19 revision: "$Revision$"
20
21 class
22 CLASS_TEXT_MODIFIER
23
24 inherit
25 ANY
26 redefine
27 default_create
28 end
29
30 EB_CLASS_TEXT_MANAGER
31 export
32 {NONE} all
33 undefine
34 default_create
35 end
36
37 SHARED_ERROR_HANDLER
38 export
39 {NONE} all
40 undefine
41 default_create
42 end
43
44 EB_SHARED_PREFERENCES
45 export
46 {NONE} all
47 undefine
48 default_create
49 end
50
51 EB_CONSTANTS
52 export
53 {NONE} all
54 undefine
55 default_create
56 end
57
58 EV_SHARED_APPLICATION
59 export
60 {NONE} all
61 undefine
62 default_create
63 end
64
65 EB_SHARED_MANAGERS
66 undefine
67 default_create
68 end
69
70 FEATURE_CLAUSE_NAMES
71 undefine
72 default_create
73 end
74
75 SHARED_INST_CONTEXT
76 undefine
77 default_create
78 end
79
80 create
81 make_with_tool,
82 make
83
84 feature {NONE} -- Initialization
85
86 default_create is
87 -- Create an CLASS_TEXT_MODIFIER.
88 do
89 create {ARRAYED_LIST [TUPLE [STRING, INTEGER]]} last_added_code.make (10)
90 create {ARRAYED_LIST [TUPLE [STRING, INTEGER]]} last_removed_code.make (10)
91 end
92
93 make (a_class: CLASS_I) is
94 --
95 require
96 a_class_not_void: a_class /= Void
97 do
98 default_create
99 class_i := a_class
100 reset_date
101 ensure
102 set: class_i = a_class
103 end
104
105 make_with_tool (a_class: CLASS_I; a_tool: like context_editor) is
106 -- Make for `a_class'.
107 require
108 a_class_not_void: a_class /= Void
109 a_tool_not_void: a_tool /= Void
110 do
111 default_create
112 class_i := a_class
113 context_editor := a_tool
114 reset_date
115 ensure
116 a_class_assigned: a_class = class_i
117 a_tool_assigned: a_tool = context_editor
118 end
119
120 feature -- Access
121
122 last_feature_as: FEATURE_AS
123 -- AST of last added feature.
124
125 last_removed_code: ARRAYED_LIST [TUPLE [STRING, INTEGER]]
126 -- List of code and positions that has been removed.
127
128
129 last_added_code: ARRAYED_LIST [TUPLE[STRING, INTEGER]]
130 -- List of added code and position.
131
132 class_as: CLASS_AS
133 -- Current class AST.
134
135 feature -- Status report
136
137 valid_syntax: BOOLEAN is
138 -- Was syntax valid when the class was parsed last time?
139 do
140 Result := class_as /= Void
141 end
142
143 is_modified: BOOLEAN
144 -- Has `class_text' been modified since it was parsed last time?
145
146 text_managed: BOOLEAN is
147 -- Is `text' loaded or retrieved from editor?
148 do
149 Result := text /= Void
150 end
151
152 extend_from_diagram_successful: BOOLEAN
153 -- Was last call to `extend_feature_from_diagram_with_wizard' successful?
154
155 class_modified_outside_diagram: BOOLEAN
156
157 feature -- Status setting
158
159 prepare_for_modification is
160 -- Retrieve `class_text' from file or from an editor if
161 -- the class is open.
162 -- Callers should check `valid_syntax' afterwards to see if
163 -- modification of the class is legal.
164 do
165 if text = Void then
166 text := class_text (class_i)
167 -- Ensured that there is some text in the class we are loading
168 -- so that we can properly find out if we are using a Unix text
169 -- file format.
170 if not text.is_empty and then text.item (text.count) = '%N' then
171 is_unix_file := (text.count = 1) or else (text.item (text.count - 1) /= '%R')
172 else
173 -- Text is messed up, we use the platform default
174 is_unix_file := (create {PLATFORM_CONSTANTS}).is_unix
175 end
176 text.prune_all ('%R')
177 end
178 reparse
179 last_removed_code.wipe_out
180 last_added_code.wipe_out
181 class_modified_outside_diagram := False
182 ensure
183 text_managed: text_managed
184 syntax_still_valid: old valid_syntax implies valid_syntax
185 modified_flag_cleared: not is_modified
186 last_removed_code_empty: last_removed_code.is_empty
187 last_added_code_empty: last_added_code.is_empty
188 end
189
190 commit_modification is
191 -- Save `class_text' to file when not opened in an editor
192 -- or display changes in editors, and reset `date'.
193 require
194 text_managed: text_managed
195 do
196 set_class_text (class_i, text)
197 reset_date
198 text := Void
199 class_as := Void
200 ensure
201 text_unreferenced: not text_managed
202 end
203
204 reset_date is
205 -- A modifying session is about to begin.
206 -- Update `date'.
207 local
208 class_file: PLAIN_TEXT_FILE
209 do
210 create class_file.make (class_i.file_name)
211 if class_file.exists then
212 date := class_file.date
213 end
214 end
215
216 feature -- Element change
217
218 insert_code (a_text: STRING) is
219 -- Insert in `class_text' on `insertion_position', `a_text'.
220 require
221 text_managed: text_managed
222 do
223 last_added_code.extend ([a_text, insertion_position])
224 text.insert_string (a_text, insertion_position)
225 insertion_position := insertion_position + a_text.count
226 is_modified := True
227 ensure
228 is_modified: is_modified
229 end
230
231 remove_code (start_pos, end_pos: INTEGER) is
232 -- Remove code between `start_pos' and `end_pos'.
233 require
234 start_pos_smaller_than_end_pos: start_pos <= end_pos
235 text_managed: text_managed
236 do
237 last_removed_code.put_front ([text.substring (start_pos, end_pos), start_pos])
238 text.replace_substring ("", start_pos, end_pos)
239 is_modified := True
240 ensure
241 is_modified: is_modified
242 end
243
244 replace_code (new_code: STRING; start_pos, end_pos: INTEGER) is
245 -- Replace code between `start_pos' and `end_pos' with `new_code'.
246 require
247 start_pos_smaller_than_end_pos: start_pos <= end_pos
248 text_managed: text_managed
249 new_code_not_void: new_code /= Void
250 do
251 text.replace_substring (new_code, start_pos, end_pos)
252 is_modified := True
253 ensure
254 is_modified: is_modified
255 end
256
257 code (start_pos, end_pos: INTEGER): STRING is
258 -- Code between `start_pos' and `end_pos'.
259 require
260 start_pos_smaller_than_end_pos: start_pos <= end_pos
261 text_managed: text_managed
262 do
263 Result := text.substring (start_pos, end_pos)
264 end
265
266 index_of (c: CHARACTER; start: INTEGER): INTEGER is
267 -- Position of first occurrence of `c' at or after `start';
268 -- 0 if none.
269 require
270 start_large_enough: start >= 1
271 do
272 if start <= text.count + 1 then
273 Result := text.index_of (c, start)
274 end
275 end
276
277 feature -- Modification (Add/Remove feature)
278
279 new_feature is
280 -- Complete steps for adding a feature to a class.
281 -- If class text is ready for code generation (no
282 -- syntax errors), pops up the Feature Composition Wizard (FCW)
283 -- If user clicks OK and entered data is correct,
284 -- generates the feature.
285 -- Sets `last_feature_as' if everything was successful.
286 do
287
288 last_feature_as := Void
289 prepare_for_modification
290 if valid_syntax then
291 execute_wizard (create {EB_FEATURE_COMPOSITION_WIZARD}.make)
292 else
293 create warning_dialog.make_with_text (Warning_messages.w_Class_syntax_error)
294 warning_dialog.show_modal_to_window (Window_manager.last_focused_development_window.window)
295 end
296 end
297
298 remove_ancestor (a_name: STRING) is
299 -- Remove `a_name' from the parent list of `class_as'.
300 require
301 a_name_not_void: a_name /= Void
302 local
303 p: PARENT_AS
304 class_file: PLAIN_TEXT_FILE
305 do
306 create class_file.make (class_i.file_name)
307 check class_file.exists end
308 if class_file.date /= date then
309 put_class_modified_outside_diagram_warning
310 date := class_file.date
311 class_modified_outside_diagram := True
312 end
313 prepare_for_modification
314 if valid_syntax then
315 p := class_as.parent_with_name (a_name)
316 if p /= Void then
317 remove_code (p.start_position, p.end_position)
318 reparse
319 if valid_syntax then
320 if class_as.parents = Void or else class_as.parents.is_empty then
321 remove_code (
322 position_before_inherit,
323 class_as.inherit_clause_insert_position - 1)
324 reparse
325 end
326 end
327 if valid_syntax then
328 commit_modification
329 end
330 end
331 end
332 end
333
334 add_ancestor (a_name: STRING) is
335 -- Reinclude `code' to inheritance clause.
336 require
337 a_name /= Void
338 local
339 class_file: PLAIN_TEXT_FILE
340 do
341 create class_file.make (class_i.file_name)
342 check class_file.exists end
343 if class_file.date /= date then
344 put_class_modified_outside_diagram_warning
345 date := class_file.date
346 class_modified_outside_diagram := True
347 end
348 prepare_for_modification
349 if valid_syntax then
350 insertion_position := class_as.inherit_clause_insert_position
351 if class_as.parents = Void then
352 insert_code ("inherit%N")
353 end
354 insert_code ("%T" + a_name + "%N%N")
355 commit_modification
356 end
357 end
358
359 remove_features (data: LIST [FEATURE_AS]) is
360 -- Remove features in `data', store removed.
361 require
362 data_not_void: data /= Void
363 local
364 class_file: PLAIN_TEXT_FILE
365 actual_feature_as: FEATURE_AS
366 l_item: FEATURE_AS
367 feat_code: STRING
368 f_name: FEATURE_NAME
369 names: EIFFEL_LIST [FEATURE_NAME]
370 name_index, name_start_position, name_end_position, tmp: INTEGER
371 do
372 create class_file.make (class_i.file_name)
373 check class_file.exists end
374 if class_file.date /= date then
375 put_class_modified_outside_diagram_warning
376 date := class_file.date
377 class_modified_outside_diagram := True
378 end
379 prepare_for_modification
380 if valid_syntax then
381 from
382 data.start
383 until
384 data.after
385 loop
386 l_item := data.item
387 actual_feature_as := class_as.feature_with_name (l_item.feature_name)
388 if actual_feature_as /= Void then
389 if actual_feature_as.feature_names.count = 1 then
390 feat_code := code (actual_feature_as.start_position, actual_feature_as.end_position)
391
392 --| FIXME We assume here that features are indented in a standard way.
393 if feat_code.item (feat_code.count) = '%T' then
394 feat_code.remove (feat_code.count)
395 end
396 remove_feature_with_ast (actual_feature_as)
397 else
398 feat_code := code (actual_feature_as.start_position, actual_feature_as.end_position)
399 f_name := Void
400 names := actual_feature_as.feature_names
401 name_index := 1
402 from
403 names.start
404 until
405 f_name /= Void or else names.after
406 loop
407 if names.item.internal_name.is_equal (l_item.feature_name) then
408 f_name := names.item
409 else
410 name_index := name_index + 1
411 names.forth
412 end
413 end
414
415 check f_name /= Void end
416 if name_index = names.count then
417 -- `f_name' is last.
418 name_start_position := actual_feature_as.start_position +
419 feat_code.last_index_of (',', feat_code.count) - 1
420 name_end_position := actual_feature_as.start_position +
421 feat_code.index_of (':', 1) - 1
422 feat_code := code (name_start_position, name_end_position - 1)
423 remove_code (name_start_position, name_end_position - 1)
424 reparse
425 else
426 tmp := feat_code.substring_index (l_item.feature_name, 1)
427 name_start_position := actual_feature_as.start_position + tmp
428 name_end_position := actual_feature_as.start_position +
429 feat_code.index_of (',', tmp) + 1
430 feat_code := code (name_start_position, name_end_position)
431 remove_code (name_start_position, name_end_position)
432 reparse
433 end
434 end
435 end
436 data.forth
437 end
438 commit_modification
439 end
440 end
441
442 undelete_code (data: LIST [TUPLE [STRING, INTEGER]]) is
443 -- Reinclude code in `data'.
444 require
445 data_not_void: data /= Void
446 local
447 class_file: PLAIN_TEXT_FILE
448 l_item: TUPLE [STRING, INTEGER]
449 str: STRING
450 do
451 create class_file.make (class_i.file_name)
452 check class_file.exists end
453 if class_file.date /= date then
454 put_class_modified_outside_diagram_warning
455 date := class_file.date
456 class_modified_outside_diagram := True
457 end
458 prepare_for_modification
459 if valid_syntax then
460 from
461 data.start
462 until
463 data.after
464 loop
465 l_item := data.item
466 str ?= l_item.item (1)
467 insertion_position := l_item.integer_item (2)
468 check
469 insertion_position <= text.count
470 end
471 insert_code (str)
472 data.forth
473 end
474 commit_modification
475 end
476 end
477
478 delete_code (data: LIST [TUPLE [STRING, INTEGER]]) is
479 --
480 local
481 class_file: PLAIN_TEXT_FILE
482 l_item: TUPLE [STRING, INTEGER]
483 str: STRING
484 pos: INTEGER
485 do
486 create class_file.make (class_i.file_name)
487 check class_file.exists end
488 if class_file.date /= date then
489 put_class_modified_outside_diagram_warning
490 date := class_file.date
491 class_modified_outside_diagram := True
492 end
493 prepare_for_modification
494 if valid_syntax then
495 from
496 data.finish
497 until
498 data.before
499 loop
500 l_item := data.item
501 str ?= l_item.item (1)
502 pos := l_item.integer_item (2)
503 check
504 text.has_substring (str)
505 end
506 check
507 text.substring_index (str, 1) = pos
508 end
509 check
510 text.substring (pos, pos + str.count - 1).is_equal (str)
511 end
512 remove_code (pos, pos + str.count - 1)
513 data.back
514 end
515 commit_modification
516 end
517 end
518
519 new_query_from_diagram (preset_type: STRING; x_pos, y_pos, screen_w, screen_h: INTEGER) is
520 -- Complete steps for adding a supplier of `preset_type'.
521 require
522 preset_type_not_void: preset_type /= Void
523 local
524 qcw: EB_QUERY_COMPOSITION_WIZARD
525 x, y: INTEGER
526 do
527 context_editor.develop_window.window.set_pointer_style (context_editor.default_pixmaps.Wait_cursor)
528 last_feature_as := Void
529 prepare_for_modification
530 if valid_syntax then
531 create qcw.make
532 qcw.set_type (preset_type)
533 qcw.set_name_number (context_editor.graph.next_feature_name_number)
534 if x_pos + qcw.width > screen_w then
535 x := screen_w - qcw.width - 150
536 else
537 x := x_pos - 150
538 end
539 if y_pos + qcw.height > screen_h then
540 y := screen_h - qcw.height - 180
541 else
542 y := y_pos - 150
543 end
544 qcw.set_position (x, y)
545 context_editor.develop_window.window.set_pointer_style (context_editor.default_pixmaps.Standard_cursor)
546 execute_wizard_from_diagram (qcw)
547 else
548 create warning_dialog.make_with_text (
549 Warning_messages.w_Class_syntax_error_before_generation (class_i.name_in_upper))
550 warning_dialog.show_modal_to_window (context_editor.develop_window.window)
551 warning_dialog := Void
552 extend_from_diagram_successful := False
553 invalidate_text
554 context_editor.develop_window.window.set_pointer_style (context_editor.default_pixmaps.Standard_cursor)
555 end
556 end
557
558 new_aggregate_query_from_diagram (preset_type: STRING; x_pos, y_pos, screen_w, screen_h: INTEGER) is
559 -- Complete steps for adding a supplier of `preset_type'.
560 require
561 preset_type_not_void: preset_type /= Void
562 local
563 qcw: EB_QUERY_COMPOSITION_WIZARD
564 x, y: INTEGER
565 do
566 context_editor.develop_window.window.set_pointer_style (context_editor.Default_pixmaps.Wait_cursor)
567 last_feature_as := Void
568 prepare_for_modification
569 if valid_syntax then
570 create qcw.make
571 qcw.set_type (preset_type)
572 qcw.set_name_number (context_editor.graph.next_feature_name_number)
573 qcw.enable_expanded_needed
574 if x_pos + qcw.width > screen_w then
575 x := screen_w - qcw.width - 150
576 else
577 x := x_pos - 150
578 end
579 if y_pos + qcw.height > screen_h then
580 y := screen_h - qcw.height - 180
581 else
582 y := y_pos - 150
583 end
584 qcw.set_position (x, y)
585 context_editor.develop_window.window.set_pointer_style (context_editor.Default_pixmaps.Standard_cursor)
586 execute_wizard_from_diagram (qcw)
587 else
588 create warning_dialog.make_with_text (
589 Warning_messages.w_Class_syntax_error_before_generation (class_i.name_in_upper))
590 warning_dialog.show_modal_to_window (context_editor.develop_window.window)
591 warning_dialog := Void
592 extend_from_diagram_successful := False
593 invalidate_text
594 context_editor.develop_window.window.set_pointer_style (context_editor.Default_pixmaps.Standard_cursor)
595 end
596 end
597
598 extend_feature_with_wizard (fcw: EB_FEATURE_COMPOSITION_WIZARD) is
599 -- Add feature described in `fcw' to the class.
600 require
601 wizard_not_void: fcw /= Void
602 local
603 inv: STRING
604 retried: BOOLEAN
605 do
606 if not retried then
607 prepare_for_modification
608 if valid_syntax then
609 if fcw.generate_setter_procedure then
610 set_position_by_feature_clause ("", fc_Element_change)
611 insert_code (setter_procedure (
612 fcw.feature_name,
613 fcw.feature_type,
614 fcw.precondition
615 ))
616 reparse
617 end
618 if valid_syntax then
619 inv := fcw.invariant_part
620 if inv /= Void then
621 extend_invariant (inv)
622 reparse
623 end
624 set_position_by_feature_clause (fcw.clause_export, fcw.clause_comment)
625 insert_code (fcw.code)
626 if valid_syntax then
627 commit_modification
628 else
629 create warning_dialog.make_with_text (Warning_messages.w_New_feature_syntax_error)
630 warning_dialog.show_modal_to_window (Window_manager.last_focused_development_window.window)
631 warning_dialog := Void
632 invalidate_text
633 end
634 else
635 create warning_dialog.make_with_text (Warning_messages.w_New_feature_syntax_error)
636 warning_dialog.show_modal_to_window (Window_manager.last_focused_development_window.window)
637 warning_dialog := Void
638 invalidate_text
639 end
640 else
641 create warning_dialog.make_with_text (
642 Warning_messages.w_Class_syntax_error_before_generation (class_i.name_in_upper))
643 warning_dialog.show_modal_to_window (Window_manager.last_focused_development_window.window)
644 warning_dialog := Void
645 invalidate_text
646 end
647 end
648 end
649
650
651 -- extend_ancestor (a_name: STRING; ihf: BON_INHERITANCE_FIGURE) is
652 -- -- Add `a_name' to parent list of the class
653 -- -- with respect to `ihf' if is is not Void.
654 -- require
655 -- a_name_not_void: a_name /= Void
656 -- text_managed: text_managed
657 -- valid_syntax: valid_syntax
658 -- not_modified: not is_modified
659 -- do
660 ---- insertion_position := class_as.inherit_clause_insert_position + 1
661 ---- if class_as.parents = Void then
662 ---- insert_code ("inherit%N")
663 ---- end
664 ---- if ihf /= Void and then ihf.code /= Void then
665 ---- insert_code (ihf.code)
666 ---- else
667 ---- insert_code ("%T" + a_name + "%N%N")
668 ---- end
669 ---- reparse
670 -- end
671 --
672
673 -- remove_feature_from_diagram_with_wizard (fcw: EB_FEATURE_COMPOSITION_WIZARD; supplier_data: CASE_SUPPLIER) is
674 -- -- Remove feature described in `fcw' from the class.
675 -- require
676 -- wizard_not_void: fcw /= Void
677 -- local
678 -- class_file: PLAIN_TEXT_FILE
679 -- editor: EB_SMART_EDITOR
680 -- do
681 ---- editor := diagram.context_editor.development_window.editor_tool.text_area
682 ---- if not editor.is_empty then
683 ---- -- Wait for the editor to read class text.
684 ---- from
685 ---- process_events_and_idle
686 ---- until
687 ---- editor.text_is_fully_loaded
688 ---- loop
689 ---- end
690 ---- end
691 ----
692 ---- create class_file.make (class_i.file_name)
693 ---- check class_file.exists end
694 ---- if date = class_file.date then
695 ---- prepare_for_modification
696 ---- if valid_syntax then
697 ---- if fcw.invariant_part /= Void then
698 ---- remove_code (
699 ---- supplier_data.invariant_insertion_position,
700 ---- class_as.invariant_insertion_position - 1)
701 ---- reparse
702 ---- end
703 ---- if fcw.generate_setter_procedure then
704 ---- remove_feature ("set_" + fcw.feature_name)
705 ---- end
706 ---- remove_feature (fcw.feature_name)
707 ---- commit_modification
708 ---- supplier_data.remove
709 ---- end
710 ---- else
711 ---- create warning_dialog.make_with_text (Warning_messages.w_Class_modified_outside_diagram)
712 ---- warning_dialog.show_modal_to_window (diagram.context_editor.development_window.window)
713 ---- warning_dialog := Void
714 ---- diagram.context_editor.reset_history
715 ---- date := class_file.date
716 ---- end
717 -- end
718 --
719 -- extend_features_with_data (data: LINKED_LIST [CASE_SUPPLIER]) is
720 -- -- Extend features associated to `data' items.
721 -- require
722 -- data_not_void: data /= Void
723 -- local
724 -- class_file: PLAIN_TEXT_FILE
725 -- cs: CASE_SUPPLIER
726 -- saved_code: STRING
727 -- do
728 ---- create class_file.make (class_i.file_name)
729 ---- check class_file.exists end
730 ---- if date = class_file.date then
731 ---- prepare_for_modification
732 ---- if valid_syntax then
733 ---- from
734 ---- data.start
735 ---- until
736 ---- data.after
737 ---- loop
738 ---- cs := data.item
739 ---- if cs.feature_code /= Void then
740 ---- insertion_position := cs.insertion_position
741 ---- saved_code := cs.feature_code
742 ---- insert_code (saved_code)
743 ---- cs.restore
744 ---- end
745 ---- data.forth
746 ---- end
747 ---- commit_modification
748 ---- end
749 ---- else
750 ---- create warning_dialog.make_with_text (Warning_messages.w_Class_modified_outside_diagram)
751 ---- warning_dialog.show_modal_to_window (diagram.context_editor.development_window.window)
752 ---- warning_dialog := Void
753 ---- diagram.context_editor.reset_history
754 ---- date := class_file.date
755 ---- end
756 -- end
757 --
758 -- remove_feature (a_name: STRING) is
759 -- -- Remove `a_name' from the class.
760 -- require
761 -- a_name_not_void: a_name /= Void
762 -- text_managed: text_managed
763 -- valid_syntax: valid_syntax
764 -- not_modified: not is_modified
765 -- local
766 -- old_comment: STRING
767 -- f: FEATURE_AS
768 -- clauses: EIFFEL_LIST [FEATURE_CLAUSE_AS]
769 -- old_f_clause, f_clause: FEATURE_CLAUSE_AS
770 -- do
771 -- f := class_as.feature_with_name (a_name.as_lower)
772 -- clauses := class_as.features
773 -- from
774 -- clauses.start
775 -- until
776 -- old_f_clause /= Void or else clauses.after
777 -- loop
778 -- if clauses.item.has_feature (f) then
779 -- old_f_clause := clauses.item
780 -- end
781 -- clauses.forth
782 -- end
783 -- old_comment := old_f_clause.comment (text)
784 --
785 -- --| FIXME: Why is `clients' set to Void when feature clause is empty?
786 -- old_f_clause.set_clients (Void)
787 --
788 -- remove_feature_with_ast (f)
789 -- clauses := class_as.features
790 -- from
791 -- clauses.start
792 -- until
793 -- f_clause /= Void or else clauses.after
794 -- loop
795 -- if clauses.item.has_same_clients (old_f_clause) and
796 -- clauses.item.comment (text).is_equal (old_comment) then
797 -- f_clause := clauses.item
798 -- end
799 -- clauses.forth
800 -- end
801 --
802 -- --| The following check should not be needed (see previous FIXME).
803 -- if f_clause /= Void then
804 -- if f_clause.features.is_empty then
805 -- remove_code (
806 -- f_clause.end_position - 7,
807 -- text.substring_index ("%N", f_clause.end_position) + 1)
808 -- reparse
809 -- end
810 -- end
811 -- end
812 --
813 -- set_formal_generics (a_formal_list: STRING) is
814 -- -- Set formal generics of class to `a_formal_list'.
815 -- require
816 -- a_formal_list_not_void: a_formal_list /= Void
817 -- text_managed: text_managed
818 -- valid_syntax: valid_syntax
819 -- not_modified: not is_modified
820 -- do
821 -- remove_formal_generics
822 -- insertion_position := class_as.generics_start_position
823 -- insert_code (a_formal_list)
824 -- end
825 --
826 -- remove_formal_generics is
827 -- -- Remove all formal generics for this class.
828 -- require
829 -- text_managed: text_managed
830 -- valid_syntax: valid_syntax
831 -- not_modified: not is_modified
832 -- do
833 -- if class_as.generics_end_position > 0 then
834 -- remove_code (class_as.generics_start_position + 1, class_as.generics_end_position + 1)
835 -- end
836 -- end
837
838 feature -- Modification (Change class name)
839
840 set_class_name_declaration (a_name, a_generics: STRING) is
841 -- Set `a_name' `a_generics' as new class header.
842 require
843 a_name_not_void: a_name /= Void
844 a_generics_not_void: a_generics /= Void
845 text_managed: text_managed
846 valid_syntax: valid_syntax
847 not_modified: not is_modified
848 local
849 click_ast: CLICK_AST
850 sp, ep: INTEGER
851 do
852 click_ast := class_as.click_ast
853 sp := click_ast.start_position
854 if class_as.generics_end_position > 0 then
855 ep := class_as.generics_end_position
856 else
857 ep := click_ast.end_position
858 end
859
860 remove_code (sp, ep)
861 insertion_position := sp
862 insert_code (a_name)
863 if not a_generics.is_empty then
864 insert_code (" " + a_generics)
865 end
866 end
867
868 set_end_mark (a_name: STRING) is
869 -- Set `a_name' as X in "end -- class X".
870 require
871 a_name_not_void: a_name /= Void
872 text_managed: text_managed
873 local
874 i, j: INTEGER
875 end_mark: STRING
876 do
877 end_mark := "end -- class "
878 i := text.substring_index (end_mark, 1)
879 if i > 0 then
880 j := text.index_of ('%N', i)
881 if j = 0 then
882 j := text.count
883 else
884 j := j - 1
885 end
886 remove_code (i, j)
887 insertion_position := i
888 insert_code (end_mark + a_name)
889 is_modified := True
890 end
891 end
892
893
894 feature {NONE} -- Implementation
895
896 text: STRING
897 -- Current class text.
898
899 is_unix_file: BOOLEAN
900 -- is current file a unix file ?
901 -- (i.e. is "%N" line separator ?)
902
903 insertion_position: INTEGER
904 -- Current place to insert code at.
905
906 match_list: LEAF_AS_LIST
907 -- Match list from `reparse'
908
909 parser: EIFFEL_PARSER is
910 -- Eiffel parser
911 once
912 create Result.make_with_factory (create {AST_ROUNDTRIP_COMPILER_FACTORY})
913 end
914
915 reparse is
916 -- Parse `class_text' and assign AST to `class_as'.
917 require
918 text_managed: text_managed
919 local
920 retried: BOOLEAN
921 l_class_c: CLASS_C
922 do
923 if not retried then
924 --| FIXME set `current_class' in `system'.
925 if class_i.compiled then
926 l_class_c := class_i.compiled_class
927 class_i.system.set_current_class (l_class_c)
928 end
929 inst_context.set_group (class_i.group)
930 parser.parse_from_string (text)
931 if parser.root_node /= Void and then parser.match_list /= Void then
932 class_as := parser.root_node
933 match_list := parser.match_list
934 end
935 is_modified := False
936 else
937 class_as := Void
938 end
939 rescue
940 retried := True
941 Error_handler.error_list.wipe_out
942 retry
943 end
944
945 remove_feature_with_ast (f: FEATURE_AS) is
946 -- Remove `f' from the class.
947 require
948 text_managed: text_managed
949 valid_syntax: valid_syntax
950 not_modified: not is_modified
951 do
952 if f /= Void then
953 remove_code (f.start_position, f.end_position)
954 reparse
955 end
956 end
957
958 execute_wizard (fcw: EB_FEATURE_COMPOSITION_WIZARD) is
959 -- Show `fcw' and generate code if requested.
960 require
961 valid_syntax: valid_syntax
962 unmodified: not is_modified
963 do
964 fcw.show_modal_to_window (Window_manager.last_focused_development_window.window)
965 if fcw.ok_clicked then
966 extend_feature_with_wizard (fcw)
967 end
968 end
969
970 set_last_feature_as (a_name: STRING) is
971 -- Assign `last_feature_as'.
972 do
973 last_feature_as := Void
974 reparse
975 if class_as /= Void then
976 last_feature_as := class_as.feature_with_name (a_name)
977 end
978 end
979
980 setter_procedure (a_attribute, a_type, a_pc: STRING): STRING is
981 -- Add in "Element change" for `a_attribute'.
982 -- If `a_pc' not Void, add as precondition.
983 require
984 a_attribute_not_void: a_attribute /= Void
985 a_type_not_void: a_type /= Void
986 local
987 s: STRING
988 first_character: CHARACTER
989 preposition: STRING
990 do
991 create s.make (60)
992 first_character := a_attribute.item (1)
993 if first_character = 'a' or first_character = 'e' or first_character = 'i' or
994 first_character = 'o' or first_character = 'u' then
995
996 preposition := "an_"
997 else
998 preposition := "a_"
999 end
1000 s.append ("%Tset_" + a_attribute + " (" + preposition + a_attribute + ": like " + a_attribute + ") is%N")
1001 s.append ("%T%T%T-- Set `" + a_attribute + "' to `" + preposition + a_attribute + "'.%N")
1002 if a_pc /= Void then
1003 s.append ("%T%Trequire%N")
1004 s.append ("%T%T%T" + a_pc + "%N")
1005 end
1006 s.append ("%T%Tdo%N")
1007 s.append ("%T%T%T" + a_attribute + " := " + preposition + a_attribute + "%N")
1008 s.append ("%T%Tensure%N")
1009 s.append ("%T%T%T" + a_attribute + "_assigned: " + a_attribute + " = " + preposition + a_attribute + "%N")
1010 s.append ("%T%Tend%N")
1011 s.append ("%N")
1012 Result := s
1013 end
1014
1015 feature_insert_position (f: FEATURE_CLAUSE_AS): INTEGER is
1016 -- Insertion position for `f'.
1017 do
1018 Result := f.feature_keyword.final_position
1019 Result := index_of ('%N', Result) + 1
1020 Result := index_of ('%N', Result) + 1
1021 end
1022
1023 set_position_by_feature_clause (a_export, a_comment: STRING) is
1024 -- Go to `insertion_position' at feature clause with `a_export' and `a_comment'.
1025 -- If it does not exist, add it to the class in the right place.
1026 -- `a_comment' will be compared case sensitive.
1027 require
1028 a_export_not_void: a_export /= Void
1029 a_comment_not_void: a_comment /= Void
1030 a_comment_clean: not a_comment.has ('%R')
1031 text_managed: text_managed
1032 valid_syntax: valid_syntax
1033 not_modified: not is_modified
1034 local
1035 l: EIFFEL_LIST [FEATURE_CLAUSE_AS]
1036 exp, s, c: STRING
1037 lcs: like leading_clauses
1038 l_match_list: LEAF_AS_LIST
1039 l_comments: EIFFEL_COMMENTS
1040 do
1041 l_match_list := match_list
1042 exp := a_export.as_lower
1043 insertion_position := 0
1044
1045 -- Check if specified clause is present.
1046 l := class_as.features
1047 if l /= Void then
1048 from l.start until insertion_position > 0 or else l.after loop
1049 if l.item.clients /= Void then
1050 s := l.item.clients.dump
1051 else
1052 s := ""
1053 end
1054 l_comments := l.item.comment (l_match_list)
1055 if l_comments = Void or else l_comments.is_empty then
1056 c := ""
1057 else
1058 c := l_comments.first.content
1059 if not c.is_equal (" ") then
1060 c.left_adjust
1061 end
1062 end
1063 c.prune_all_trailing ('%R')
1064 if s.is_equal (exp) and c.is_equal (a_comment) then
1065 insertion_position := feature_insert_position (l.item)
1066 end
1067 l.forth
1068 end
1069 end
1070
1071 -- If no insert position set, feature clause is not
1072 -- present. Find position based on feature clause order.
1073 if insertion_position = 0 then
1074 lcs := leading_clauses (a_comment)
1075
1076 l := class_as.features
1077 if l /= Void then
1078 from
1079 l.start
1080 until
1081 insertion_position > 0 or else l.after
1082 loop
1083 l_comments := l.item.comment (l_match_list)
1084 if l_comments = Void or else l_comments.is_empty then
1085 c := ""
1086 else
1087 c := l_comments.first.content
1088 if not c.is_equal (" ") then
1089 c.left_adjust
1090 end
1091 end
1092 c.prune_all_trailing ('%R')
1093 if not lcs.has (c) then
1094 insertion_position := l.item.feature_keyword.position
1095 end
1096 l.forth
1097 end
1098 end
1099 if insertion_position = 0 then
1100 insertion_position := class_as.feature_clause_insert_position
1101 end
1102
1103 insert_feature_clause (a_export, a_comment)
1104 end
1105 end
1106
1107 insert_feature_clause (a_export, a_comment: STRING) is
1108 -- Insert in `insertion_position' a new empty feature clause with
1109 -- `a_export' and `a_comment'.
1110 require
1111 a_export_not_void: a_export /= Void
1112 a_comment_not_void: a_comment /= Void
1113 text_managed: text_managed
1114 local
1115 s, up: STRING
1116 do
1117 create s.make (20)
1118 s.append ("feature")
1119 if not a_export.is_empty then
1120 s.append (" {")
1121 up := a_export.as_upper
1122 s.append (up)
1123 s.extend ('}')
1124 end
1125 if not a_comment.is_empty then
1126 s.append (" -- ")
1127 s.append (a_comment)
1128 end
1129 s.append ("%N%N")
1130 insert_code (s)
1131 end
1132
1133 -- trailing_clauses (a_clause: STRING): ARRAYED_LIST [STRING] is
1134 -- -- Subset of `feature_clause_order' that should appear after `c' in the class text.
1135 -- require
1136 -- a_clause_not_void: a_clause /= Void
1137 -- do
1138 -- create Result.make (20)
1139 -- Result.fill (feature_clause_order)
1140 -- Result.compare_objects
1141 -- if not Result.is_empty then
1142 -- Result.start
1143 -- Result.search (a_clause)
1144 -- if Result.exhausted then
1145 -- Result.start
1146 -- Result.search (fc_Other)
1147 -- if Result.exhausted then
1148 -- Result.wipe_out
1149 -- end
1150 -- end
1151 -- from
1152 -- until
1153 -- Result.off
1154 -- loop
1155 -- Result.remove
1156 -- Result.back
1157 -- end
1158 -- Result.prune_all (fc_Other)
1159 -- end
1160 -- end
1161
1162 leading_clauses (a_clause: STRING): ARRAYED_LIST [STRING] is
1163 -- Subset of `feature_clause_order' that should appear before `c' in the class text.
1164 require
1165 a_clause_not_void: a_clause /= Void
1166 do
1167 create Result.make (20)
1168 Result.fill (preferences.flat_short_data.feature_clause_order)
1169 Result.compare_objects
1170 if not Result.is_empty then
1171 Result.start
1172 Result.search (a_clause)
1173 if Result.exhausted then
1174 Result.start
1175 Result.search (fc_Other)
1176 if Result.exhausted then
1177 Result.wipe_out
1178 end
1179 end
1180 from
1181 until
1182 Result.off
1183 loop
1184 Result.remove
1185 end
1186 Result.prune_all (fc_Other)
1187 end
1188 end
1189
1190 position_before_inherit: INTEGER is
1191 -- Position in `text' before inherit keyword.
1192 local
1193 i: INTEGER
1194 do
1195 from
1196 i := class_as.inherit_clause_insert_position
1197 until
1198 i <= 0 or Result > 0
1199 loop
1200 i := i - 1
1201 Result := text.substring_index ("inherit", i)
1202 end
1203 end
1204
1205 class_i: CLASS_I
1206 -- Subject for modification.
1207
1208 date: INTEGER
1209 -- Date of last modification on `class_i' by `Current'.
1210
1211 context_editor: EB_DIAGRAM_TOOL
1212 --
1213
1214 warning_dialog: EV_WARNING_DIALOG
1215 -- Window that warns user of incorrect syntax or file modification.
1216
1217 invalidate_text is
1218 -- Errors were found during last parsing.
1219 -- Class text will have to be reloaded.
1220 do
1221 text := Void
1222 end
1223
1224
1225 execute_wizard_from_diagram (fcw: EB_FEATURE_COMPOSITION_WIZARD) is
1226 -- Show `fcw' and generate code if requested.
1227 -- Add any graphical items.
1228 require
1229 valid_syntax: valid_syntax
1230 unmodified: not is_modified
1231 do
1232 fcw.show_modal_to_window (context_editor.develop_window.window)
1233 if fcw.ok_clicked then
1234 extend_from_diagram_successful := True
1235 extend_feature_on_diagram_with_wizard (fcw)
1236 else
1237 extend_from_diagram_successful := False
1238 end
1239 end
1240
1241 extend_feature_on_diagram_with_wizard (fcw: EB_FEATURE_COMPOSITION_WIZARD) is --; supplier_data: CASE_SUPPLIER) is
1242 -- Add feature described in `fcw' to the class.
1243 require
1244 wizard_not_void: fcw /= Void
1245 local
1246 class_file: PLAIN_TEXT_FILE
1247 inv: STRING
1248 editor: EB_SMART_EDITOR
1249 new_code: STRING
1250 do
1251 editor := context_editor.develop_window.editors_manager.current_editor
1252 if editor /= Void and then not editor.is_empty then
1253 -- Wait for the editor to read class text.
1254 from
1255 process_events_and_idle
1256 until
1257 editor.text_is_fully_loaded
1258 loop
1259 end
1260 end
1261
1262 create class_file.make (class_i.file_name)
1263 check class_file.exists end
1264 if class_file.date /= date then
1265 put_class_modified_outside_diagram_warning
1266 date := class_file.date
1267 class_modified_outside_diagram := True
1268 end
1269
1270 prepare_for_modification
1271 if valid_syntax then
1272 if fcw.generate_setter_procedure then
1273 set_position_by_feature_clause ("", fc_Element_change)
1274 new_code := setter_procedure (
1275 fcw.feature_name,
1276 fcw.feature_type,
1277 fcw.precondition
1278 )
1279 insert_code (new_code)
1280 reparse
1281 end
1282 if valid_syntax then
1283 set_position_by_feature_clause (fcw.clause_export, fcw.clause_comment)
1284 new_code := fcw.code
1285 insert_code (new_code)
1286 set_last_feature_as (fcw.feature_name)
1287 if valid_syntax then
1288 inv := fcw.invariant_part
1289 if inv /= Void then
1290 extend_invariant (inv)
1291 reparse
1292 end
1293 if valid_syntax then
1294 commit_modification
1295 else
1296 create warning_dialog.make_with_text (Warning_messages.w_New_feature_syntax_error)
1297 warning_dialog.show_modal_to_window (context_editor.develop_window.window)
1298 warning_dialog := Void
1299 extend_from_diagram_successful := False
1300 invalidate_text
1301 end
1302 else
1303 create warning_dialog.make_with_text (Warning_messages.w_New_feature_syntax_error)
1304 warning_dialog.show_modal_to_window (context_editor.develop_window.window)
1305 warning_dialog := Void
1306 extend_from_diagram_successful := False
1307 invalidate_text
1308 end
1309 else
1310 create warning_dialog.make_with_text (Warning_messages.w_New_feature_syntax_error)
1311 warning_dialog.show_modal_to_window (context_editor.develop_window.window)
1312 warning_dialog := Void
1313 extend_from_diagram_successful := False
1314 invalidate_text
1315 end
1316 else
1317 create warning_dialog.make_with_text (
1318 Warning_messages.w_Class_syntax_error_before_generation (class_i.name_in_upper))
1319 warning_dialog.show_modal_to_window (context_editor.develop_window.window)
1320 warning_dialog := Void
1321 extend_from_diagram_successful := False
1322 invalidate_text
1323 end
1324 end
1325
1326 extend_invariant (a_inv: STRING) is
1327 -- Add `a_inv' to end of invariant.
1328 require
1329 a_inv_not_void: a_inv /= Void
1330 text_managed: text_managed
1331 valid_syntax: valid_syntax
1332 not_modified: not is_modified
1333 do
1334 insertion_position := class_as.invariant_insertion_position
1335 if class_as.invariant_part = Void and not class_as.has_empty_invariant then
1336 insert_code ("invariant%N%T")
1337 insert_code (a_inv)
1338 insert_code ("%N%N")
1339 else
1340 insert_code ("%N%T")
1341 insert_code (a_inv)
1342 end
1343 end
1344
1345 put_class_modified_outside_diagram_warning is
1346 -- Inform user, that class was modified outside diagram.
1347 do
1348 if not context_editor.history.is_empty then
1349 output_manager.add_multiline_string (warning_messages.w_class_modified_outside_diagram, 0)
1350 output_manager.add_new_line
1351 context_editor.reset_history
1352 end
1353 end
1354
1355 indexing
1356 copyright: "Copyright (c) 1984-2006, Eiffel Software"
1357 license: "GPL version 2 (see http://www.eiffel.com/licensing/gpl.txt)"
1358 licensing_options: "http://www.eiffel.com/licensing"
1359 copying: "[
1360 This file is part of Eiffel Software's Eiffel Development Environment.
1361
1362 Eiffel Software's Eiffel Development Environment is free
1363 software; you can redistribute it and/or modify it under
1364 the terms of the GNU General Public License as published
1365 by the Free Software Foundation, version 2 of the License
1366 (available at the URL listed under "license" above).
1367
1368 Eiffel Software's Eiffel Development Environment is
1369 distributed in the hope that it will be useful, but
1370 WITHOUT ANY WARRANTY; without even the implied warranty
1371 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1372 See the GNU General Public License for more details.
1373
1374 You should have received a copy of the GNU General Public
1375 License along with Eiffel Software's Eiffel Development
1376 Environment; if not, write to the Free Software Foundation,
1377 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1378 ]"
1379 source: "[
1380 Eiffel Software
1381 356 Storke Road, Goleta, CA 93117 USA
1382 Telephone 805-685-1006, Fax 805-685-6869
1383 Website http://www.eiffel.com
1384 Customer support http://support.eiffel.com
1385 ]"
1386
1387 end -- class CLASS_TEXT_MODIFIER

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.23