Skip to content
Merged
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
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,30 @@ Your .project file should look something like this:

Of course this is a example to apply Drupal code sniffer. This could be anything. Whatever you can have on this package settings it can be overwritten under the settings -> phpcs

### Multi-Platform Settings

If you use this plugin across multiple operating systems (e.g. syncing settings between Windows and Linux), you can specify platform-specific values for any path setting by using a dictionary instead of a string. The supported platform keys are `"windows"`, `"linux"`, and `"osx"`. You can also specify a `"default"` key as a fallback for platforms not explicitly listed.

```json
{
"phpcs_executable_path": {
"windows": "c:\\xampp\\php\\bin\\phpcs",
"linux": "/usr/bin/phpcs",
"osx": "/usr/local/bin/phpcs"
},
"php_cs_fixer_executable_path": {
"windows": "c:\\xampp\\php\\bin\\php-cs-fixer",
"default": "/usr/local/bin/php-cs-fixer"
},
"phpcs_php_prefix_path": {
"windows": "c:\\xampp\\php\\bin\\php",
"default": ""
}
}
```

This works for all path settings: `phpcs_executable_path`, `phpcs_php_prefix_path`, `phpcs_php_path`, `php_cs_fixer_executable_path`, `phpcbf_executable_path`, and `phpmd_executable_path`. Plain string values continue to work as before.

## FAQ

### What do I do when I get "OSError: [Errno 8] Exec format error"?
Expand Down
23 changes: 21 additions & 2 deletions phpcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,28 @@ def load(self):

def get(self, key):
if key in self.project_settings:
return self.project_settings.get(key)
raw = self.project_settings.get(key)
else:
return self.settings.get(key)
raw = self.settings.get(key)
return self._resolve_platform_value(raw)

def _resolve_platform_value(self, value):
"""
If value is a dict, resolve it to the value for the current platform.
Supports keys: "osx", "linux", "windows", and "default" as a fallback.
If value is not a dict, return it as-is for backward compatibility.
"""
if isinstance(value, dict) and any(
k in value for k in ("osx", "linux", "windows", "default")
):
platform = sublime.platform()
if platform in value:
return value[platform]
elif "default" in value:
return value["default"]
else:
return ""
return value

def set(self, key, value):
if key in self.project_settings:
Expand Down
42 changes: 42 additions & 0 deletions phpcs.sublime-settings
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@
// The path to the php executable.
// Needed for windows, or anyone who doesn't/can't make phars
// executable. Avoid setting this if at all possible
//
// You can use a dictionary to specify different paths per platform:
// "phpcs_php_prefix_path": {
// "windows": "c:\\xampp\\php\\bin\\php",
// "linux": "/usr/bin/php",
// "osx": "/usr/local/bin/php"
// }
"phpcs_php_prefix_path": "",

// Options include:
Expand Down Expand Up @@ -61,6 +68,13 @@

// It seems python/sublime cannot always find the phpcs application
// If empty, then use PATH version of phpcs, else use the set value
//
// You can use a dictionary to specify different paths per platform:
// "phpcs_executable_path": {
// "windows": "c:\\xampp\\php\\bin\\phpcs",
// "linux": "/usr/bin/phpcs",
// "osx": "/usr/local/bin/phpcs"
// }
"phpcs_executable_path": "",

// Additional arguments you can specify into the application
Expand All @@ -84,6 +98,13 @@
"php_cs_fixer_show_quick_panel": false,

// Path to where you have the php-cs-fixer installed
//
// You can use a dictionary to specify different paths per platform:
// "php_cs_fixer_executable_path": {
// "windows": "c:\\xampp\\php\\bin\\php-cs-fixer",
// "linux": "/usr/local/bin/php-cs-fixer",
// "osx": "/usr/local/bin/php-cs-fixer"
// }
"php_cs_fixer_executable_path": "",

// Additional arguments you can specify into the application
Expand All @@ -98,6 +119,13 @@
"phpcbf_show_quick_panel": false,

// Path to where you have the phpcbf installed
//
// You can use a dictionary to specify different paths per platform:
// "phpcbf_executable_path": {
// "windows": "c:\\xampp\\php\\bin\\phpcbf",
// "linux": "/usr/local/bin/phpcbf",
// "osx": "/usr/local/bin/phpcbf"
// }
"phpcbf_executable_path": "",

// Additional arguments you can specify into the application
Expand All @@ -121,6 +149,13 @@

// It seems python/sublime cannot always find the php application
// If empty, then use PATH version of php, else use the set value
//
// You can use a dictionary to specify different paths per platform:
// "phpcs_php_path": {
// "windows": "c:\\xampp\\php\\bin\\php",
// "linux": "/usr/bin/php",
// "osx": "/usr/local/bin/php"
// }
"phpcs_php_path": "",

