Page MenuHomePhabricator

D9678.id27512.diff
No OneTemporary

D9678.id27512.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -150,6 +150,8 @@
'PhutilDocblockParserTestCase' => 'parser/__tests__/PhutilDocblockParserTestCase.php',
'PhutilEditDistanceMatrix' => 'utils/PhutilEditDistanceMatrix.php',
'PhutilEditDistanceMatrixTestCase' => 'utils/__tests__/PhutilEditDistanceMatrixTestCase.php',
+ 'PhutilEditorConfig' => 'parser/PhutilEditorConfig.php',
+ 'PhutilEditorConfigTestCase' => 'parser/__tests__/PhutilEditorConfigTestCase.php',
'PhutilEmailAddress' => 'parser/PhutilEmailAddress.php',
'PhutilEmailAddressTestCase' => 'parser/__tests__/PhutilEmailAddressTestCase.php',
'PhutilEmptyAuthAdapter' => 'auth/PhutilEmptyAuthAdapter.php',
@@ -587,6 +589,7 @@
'PhutilDisqusAuthAdapter' => 'PhutilOAuthAuthAdapter',
'PhutilDocblockParserTestCase' => 'PhutilTestCase',
'PhutilEditDistanceMatrixTestCase' => 'PhutilTestCase',
+ 'PhutilEditorConfigTestCase' => 'PhutilTestCase',
'PhutilEmailAddressTestCase' => 'PhutilTestCase',
'PhutilEmptyAuthAdapter' => 'PhutilAuthAdapter',
'PhutilErrorHandlerTestCase' => 'PhutilTestCase',
diff --git a/src/parser/PhutilEditorConfig.php b/src/parser/PhutilEditorConfig.php
new file mode 100644
--- /dev/null
+++ b/src/parser/PhutilEditorConfig.php
@@ -0,0 +1,90 @@
+<?php
+
+/**
+ * Utilities for parsing [[http://editorconfig.org/ | EditorConfig]] files.
+ */
+final class PhutilEditorConfig {
+
+ private $root;
+
+ private static $knownProperties = array(
+ 'end_of_line',
+ 'indent_style',
+ 'indent_size',
+ 'insert_final_newline',
+ 'trim_trailing_whitespace',
+ 'charset',
+ );
+
+ /**
+ * Constructor.
+ *
+ * @param string The root directory.
+ */
+ public function __construct($root) {
+ $this->root = $root;
+ }
+
+ public function getConfig($path, $key) {
+ $editorconfigs = $this->getEditorConfigs($path);
+
+ foreach ($editorconfigs as $editorconfig) {
+ list($path_prefix, $config) = $editorconfig;
+ $value = null;
+
+ foreach ($config as $glob => $options) {
+ if (!$glob) {
+ continue;
+ }
+
+ switch (strpos($glob, '/')) {
+ case false:
+ $glob = '**/'.$glob;
+ break;
+
+ case 0:
+ $glob = substr($glob, 1);
+ break;
+ }
+
+ $glob = $path_prefix.'/'.$glob;
+ $glob = str_replace('**/', '{,*/,**/}', $glob);
+ $regex = phutil_glob_to_regex($glob);
+
+ if (!preg_match($regex, $path)) {
+ continue;
+ }
+
+ $value = $options[$key];
+
+ // TODO: What if it really is `null`?
+ if (json_decode($value, true) !== null) {
+ $value = json_decode($value, true);
+ }
+ }
+
+ if ($value !== null) {
+ return $value;
+ }
+ }
+ }
+
+ private function getEditorConfigs($path) {
+ $configs = array();
+
+ do {
+ $path = dirname($path);
+ $file = $path.'/.editorconfig';
+
+ if (!Filesystem::pathExists($file)) {
+ continue;
+ }
+
+ $config = phutil_ini_decode(Filesystem::readFile($file));
+ $configs[] = array($path, ($config));
+ } while ($path != $this->root);
+
+ return $configs;
+ }
+
+}
diff --git a/src/parser/__tests__/PhutilEditorConfigTestCase.php b/src/parser/__tests__/PhutilEditorConfigTestCase.php
new file mode 100644
--- /dev/null
+++ b/src/parser/__tests__/PhutilEditorConfigTestCase.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * @group testcase
+ */
+final class PhutilEditorConfigTestCase extends PhutilTestCase {
+
+ public function testGetPaths() {
+ $parser = new PhutilEditorConfig(dirname(phutil_get_library_root()));
+
+ $tests = array(
+ 'file.txt' => array(
+ 'indent_style' => 'tab',
+ 'indent_size' => 4,
+ 'charset' => 'utf-8',
+ 'trim_trailing_whitespace' => false,
+ 'insert_final_newline' => false,
+ ),
+ 'indent.txt' => array(
+ 'indent_style' => 'space',
+ 'indent_size' => 2,
+ ),
+ );
+
+ foreach ($tests as $path => $config) {
+ foreach ($config as $key => $value) {
+ $this->assertEqual(
+ $value,
+ $parser->getConfig($this->getTestFile($path), $key));
+ }
+ }
+ }
+
+ private function getTestFile($path) {
+ return dirname(__FILE__).'/editorconfig/'.$path;
+ }
+
+}
diff --git a/src/parser/__tests__/editorconfig/.editorconfig b/src/parser/__tests__/editorconfig/.editorconfig
new file mode 100644
--- /dev/null
+++ b/src/parser/__tests__/editorconfig/.editorconfig
@@ -0,0 +1,10 @@
+[*]
+indent_style = tab
+indent_size = 4
+charset = utf-8
+trim_trailing_whitespace = false
+insert_final_newline = false
+
+[indent.txt]
+indent_style = space
+indent_size = 2

File Metadata

Mime Type
text/plain
Expires
Wed, Apr 2, 4:23 PM (3 w, 1 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7729578
Default Alt Text
D9678.id27512.diff (4 KB)

Event Timeline