forked from nbe95/codesys-tools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathformat-code.ps1
executable file
·134 lines (104 loc) · 5.22 KB
/
format-code.ps1
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
param (
[string[]]$Targets = (".\")
)
enum Result { Ok; Changed; Ignored }
Function Format-CodesysFile {
param([string] $File)
$Content = Get-Content -Raw -Path $File
if ($Content.Length -eq 0) {
Return [Result]::Ok
}
if ($Content.ToUpper().Contains("@NOFORMAT")) {
Return [Result]::Ignored
}
$Formatted = $Content
# Enforce spaces around operators :=, =>, <=, >=, <>, =, <, >
$Formatted = $Formatted -replace ' *?(:=|=>|<=|>=|<>|=|<(?!=|-)|(?<!=|-)>) *?', ' $1 '
# Enforce spaces before/after - and / (unless in comments, strings or constructed type like DT#1970-01-01-00:00:00)
# Note: Find and mark relevant chars first, then replace them in a second step
$Formatted = $Formatted -replace '((?:\(\*(?:.|\r?\n)*?\*\)|''.*?''))|[\t ]*\/[\t ]*', '$1{slash}'
$Formatted = $Formatted -replace '((?:\(\*(?:.|\r?\n)*?\*\)|''.*?''|#[\d\-_:]+))|(?<!\W|\n)[\t ]*\-[\t ]*', '$1{hyphen}'
$Formatted = $Formatted -replace '((?:\(\*(?:.|\r?\n)*?\*\)|''.*?''|#[\d\-_:]+))(?:{(?:slash|hyphen)})+', '$1'
$Formatted = $Formatted -replace '{hyphen}', ' - '
$Formatted = $Formatted -replace '{slash}', ' / '
# Put spaces around other arithmetical operators +, *
$Formatted = $Formatted -replace '(?<![\s\(+*]|^)([+*])(?![+*\)])', ' $1'
$Formatted = $Formatted -replace '(?<![+*\(])([+*])(?![\s\)+*]|$)', '$1 '
# Remove leading/trailing space and spaces in round/square brackets
$Formatted = $Formatted -replace '(?<=\r?\n) +', ''
$Formatted = $Formatted -replace '[\t ]+(?=\r?\n)', ''
$Formatted = $Formatted -replace '(?<=[\(\[]) +', ''
$Formatted = $Formatted -replace ' +(?=[\)\]])', ''
# Open and close comments with a single space
$Formatted = $Formatted -replace '\(\*(?!$|\r?\n)\s*', '(* '
$Formatted = $Formatted -replace '\s*(?<!^|\n)\*\)', ' *)'
# Remove multiple spaces and those surrounded by tabs
$Formatted = $Formatted -replace '(?:(?<=\t) +| +(?=\t))', ''
$Formatted = $Formatted -replace ' +', ' '
# Remove spaces in front of semicolons
$Formatted = $Formatted -replace '[\t ]+(?=;)', ''
# Remove superfluous line breaks
$Formatted = $Formatted -replace '(\r?\n)+(\(\* @(?:END_DECLARATION|OBJECT_END) .+? \*\))', '$1$2'
$Formatted = $Formatted -replace '(\r?\n)+(END_(?:VAR|TYPE))', '$1$2'
$Formatted = $Formatted -replace '(\r?\n){3,}(END_(?:PROGRAM|FUNCTION_BLOCK|FUNCTION))', '$1$2'
$Formatted = $Formatted -replace '((?:\r?\n){3})(?:\r?\n)+', '$1'
# Remove unnecessary semicolons after specific keywords
$Formatted = $Formatted -replace '(?<=THEN|END_IF|END_FOR|END_WHILE|END_REPEAT|END_CASE);', ''
# Initialize strings and arrays properly using square brackets
$Formatted = $Formatted -replace '(?<!\S)STRING\s*?\((.+?)\)', 'STRING[$1]'
$Formatted = $Formatted -replace 'ARRAY\s*?\[(.+?)\]', 'ARRAY[$1]'
# Only use NOT operator with parentheses and remove any space between
$Formatted = $Formatted -creplace '(?<=\W)NOT\s+(?!_)((?>\w+(?>(?>\[(?>\((?<array>)|[^[\]]+|\](?<-array>))*(?(array)(?!))\]|\((?>\((?<expr>)|[^()]+|\)(?<-expr>))*(?(expr)(?!))\))?\.?)*)+)', 'NOT($1)'
$Formatted = $Formatted -creplace 'NOT\s+\(', 'NOT('
# Because of performance and encoding issues, for the following operations each line must be processed individually
$Lines = @()
$Formatted -split "\r\n" | ForEach-Object {
# Skip any non-code-related lines
if ($_ -match '^(?!VISUALISATION|_|\(\* @).') {
# Make sure each comma has no leading space and is followed by exactly one space, unless at the end of a line
$FormattedLine = $_ -replace '\s*?,(?!\t|\r?\n|$)(?: +)?', ', '
$Lines += $FormattedLine
} else {
$Lines += $_
}
}
$Formatted = $Lines -join [Environment]::NewLine
Remove-Variable Lines
# Check if anything was modified
if ((Compare-Object $Content $Formatted -SyncWindow 0).Length -ne 0) {
Set-Content $File $Formatted -NoNewline
Return [Result]::Changed
}
Return [Result]::Ok
}
$CountAll = 0
$CountChanged = 0
$CountIgnored = 0
# Search the given target path(s) recursively for export files
Get-ChildItem -Path $Targets -File -Filter *.exp -Exclude _* -FollowSymLink -Recurse | ForEach-Object {
# Format code and print result
$Result = Format-CodesysFile $_.FullName
$ResultStr = " OK "
$ResultStyle = @{ForegroundColor = "Green"}
$CountAll++
If ($Result -eq [Result]::Changed) {
$ResultStr = "CHANGE"
$ResultStyle = @{ForegroundColor = "Red"}
$CountChanged++
}
If ($Result -eq [Result]::Ignored) {
$ResultStr = "IGNORE"
$ResultStyle = @{ForegroundColor = "Yellow"}
$CountIgnored++
}
Write-Host "[" -NoNewline -ForegroundColor "DarkGray"
Write-Host $ResultStr -NoNewline @ResultStyle
Write-Host "] " -NoNewline -ForegroundColor "DarkGray"
Write-Host $_.FullName
}
# Print overall result
Write-Host ("`n{0} file(s) processed, {1} formatted, {2} ignored." -f $CountAll, $CountChanged, $CountIgnored)
if ($CountChanged -gt 0) {
exit 1
}
exit 0