Étant donné que clang-format
est un outil permettant uniquement de reformater le code, est-il possible qu'un tel formatage permette de casser le code qui fonctionne ou au moins de changer son fonctionnement? Existe-t-il un type de contrat qui modifie/empêche le fonctionnement du code?
Nous souhaitons formater beaucoup de code avec clang-format
. Cela signifie que beaucoup de lignes de code vont changer. Ne pas avoir à examiner chaque ligne de code qui a seulement changé en raison d'un clang-format
simplifierait grandement ce processus.
Je dirais que clang-format
ne changera pas le fonctionnement du code. Par contre, je ne suis pas sûr à 100%, si cela peut être garanti.
L'outil clang-format
a une option -sort-includes
. Changer l'ordre des directives #include
peut définitivement changer le comportement du code existant, etpeut casser le code existant.
Puisque l'option SortIncludes
correspondante est définie sur true
par plusieurs des styles intégrés, il n'est peut-être pas évident que clang-format
va réorganiser vos inclus.
MyStruct.h:
struct MyStruct {
uint8_t value;
};
original.c:
#include <stdint.h>
#include <stddef.h>
#include "MyStruct.h"
int main (int argc, char **argv) {
struct MyStruct s = { 0 };
return s.value;
}
Maintenant, supposons que nous exécutons clang-format -style=llvm original.c > restyled.c
.
restyled.c:
#include "MyStruct.h"
#include <stddef.h>
#include <stdint.h>
int main(int argc, char **argv) {
struct MyStruct s = {0};
return s.value;
}
En raison de la réorganisation des fichiers d'en-tête, j'obtiens le message d'erreur suivant lors de la compilation de restyled.c
:
In file included from restyled.c:1:
./MyStruct.h:2:5: error: unknown type name 'uint8_t'
uint8_t value;
^
1 error generated.
Cependant, ce problème devrait être facile à résoudre. Il est peu probable que vous ayez des inclusions dépendantes de l'ordre, mais si vous le faites, vous pouvez résoudre le problème en insérant une ligne vide entre les groupes d'en-têtes nécessitant un ordre spécifique, car apparemment clang-format
ne trie que les groupes de directives #include
sans #include
lignes entre les deux.
fixed-original.c:
#include <stdint.h>
#include <stddef.h>
#include "MyStruct.h"
int main (int argc, char **argv) {
struct MyStruct s = { 0 };
return s.value;
}
fixed-restyled.c:
#include <stddef.h>
#include <stdint.h>
#include "MyStruct.h"
int main(int argc, char **argv) {
struct MyStruct s = {0};
return s.value;
}
Notez que stdint.h
et stddef.h
étaient toujours réorganisés car leurs inclusions sont toujours "groupées", mais que la nouvelle ligne vide empêchait MyStruct.h
d'être déplacé avant la bibliothèque standard.
Si la réorganisation de vos directives #include
rompt votre code, vous devriez probablement effectuer l'une des opérations suivantes:
Incluez explicitement les dépendances de chaque en-tête dans le fichier d'en-tête. Dans mon exemple, je devrais inclure stdint.h
dans MyStruct.h
.
Ajoutez une ligne de commentaire entre les groupes d'inclusion qui énonce explicitement la dépendance de commande. Rappelez-vous que toute ligne non -#include
doit séparer un groupe, les lignes de commentaires fonctionnent donc également. La ligne de commentaire dans le code suivant empêche également clang-format
d'inclure MyStruct.h
avant les en-têtes de bibliothèque standard.
alternate-original.c:
#include <stdint.h>
#include <stddef.h>
// must come after stdint.h
#include "MyStruct.h"
int main (int argc, char **argv) {
struct MyStruct s = { 0 };
return s.value;
}
Bien sûr, cela peut changer le fonctionnement de votre code. Et la raison en est que le programme C peut afficher certaines propriétés de son code source. Je pense à la macro __LINE__
, mais je ne suis pas sûre qu'il n'y ait pas d'autre moyen.
Considérez 1.c
:
#include <stdio.h>
int main(){printf("%d\n", __LINE__);}
Ensuite:
> clang 1.c -o 1.exe & 1.exe
2
Maintenant, faites quelques clang-format
:
> clang-format -style=Chromium 1.c >2.c
Et 2.c
est:
#include <stdio.h>
int main() {
printf("%d\n", __LINE__);
}
Et bien sûr, la sortie a changé:
> clang 2.c -o 2.exe & 2.exe
3
Étant donné que clang-format
n'affecte que les caractères d'espacement, vous pouvez vérifier que les fichiers avant et après clang-format
ing sont identiques aux espaces. Sous Linux/BSD/OS X, vous pouvez utiliser diff
et tr
pour cela:
$ diff --ignore-all-space <(tr '\n' ' ' < 2.c ) <(tr '\n' ' ' < 1.c)
1.c:
#include <stdio.h>
int main() {printf("Hello, world!\n"); return 0;}
2.c:
#include <stdio.h>
int main() {
printf("Hello, world!\n");
return 0;
}
La sortie de la commande diff
est vide, ce qui signifie que les fichiers 1.c
et 2.c
sont identiques jusqu’à des espaces.
En tant que Karoly mentionné dans son commentaire, notez que dans des conditions idéales, vous devez toujours vérifier les espaces qui comptent, par exemple. littéraux de chaîne. Mais dans le monde réel, je pense que ce test est largement suffisant.
Oui
il ne sera pas briser le flux de travail
le système dispose du commutateur de configuration: "C_Cpp.clang_format_sortIncludes": false ,
ma version est: ms-vscode.cpptools-0.13.1
c'est ma solution:
pour le flux de travail stable, utilisez la grammaire:
// format-off désactivé
... voici votre code
// format clang sur
le code ASM reformaté au format clang dans un projet parce que nous avons effectivement fait ceci:
#define ASM _asm
ASM {
...
}