// What is the regex for the linter? Has to provide a named match for 'message' and 'line'
Expand All @@ -136,6 +171,13 @@

// It seems python/sublime cannot always find the phpmd application
// If empty, then use PATH version of phpmd, else use the set value
//
// You can use a dictionary to specify different paths per platform:
// "phpmd_executable_path": {
// "windows": "c:\\xampp\\php\\bin\\phpmd",
// "linux": "/usr/local/bin/phpmd",
// "osx": "/usr/local/bin/phpmd"
// }
"phpmd_executable_path": "",

// Additional arguments you can specify into the application
Expand Down
90 changes: 89 additions & 1 deletion tests/test_phpcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import sublime

from Phpcs.phpcs import Sniffer
from Phpcs.phpcs import Pref, Sniffer


class TestSniffer(TestCase):
Expand Down Expand Up @@ -37,3 +37,91 @@ def test_we_can_parse_phpcs_standards_output(self, shell_mock):
expected = ["One", "NeutronStandard", "Two", "Three"]

self.assertEqual(expected, standards)


class TestPrefPlatformResolution(TestCase):
def setUp(self):
self.pref = Pref()

def test_string_value_passes_through_unchanged(self):
result = self.pref._resolve_platform_value("/usr/bin/phpcs")
self.assertEqual("/usr/bin/phpcs", result)

def test_empty_string_passes_through_unchanged(self):
result = self.pref._resolve_platform_value("")
self.assertEqual("", result)

def test_non_platform_dict_passes_through_unchanged(self):
value = {"--standard": "PSR2", "-n": ""}
result = self.pref._resolve_platform_value(value)
self.assertEqual(value, result)

@patch("Phpcs.phpcs.sublime.platform", return_value="osx")
def test_dict_resolves_to_osx_value(self, _):
value = {
"windows": "c:\\xampp\\php\\bin\\phpcs",
"linux": "/usr/bin/phpcs",
"osx": "/usr/local/bin/phpcs",
}
result = self.pref._resolve_platform_value(value)
self.assertEqual("/usr/local/bin/phpcs", result)

@patch("Phpcs.phpcs.sublime.platform", return_value="linux")
def test_dict_resolves_to_linux_value(self, _):
value = {
"windows": "c:\\xampp\\php\\bin\\phpcs",
"linux": "/usr/bin/phpcs",
"osx": "/usr/local/bin/phpcs",
}
result = self.pref._resolve_platform_value(value)
self.assertEqual("/usr/bin/phpcs", result)

@patch("Phpcs.phpcs.sublime.platform", return_value="windows")
def test_dict_resolves_to_windows_value(self, _):
value = {
"windows": "c:\\xampp\\php\\bin\\phpcs",
"linux": "/usr/bin/phpcs",
"osx": "/usr/local/bin/phpcs",
}
result = self.pref._resolve_platform_value(value)
self.assertEqual("c:\\xampp\\php\\bin\\phpcs", result)

@patch("Phpcs.phpcs.sublime.platform", return_value="osx")
def test_dict_falls_back_to_default_when_platform_missing(self, _):
value = {
"windows": "c:\\xampp\\php\\bin\\phpcs",
"default": "/usr/bin/phpcs",
}
result = self.pref._resolve_platform_value(value)
self.assertEqual("/usr/bin/phpcs", result)

@patch("Phpcs.phpcs.sublime.platform", return_value="osx")
def test_dict_returns_empty_string_when_platform_and_default_missing(self, _):
value = {
"windows": "c:\\xampp\\php\\bin\\phpcs",
"linux": "/usr/bin/phpcs",
}
result = self.pref._resolve_platform_value(value)
self.assertEqual("", result)

@patch("Phpcs.phpcs.sublime.platform", return_value="linux")
def test_dict_prefers_platform_over_default(self, _):
value = {
"linux": "/usr/bin/phpcs",
"default": "/opt/phpcs",
}
result = self.pref._resolve_platform_value(value)
self.assertEqual("/usr/bin/phpcs", result)

def test_none_value_passes_through(self):
result = self.pref._resolve_platform_value(None)
self.assertIsNone(result)

def test_list_value_passes_through(self):
value = ["Sniffer", "Fixer"]
result = self.pref._resolve_platform_value(value)
self.assertEqual(["Sniffer", "Fixer"], result)

def test_boolean_value_passes_through(self):
result = self.pref._resolve_platform_value(True)
self.assertTrue(result)