Js-beautify: l'indentation en guirlande entraîne une surindentation

Créé le 20 juin 2014  ·  18Commentaires  ·  Source: beautify-web/js-beautify

En utilisant ceci via https://github.com/enginespot/js-beautify-sublime

Attendu:

.foo()
.bar();

Réel:

  .foo()
  .bar();

Pour illustrer le problème : l'indentation actuelle peut conduire à des EOF comme celui-ci :

      });
    });
})();

Cela ressemble à une erreur pour moi et m'incitera à rechercher la cause - ou pire, me rendra aveugle aux vraies =(

enhancement

Commentaire le plus utile

Je dois +1 cette demande, c'est particulièrement pratique lorsque je travaille avec Promises.

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

Cet enchaînement peut continuer pendant un certain temps, en particulier lors de l'écriture d'un point final d'api plus complexe, et au moment où vous regardez en bas, vous êtes constamment déconcerté par la façon dont l'indentation se termine par rapport à quelque chose de proche.

Je pense qu'il est important que toutes les indentations de fermeture soient d'un niveau de différence de profondeur par rapport au suivant le plus proche.

Tous les 18 commentaires

Pourriez-vous nous donner l'entrée complète et la sortie attendue, ainsi que votre configuration ? J'ai du mal à corréler votre fragment attendu (qui semble incorrect, honnêtement) aux blocs de fermeture. Merci!

Comme beaucoup de choses dans ce domaine, c'est bien sûr une question de préférence personnelle et d'habitude plutôt qu'une vérité objective.

Après le traitement, vous pouvez voir quelque chose comme ceci :

(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 {};
            }
        ]);
})();

Je voudrais ceci:

(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 {};
        }
    ]);
})();

Voici ma config :

{
    "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

Le problème dont vous parlez est celui-ci :

    angular
        .module('module', [])

Je vais prendre une minute pour ressentir une touche de génial que nous soyons si proches de ce que vous voulez voir. Autrefois, nous ne nous serions jamais rapprochés. :le sourire:

L'indentation ici est destinée à garder la clarté sur les éléments qui font partie d'une déclaration particulière. Dans le cas général, l'indentation est fondamentalement correcte. Dans ce cas précis, vous avez une très longue déclaration, mais selon # 200, l'embellisseur ne sait pas qu'il n'y a pas de déclarations significatives après celle-ci. L'embellisseur n'est pas censé être un formateur entièrement configurable - il est destiné à traiter le cas général

Pour ajouter un peu de profondeur à cette discussion, veuillez jeter un œil à ces exemples et dites-moi à quoi devrait ressembler le formatage.

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()

Je vais prendre une minute pour ressentir une touche de génial que nous soyons si proches de ce que vous voulez voir.

Absolument! =)

En ce qui concerne l'indentation, je pense que votre exemple devrait ressembler à ceci:

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()

La maxime ici est la même que pour les accolades : le début et la fin doivent être à la même indentation. De plus, les conventions de code de Douglas Crockford prescrivent le switch exactement comme elles le font pour éviter la surindentation.

Sauf que js-beautify ne suit pas crockford par défaut, et si vous exécutez ce qui précède via jslint, il se plaindra que .cooker( est à la mauvaise indentation.

Dans votre exemple, il me semble qu'il est beaucoup trop facile pour beta(zeta); d'être négligé.
En outre, vous montrez des indentations en guirlande et d'autres non. Quelle logique l'embellisseur doit-il utiliser pour décider lesquels indentent et lesquels ne le font pas ?

Je vais laisser cela ouvert - l'exemple que vous fournissez semble être basé sur AngularJS, donc cet idiome peut être plus largement accepté avec le temps. Mais ce n'est pas quelque chose que nous pourrons intégrer de si tôt.

Je suis terriblement désolé : j'ai bâclé l'indentation. Aucun d'entre eux n'était censé être en retrait. Et pour que beta(zeta); ne soit pas oublié, j'utiliserais des lignes vides, comme ceci :

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();

Comme je l'ai dit au début, je pense que c'est une question de goût personnel. Et spécifiquement avec les chaînes à une seule ligne, je suis moins enclin à réduire l'indentation. Mais je trouve le cas multi-lignes très mauvais et avoir des styles mixtes serait horrible, donc je m'en tiendrai définitivement à la stratégie de moins d'indentation, toujours.

Vous pourriez regarder #485. Avec ce correctif à venir, les éléments suivants resteront désormais inchangés lorsqu'ils passeront par l'embellisseur :

(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 {};
        }]);
})();

