XMake: add auto-fixer script
This commit is contained in:
parent
8d5276ddac
commit
b8309fd511
|
|
@ -0,0 +1,376 @@
|
|||
|
||||
task("check-files")
|
||||
|
||||
set_menu({
|
||||
-- Settings menu usage
|
||||
usage = "xmake check-files [options]",
|
||||
description = "Check every file for consistency (can fix some errors)",
|
||||
options =
|
||||
{
|
||||
-- Set k mode as key-only bool parameter
|
||||
{'f', "fix", "k", nil, "Attempt to automatically fix files." }
|
||||
}
|
||||
})
|
||||
|
||||
local function CompareLines(referenceLines, lines, firstLine, lineCount)
|
||||
firstLine = firstLine or 1
|
||||
lineCount = lineCount or (#lines - firstLine + 1)
|
||||
if lineCount ~= #referenceLines then
|
||||
return false
|
||||
end
|
||||
|
||||
for i = 1, lineCount do
|
||||
if lines[firstLine + i - 1] ~= referenceLines[i] then
|
||||
print(lines[firstLine + i])
|
||||
print(referenceLines[i])
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
on_run(function ()
|
||||
import("core.base.option")
|
||||
|
||||
local modules = os.dirs("include/Nazara/*")
|
||||
|
||||
local fileLines = {}
|
||||
local updatedFiles = {}
|
||||
local function GetFile(filePath)
|
||||
filePath = path.translate(filePath)
|
||||
|
||||
local lines = fileLines[filePath]
|
||||
if not lines then
|
||||
lines = table.to_array(io.lines(filePath))
|
||||
if not lines then
|
||||
os.raise("failed to open " .. filePath)
|
||||
end
|
||||
|
||||
fileLines[filePath] = lines
|
||||
end
|
||||
|
||||
return lines
|
||||
end
|
||||
|
||||
local function UpdateFile(filePath, lines)
|
||||
filePath = path.translate(filePath)
|
||||
|
||||
if lines then
|
||||
fileLines[filePath] = lines
|
||||
end
|
||||
|
||||
updatedFiles[filePath] = true
|
||||
end
|
||||
|
||||
local checks = {}
|
||||
|
||||
table.insert(checks, {
|
||||
Name = "remove empty lines at the beginning",
|
||||
Check = function (moduleName)
|
||||
local files = table.join(
|
||||
os.files("include/Nazara/" .. moduleName .. "/**.hpp"),
|
||||
os.files("include/Nazara/" .. moduleName .. "/**.inl"),
|
||||
os.files("src/Nazara/" .. moduleName .. "/**.hpp"),
|
||||
os.files("src/Nazara/" .. moduleName .. "/**.inl"),
|
||||
os.files("src/Nazara/" .. moduleName .. "/**.cpp")
|
||||
)
|
||||
|
||||
local fixes = {}
|
||||
|
||||
for _, filePath in pairs(files) do
|
||||
local lines = GetFile(filePath)
|
||||
|
||||
for i = 1, #lines do
|
||||
if not lines[i]:match("^%s*$") then
|
||||
if i ~= 1 then
|
||||
print(filePath .. " starts with empty lines")
|
||||
|
||||
table.insert(fixes, {
|
||||
File = filePath,
|
||||
Func = function (lines)
|
||||
for j = 1, i - 1 do
|
||||
table.remove(lines, 1)
|
||||
end
|
||||
|
||||
UpdateFile(filePath, lines)
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return fixes
|
||||
end
|
||||
})
|
||||
|
||||
table.insert(checks, {
|
||||
Name = "copyright",
|
||||
Check = function (moduleName)
|
||||
local files = table.join(
|
||||
os.files("include/Nazara/" .. moduleName .. "/**.hpp|Config.hpp"),
|
||||
os.files("include/Nazara/" .. moduleName .. "/**.inl"),
|
||||
os.files("src/Nazara/" .. moduleName .. "/**.hpp"),
|
||||
os.files("src/Nazara/" .. moduleName .. "/**.inl"),
|
||||
os.files("src/Nazara/" .. moduleName .. "/**.cpp")
|
||||
)
|
||||
|
||||
local currentYear = os.date("%Y")
|
||||
local engineAuthor = "Jérôme \"Lynix\" Leclercq (lynix680@gmail.com)"
|
||||
local prevAuthor = "Jérôme Leclercq"
|
||||
local fixes = {}
|
||||
|
||||
local moduleDesc
|
||||
if #moduleName > 8 and moduleName:endswith("Renderer") then
|
||||
moduleDesc = moduleName:sub(1, -9) .. " renderer"
|
||||
else
|
||||
moduleDesc = moduleName .. " module"
|
||||
end
|
||||
|
||||
-- Config
|
||||
do
|
||||
local configFilePath = path.translate("include/Nazara/" .. moduleName .. "/Config.hpp")
|
||||
local lines = GetFile(configFilePath)
|
||||
local pragmaLine
|
||||
for i = 1, #lines do
|
||||
if lines[i] == "#pragma once" then
|
||||
pragmaLine = i
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
local canFix = true
|
||||
|
||||
repeat
|
||||
if not pragmaLine then
|
||||
print(configFilePath .. ": pragma once not found")
|
||||
canFix = false
|
||||
break
|
||||
end
|
||||
|
||||
local licenseText = [[
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once]]
|
||||
|
||||
local licenseLines = licenseText:split("\r?\n", { strict = true })
|
||||
local shouldFix = false
|
||||
|
||||
-- Try to retrieve year and authors
|
||||
if lines[1] ~= "/*" then
|
||||
print(configFilePath .. ": file doesn't begin with block comment")
|
||||
break
|
||||
end
|
||||
|
||||
|
||||
if lines[2]:match("\tNazara Engine - " .. moduleDesc) then
|
||||
print(configFilePath .. ": module description doesn't match")
|
||||
shouldFix = true
|
||||
end
|
||||
|
||||
if lines[3] ~= "" then
|
||||
-- Not really empty because of space characters? Not a big deal
|
||||
if lines[3]:match("^%s*$") then
|
||||
shouldFix = true
|
||||
else
|
||||
print(configFilePath .. ": expected space after project name")
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
local year, moduleAuthor = lines[4]:match("^\tCopyright %(C%) (Y?E?A?R?%d*) (.+)$")
|
||||
if not year then
|
||||
print(configFilePath .. ": couldn't parse copyright date and author")
|
||||
break
|
||||
end
|
||||
|
||||
if year ~= currentYear then
|
||||
print(configFilePath .. ": incorrect copyright year")
|
||||
shouldFix = true
|
||||
end
|
||||
|
||||
local additionalAuthors = {}
|
||||
for i = 5, #lines do
|
||||
if lines[i]:match("^%s*$") then
|
||||
-- Empty line
|
||||
if not CompareLines(licenseLines, lines, i, pragmaLine - i + 1) then
|
||||
shouldFix = true
|
||||
end
|
||||
|
||||
break
|
||||
end
|
||||
|
||||
if lines[i]:match("%s*Permission is hereby granted") then
|
||||
print(configFilePath .. ": missing empty line before licence text")
|
||||
shouldFix = true
|
||||
break
|
||||
end
|
||||
|
||||
table.insert(additionalAuthors, lines[i]:match("%s*(.+)"))
|
||||
end
|
||||
|
||||
if shouldFix then
|
||||
table.insert(fixes, {
|
||||
File = configFilePath,
|
||||
Func = function (lines)
|
||||
local newLines = {
|
||||
"/*",
|
||||
"\tNazara Engine - " .. moduleDesc,
|
||||
"",
|
||||
}
|
||||
|
||||
local copyrightNotice = "Copyright (C) " .. currentYear
|
||||
table.insert(newLines, "\t" .. copyrightNotice .. " " .. moduleAuthor)
|
||||
|
||||
for _, author in ipairs(additionalAuthors) do
|
||||
table.insert(newLines, "\t" .. string.rep(" ", #copyrightNotice) .. " " .. author)
|
||||
end
|
||||
|
||||
for _, line in ipairs(licenseLines) do
|
||||
table.insert(newLines, line)
|
||||
end
|
||||
|
||||
for i = pragmaLine + 1, #lines do
|
||||
table.insert(newLines, lines[i])
|
||||
end
|
||||
|
||||
UpdateFile(configFilePath, newLines)
|
||||
end
|
||||
})
|
||||
end
|
||||
until true
|
||||
|
||||
if not canFix then
|
||||
print(configFilePath .. ": header couldn't be parsed, no automated fix will be done")
|
||||
end
|
||||
end
|
||||
|
||||
-- Headers
|
||||
for _, filePath in pairs(files) do
|
||||
local lines = GetFile(filePath)
|
||||
|
||||
local hasCopyright
|
||||
local shouldFix = false
|
||||
|
||||
if lines[1]:lower():match("^// this file was automatically generated") then
|
||||
goto skip
|
||||
end
|
||||
|
||||
local year, authors = lines[1]:match("^// Copyright %(C%) (Y?E?A?R?%d*) (.+)$")
|
||||
hasCopyright = year ~= nil
|
||||
|
||||
if authors == "AUTHORS" then
|
||||
authors = engineAuthor
|
||||
else
|
||||
local fixedAuthors = authors:gsub(prevAuthor, engineAuthor)
|
||||
if fixedAuthors ~= authors then
|
||||
authors = fixedAuthors
|
||||
shouldFix = true
|
||||
end
|
||||
end
|
||||
|
||||
if hasCopyright then
|
||||
if year ~= currentYear then
|
||||
print(filePath .. ": copyright year error")
|
||||
shouldFix = true
|
||||
end
|
||||
|
||||
local copyrightModule = lines[2]:match("^// This file is part of the \"Nazara Engine %- (.+)\"$")
|
||||
if copyrightModule ~= moduleDesc then
|
||||
print(filePath .. ": copyright module error")
|
||||
shouldFix = true
|
||||
end
|
||||
|
||||
if lines[3] ~= "// For conditions of distribution and use, see copyright notice in Config.hpp" then
|
||||
print(filePath .. ": copyright file reference error")
|
||||
shouldFix = true
|
||||
end
|
||||
else
|
||||
print(filePath .. ": copyright not found")
|
||||
shouldFix = true
|
||||
end
|
||||
|
||||
if shouldFix then
|
||||
table.insert(fixes, {
|
||||
File = filePath,
|
||||
Func = function(lines)
|
||||
local copyrightLines = {
|
||||
"// Copyright (C) " .. currentYear .. " " .. (authors or engineAuthor),
|
||||
"// This file is part of the \"Nazara Engine - " .. moduleDesc .. "\"",
|
||||
"// For conditions of distribution and use, see copyright notice in Config.hpp"
|
||||
}
|
||||
|
||||
if hasCopyright then
|
||||
for i, line in ipairs(copyrightLines) do
|
||||
lines[i] = line
|
||||
end
|
||||
else
|
||||
for i, line in ipairs(copyrightLines) do
|
||||
table.insert(lines, i, line)
|
||||
end
|
||||
table.insert(lines, #copyrightLines + 1, "")
|
||||
end
|
||||
|
||||
UpdateFile(filePath, lines)
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
::skip::
|
||||
end
|
||||
|
||||
return fixes
|
||||
end
|
||||
})
|
||||
|
||||
local shouldFix = option.get("fix") or false
|
||||
|
||||
for _, check in pairs(checks) do
|
||||
print("Running " .. check.Name .. " check...")
|
||||
|
||||
local fixes = {}
|
||||
for _, modulePath in pairs(modules) do
|
||||
local moduleName = modulePath:match(".*[\\/](.*)")
|
||||
|
||||
table.join2(fixes, check.Check(moduleName))
|
||||
end
|
||||
|
||||
if shouldFix then
|
||||
for _, fix in pairs(fixes) do
|
||||
print("Fixing " .. fix.File)
|
||||
fix.Func(assert(fileLines[fix.File]))
|
||||
end
|
||||
|
||||
for filePath, _ in pairs(updatedFiles) do
|
||||
local lines = assert(fileLines[filePath])
|
||||
if lines[#lines] ~= "" then
|
||||
table.insert(lines, "")
|
||||
end
|
||||
|
||||
print("Saving changes to " .. filePath)
|
||||
io.writefile(filePath, table.concat(lines, "\n"))
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
|
@ -118,7 +118,7 @@ on_run(function ()
|
|||
error("Failed to create header file (" .. v.Target .. "): " .. err)
|
||||
end
|
||||
|
||||
header:write("// This file was automatically generated\n\n")
|
||||
header:write("// this file was automatically generated and should not be edited\n\n")
|
||||
if (v.Header) then
|
||||
header:write(v.Header)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ headerFile:write([[
|
|||
|
||||
// Copyright (C) ]] .. os.date("%Y") .. [[ Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Shader module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Shader/SpirvData.hpp>
|
||||
#include <algorithm>
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ local DirectionToString = {}
|
|||
|
||||
// Copyright (C) ]] .. os.date("%Y") .. [[ Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Core module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
]])
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue