mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-22 20:24:12 +02:00
223 lines
5.4 KiB
ObjectPascal
223 lines
5.4 KiB
ObjectPascal
unit RemoveUnneededWhiteSpace;
|
|
|
|
{(*}
|
|
(*------------------------------------------------------------------------------
|
|
Delphi Code formatter source code
|
|
|
|
The Original Code is RemoveUnneededWhiteSpace, 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
|
|
|
|
{ AFS 29 December 2002
|
|
Obfuscation visitor
|
|
This is to completely remove white space
|
|
when it is not needed, e.g. turn "a := a + 1 ;" to "a:=a+1;"
|
|
}
|
|
|
|
uses SwitchableVisitor;
|
|
|
|
type
|
|
TRemoveUnneededWhiteSpace = class(TSwitchableVisitor)
|
|
protected
|
|
function EnabledVisitSourceToken(const pcNode: TObject): Boolean; override;
|
|
public
|
|
constructor Create; override;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
{ local }
|
|
SourceToken, Tokens, ParseTreeNodeType,
|
|
JcfUnicode,
|
|
FormatFlags, TokenUtils;
|
|
|
|
function TextOrNumberString(const str: WideString): boolean;
|
|
var
|
|
liLoop: integer;
|
|
ch: WideChar;
|
|
begin
|
|
Result := True;
|
|
|
|
for liLoop := 1 to Length(str) do
|
|
begin
|
|
ch := str[liLoop];
|
|
if not (WideCharIsAlphaNum(ch) or (ch = '_') or (ch = '.')) then
|
|
begin
|
|
Result := False;
|
|
break;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
const
|
|
MiscUnspacedTokens: TTokenTypeSet = [
|
|
ttQuotedLiteralString, ttSemiColon, ttColon, ttComma,
|
|
ttDot, ttDoubleDot, ttAssign, ttReturn, ttPlusAssign, ttMinusAssign, ttTimesAssign, ttFloatDivAssign];
|
|
|
|
DoNotConcat = [ttGreaterThan, ttLessThan, ttEquals];
|
|
|
|
|
|
function NeedSpaceBetween(const pt1, pt2: TSourceToken): boolean;
|
|
const
|
|
SPACED_ASM_TOKENS = [ttAtSign, ttAmpersand];
|
|
var
|
|
lcLast: TSourceToken;
|
|
begin
|
|
Result := True;
|
|
|
|
if ((pt1 = nil) or (pt2 = nil)) then
|
|
begin
|
|
Result := False;
|
|
exit;
|
|
end;
|
|
|
|
if (pt1.TokenType in DoNotConcat) and (pt2.TokenType in DoNotConcat) then
|
|
begin
|
|
exit;
|
|
end;
|
|
|
|
|
|
{ can loose everything after the final end }
|
|
if (pt1.TokenType = ttDot) then
|
|
begin
|
|
lcLast := pt1.PriorSolidToken;
|
|
if (lcLast.TokenType = ttEnd) and (pt1.HasParentNode(TopOfFileSection, 1)) then
|
|
begin
|
|
Result := False;
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
{ need to keep space before Asm @@ and '&' thingy}
|
|
if (pt2.TokenType in SPACED_ASM_TOKENS) and pt2.HasParentNode(nAsmStatement) then
|
|
exit;
|
|
|
|
{ never need a space next to a bracket }
|
|
if (pt1.TokenType in BracketTokens) or (pt2.TokenType in BracketTokens) then
|
|
begin
|
|
Result := False;
|
|
exit;
|
|
end;
|
|
|
|
{ never need space around semicolon }
|
|
if (pt1.TokenType = ttSemiColon) or (pt2.TokenType = ttSemiColon) then
|
|
begin
|
|
Result := False;
|
|
exit;
|
|
end;
|
|
|
|
{ or dot or comma etc }
|
|
if (pt1.TokenType in MiscUnspacedTokens) or (pt2.TokenType in MiscUnspacedTokens) then
|
|
begin
|
|
Result := False;
|
|
exit;
|
|
end;
|
|
|
|
{ before a comment. Comments are removed by another process (except for compiler directives) }
|
|
if (pt2.TokenType = ttComment) then
|
|
begin
|
|
Result := False;
|
|
exit;
|
|
end;
|
|
|
|
{ similartly, after a comment unless it starts with '//' }
|
|
if (pt1.TokenType = ttComment) and (pt1.CommentStyle <> eDoubleSlash) then
|
|
begin
|
|
Result := False;
|
|
exit;
|
|
end;
|
|
|
|
if (pt1.TokenType in TextOrNumberTokens) and (pt2.TokenType = ttAtSign) and
|
|
(pt1.HasParentnode(nAsm)) then
|
|
begin
|
|
Result := False;
|
|
exit;
|
|
end;
|
|
|
|
{ if one token is text or number, and the other not, don't need white space
|
|
for this numbers count as text, for e.g.
|
|
"for liLoop := 0to3do" is not valid, neither is "for liLoop := 0 to3 do",
|
|
must be for liLoop := 0 to 3 do
|
|
}
|
|
|
|
if TextOrNumberString(pt1.SourceCode) and TextOrNumberString(pt2.SourceCode) then
|
|
begin
|
|
{ always space between two text/number tokens }
|
|
Result := True;
|
|
exit;
|
|
end;
|
|
|
|
{ if one token is a number, even a number like "$000080FF",
|
|
must space them }
|
|
if TextOrNumberString(pt1.SourceCode) and (pt2.TokenType = ttNumber) then
|
|
begin
|
|
Result := True;
|
|
exit;
|
|
end;
|
|
|
|
if (pt1.TokenType = ttNumber) and TextOrNumberString(pt2.SourceCode) then
|
|
begin
|
|
Result := True;
|
|
exit;
|
|
end;
|
|
|
|
Result := False;
|
|
end;
|
|
|
|
|
|
constructor TRemoveUnneededWhiteSpace.Create;
|
|
begin
|
|
inherited;
|
|
FormatFlags := FormatFlags + [eObfuscate];
|
|
end;
|
|
|
|
function TRemoveUnneededWhiteSpace.EnabledVisitSourceToken(const pcNode: TObject): Boolean;
|
|
var
|
|
lcSpace, lcBefore, lcAfter: TSourceToken;
|
|
begin
|
|
Result := False;
|
|
|
|
{ this visitor needs to operate on the white space token
|
|
depending on what comes before and after it
|
|
}
|
|
lcSpace := TSourceToken(pcNode);
|
|
if lcSpace.TokenType <> ttWhiteSpace then
|
|
exit;
|
|
|
|
lcBefore := lcSpace.PriorToken;
|
|
if lcBefore = nil then
|
|
exit;
|
|
|
|
lcAfter := lcSpace.NextToken;
|
|
if lcAfter = nil then
|
|
exit;
|
|
|
|
if not NeedSpaceBetween(lcBefore, lcAfter) then
|
|
BlankToken(lcSpace);
|
|
end;
|
|
|
|
end.
|