![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
The Ada Editor The Ada editor is a powerful text editor with special features for editing Ada source files.
Note: The Ada editor is only available with Rational Apex Ada 95/83 and Rational Apex Duo.
About This Chapter
This chapter describes the Ada editor and shows how to use it. Specifically, this chapter covers the following topics:
- The Ada Editor Window
- Starting the Ada Editor
- Editing Source Code
- Ada-Specific Editing
- Semantic Completion
- Delimiter Alignment
This chapter describes the commands available from the Apex editor's File, Edit, View, Navigate, and Compile menus. The Control and Debug menus are covered in other chapters. The Control menu is examined in Using and Customizing Summit/CM and the Debug menu is described in Using the Apex Debugger.
The Ada Editor WindowThe Ada editor window is similar to the text-editor window described in The Apex Editor Window
The Ada editor is used to create, view, and edit Ada source code. An Ada editor window with code is illustrated in Figure 17.
Figure 17 The Ada Editor Window
![]()
Note: The Ada editor was designed using the standard Motif text widget, so its basic editing commands are similar to those of many other Motif clients (and emacs, too). Some keystroke combinations recognized by the Apex editor are actually accelerators for the commands on the Edit menu.
Starting the Ada EditorThere are several ways to start the Ada editor. You can:
- Create a new Ada unit by selecting the File > New > New Ada command.
- Open an existing Ada unit in an editor window by choosing the Open command from the File menu.
Apex then displays an Open dialog box, which you can use to open an Ada unit. (To learn how to use the Open dialog box, see Using and Customizing the GUI.)
- Open an existing Ada unit in an editor window by selecting the unit from the Apex directory-viewer window.
To learn how to use the directory-viewer window, see Using and Customizing the GUI.
Editing Source CodeThe editing commands recognized by the Ada editor are the same as those recognized by the Apex text editor described in The Apex Text Editor. By choosing commands from the Edit menu, you can:
- Perform standard delete, cut, copy, and paste commands
- Undo editing commands that have been issued in error
- Reinstate editing commands that have been undone using the Undo command
- Search text displayed in the editor window for specified patterns and expressions
- Comment out text in Ada source-code listing
- Uncomment Ada source code that has been commented out
There are two ways to execute editing commands: by choosing commands from the Edit menu and by typing keyboard shortcuts. For details, see Using the Text Editor.
Editor Modes
The Ada editor, like the text editor, is always in one of two modes: edit mode or the default read-only mode. When the editor is in edit mode, you can modify files. When the editor is in read-only mode, commands that modify files are inactive or grayed. To toggle between edit and read-only mode, select File > Edit or click the Edit button.
Searching for Text and Replacing Text
To search for text that matches a specified string in a source file, choose Search from the Edit menu or type keyboard shortcuts. You can also search for text and replace it with a different string. For details, see Selecting Text and Replacing Text.
Cutting and Pasting Text
To cut selected text from the Ada editor window and transfer it to an internal clipboard, choose the Cut command from the Edit menu. When text has been transferred from an Apex window to the clipboard, you can paste the text into windows displayed by other applications running under the Motif window manager. For more information on cutting and pasting text, see Editing Text.
To delete selected text from the edit window, choose Delete from the Edit menu or execute one of the keyboard shortcuts listed in Deleting Text from a Document.
Ada-Specific EditingIn addition to its standard text-editing features, the Apex editor offers many Ada-specific editing features. You choose commands from the editor's Compile and Navigate menus to use these features.
Ada units are made up of objects such as keywords, identifiers, statements, and declarations. These objects are arranged in a hierarchical structure and are related to each other in various ways. The Apex editor is designed to recognize the structure of Ada objects and the relationships that Ada objects have with each other, and to offer special browsing, selecting, formatting, and error-checking commands for Ada units.
Browsing
With the Ada editor, you can browse through interdependent Ada units in the same way you might browse through a printed cross-reference listing. However, with Apex, no listing is required; browsing is interactive and automatic. Browsing is useful, for example, when you are:
- Inspecting someone else's program and want to find type definitions for program variables
- Debugging a problem and want to see where and how a particular subprogram is implemented
- Considering a change to a subprogram and want to know exactly where that subprogram is used
Coloring
The default Ada object editor now does both language coloring and "as you type casing". These can be turned off by setting the APEX_NO_ADA_LANGUAGE_MARKS and APEX_NO_AS_YOU_TYPE_CASING environment variables to true.
The casing is consistent with the pretty printer switches. Currently only the Ada object editor does language coloring. The C/C++ editor does not do this.
The new color scheme is consistent with the color scheme used with Apex NT and with other environments such as MSVC++. Language constructs (keywords, strings, comments, etc.) have a foreground color with a white background while messages and prompts have a background color and a white foreground.
Here are the default settings for the common constructs:
Traversing
To traverse Ada objects, place the cursor on an object and select one of the following Visit or Visit In Place commands (for more information on the Visit or Visit In Place commands, see Using and Customizing the GUI),
- Navigate > Visit or Navigate > Visit In Place —— Traverses to the defining occurrence of a program object such as a subprogram, variable, or type.
- Navigate > Visit Ada Name —— Opens a dialog box you can use to traverse to an Ada unit, given its name.
- Navigate > Visit Body or Navigate > Visit Body In Place —— Traverses to the body of an Ada specification.
- Navigate > Other Part or Navigate > Visit Other Part In Place —— Traverses to any selected part of an Ada specification.
For example, to traverse to the defining occurrence of a program object such as a subprogram, variable, or type:
- 1 . Place the cursor on any occurrence of the object.
- 2 . Choose the Navigate > Visit command. (Visit is also available on the button bar and pop-up menu.)
Note that browsing operations depend on semantic information about your Ada units that is collected during semantic analysis. If you have difficulty browsing because you have made changes since the last time you analyzed a unit, select Compile > Analyze and then try browsing again.
Viewing the Usage of Ada Objects
When you execute commands available from the Compile menu, you can find:
- All the places where a particular Ada object is used
- All Ada objects that are not used
The commands for viewing the usage of Ada objects are:
By default, all three of the commands listed above display dialog boxes that let you specify Ada items. Alternatively, you can execute each of these three commands as a "just-do-it" command by holding down the Shift key while you choose the command you want to execute. (For more information on "just-do-it" menu items, see Using and Customizing the GUI.)
Table 12 lists the effects of executing the Show Usage, Local Usage, and Show Unused commands:
When you execute one of the commands listed in the above table, Apex highlights each occurrence it finds. You can then traverse from one occurrence to another by clicking the Message -> button or the Message <- button in the Apex editor's button bar.
If many units reference an object, Apex displays a window listing all such units. You can then visit each unit in turn and click Message -> or Message <- to traverse between references.
Ada-Specific Selection Commands
Some of the selection commands available in the editor are Ada-specific. The Ada-specific selection commands are listed in Table 13.
As an illustration of how Ada-specific selection commands work, consider the following Ada code fragment:
if Check_Level then case Level is when 0 => Emergency_Stop; when 1 .. 4 => Check (Level); when others => null; end case; end if;
Assume the cursor is on the word Level in the statement Check (Level) and that no previous selections exist. Pressing Control-¨ repeatedly has these results:
- The first time Control-¨ is pressed, the variable Level is selected.
- The second time Control-¨ is pressed, the argument list (Level) is selected.
- The third time Control-¨ is pressed, the procedure call Check (Level) is selected.
- Finally, the when alternative is selected:
when 1 .. 4 => Check (Level);
After all this has taken place, Control-¦ and Control-Ø move the selection from one when alternative to another. Continuing to press Control-¨ has these results:
- All the when alternatives are selected.
- The entire case statement is selected.
- The entire if statement is selected.
- Finally, pressing Control-Æ repeatedly reduces the selection to the case statement, then the when alternatives, and so on.
Ada-Specific Commands
Several commands available from the Compile menu make the formatting of Ada units easier and more convenient.
These are the Ada-specific formatting commands available from the Apex editor's Compile menu:
- Compile > Build Body —— Creates a skeletal Ada body for an existing Ada specification. This command incrementally builds only missing bodies.
- Compile > Syntax —— Does syntactic completion and pretty-printing. Syntactic completion completes Ada constructs by inserting:
- Prompts for missing statements, expressions, identifiers, and the like
- Ending punctuation such as right parentheses, closing quotation marks, and semicolons
- Reserved words such as begin, return, and end if
- Matching identifiers in the end statements of loops, blocks, subprogram bodies, and packages
- Capitalization of identifiers
- Line breaks
- Indentation level
- Spacing around certain delimiters and operators
The pretty printer settings can be modified by changing the values of the pretty-printing switches. These are outlined in Pretty Printing.
- Compile > Pretty Print pretty-prints an Ada unit that was modified with some other editor —— for example, vi or emacs.
- Compile > Complete —— Does semantic completion. Semantic completion completes the selected Ada identifier using Ada semantics for name resolution, including:
- with clauses
- use clauses
- renames declarations
For example, when entering a procedure call, you can enter its name and then select Compile > Complete to add its parameters. If more than one name can complete the identifier, a list of choices is displayed in a viewer window.
- Compile > Make Inline —— Absorbs a subunit into the subunit's parent unit at the site of a stub. "Withs" of the subunit are merged with the "withs" in the parent unit.
- Make Inline —— Can be invoked either from the directory editor, or the Ada editor. If invoked from the directory editor, a dialog box comes up in which the units to be inlined are to be indicated
- If no text is selected, Make Inline applies to the current unit. If a stub is selected, the command applies to a subunit.
- The Control-Make Inline command opens a dialog box in which you can specify the name of the unit to be inlined.
- Compile > Make Separate —— Converts a selected subprogram, task, or package body into a separate unit. Because this command involves changing the parent unit of the selected unit, the parent must be checked out or uncontrolled when the command is executed.
- Edit > Comment —— Adds two hyphens to the beginning of selected lines to turn them into Ada comments. Edit > Uncomment removes the hyphens.
- Compile > Maintenance > Import Text Files- Brings in text files containing Ada source code. The parsed files are then considered Ada units. Each separate ADa unit is renamed with the appropriate .1.ada or .2.ada extension.
Pretty Printing
The Apex Ada pretty printer adjusts the following in your code:
- Capitalization of identifiers
- Line breaks
- Indentation level
- Spacing around certain delimiters and operators
The default pretty printer settings can be modified by changing the values of the pretty-printing switches. These switches are listed in Table 14 . Note that all these switches are only valid in Ada views.
The pretty printer is invoked using the Compile > Pretty_Print command from the GUI, or the pretty_print command from the command line
Error Checking
When you write Ada source code using the Ada editor, you can check Ada units for syntactic and semantic errors as you edit them. The Compile > Syntax command performs syntactic checking. The Compile > Analyze command performs both semantic and syntactic checking.
When you execute the Syntax command or the Analyze command, Apex highlights any errors found. You can traverse from one error to another by clicking either the Message -> or Message <- button inside the Apex editor button bar.
For help in correcting each error that is found, you can execute the:
- Help > Explain command to display the corresponding error message.
- Help > Reference command to display related material from the online Ada 83 LRM or Ada 95 LRM.
Semantic CompletionOverview
Semantic completion uses the semantic information (about names, visibility, types, etc.) available to the Ada editor to expand incomplete identifiers or constructs. It may be used when entering code to avoid the tedious and error-prone task of typing the parameters and components required for subprogram calls, generic instantiations, pragmas, constraints, aggregates and statements. It may also be used on existing code to normalize parameter and component lists, thereby improving the legibility of the code.
Designating Constructs to Complete
The constructs to complete may be designated either using the selection, or using the cursor.
If there is a selection, every identifier that intersects the selection is marked for completion. Also, every expandable construct that intersects the selection is marked for completion.See How Completion Works for more information.
If there is no selection, the cursor is used to determine the constructs to complete. If the cursor is on an identifier (including: immediately before or immediately after an identifier), then that identifier is marked for completion. Moreover, if the identifier is the name of a subprogram in a context where a subprogram call is legal, or the name of the generic in a generic instantiation, then the subprogram call or generic instantiation is marked for completion.
Note that in order to complete a case statement without completing any of the constructs that it contains, you must put the cursor on the reserved word "case".
At any place within an identifier, the character @ may be used as a wildcard to mean "any string of zero or more characters".
How Completion Works
Once the relevant identifiers and expandable constructs have been marked for completion, the compiler is called to check the legality of appropriate parts of the source code. When it encounters an identifier that has been marked for completion, the compiler checks the semantics of Ada. The default behavior is as follows:
- When resolving names, any identifier is assumed to be a wildcard ending with the character @. This means that any name that matches the given identifier is considered a candidate, provided that it has the right class (i.e., package name, component name, subprogram name, etc.).
- When checking subprogram calls, missing parameters are considered acceptable.
- A qualified or parenthesized expression is considered an aggregate if its type does not match the type required by the context. Similarly a qualified expression appearing alone in a statement part is considered a code statement.
The behavior of the compiler can be controlled by using the Completion Options dialog box described below.
After the compiler has analyzed the constructs to complete, the Ada editor first processes the identifiers marked for completion, and then the expandable construct.
Completion of Identifiers
For each identifier, all the candidate resolutions found by the compiler are considered. If there is only one such resolution, the identifier is completed without user intervention. If there is more than one candidate resolution, the identifier is completed by adding as many characters as possible, possibly followed by the character @ to avoid syntactic illegalities. A menu is then brought up which list, for each ambiguous identifier, the candidate declarations found by the compiler.
When users select an entry in the completion menu and hit Complete, the identifier is completed, and any expandable construct to which it belongs is completed.
For example, consider the code fragment:
A_Very_Long_Name : Boolean; A_Very_Weird_Name : Boolean; A_Very_Silly_Name : Float; U : Boolean; V : Float; Protected1, Protected2 : T; begin U := A; V := A; Prot := Prot;
When completion is run on the three assignment statements, it yields:
U := A_Very_@; V := A_Very_Silly_Name; Protected@ := Protected@;
and a menu is brought up which lists the possible choices for the (incomplete) identifiers A_Very_@ and Protected@ (there are two instances of the latter).
Note that type information was used to disambiguate the second assignment. Also, note the @ character that was added to the end of the names in the first and third assignment; that's necessary because a name ending with an underscore is illegal, and because protected is a reserved word (in Ada 95).
Completion of Expandable Constructs
Once the identifiers have been unambiguously resolved the expandable constructs are processed. The constructs that are considered expandable by completion are the following:
- Subprogram calls: completion adds parameter associations for any missing (or defaulted) parameter, and uses named associations for all the parameters.
- Generic instantiations: completion adds parameter associations for any missing (or defaulted) parameter, and uses named associations as much as possible (for generic instantiations, named associations are not always legal because the formal parameters may be overloaded).
- Record aggregates: completion adds component associations for any missing component, and uses named associations for all the components. Note that which components are considered missing generally depends on the value of the discriminants. Completion only builds a complete aggregate if (static) values are given for all the discriminants. If the type of the aggregate is descended from a private type (or a private extension), completion builds an extension aggregate.
- Array aggregates: completion adds component associations for any missing component, and uses named associations for all the components. Note that for array aggregates, the missing components are those that are necessary to cover a contiguous range of indices; this is necessary for legality, but it doesn't necessary prevent length mismatch at execution time.
- Pragmas: completion adds parameter associations for any missing (or defaulted) parameter, and uses named associations whenever possible (not all pragmas have named parameters).
- Discriminant Constraints: completion adds component associations for any missing discriminants, and uses named associations for all the discriminants.
- Index Constraints: completion adds range constraints for the dimensions for which no constraint was specified.
- Case Statement: completion adds choices and alternatives for any value of the case expression subtype that is not covered. If the case expression is of type universal integer, or of a generic formal type, a "when others" alternative is added.
The remainder of this section illustrates a few examples of completion, assuming that the behavior of completion is not modified using the Completion Options dialog box.
Completion of Subprogram Calls
In the following example, Ada.Text_IO.Create, Ada.Text_IO.Put and Ada.Streams.Stream_IO.End_@ are considered candidates for procedure calls and function calls, even though their name is incomplete and their parameters do not match the profile of any of the candidate subprograms:
with Ada.Streams.Stream_IO; with Ada.Text_IO; procedure Main is begin Ada.Text_IO.Create; Ada.Text_IO.Put; while Ada.Streams.Stream_IO.End_@ loop
When completion is run on the statement part of this unit, the calls to Create and End_@ are immediately completed:
Ada.Text_Io.Create (File => [FILE_TYPE-expression], Mode => Ada.Text_Io.Out_File, Name => "", Form => "") Ada.Text_IO.Put; while Ada.Streams.Stream_Io.End_Of_File (File => [FILE_TYPE-expression]) loop
Note that default values are provided for the parameters Mode, Name and Form in the call to Create. These default values come from the declaration of the subprogram Create.
In addition, a menu is brought up, which lists the possible completions of Put (there are six such completions: four named Put and two named Put_Line). If the user selects the first choice and hits Complete, the source text is changed to:
Ada.Text_Io.Put (File => [FILE_TYPE-expression], Item => [CHARACTER-expression]);
Completion of Generic Instantiations
In the following example the name G unambiguously refers to the preceding generic declaration:
Generic type T is limited private; with function "-" (X : T) return T; with function "-" (X, Y : T) return T; with function "*" (X, Y : T) return T is <>; X : T; procedure G (A : Boolean); procedure I is new G;
When completion is run on the generic instantiation, a parameter part is created as follows:
procedure I is new G ([expression], [expression], [expression], "*" => "*", X => [T-expression]);
Note that named associations are not usable for the first three parameters, because of the overloaded "-" operators. Also note that the default for parameter "*" (a box) is used to build an actual parameter in the instantiation.
Completion of Record Aggregates
In the following example we have a variant record type declaration, and two aggregates for that record type:
type T (D : Boolean) is record C0 : Integer := 0; case D is when True => C1 : Float; when False => C2 : Character := 'a'; end case; end record; X1 : T := (True, 1); X2 : T := ([id]);
When completion is run on the first aggregate, the (static) value True for the discriminant D is used to select the proper variant, and a complete aggregate is generated:
X1 : T := (D => True, C0 => 1, C1 => [FLOAT-expression]);
When completion is run on the second aggregate, the prompt [id] is not sufficient to select a variant in type T, and a partial aggregate is generated, containing only the components which are not part of a variant:
X2 : T := (D => [id], C0 => 0);
If the prompt [id] is then filled with a static value, e.g., False, running completion again produces a complete aggregate:
X2 : T := (D => False, C0 => 0, C2 => 'a');
Note that default values are provided for some of the components. These default values come from the declaration of the corresponding component.
Completion of Array Aggregates
The following example demonstrates the completion of both positional and named array aggregates:
type T is array (Character range <>) of Integer; X1 : T := ('a' .. 'z' => 1, 'A' .. 'Z' => 2); X2 : T := (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
If completion is run on the first aggregate, the Ada editor notices that the aggregate doesn't cover a contiguous range of indices, and it add a named association for the missing choices:
X1 : T := ('[' .. '\Q' => [INTEGER-expression], 'a' .. 'z' => 1, 'A' .. 'Z' => 2);
When completion is run on the second aggregate, each positional association is turned into a named association for the proper index:
X2 : T := (Ascii.Nul => 1, Ascii.Soh => 2, Ascii.Stx => 3, Ascii.Etx => 4, Ascii.Eot => 5, Ascii.Enq => 6, Ascii.Ack => 7, Ascii.Bel => 8, Ascii.Bs => 9, Ascii.Ht => 10)
Completion of Pragmas
In the following example the name P unambiguously refers to the preceding subprogram declaration:
procedure P; pragma Export (C, P);
When completion is run on the pragma, a parameter part is created as follows:
procedure P; pragma Export (Convention => C, Entity => P, External_Name => [expression], Link_Name => [expression]);
Completion of Discriminant Constraints
The following example demonstrates the completion of discriminant constraints. Type R has three defaulted discriminants, but the declaration of X only provides a constraint for the first one:
type R (D1 : Integer := 3; D2 : Boolean := True; D3 : access Float := new Float'(9.0)) is null record; X : R (5);
When completion is run on the declaration of X, the positional association for D1 is turned into a named association, and two new named associations are added for D2 and D3. The actual values provided in the constraint for D2 and D3 correspond to the defaults appearing in the record type declaration:
type R (D1 : Integer := 3; D2 : Boolean := True; D3 : access Float := new Float'(9.0)) is null record; X : R (D1 => 5, D2 => True, D3 => new Float'(9.0));
Completion of Index Constraints
The following example demonstrates the completion of index constraints. Type A has two dimensions, but the declaration of Y1 doesn't provide any index constraints, and the declaration of Y2 only provides a constraint for the first dimension:
type A is array (Positive range <>, Boolean range <>) of Character; Y1 : A; Y2 : A (1 .. 2);
When completion is run on the declarations of Y1 and Y2, two index constraints are added for Y1, and a constraint for the last dimension is added for Y2. Since there is no notion of default values for index constraints, prompts are generated for the bounds; the text of the prompt indicates the expected subtype of each expression:
type A is array (Positive range <>, Boolean range <>) of Character; Y1 : A ([POSITIVE-expression] .. [POSITIVE-expression], [BOOLEAN-expression] .. [BOOLEAN-expression]); Y2 : A (1 .. 2, [BOOLEAN-expression] .. [BOOLEAN-expression]);
Completion of Case Statements
The completion of case statements adds choices and alternatives to make sure that the subtype of the case expression is covered. In the following example, the case statement only covers the values Up and Top of type T:
type T is (Up, Down, Top, Bottom, Charm, Strange); X : T; begin case X2 is when Up | Top => null; when [expression] => null; end case;
When completion is run on the case statement, the prompt is replaced by a list of choices covering the values Down, Bottom, Charm and Strange. Completion uses ranges whenever possible to reduce the number of choices that it generates:
case X2 is when Up | Top => null; when Down | Bottom .. Strange => null; end case;
Note that in this case the last alternative had a single choice, which was a prompt. This caused completion to replace the prompt, rather than add a new alternative. The purpose of this behavior is to make it easy to remove an "others" choice in a case statement. Say that you start with the code:
case X2 is when Up | Top => null; when others => null; end case;
You can select the word "others", delete it, and format the image. This effectively replaces "others" with the prompt "[expression]". Running completion on the case statement causes the prompt to be replaced by the appropriate choices. Thus, it is possible to eliminate an others choice with a few mouse clicks.
If the last alternative doesn't contain a single prompt, then completion leaves it alone and adds another alternative containing the missing choices. For instance, starting from:
case X2 is when Up | Top => null; when Down => null; end case;
completion adds a new alternative to covers the choices Bottom to Strange:
case X2 is when Up | Top => null; when Down => null; when Bottom .. Strange => [statement] end case;
Controlling the Behavior of CompletionThe previous sections have described the default behavior of completion. For most uses, the default behavior is appropriate. However, there might be circumstances under which finer control over completion is useful. If the Control key is depressed while clicking on the menu item Compile > Complete, the Completion Options dialog box is brought up:
The Completion Options dialog box has six tabs, which are described in detail in the Online Reference.
Hints and Tips
Most of the time, completion will have no difficulties identifying and completing constructs. However, there are a number of guidelines that make it more likely that completion will "do the right thing".
For each identifier marked for completion, the compiler will have to consider a large number of meanings; for instance, if the identifier B is marked for completion, Boolean is a candidate that will be considered in all cases (because it's a name declared in Standard). Most of the time the compiler will be able to lift the ambiguities created by all these candidates, but in some cases it will fail. When that happens the Ada editor will be unable to complete some constructs, or will bring up inordinately long menus. This is more likely to happen if you select a large area of the program text (maybe even the entire unit), in this situation, try selecting a smaller area (e.g., only one statement or only one declaration), to reduce the number of ambiguities, or try disabling implicit wildcarding in the Completion Options dialog box.
In some cases, the Ada editor may need syntactic clues to perform the proper completion. For instance in the declaration:
B : Boolean := "=";
the token "=" is considered to be a string literal, not the name of an operator, so it is not completed. You need to add parentheses to make it clear that the construct is intended to be a call to an operator:
B : Boolean := "=" ([expression);
Similarly a call to a member of an entry family must have two sets of parentheses; otherwise, only procedures and simple entries are considered:
task T1 is entry F (Character) (X : Integer; Y : Float); end T1; begin T1.F ('a') ([expression]);
While the compiler is capable of dealing with incomplete or otherwise incorrect constructs, there are limits to the illegalities that it is prepared to handle. In particular, the candidates that are considered when resolving names are essentially based on the visibility rules of Ada. This means that the proper visibility must be achieved (by means of with clauses, use clauses, renamings, etc.) for completion to work satisfactorily.
Also, completion is not going to work on constructs that are grossly illegal. For instance, an attempt to complete an array aggregate having both named and positional associations, or to complete the name of a procedure in the condition of an if statement, are bound to fail.
When completion creates expressions using the default values provided for parameters or components, it assumes that the entities referenced by the expressions are visible at the place of the call, instantiation or aggregate. If this is not the case, with clauses may have to be added. Consider for instance the code fragment:
with Text_IO; procedure Main is begin Text_IO.Create;
If completion is run on the call to Create, the following parameter part is created:
Text_Io.Create (File => [FILE_TYPE-expression], Mode => Ada.Text_Io.Out_File, Name => "", Form => "")
Note that the expression Ada.Text_IO.Out_File references the package Ada.Text_IO, which is not mentioned in a with clause (even though its renaming, Text_IO, is mentioned). At this point you must either add a with clause for Ada.Text_IO, or change the actual parameter to be Text_IO.Out_File (without the Ada prefix).
Delimiter AlignmentStarting with version 4.0.2, the Apex Ada editor supports delimiter alignment. Delimiter alignment is an option of the pretty-printer, which causes lexical delimiters to be vertically aligned to improve readability of the source code.
Context Switch
Delimiter alignment is controlled by the boolean context switch ALIGN_DELIMITERS. This switch defaults to False. To enable delimiter alignment, the switch must be set to True by editing the switch file for the appropriate view(s):
ALIGN_DELIMITERS: True
Once this switch has been set, the pretty-printer, which can be invoked either by selecting Compile > Pretty Print or by Compile > Syntax, will automatically perform delimiter alignment.
Effects of Delimiter Alignment
Delimiter alignment causes the colon (:), arrow (=>) and assignment (:=) delimiters to be vertically aligned, by appropriate insertion of white space. The following code fragments show simple examples of alignment for each of these delimiters:
Un : Integer; Deux : Integer; Trois : Integer;
Un := 1; Deux := 2; Trois := 3;
Proc (Un => 1, Deux => 2, Trois => 3);
A given construct may contain more than one kind of delimiter, so more complex alignment patterns are possible:
Un : constant Integer := Func (One => 1.0, Two => 2.0, Three => 3.0); Deux : Integer := 2; Trois : Integer := G (Ein => 1, Zwei => 2, Drei => 3);
Preventing Alignment
The delimiters are aligned as shown above as long as the statements or declarations form a consecutive group. If it is desirable to prevent alignment from happening for some piece of code (e.g., because it results in the insertion of too much white space), it is possible to do so by inserting a blank line. In the example above, the presence of the word "constant" in the declaration of Un causes the insertion of lots of white space in the declarations of Deux and Trois. This can be avoided by inserting a blank line before the declaration of Deux:
Un : constant Integer := Func (One => 1.0, Two => 2.0, Three => 3.0); Deux : Integer := 2; Trois : Integer := G (Ein => 1, Zwei => 2, Drei => 3);
With this change we now have two groups of declarations where the delimiters are independently aligned.
Effect of Large Statements or Declarations
In order to avoid aligning the delimiters of statements or declarations which are separated by hundreds of lines of code, the pretty-printer breaks alignment groups when it encounters a "large" statement or declaration. Consider the following variation of one of the simple examples shown above:
Un := 1; case | is when | => when | => end case; Deux := 2; Trois := 3;
Because case statements are generally large statements which may contain tens or hundreds of lines of code, it would not make sense to align the assignment delimiters for the assignment to Un with those for the assignments to Deux and Trois: the resulting presentation would probably be unappealing and surprising. Therefore, a case statement acts as a separator for alignment purposes, regardless of the occurrence of blank lines.
Exactly what statements and declarations are considered "large" is the subject of a heuristic decision, but the general rule is that compound statements and nested declarative parts are all large for alignment purposes.
Rational Software Corporation http://www.rational.com support@rational.com techpubs@rational.com Copyright © 1993-2002, Rational Software Corporation. All rights reserved. |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |