--- Build strict file-reference rules for CMake files
-- @module formats.cmake.references

local cmake_references = {}

-- Pattern breakdown: CMake command names are case-insensitive and end immediately before their first argument
local include_prefix = "%f[%w_]include%f[^%w_]%s*%(%s*"
local subdirectory_prefix = "%f[%w_]add_subdirectory%f[^%w_]%s*%(%s*"
local configure_file_prefix = "%f[%w_]configure_file%f[^%w_]%s*%(%s*"

--- Provide the literal include name and its conventional '.cmake' form
-- @param reference table parsed include reference
-- @return table candidates
local function include_candidates(reference)
	if reference.path:lower():match("%.cmake$") then
		return { reference.path }
	end

	return { reference.path, reference.path .. ".cmake" }
end

--- Point one source-directory argument at the CMake file inside it
-- @param reference table parsed directory reference
-- @return table candidates
local function subdirectory_candidates(reference)
	local directory = reference.path:gsub("[/\\]+$", "")

	return { directory .. PATHSEP .. "CMakeLists.txt" }
end

--- Return references from CMake commands with direct file meaning
-- @return table rules
function cmake_references.new()
	return {
		{ prefix = include_prefix, open = "\"", close = "\"", candidates = include_candidates, caseless = true },
		{ prefix = include_prefix, candidates = include_candidates, caseless = true },
		{ prefix = subdirectory_prefix, open = "\"", close = "\"", candidates = subdirectory_candidates, caseless = true },
		{ prefix = subdirectory_prefix, candidates = subdirectory_candidates, caseless = true },
		{ prefix = configure_file_prefix, open = "\"", close = "\"", caseless = true },
		{ prefix = configure_file_prefix, caseless = true },
	}
end

return cmake_references
