1 unit IndentAsmParam;
2 
3 {(*}
4 (*------------------------------------------------------------------------------
5  Delphi Code formatter source code
6 
7 The Original Code is IndentAsmParam, released October 2007.
8 The Initial Developer of the Original Code is Anthony Steele.
9 Portions created by Anthony Steele are Copyright (C) 1999-2008 Anthony Steele.
10 All Rights Reserved.
11 Contributor(s): Anthony Steele.
12 
13 The contents of this file are subject to the Mozilla Public License Version 1.1
14 (the "License"). you may not use this file except in compliance with the License.
15 You may obtain a copy of the License at http://www.mozilla.org/NPL/
16 
17 Software distributed under the License is distributed on an "AS IS" basis,
18 WITHOUT WARRANTY OF ANY KIND, either express or implied.
19 See the License for the specific language governing rights and limitations
20 under the License.
21 
22 Alternatively, the contents of this file may be used under the terms of
23 the GNU General Public License Version 2 or later (the "GPL")
24 See http://www.gnu.org/licenses/gpl.html
25 ------------------------------------------------------------------------------*)
26 {*)}
27 
28 {$I JcfGlobal.inc}
29 
30 interface
31 
32 {
33   process to indent asm params to the required stop
34   this is similar to the alin processes
35   but it does not make the params the same indent as the furthest one
36   it puts them all at the same fixed indent, if possible
37 }
38 
39 uses SwitchableVisitor;
40 
41 type
42   TIndentAsmParam = class(TSwitchableVisitor)
43   private
44     fcLastProcessed: TObject;
45   protected
EnabledVisitSourceTokennull46     function EnabledVisitSourceToken(const pcNode: TObject): Boolean; override;
47   public
48 
IsIncludedInSettingsnull49     function IsIncludedInSettings: boolean; override;
50   end;
51 
52 
53 implementation
54 
55 uses
56   ParseTreeNodeType, ParseTreeNode, Nesting,
57   TokenUtils,
58   SourceToken,
59   JcfSettings;
60 
IsFirstAsmParamnull61 function IsFirstAsmParam(const pcSourceToken: TSourceToken): boolean;
62 var
63   lcPrev: TSourceToken;
64 begin
65   Result := False;
66 
67   if not IsInsideAsm(pcSourceToken) then
68     exit;
69 
70   // looking for the first asm param on the line
71   if not pcSourceToken.HasParentNode(nAsmParam, 4) then
72     exit;
73 
74   lcPrev := pcSourceToken.PriorSolidToken;
75 
76   if (lcPrev <> nil) then
77   begin
78     if lcPrev.HasParentNode(nAsmOpCode, 3) then
79     begin
80       Result := True;
81     end;
82   end;
83 end;
84 
GetAsmIndentnull85 function GetAsmIndent(const pcSourceToken: TSourceToken): integer;
86 var
87   liIndentLevel: integer;
88   lcAsm: TParseTreeNode;
89 begin
90   liIndentLevel := pcSourceToken.Nestings.GetLevel(nlBlock);
91 
92   // nesting of asm inside a proc is treaded differently from an asm proc
93   // which is not a good feature
94   // but can work with it
95   lcAsm := pcSourceToken.GetParentNode(nAsm);
96   if lcAsm = nil then
97   begin
98     Result := 0;
99     exit;
100   end;
101   if lcAsm.Parent.NodeType = nStatement then
102   begin
103     inc(liIndentLevel);
104   end;
105 
106   Result := FormattingSettings.Indent.SpacesForIndentLevel(liIndentLevel);
107   Result := Result + FormattingSettings.SetAsm.ParamsIndent;
108 end;
109 
EnabledVisitSourceTokennull110 function TIndentAsmParam.EnabledVisitSourceToken(const pcNode: TObject): Boolean;
111 var
112   lcSourceToken: TSourceToken;
113   liDesiredIndent: integer;
114   liActualIndent: integer;
115 begin
116   Result := False;
117 
118   // prevent it being processed again after a space is inserted
119   if pcNode = fcLastProcessed then
120     exit;
121 
122   lcSourceToken := TSourceToken(pcNode);
123 
124   if IsFirstAsmParam(lcSourceToken) then
125   begin
126     liDesiredIndent := GetAsmIndent(lcSourceToken);
127     liActualIndent := lcSourceToken.XPosition - 1;
128 
129     if liActualIndent < liDesiredIndent then
130     begin
131       InsertTokenBefore(lcSourceToken, NewSpace(liDesiredIndent - liActualIndent));
132       lcSourceToken.XPosition := liDesiredIndent;
133       fcLastProcessed := lcSourceToken;
134       Result := True;
135     end;
136   end;
137 
138 end;
139 
IsIncludedInSettingsnull140 function TIndentAsmParam.IsIncludedInSettings: boolean;
141 begin
142   Result := FormattingSettings.SetAsm.ParamsIndentEnabled;
143 end;
144 
145 end.
146