Ce n'est toujours pas ce que vous voudriez, mais l'embellisseur ne forcera plus la déclaration de la fonction à une nouvelle ligne (tout en respectant une nouvelle ligne si vous l'incluez).

Je dois +1 cette demande, c'est particulièrement pratique lorsque je travaille avec Promises.

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

Cet enchaînement peut continuer pendant un certain temps, en particulier lors de l'écriture d'un point final d'api plus complexe, et au moment où vous regardez en bas, vous êtes constamment déconcerté par la façon dont l'indentation se termine par rapport à quelque chose de proche.

Je pense qu'il est important que toutes les indentations de fermeture soient d'un niveau de différence de profondeur par rapport au suivant le plus proche.

:+1:

Je pense qu'il est important que toutes les indentations de fermeture soient d'un niveau de différence de profondeur par rapport au suivant le plus proche.

Pour moi, c'est l'élément décisif qui prouve qu'une indentation supplémentaire est trompeuse et finalement une erreur. Je me rends compte que certains peuvent penser qu'il y a un certain sens dans lequel

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

semble refléter que le then() a en quelque sorte une relation parent-enfant avec Promise.resolve() , mais si cela est vrai, alors chaque then() a cette relation avec le précédent then() . Bien sûr, il n'y a vraiment _aucune_ telle relation parent-enfant, et l'indentation comme s'il y en avait jusqu'au bout ferait un grand gâchis, donc personne ne le fait. Mais indenter le premier then() fait juste un _petit_ gâchis au lieu d'un énorme - c'est juste que certaines personnes semblent disposées à supporter ce petit gâchis, tandis que certains d'entre nous préfèrent ne pas avoir _aucun_ gâchis dans notre code si nous pouvons l'aider.

Il peut être agréable d'avoir l'indication visuelle fournie par l'indentation, mais dans ce cas, cela surcharge la signification de l'indentation, non seulement en indiquant une nouvelle portée, mais également en indiquant une méthode chaînée. Cependant, nous avons déjà le . pour indiquer une méthode chaînée, et comme le . est au début du texte sur la ligne, il fournit vraiment toute la (pseudo-)indentation nécessaire tant que vous y prêtez attention.

Ce n'est donc pas _vraiment_ _juste _ une question de préférence personnelle, c'est une question d'avantages et d'inconvénients des deux approches. (La préférence personnelle _est_ bien sûr impliquée, car certains peuvent ne pas se soucier de certains inconvénients ou de certains avantages, mais la discussion peut être plus fructueuse si nous discutons de ce que sont ces avantages et inconvénients, plutôt que de simplement dire "je préfère _x_" ou "je préférez _y_".)

Je pense que le cas est fort que les inconvénients de l'indentation supplémentaire sont importants, tandis que les avantages peuvent être obtenus d'une autre manière.

Inconvénients de l'indentation supplémentaire pour les méthodes chaînées :

  • votre indentation n'est plus un indicateur fiable de la portée
  • votre ponctuation finale est susceptible de vous faire penser que vous avez fait une erreur

Avantages:

  • vous obtenez une plus grande indication visuelle du chaînage de méthodes que ce qu'un simple . seul fournit (MAIS vous _do_ obtenez cette indication avec juste un . )

+1

+1 Cela conduit à des erreurs Expected exactly one space between '{a}' and '{b}' dans jslint.

Exemple:

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('./'));
});

Les erreurs:

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

Manière correcte (pour 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('./'));
});

Je préférerais de loin avoir cela en option, principalement pour éviter une indentation supplémentaire inutile dans le chaînage des promesses :

  // 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 : ''));
  });

Je pense que l'indentation supplémentaire est l'équivalent de:

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

Cela a du sens si le jeton enfant qui entoure un bloc d'indentation se trouve sur une nouvelle ligne à partir de la variable initiale :

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

vs.

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

Mais si tout peut tenir sur une seule ligne, la double indentation ne devrait pas se produire.

(Dans l'état actuel des choses, ce qui précède serait pelucheux/attendu comme :)

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

J'ai marqué cela comme une amélioration.
Je ne conteste pas que ce soit une bonne idée, je n'ai juste pas le temps.

Tous vous "+1"-ers et ceux qui ont commenté, n'hésitez pas à contribuer une pull request.

+1 envie

J'ai ouvert un PR pour ça

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

si l'intégration continue mettait finalement à jour le statut du PR, il devrait être prêt à fusionner.

+1 C'est ennuyeux comme l'enfer

Cette page vous a été utile?
0 / 5 - 0 notes