diff options
Diffstat (limited to 'lua/intellij_to_vscode/converter.lua')
| -rw-r--r-- | lua/intellij_to_vscode/converter.lua | 140 | 
1 files changed, 22 insertions, 118 deletions
diff --git a/lua/intellij_to_vscode/converter.lua b/lua/intellij_to_vscode/converter.lua index 5d87cd8..1b5572f 100644 --- a/lua/intellij_to_vscode/converter.lua +++ b/lua/intellij_to_vscode/converter.lua @@ -1,6 +1,4 @@  local M = {} -local uv = vim.loop -local api = vim.api  local function read_file(path)  	local fd = io.open(path, "r") @@ -25,17 +23,14 @@ local function write_file(path, content)  	fd:close()  end --- Minimal XML attribute extractor for a tag like: <option name="MAIN_CLASS_NAME" value="com.example.Main" />  local function extract_attributes(tag)  	local attrs = {} -	for k, v in tag:gmatch('(%w+)%s*=\\s*"([^"]*)"') do +	for k, v in tag:gmatch('(%w+)%s*=%s*"([^"]*)"') do  		attrs[k] = v  	end  	return attrs  end --- Given the whole xml content, return table: --- { type = "Application", name = "MyApp", options = { [name] = value, ... }, env = {k=v}, method = {...} }  local function parse_run_configuration(xml)  	-- find <configuration ...> ... </configuration>  	local cfg_tag, body = xml:match("<configuration%s+([^>]*)>(.-)</configuration>") @@ -49,7 +44,7 @@ local function parse_run_configuration(xml)  	end  	local cfg_attrs = extract_attributes(cfg_tag) -	local result = { _attrs = cfg_attrs, options = {}, env = {}, method = {} } +	local result = { _attrs = cfg_attrs, options = {} }  	-- options: <option name="..." value="..."/>  	for option in body:gmatch("<option%s+([^>/]-)/>") do @@ -58,135 +53,45 @@ local function parse_run_configuration(xml)  			result.options[a.name] = a.value  		end  	end +	return result +end -	-- envs: <envs><env name="K" value="V"/></envs> -	local envs_block = body:match("<envs>(.-)</envs>") -	if envs_block then -		for envtag in envs_block:gmatch("<env%s+([^>/]-)/>") do -			local a = extract_attributes(envtag) -			if a.name and a.value then -				result.env[a.name] = a.value -			end -		end -	end +local function print_table(t, indent) +	indent = indent or 0 +	local prefix = string.rep("  ", indent) -	-- method (for JUnit): <method v="2"> <option name="..." value="..."/> </method> -	local method_block = body:match("<method%s+([^>]*)>(.-)</method>") -	if method_block then -		local method_tag, method_body = body:match("<method%s+([^>]*)>(.-)</method>") -		if method_tag then -			result.method._attrs = extract_attributes(method_tag) -			result.method.options = {} -			for opt in method_body:gmatch("<option%s+([^>/]-)/>") do -				local a = extract_attributes(opt) -				if a.name and a.value then -					result.method.options[a.name] = a.value -				end -			end +	for key, value in pairs(t) do +		if type(value) == "table" then +			print(prefix .. tostring(key) .. ":") +			print_table(value, indent + 1) +		else +			print(prefix .. tostring(key) .. " = " .. tostring(value))  		end  	end - -	return result  end  -- Map a single parsed config to a VSCode launch configuration (as Lua table) -local function map_to_vscode(name, parsed) -	local t = parsed._attrs.type or parsed._attrs.factoryName or "" +local function map_to_vscode(parsed) +	local type = parsed._attrs.type or parsed._attrs.factoryName or ""  	local vscode = { -		name = name or parsed._attrs.name or "Converted", +		name = parsed._attrs.name or "<undefined>",  		request = "launch",  	}  	-- Common Application type -	if t:match("[Aa]pplication") or parsed.options.MAIN_CLASS_NAME then +	if type:match("[Aa]pplication") then  		vscode.type = "java" -		vscode.mainClass = parsed.options.MAIN_CLASS_NAME or parsed.options.MAIN_CLASS -		if parsed.options.PROGRAM_PARAMETERS and parsed.options.PROGRAM_PARAMETERS ~= "" then -			-- split by space respecting simple quotes (basic) -			local args = {} -			for a in parsed.options.PROGRAM_PARAMETERS:gmatch("%S+") do -				table.insert(args, a) -			end -			vscode.args = args -		end -		if parsed.options.VM_PARAMETERS and parsed.options.VM_PARAMETERS ~= "" then -			vscode.vmArgs = parsed.options.VM_PARAMETERS -		end -		if parsed.options.WORKING_DIRECTORY and parsed.options.WORKING_DIRECTORY ~= "" then -			vscode.cwd = parsed.options.WORKING_DIRECTORY:gsub("%$PROJECT_DIR%$", "${workspaceFolder}") -		else -			vscode.cwd = "${workspaceFolder}" -		end -		if next(parsed.env) then -			vscode.env = parsed.env -		end -		-- If module present, attach projectName (useful for java extension) -		if parsed.options.MODULE_NAME then -			vscode.projectName = parsed.options.MODULE_NAME -		end - +		vscode.mainClass = parsed.options.MAIN_CLASS_NAME  		return vscode  	end -	-- JUnit test configuration -	if -		t:match("[Jj]Unit") -		or parsed.method.options and (parsed.method.options.CLASS_NAME or parsed.method.options.METHOD_NAME) -	then -		vscode.type = "java" -		-- Use test runner config via mainClass (JUnit runner) or use builtin test adapters -		if parsed.method.options.CLASS_NAME then -			vscode.name = (parsed._attrs.name or "JUnit:") .. " " .. parsed.method.options.CLASS_NAME -			-- map to a launch that runs the single test class -			vscode.mainClass = parsed.method.options.CLASS_NAME -			vscode.args = {} -		end -		if next(parsed.env) then -			vscode.env = parsed.env -		end -		vscode.cwd = parsed.options.WORKING_DIRECTORY -				and parsed.options.WORKING_DIRECTORY:gsub("%$PROJECT_DIR%$", "${workspaceFolder}") -			or "${workspaceFolder}" -		return vscode -	end - -	-- Gradle run config -	if t:match("[Gg]radle") or parsed._attrs.type == "Gradle" or parsed.options.TASK_NAME then -		-- Represent as a 'command' launch using terminal.integrated (fallback) -		vscode.type = "pwa-node" -- generic terminal-ish; user may change -		vscode.name = parsed._attrs.name or "Gradle Task" -		local task = parsed.options.TASK_NAME or parsed.options.GRADLE_TASK -		vscode.request = "launch" -		vscode.runtimeExecutable = "gradle" -		vscode.args = {} -		if task and task ~= "" then -			for tkn in (task .. ""):gmatch("%S+") do -				table.insert(vscode.args, tkn) -			end -		end -		vscode.cwd = parsed.options.WORKING_DIRECTORY -				and parsed.options.WORKING_DIRECTORY:gsub("%$PROJECT_DIR%$", "${workspaceFolder}") -			or "${workspaceFolder}" -		if next(parsed.env) then -			vscode.env = parsed.env -		end -		return vscode -	end - -	-- Fallback: produce a shell launch that echos an unsupported type -	return { -		type = "pwa-node", -		name = parsed._attrs.name or "Converted (unsupported)", -		request = "launch", -		program = "${file}", -		cwd = "${workspaceFolder}", -	} +	error("Unknown configuration type: " .. type)  end  -- Main: scan .idea/runConfigurations and convert  function M.convert_all(opts)  	opts = opts or {} -	local pattern = ".run/*.xml" +	local pattern = ".idea/runConfigurations/*.xml"  	local files = vim.tbl_filter(function(p)  		return p ~= ""  	end, vim.fn.glob(pattern, false, true)) @@ -200,10 +105,9 @@ function M.convert_all(opts)  		if not content then  			vim.notify("Cannot read " .. f, vim.log.levels.WARN)  		end -		local name = f:match("([^/]+)%.xml$") or f  		local parsed = parse_run_configuration(content)  		if parsed then -			local vs = map_to_vscode(name, parsed) +			local vs = map_to_vscode(parsed)  			table.insert(configs, vs)  		else  			vim.notify("Skipping (unrecognized) " .. f, vim.log.levels.DEBUG) @@ -211,7 +115,7 @@ function M.convert_all(opts)  	end  	local launch = { version = "0.2.0", configurations = configs } -	local ok, j = pcall(vim.fn.json_encode, launch) +	local ok, j = pcall(vim.json.encode, launch)  	if not ok then  		error("Failed to encode launch.json")  	end  | 
