File: NoSpaceAfter.pas

package info (click to toggle)
lazarus 2.0.0%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 214,460 kB
  • sloc: pascal: 1,862,622; xml: 265,709; cpp: 56,595; sh: 3,008; java: 609; makefile: 535; perl: 297; sql: 222; ansic: 137
file content (182 lines) | stat: -rw-r--r-- 4,997 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
unit NoSpaceAfter;

{ AFS 9 Dec 1999
  no space after  certain tokens }

{(*}
(*------------------------------------------------------------------------------
 Delphi Code formatter source code 

The Original Code is NoSpaceAfter, released May 2003.
The Initial Developer of the Original Code is Anthony Steele. 
Portions created by Anthony Steele are Copyright (C) 1999-2008 Anthony Steele.
All Rights Reserved. 
Contributor(s): Anthony Steele. 

The contents of this file are subject to the Mozilla Public License Version 1.1
(the "License"). you may not use this file except in compliance with the License.
You may obtain a copy of the License at http://www.mozilla.org/NPL/

Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied.
See the License for the specific language governing rights and limitations 
under the License.

Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 2 or later (the "GPL") 
See http://www.gnu.org/licenses/gpl.html
------------------------------------------------------------------------------*)
{*)}

{$I JcfGlobal.inc}

interface

uses SwitchableVisitor, SourceToken;

type
  TNoSpaceAfter = class(TSwitchableVisitor)
  private
    fcLastSolidToken: TSourceToken;
    fbSafeToRemoveReturn: boolean;  // this taken from NoReturnBefore
  protected
    function EnabledVisitSourceToken(const pcNode: TObject): boolean; override;
  public
    constructor Create; override;

    function IsIncludedInSettings: boolean; override;
  end;


implementation

uses
  JcfStringUtils,
  Tokens, ParseTreeNodeType, JcfSettings, FormatFlags,
  TokenUtils, SettingsTypes;

{ TNoSpaceAfter }


function NeedsNoSpace(const pt, ptNext: TSourceToken): boolean;
const
  NoSpaceAnywhere: TTokenTypeSet = [ttOpenBracket, ttOpenSquareBracket, ttDot];
begin
  Result := False;

  if pt = nil then
    exit;

  { if the next thing is a comment, leave well enough alone }
  if ptNext.TokenType = ttComment then
    exit;

  if pt.TokenType in NoSpaceAnywhere then
  begin
    Result := True;
    exit;
  end;

  if (FormattingSettings.Spaces.SpaceForOperator = eNever) then
  begin
    if IsSymbolOperator(pt) then
    begin
      Result := True;
      exit;
    end;
  end;


  { no space between method name and open bracket for param list
    no space between type & bracket for cast
    no space between fn name & params for procedure call }
  if pt.HasParentNode([nProcedureDecl, nFunctionDecl, nConstructorDecl,
    nDestructorDecl, nStatementList]) and
    (IsIdentifier(pt, idAllowDirectives) or (pt.TokenType in BuiltInTypes)) then
  begin
    if (ptNext.TokenType in OpenBrackets) and (not IsInsideAsm(ptNext)) then
    begin
      Result := True;
      exit;
    end;
  end;

  { the above takes care of procedure headers but not procedure type defs
   eg type TFred = procedure(i: integer) of object;
    note no space before the open bracket }
  if pt.HasParentNode(nTypeDecl) and (pt.IsOnRightOf(nTypeDecl, ttEquals)) and
    (pt.TokenType in ProcedureWords) then
  begin
    if (ptNext.TokenType in OpenBrackets) then
    begin
      Result := True;
      exit;
    end;
  end;

  { no space after unary operator in expression }
  if pt.HasParentNode(nExpression) and IsUnaryOperator(pt) and
    ( not StrHasAlpha(pt.SourceCode)) then
  begin
    Result := True;
    exit;
  end;

  { no space before class heritage ? could be one of 3 things
    TFoo = class; - no space, but "No space before semicolon" should take care of that
    TBar = class(TBaz) - no space unless you are Marcel van Brakel
    TWibble = class of TFish - has space

    see SingleSpaceAfter

    also applies to type TFoo = interface(IDispatch) }
  if (pt.HasParentNode(nRestrictedType)) and (pt.TokenType in ObjectTypeWords) and
    ( not (FormattingSettings.Spaces.SpaceBeforeClassHeritage)) then
  begin
    if (ptNext.TokenType in [ttOpenBracket, ttSemiColon]) then
    begin
      Result := True;
      exit;
    end;
  end;
end;


constructor TNoSpaceAfter.Create;
begin
  inherited;
  fbSafeToRemoveReturn := True;
  FormatFlags := FormatFlags + [eRemoveSpace];
end;

function TNoSpaceAfter.EnabledVisitSourceToken(const pcNode: TObject): boolean;
var
  lcSourceToken: TSourceToken;
  lcNextSolid:   TSourceToken;
begin
  Result := False;
  lcSourceToken := TSourceToken(pcNode);

  if lcSourceToken.TokenType = ttWhiteSpace then
  begin
    lcNextSolid := lcSourceToken.NextTokenWithExclusions([ttWhiteSpace, ttReturn]);
    if lcNextSolid <> nil then
    begin
      if NeedsNoSpace(fcLastSolidToken, lcNextSolid) then
        BlankToken(lcSourceToken);
    end;
  end
  else
  begin
    { store for next time }
    if not (lcSourceToken.TokenType in [ttWhiteSpace, ttReturn]) then
      fcLastSolidToken := lcSourceToken;
  end;
end;

function TNoSpaceAfter.IsIncludedInSettings: boolean;
begin
  Result := FormattingSettings.Spaces.FixSpacing;
end;

end.