1 unit NoSpaceAfter;
2
3 { AFS 9 Dec 1999
4 no space after certain tokens }
5
6 {(*}
7 (*------------------------------------------------------------------------------
8 Delphi Code formatter source code
9
10 The Original Code is NoSpaceAfter, released May 2003.
11 The Initial Developer of the Original Code is Anthony Steele.
12 Portions created by Anthony Steele are Copyright (C) 1999-2008 Anthony Steele.
13 All Rights Reserved.
14 Contributor(s): Anthony Steele.
15
16 The contents of this file are subject to the Mozilla Public License Version 1.1
17 (the "License"). you may not use this file except in compliance with the License.
18 You may obtain a copy of the License at http://www.mozilla.org/NPL/
19
20 Software distributed under the License is distributed on an "AS IS" basis,
21 WITHOUT WARRANTY OF ANY KIND, either express or implied.
22 See the License for the specific language governing rights and limitations
23 under the License.
24
25 Alternatively, the contents of this file may be used under the terms of
26 the GNU General Public License Version 2 or later (the "GPL")
27 See http://www.gnu.org/licenses/gpl.html
28 ------------------------------------------------------------------------------*)
29 {*)}
30
31 {$I JcfGlobal.inc}
32
33 interface
34
35 uses SwitchableVisitor, SourceToken;
36
37 type
38 TNoSpaceAfter = class(TSwitchableVisitor)
39 private
40 fcLastSolidToken: TSourceToken;
41 fbSafeToRemoveReturn: boolean; // this taken from NoReturnBefore
42 protected
EnabledVisitSourceTokennull43 function EnabledVisitSourceToken(const pcNode: TObject): boolean; override;
44 public
45 constructor Create; override;
46
IsIncludedInSettingsnull47 function IsIncludedInSettings: boolean; override;
48 end;
49
50
51 implementation
52
53 uses
54 JcfStringUtils,
55 Tokens, ParseTreeNodeType, JcfSettings, FormatFlags,
56 TokenUtils, SettingsTypes;
57
58 { TNoSpaceAfter }
59
60
NeedsNoSpacenull61 function NeedsNoSpace(const pt, ptNext: TSourceToken): boolean;
62 const
63 NoSpaceAnywhere: TTokenTypeSet = [ttOpenBracket, ttOpenSquareBracket, ttDot];
64 begin
65 Result := False;
66
67 if pt = nil then
68 exit;
69
70 { if the next thing is a comment, leave well enough alone }
71 if ptNext.TokenType = ttComment then
72 exit;
73
74 if (pt.TokenType in [ttLessThan,ttGreaterThan]) and pt.HasParentNode(nGeneric,1) then
75 exit(True);
76
77 if pt.TokenType in NoSpaceAnywhere then
78 exit(True);
79
80 if (FormattingSettings.Spaces.SpaceForOperator = eNever) then
81 if IsSymbolOperator(pt) then
82 exit(True);
83
84 { no space between method name and open bracket for param list
85 no space between type & bracket for cast
86 no space between fn name & params for procedure call }
87 if pt.HasParentNode([nProcedureDecl, nFunctionDecl, nConstructorDecl,
88 nDestructorDecl, nStatementList]) and
89 (IsIdentifier(pt, idAllowDirectives) or (pt.TokenType in BuiltInTypes))
90 then
91 if (ptNext.TokenType in OpenBrackets) and (not IsInsideAsm(ptNext)) then
92 exit(True);
93
94 { the above takes care of procedure headers but not procedure type defs
95 eg type TFred = procedure(i: integer) of object;
96 note no space before the open bracket }
97 if pt.HasParentNode(nTypeDecl) and (pt.IsOnRightOf(nTypeDecl, ttEquals)) and
98 (pt.TokenType in ProcedureWords)
99 then
100 if (ptNext.TokenType in OpenBrackets) then
101 exit(True);
102
103 { no space after unary operator in expression }
104 if pt.HasParentNode(nExpression) and IsUnaryOperator(pt) and (not StrHasAlpha(pt.SourceCode)) then
105 exit(True);
106
107 { no space before class heritage ? could be one of 3 things
108 TFoo = class; - no space, but "No space before semicolon" should take care of that
109 TBar = class(TBaz) - no space unless you are Marcel van Brakel
110 TWibble = class of TFish - has space
111
112 see SingleSpaceAfter
113
114 also applies to type TFoo = interface(IDispatch) }
115 if (pt.HasParentNode(nRestrictedType)) and (pt.TokenType in ObjectTypeWords) and
116 ( not (FormattingSettings.Spaces.SpaceBeforeClassHeritage))
117 then
118 if (ptNext.TokenType in [ttOpenBracket, ttSemiColon]) then
119 exit(True);
120 end;
121
122 constructor TNoSpaceAfter.Create;
123 begin
124 inherited;
125 fbSafeToRemoveReturn := True;
126 FormatFlags := FormatFlags + [eRemoveSpace];
127 end;
128
EnabledVisitSourceTokennull129 function TNoSpaceAfter.EnabledVisitSourceToken(const pcNode: TObject): boolean;
130 var
131 lcSourceToken: TSourceToken;
132 lcNextSolid: TSourceToken;
133 begin
134 Result := False;
135 lcSourceToken := TSourceToken(pcNode);
136
137 if lcSourceToken.TokenType = ttWhiteSpace then
138 begin
139 lcNextSolid := lcSourceToken.NextTokenWithExclusions([ttWhiteSpace, ttReturn]);
140 if lcNextSolid <> nil then
141 begin
142 if NeedsNoSpace(fcLastSolidToken, lcNextSolid) then
143 BlankToken(lcSourceToken);
144 end;
145 end
146 else
147 begin
148 { store for next time }
149 if not (lcSourceToken.TokenType in [ttWhiteSpace, ttReturn]) then
150 fcLastSolidToken := lcSourceToken;
151 end;
152 end;
153
IsIncludedInSettingsnull154 function TNoSpaceAfter.IsIncludedInSettings: boolean;
155 begin
156 Result := FormattingSettings.Spaces.FixSpacing;
157 end;
158
159 end.
160