Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 39 additions & 4 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,36 @@
import * as vscode from 'vscode';
import { exec } from 'child_process';
import { exec, execSync } from 'child_process';
import * as os from 'os';
import * as fs from 'fs';

function isWSL(): boolean {
return process.platform === 'linux' && fs.existsSync('/proc/version') &&
fs.readFileSync('/proc/version', 'utf8').toLowerCase().includes('microsoft');
}

function getWSLWindowsPath(): string {
try {
const result = execSync('cmd.exe /c echo %LOCALAPPDATA%', { encoding: 'utf8' });
return result.trim();
} catch (error) {
console.error('Failed to get Windows path:', error);
return '';
}
}

function convertWSLPathToWindows(path: string): string {
try {
// Convert path using wslpath
const windowsPath = execSync(`wslpath -w "${path}"`, { encoding: 'utf8' }).trim();

// Replace backslashes to ensure correct path format
return windowsPath.replace(/\\/g, '\\\\');
} catch (error) {
console.error('Failed to convert WSL path:', error);
return path;
}
}

function getMacIdeaPath(): string {
const commonPaths = [
'/Applications/IDEA.app',
Expand Down Expand Up @@ -98,7 +126,10 @@ export function activate(context: vscode.ExtensionContext) {
}

let command: string;
if (os.platform() === 'darwin') {
if (isWSL()) {
const windowsFilePath = convertWSLPathToWindows(filePath);
command = `cmd.exe /c "${ideaPath}" --line ${line} --column ${column} "${windowsFilePath}"`;
} else if (os.platform() === 'darwin') {
const ideaUrl = `idea://open?file=${encodeURIComponent(filePath)}&line=${line}&column=${column}`;
// If IDEA is already open, using the 'idea' command will show two IDEA icons in the dock temporarily
// Using the 'open' command instead will prevent this issue
Expand Down Expand Up @@ -141,7 +172,11 @@ export function activate(context: vscode.ExtensionContext) {
}

let command: string;
if (os.platform() === 'darwin') {
if (isWSL()) {
const windowsProjectPath = convertWSLPathToWindows(projectPath);
// Use --project parameter to open project
command = `cmd.exe /c "${ideaPath}" --project "${windowsProjectPath}"`;
} else if (os.platform() === 'darwin') {
const ideaUrl = `idea://open?file=${encodeURIComponent(projectPath)}`;
command = `open -a "${ideaPath}" "${ideaUrl}"`;
} else {
Expand All @@ -162,4 +197,4 @@ export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(openProjectDisposable);
}

export function deactivate() {}
export function deactivate() {}
181 changes: 181 additions & 0 deletions src/test/extension.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as vscode from 'vscode';
import * as os from 'os';
import * as path from 'path';
import * as fs from 'fs';
import { execSync } from 'child_process';

suite('Switch2IDEA Extension Test Suite', () => {
// 在所有测试开始前激活扩展
Expand Down Expand Up @@ -122,4 +123,184 @@ suite('Switch2IDEA Extension Test Suite', () => {
await config.update('ideaPath', originalPath, vscode.ConfigurationTarget.Global);
}
});

test('Should handle WSL path conversion', async () => {
if (process.platform === 'linux' && fs.existsSync('/proc/version') &&
fs.readFileSync('/proc/version', 'utf8').toLowerCase().includes('microsoft')) {
// Create test file
const tmpDir = os.tmpdir();
const testFileName = 'wsl_test.txt';
const testFilePath = path.join(tmpDir, testFileName);

try {
// Create test file
fs.writeFileSync(testFilePath, 'test content');

// Test path conversion
const windowsPath = execSync(`wslpath -w "${testFilePath}"`, { encoding: 'utf8' }).trim();
assert.ok(windowsPath.startsWith('\\\\wsl.localhost\\'), 'Path should be converted to WSL format');

// Open file
const doc = await vscode.workspace.openTextDocument(testFilePath);
const editor = await vscode.window.showTextDocument(doc);

// Execute command
await vscode.commands.executeCommand('Switch2IDEA.openFileInIDEA');

// Verify command execution completed
assert.ok(true);
} finally {
// Cleanup test file
try {
fs.unlinkSync(testFilePath);
} catch (e) {
console.error('Failed to cleanup test file:', e);
}
}
}
});

test('Should handle WSL project opening', async () => {
if (process.platform === 'linux' && fs.existsSync('/proc/version') &&
fs.readFileSync('/proc/version', 'utf8').toLowerCase().includes('microsoft')) {
// Create temporary project directory
const tmpDir = os.tmpdir();
const projectDir = path.join(tmpDir, 'wsl_project_test');

try {
// Create project directory and test file
fs.mkdirSync(projectDir);
fs.writeFileSync(path.join(projectDir, 'test.txt'), 'test content');

// Test project path conversion
const windowsProjectPath = execSync(`wslpath -w "${projectDir}"`, { encoding: 'utf8' }).trim();
assert.ok(windowsProjectPath.startsWith('\\\\wsl.localhost\\'), 'Project path should be converted to WSL format');

// Execute project open command
await vscode.commands.executeCommand('Switch2IDEA.openProjectInIDEA');

// Verify command execution completed
assert.ok(true);
} finally {
// Cleanup test directory
try {
fs.rmSync(projectDir, { recursive: true, force: true });
} catch (e) {
console.error('Failed to cleanup test directory:', e);
}
}
}
});

test('Should handle Windows path in WSL environment', async () => {
if (process.platform === 'linux' && fs.existsSync('/proc/version') &&
fs.readFileSync('/proc/version', 'utf8').toLowerCase().includes('microsoft')) {
// Get Windows path
const windowsPath = execSync('cmd.exe /c echo %LOCALAPPDATA%', { encoding: 'utf8' }).trim();
assert.ok(windowsPath, 'Should be able to get Windows path');

// Test IDEA path construction
const ideaPath = `${windowsPath}\\Programs\\IntelliJ IDEA\\bin\\idea64.exe`;
assert.ok(ideaPath.includes('\\'), 'IDEA path should contain backslashes');

// Create test file
const tmpDir = os.tmpdir();
const testFileName = 'windows_path_test.txt';
const testFilePath = path.join(tmpDir, testFileName);

try {
fs.writeFileSync(testFilePath, 'test content');

// Open file
const doc = await vscode.workspace.openTextDocument(testFilePath);
const editor = await vscode.window.showTextDocument(doc);

// Execute command
await vscode.commands.executeCommand('Switch2IDEA.openFileInIDEA');

// Verify command execution completed
assert.ok(true);
} finally {
// Cleanup test file
try {
fs.unlinkSync(testFilePath);
} catch (e) {
console.error('Failed to cleanup test file:', e);
}
}
}
});

test('Should handle special characters in WSL paths', async () => {
if (process.platform === 'linux' && fs.existsSync('/proc/version') &&
fs.readFileSync('/proc/version', 'utf8').toLowerCase().includes('microsoft')) {
// Create test file with special characters
const tmpDir = os.tmpdir();
const testFileName = 'test file with spaces and @#$%^&.txt';
const testFilePath = path.join(tmpDir, testFileName);

try {
fs.writeFileSync(testFilePath, 'test content');

// Test path conversion
const windowsPath = execSync(`wslpath -w "${testFilePath}"`, { encoding: 'utf8' }).trim();
assert.ok(windowsPath, 'Path should be converted successfully');

// Open file
const doc = await vscode.workspace.openTextDocument(testFilePath);
const editor = await vscode.window.showTextDocument(doc);

// Execute command
await vscode.commands.executeCommand('Switch2IDEA.openFileInIDEA');

// Verify command execution completed
assert.ok(true);
} finally {
// Cleanup test file
try {
fs.unlinkSync(testFilePath);
} catch (e) {
console.error('Failed to cleanup test file:', e);
}
}
}
});

test('Should handle command execution errors gracefully', async () => {
// Temporarily set an invalid IDEA path
const config = vscode.workspace.getConfiguration('switch2idea');
const originalPath = config.get('ideaPath');

try {
await config.update('ideaPath', 'invalid_path', vscode.ConfigurationTarget.Global);

// Create test file
const tmpDir = os.tmpdir();
const testFilePath = path.join(tmpDir, 'error_test.txt');

try {
fs.writeFileSync(testFilePath, 'test content');

// Open file
const doc = await vscode.workspace.openTextDocument(testFilePath);
const editor = await vscode.window.showTextDocument(doc);

// Execute command
await vscode.commands.executeCommand('Switch2IDEA.openFileInIDEA');

// Verify command execution completed (should not throw exception even if failed)
assert.ok(true);
} finally {
// Cleanup test file
try {
fs.unlinkSync(testFilePath);
} catch (e) {
console.error('Failed to cleanup test file:', e);
}
}
} finally {
// Restore original settings
await config.update('ideaPath', originalPath, vscode.ConfigurationTarget.Global);
}
});
});