Js-beautify: 菊花链缩进导致过度缩进

创建于 2014-06-20  ·  18评论  ·  资料来源: beautify-web/js-beautify

通过https://github.com/enginespot/js-beautify-sublime使用它

预期的:

.foo()
.bar();

实际的:

  .foo()
  .bar();

为了说明这个问题:当前的缩进会导致像这样的 EOF:

      });
    });
})();

这对我来说似乎是一个错误,并会促使我寻找原因——或者更糟糕的是,让我对真正的原因视而不见 =(

enhancement

最有用的评论

我必须 +1 这个请求,这在使用 Promises 时特别方便。

Promise.resolve()
.then(function() {
  return foo.bar()
})
.then(function() {
  return foo.baz();
})
.then(function() {
 //...
}) //...
//...

这种链接可能会持续一段时间,尤其是在编写更复杂的 api 端点时,当您查看底部时,您会经常对缩进相对于附近事物的完成方式感到措手不及。

我认为重要的是所有闭合缩进都与下一个最近的缩进深度差一个级别。

所有18条评论

你能给我们完整的输入和预期的输出,以及你的配置吗? 我很难将您的预期片段(老实说看起来不正确)与结束块相关联。 谢谢!

与这方面的许多事情一样,这当然是个人喜好和习惯的问题,而不是客观事实。

处理后,您可能会看到如下内容:

(function () {
    'use strict';

    angular
        .module('module', [])
        .directive('appVersion', ['version',
            function (version) {
                return function (scope, elm, attrs) {
                    elm.text(version);
                };
            }
        ])
        .directive('foo', [

            function () {
                return {};
            }
        ])
        .directive('bar', [

            function () {
                return {};
            }
        ]);
})();

我想要这个:

(function () {
    'use strict';

    angular
    .module('module', [])
    .directive('appVersion', ['version',
        function (version) {
            return function (scope, elm, attrs) {
                elm.text(version);
            };
        }
    ])
    .directive('foo', [
        function () {
            return {};
        }
    ])
    .directive('bar', [
        function () {
            return {};
        }
    ]);
})();

这是我的配置:

{
    "indent_level": 0,
    "indent_with_tabs": true,
    "preserve_newlines": true,
    "max_preserve_newlines": 5,
    "jslint_happy": true,
    "brace_style": "collapse",
    "keep_array_indentation": false,
    "keep_function_indentation": false,
    "space_before_conditional": true,
    "break_chained_methods": true,
    "eval_code": false,
    "unescape_strings": false,
    "wrap_line_length": 0,

    // jsbeautify options
    "format_on_save": true,
    "use_original_indentation": true
}

+1

您正在谈论的问题是这一缩进:

    angular
        .module('module', [])

我将花一点时间来感受一下我们与您想看到的东西如此接近的感觉。 在过去,我们不会靠近。 :微笑:

那里的缩进是为了保持清楚哪些元素是特定语句的一部分。 一般情况下,缩进基本正确。 在这种特定情况下,您有一个很长的语句,但是根据 #200,美化器不知道在那之后没有重要的语句。 美化器并不是一个完全可配置的格式化程序——它是为了解决一般情况

为了增加讨论的深度,请查看这些示例并告诉我格式应该是什么样的。

alpha
    .cooker(function() {
        some
            .thing()
            .should()
            .happen();
        elsewhere
            .some_other_thing()
            .should()
            .happen();
    })
    .thenclose()
beta(zeta);
omega
    .cage(function() {
        random
            .things()
            .should()
            .happen();
        elsewhere
            .some_other_thing()
            .should()
            .happen();
    })
    .thendie()

我将花一点时间来感受一下我们与您想看到的东西如此接近的感觉。

绝对地! =)

关于缩进,我认为您的示例应如下所示:

alpha
.cooker(function() {
    some
        .thing()
        .should()
        .happen();
    elsewhere
        .some_other_thing()
        .should()
        .happen();
})
.thenclose()
beta(zeta);
omega
.cage(function() {
    random
        .things()
        .should()
        .happen();
    elsewhere
        .some_other_thing()
        .should()
        .happen();
})
.thendie()

这里的格言与花括号相同:开始和结束应该在相同的缩进。 此外, Douglas Crockford 的代码约定规定了switch的方式正是为了避免过度缩进。

除了 js-beautify 默认不遵循 crockford 之外,如果你通过 jslint 运行上面的,它会抱怨.cooker(的缩进错误。

在您的示例中,在我看来beta(zeta);太容易被忽视。
此外,您显示了一些菊花链缩进,而另一些则没有。 美化器应该使用什么逻辑来决定哪些缩进哪些不缩进?

我将保持开放状态 - 您提供的示例似乎是基于 AngularJS 的,因此随着时间的推移,这个习语可能会获得更广泛的接受。 但这不是我们很快就能整合的东西。

非常抱歉:我搞砸了缩进。 它们都不应该缩进。 为了beta(zeta);不要被忽视,我会使用空行,如下所示:

alpha
.cooker(function() {
    some
    .thing()
    .should()
    .happen();

    elsewhere
    .some_other_thing()
    .should()
    .happen();
})
.thenclose();

beta(zeta);

omega
.cage(function() {
    random
    .things()
    .should()
    .happen();

    elsewhere
    .some_other_thing()
    .should()
    .happen();
})
.thendie();

正如我一开始所说,我认为这是个人品味的问题。 特别是对于单线链,我不太倾向于减少缩进。 但是我发现多行的情况非常糟糕,混合样式会很糟糕,所以我肯定会一直坚持减少缩进的策略。

你可以看看#485。 随着这个即将到来的修复,当它通过美化器时,以下内容现在将保持不变:

(function () {
    'use strict';

    angular
        .module('module', [])
        .directive('appVersion', ['version', function (version) {
            return function (scope, elm, attrs) {
                elm.text(version);
            };
        }])
        .directive('foo', [function () {
            return {};
        }])
        .directive('bar', [function () {
            return {};
        }]);
})();

仍然不是您想要的,但美化器将不再强制函数声明为换行符(如果包含它,仍然尊重换行符)。

我必须 +1 这个请求,这在使用 Promises 时特别方便。

Promise.resolve()
.then(function() {
  return foo.bar()
})
.then(function() {
  return foo.baz();
})
.then(function() {
 //...
}) //...
//...

这种链接可能会持续一段时间,尤其是在编写更复杂的 api 端点时,当您查看底部时,您会经常对缩进相对于附近事物的完成方式感到措手不及。

我认为重要的是所有闭合缩进都与下一个最近的缩进深度差一个级别。

:+1:

我认为重要的是所有闭合缩进都与下一个最近的缩进深度差一个级别。

对我来说,这是证明额外缩进具有误导性并最终成为错误的关键。 我意识到有些人可能会觉得有某种意义

Promise.resolve()
  .then(function() {
    return foo.bar()
  })

似乎反映了then()在某种意义上与Promise.resolve()有父子关系,但如果这是真的,那么每个后续then()与以前的then() 。 当然真的_没有_这样的父子关系,缩进好像一路往下会弄得一团糟,所以没人做。 但是缩进第一个then()只会造成 _small_ 混乱而不是巨大的混乱——只是有些人似乎愿意忍受这种小小的混乱,而我们中的一些人更愿意在我们的代码中没有 _any_ 混乱,如果我们可以帮助它。

缩进提供的视觉指示可能很好,但在这种情况下,缩进的含义是重载的——不仅指示新的范围,还指示链式方法。 然而,我们已经有.来表示一个链式方法,并且因为.位于该行文本的开头,它确实提供了所有需要的(伪)缩进只要你注意它。

所以这不是_真的_ _只是 _ 个人喜好问题——这是两种方法的优缺点问题。 (当然涉及个人偏好,因为有些人可能不关心某些缺点或某些好处,但是如果我们讨论这些好处和缺点_是什么,而不是仅仅说“我更喜欢_x_”或“我更喜欢_y_”。)

我认为额外缩进的缺点很明显,而好处可以通过另一种方式获得。

链式方法额外缩进的缺点:

  • 您的缩进不再是范围的可靠指标
  • 你的结束标点可能会让你认为你犯了一个错误

好处:

  • 您获得的方法链接的视觉指示比.本身提供的更大(但是您_do_仅通过.获得该指示)

+1

+1 这会导致 jslint 中出现Expected exactly one space between '{a}' and '{b}'错误。

例子:

gulp.task('changelog', function () {
    return gulp.src('CHANGELOG.md', {
            buffer: false
        })
        .pipe(conventionalChangelog({
            preset: 'angular' // Or to any other commit message convention you use.
        }))
        .pipe(gulp.dest('./'));
});

错误:

4   Expected 'buffer' at column 9, not column 13.    buffer: false
5   Expected '}' at column 5, not column 9.  })

正确的方法(对于 jslint):

gulp.task('changelog', function () {
    return gulp.src('CHANGELOG.md', {
        buffer: false
    })
        .pipe(conventionalChangelog({
            preset: 'angular' // Or to any other commit message convention you use.
        }))
        .pipe(gulp.dest('./'));
});

我非常希望将其作为一个选项,主要是为了避免在 Promise 链接中不必要的额外缩进:

  // fetch `config.json` and then set as constant
  $http.get('config.json').then(function(response) {
    angular.module('myApp').constant('CONFIG', response.data);
  })
  .then(function() {
    angular.bootstrap(document, ['myApp']);
  })
  .catch(function(err) {
    var message = (err && err.data || err && err.message);
    console.error('Unable to bootstrap application.', err);
    window.alert('Unable to bootstrap application.' + (message ? '\n\n' + message : ''));
  });

我认为额外的缩进相当于:

try {
    // 4 spaces
  } // 2
  catch () {
    // 4
  }

如果环绕缩进块的子标记位于初始变量的新行上,这是有道理的:

    .module('module', function() {
      // .module starts on new line, so this block has 2 indents
    })

对比

  angular.module('module', function() {
    // .module is on the same line as the initial variable angular, so this block has 1 indent
  })

但是,如果它可以全部放在一行上,那么就不应该发生双缩进。

(就目前而言,上述内容将被剔除/预期为:)

angular.module('module', function() {
    // double indent
  });

我已将此标记为增强功能。
我并不反对这是一个好主意,我只是没有时间。

所有你“+1”的人和那些发表评论的人,随时贡献一个拉取请求。

+1 想要

我为此开了一个 PR

https://github.com/beautify-web/js-beautify/pull/927

如果持续集成最终会更新 PR 状态,它应该准备好合并。

+1 这太无聊了

此页面是否有帮助?
0 / 5 - 0 等级