]> git.proxmox.com Git - pve-eslint.git/blob - eslint/docs/developer-guide/code-conventions.md
3ee02286c9eea8c734e210578a3238f0015b59ef
[pve-eslint.git] / eslint / docs / developer-guide / code-conventions.md
1 # Code Conventions
2
3 Programming language style guides are important for the long-term maintainability of software. This guide is based on the [Code Conventions for the Java Programming Language](https://java.sun.com/docs/codeconv/) and [Douglas Crockford's Code Conventions for the JavaScript Programming Language](http://javascript.crockford.com/code.html). Modifications have been made due to my personal experience and preferences.
4
5 ## File Format
6
7 Each file has this same basic format:
8
9 ```js
10 /**
11 * @fileoverview Description of the file
12 * @author Your Name
13 */
14
15 "use strict";
16
17 //------------------------------------------------------------------------------
18 // Requirements
19 //------------------------------------------------------------------------------
20
21 // require() statements
22
23 //------------------------------------------------------------------------------
24 // Helpers
25 //------------------------------------------------------------------------------
26
27 // private methods/data
28
29 //------------------------------------------------------------------------------
30 // Public Interface
31 //------------------------------------------------------------------------------
32
33 // exported objects/methods
34 module.exports = {
35
36 };
37 ```
38
39 The `@author` field gives you credit for having created the file.
40
41 ## Indentation
42
43 Each indentation level is made up of four spaces. Do not use tabs.
44
45 // Good
46 if (true) {
47 doSomething();
48 }
49
50 ## Primitive Literals
51
52 Strings should always use double quotes (never single quotes) and should always appear on a single line. Never use a slash to create a new line in a string.
53
54 // Good
55 var name = "Nicholas";
56
57 // Bad: Single quotes
58 var name = 'Nicholas';
59
60 // Bad: Wrapping to second line
61 var longString = "Here's the story, of a man \
62 named Brady.";
63
64 Numbers should be written as decimal integers, e-notation integers, hexadecimal integers or floating-point decimals with at least one digit before and one digit after the decimal point. Never use octal literals.
65
66 // Good
67 var count = 10;
68
69 // Good
70 var price = 10.0;
71 var price = 10.00;
72
73 // Good
74 var num = 0xA2;
75
76 // Good
77 var num = 1e23;
78
79 // Bad: Hanging decimal point
80 var price = 10.;
81
82 // Bad: Leading decimal point
83 var price = .1;
84
85 // Bad: Octal (base 8) is deprecated
86 var num = 010;
87
88 The special value `null` should be used only in the following situations:
89
90 1. To initialize a variable that may later be assign an object value.
91 1. To compare against an initialized variable that may or may not have an object value.
92 1. To pass into a function where an object is expected.
93 1. To return from a function where an object is expected.
94
95 Examples:
96
97 // Good
98 var person = null;
99
100 // Good
101 function getPerson() {
102 if (condition) {
103 return new Person("Nicholas");
104 } else {
105 return null;
106 }
107 }
108
109 // Good
110 var person = getPerson();
111 if (person !== null){
112 doSomething();
113 }
114
115 // Bad: Testing against uninitialized variable
116 var person;
117 if (person != null){
118 doSomething();
119 }
120
121 // Bad: Testing to see if an argument was passed
122 function doSomething(arg1, arg2, arg3, arg4){
123 if (arg4 != null){
124 doSomethingElse();
125 }
126 }
127
128 Never use the special value `undefined`. To see if a variable has been defined, use the `typeof` operator:
129
130 // Good
131 if (typeof variable == "undefined") {
132 // do something
133 }
134
135 // Bad: Using undefined literal
136 if (variable == undefined) {
137 // do something
138 }
139
140 ## Operator Spacing
141
142 Operators with two operands must be preceded and followed by a single space to make the expression clear. Operators include assignments and logical operators.
143
144 // Good
145 var found = (values[i] === item);
146
147 // Good
148 if (found && (count > 10)) {
149 doSomething();
150 }
151
152 // Good
153 for (i = 0; i < count; i++) {
154 process(i);
155 }
156
157 // Bad: Missing spaces
158 var found = (values[i]===item);
159
160 // Bad: Missing spaces
161 if (found&&(count>10)) {
162 doSomething();
163 }
164
165 // Bad: Missing spaces
166 for (i=0; i<count; i++) {
167 process(i);
168 }
169
170 ## Parentheses Spacing
171
172 When parentheses are used, there should be no whitespace immediately after the opening paren or immediately before the closing paren.
173
174 // Good
175 var found = (values[i] === item);
176
177 // Good
178 if (found && (count > 10)) {
179 doSomething();
180 }
181
182 // Good
183 for (i = 0; i < count; i++) {
184 process(i);
185 }
186
187 // Bad: Extra space after opening paren
188 var found = ( values[i] === item);
189
190 // Bad: Extra space before closing paren
191 if (found && (count > 10) ) {
192 doSomething();
193 }
194
195 // Bad: Extra space around argument
196 for (i = 0; i < count; i++) {
197 process( i );
198 }
199
200 ## Object Literals
201
202 Object literals should have the following format:
203
204 * The opening brace should be on the same line as the containing statement.
205 * Each property-value pair should be indented one level with the first property appearing on the next line after the opening brace.
206 * Each property-value pair should have an unquoted property name, followed by a colon (no space preceding it), followed by the value.
207 * If the value is a function, it should wrap under the property name and should have a blank line both before and after the function.
208 * Additional empty lines may be inserted to group related properties or otherwise improve readability.
209 * The closing brace should be on a separate line.
210
211 Examples:
212
213 // Good
214 var object = {
215
216 key1: value1,
217 key2: value2,
218
219 func: function() {
220 // do something
221 },
222
223 key3: value3
224 };
225
226 // Bad: Improper indentation
227 var object = {
228 key1: value1,
229 key2: value2
230 };
231
232 // Bad: Missing blank lines around function
233 var object = {
234
235 key1: value1,
236 key2: value2,
237 func: function() {
238 // do something
239 },
240 key3: value3
241 };
242
243 When an object literal is passed to a function, the opening brace should be on the same line as if the value is a variable. All other formatting rules from above still apply.
244
245 // Good
246 doSomething({
247 key1: value1,
248 key2: value2
249 });
250
251 // Bad: All on one line
252 doSomething({ key1: value1, key2: value2 });
253
254 ## Comments
255
256 Make frequent use of comments to aid others in understanding your code. Use comments when:
257
258 * Code is difficult to understand.
259 * The code might be mistaken for an error.
260 * Browser-specific code is necessary but not obvious.
261 * Documentation generation is necessary for an object, method, or property (use appropriate documentation comments).
262
263 ### Single-Line Comments
264
265 Single-line comments should be used to document one line of code or a group of related lines of code. A single-line comment may be used in three ways:
266
267 1. On a separate line, describing the code beneath it.
268 1. At the end of a line, describing the code before it.
269 1. On multiple lines, to comment out sections of code.
270
271 When on a separate line, a single-line comment should be at the same indentation level as the code it describes and be preceded by a single line. Never use multiple single-line comments on consecutive lines, use a multi-line comment instead.
272
273 // Good
274 if (condition){
275
276 // if you made it here, then all security checks passed
277 allowed();
278 }
279
280 // Bad: No empty line preceding comment
281 if (condition){
282 // if you made it here, then all security checks passed
283 allowed();
284 }
285
286 // Bad: Wrong indentation
287 if (condition){
288
289 // if you made it here, then all security checks passed
290 allowed();
291 }
292
293 // Bad: This should be a multi-line comment
294 // This next piece of code is quite difficult, so let me explain.
295 // What you want to do is determine if the condition is true
296 // and only then allow the user in. The condition is calculated
297 // from several different functions and may change during the
298 // lifetime of the session.
299 if (condition){
300 // if you made it here, then all security checks passed
301 allowed();
302 }
303
304 For single-line comments at the end of a line, ensure there is at least one indentation level between the end of the code and the beginning of the comment:
305
306 // Good
307 var result = something + somethingElse; // somethingElse will never be null
308
309 // Bad: Not enough space between code and comment
310 var result = something + somethingElse;// somethingElse will never be null
311
312 The only acceptable time to have multiple single-line comments on successive lines is to comment out large sections of code. Multi-line comments should not be used for this purpose.
313
314 // Good
315 // if (condition){
316 // doSomething();
317 // thenDoSomethingElse();
318 // }
319
320 ### Multi-Line Comments
321
322 Multi-line comments should be used to document code that requires more explanation. Each multi-line comment should have at least three lines:
323
324 1. The first line contains only the `/*` comment opening. No further text is allowed on this line.
325 1. The next line(s) have a `*` aligned with the `*` in the first line. Text is allowed on these lines.
326 1. The last line has the `*/` comment opening aligned with the preceding lines. No other text is allowed on this line.
327
328 The first line of multi-comments should be indented to the same level as the code it describes. Each subsequent line should have the same indentation plus one space (for proper alignment of the `*` characters). Each multi-line comment should be preceded by one empty line.
329
330 // Good
331 if (condition){
332
333 /*
334 * if you made it here,
335 * then all security checks passed
336 */
337 allowed();
338 }
339
340 // Bad: No empty line preceding comment
341 if (condition){
342 /*
343 * if you made it here,
344 * then all security checks passed
345 */
346 allowed();
347 }
348
349 // Bad: Missing a space after asterisk
350 if (condition){
351
352 /*
353 *if you made it here,
354 *then all security checks passed
355 */
356 allowed();
357 }
358
359 // Bad: Wrong indentation
360 if (condition){
361
362 /*
363 * if you made it here,
364 * then all security checks passed
365 */
366 allowed();
367 }
368
369 // Bad: Don't use multi-line comments for trailing comments
370 var result = something + somethingElse; /*somethingElse will never be null*/
371
372 ### Comment Annotations
373
374 Comments may be used to annotate pieces of code with additional information. These annotations take the form of a single word followed by a colon. The acceptable annotations are:
375
376 * `TODO` - indicates that the code is not yet complete. Information about the next steps should be included.
377 * `HACK` - indicates that the code is using a shortcut. Information about why the hack is being used should be included. This may also indicate that it would be nice to come up with a better way to solve the problem.
378 * `XXX` - indicates that the code is problematic and should be fixed as soon as possible.
379 * `FIXME` - indicates that the code is problematic and should be fixed soon. Less important than `XXX`.
380 * `REVIEW` - indicates that the code needs to be reviewed for potential changes.
381
382 These annotations may be used with either single-line or multi-line comments and should follow the same formatting rules as the general comment type. Examples:
383
384 // Good
385 // TODO: I'd like to find a way to make this faster
386 doSomething();
387
388 // Good
389 /*
390 * HACK: Have to do this for IE. I plan on revisiting in
391 * the future when I have more time. This probably should
392 * get replaced before v1.2.
393 */
394 if (document.all) {
395 doSomething();
396 }
397
398 // Good
399 // REVIEW: Is there a better way to do this?
400 if (document.all) {
401 doSomething();
402 }
403
404 // Bad: Annotation spacing is incorrect
405 // TODO : I'd like to find a way to make this faster
406 doSomething();
407
408 // Bad: Comment should be at the same indentation as code
409 // REVIEW: Is there a better way to do this?
410 if (document.all) {
411 doSomething();
412 }
413
414
415 ## Variable Declarations
416
417 All variables should be declared before they are used. Variable declarations should take place at the beginning of a function using a single `var` statement with one variable per line. All lines after the first should be indented one level so the variable names line up. Variables should be initialized when declared if applicable and the equals operator should be at a consistent indentation level. Initialized variables should come first followed by uninitialized variables.
418
419 // Good
420 var count = 10,
421 name = "Nicholas",
422 found = false,
423 empty;
424
425 // Bad: Improper initialization alignment
426 var count = 10,
427 name = "Nicholas",
428 found= false,
429 empty;
430
431 // Bad: Incorrect indentation
432 var count = 10,
433 name = "Nicholas",
434 found = false,
435 empty;
436
437 // Bad: Multiple declarations on one line
438 var count = 10, name = "Nicholas",
439 found = false, empty;
440
441 // Bad: Uninitialized variables first
442 var empty,
443 count = 10,
444 name = "Nicholas",
445 found = false;
446
447 // Bad: Multiple var statements
448 var count = 10,
449 name = "Nicholas";
450
451 var found = false,
452 empty;
453
454 Always declare variables. Implied globals should not be used.
455
456 ## Function Declarations
457
458 Functions should be declared before they are used. When a function is not a method (not attached to an object) it should be defined using function declaration format (not function expression format nor using the `Function` constructor). There should be no space between the function name and the opening parentheses. There should be one space between the closing parentheses and the right brace. The right brace should be on the same line as the `function` keyword. There should be no space after the opening parentheses or before the closing parentheses. Named arguments should have a space after the comma but not before it. The function body should be indented one level.
459
460 // Good
461 function doSomething(arg1, arg2) {
462 return arg1 + arg2;
463 }
464
465 // Bad: Improper spacing of first line
466 function doSomething (arg1, arg2){
467 return arg1 + arg2;
468 }
469
470 // Bad: Function expression
471 var doSomething = function(arg1, arg2) {
472 return arg1 + arg2;
473 };
474
475 // Bad: Left brace on wrong line
476 function doSomething(arg1, arg2)
477 {
478 return arg1 + arg2;
479 }
480
481 // Bad: Using Function constructor
482 var doSomething = new Function("arg1", "arg2", "return arg1 + arg2");
483
484 Functions declared inside of other functions should be declared immediately after the `var` statement.
485
486 // Good
487 function outer() {
488
489 var count = 10,
490 name = "Nicholas",
491 found = false,
492 empty;
493
494 function inner() {
495 // code
496 }
497
498 // code that uses inner()
499 }
500
501 // Bad: Inner function declared before variables
502 function outer() {
503
504 function inner() {
505 // code
506 }
507
508 var count = 10,
509 name = "Nicholas",
510 found = false,
511 empty;
512
513 // code that uses inner()
514 }
515
516 Anonymous functions may be used for assignment of object methods or as arguments to other functions. There should be no space between the `function` keyword and the opening parentheses.
517
518 // Good
519 object.method = function() {
520 // code
521 };
522
523 // Bad: Incorrect spacing
524 object.method = function () {
525 // code
526 };
527
528 Immediately-invoked functions should surround the entire function call with parentheses.
529
530 // Good
531 var value = (function() {
532
533 // function body
534
535 return {
536 message: "Hi"
537 }
538 }());
539
540 // Bad: No parentheses around function call
541 var value = function() {
542
543 // function body
544
545 return {
546 message: "Hi"
547 }
548 }();
549
550 // Bad: Improper parentheses placement
551 var value = (function() {
552
553 // function body
554
555 return {
556 message: "Hi"
557 }
558 })();
559
560 ## Naming
561
562 Care should be taken to name variables and functions properly. Names should be limited to alphanumeric characters and, in some cases, the underscore character. Do not use the dollar sign (`$`) or back slash (`\`) characters in any names.
563
564 Variable names should be formatted in camel case with the first letter being lowercase and the first letter of each subsequent word being uppercase. The first word of a variable name should be a noun (not a verb) to avoid confusion with functions. Do not use underscore for variable names.
565
566 // Good
567 var accountNumber = "8401-1";
568
569 // Bad: Begins with uppercase letter
570 var AccountNumber = "8401-1";
571
572 // Bad: Begins with verb
573 var getAccountNumber = "8401-1";
574
575 // Bad: Uses underscore
576 var account_number = "8401-1";
577
578 Function names should also be formatted using camel case. The first word of a function name should be a verb (not a noun) to avoid confusion with variables. Do not use underscore for function names.
579
580 // Good
581 function doSomething() {
582 // code
583 }
584
585 // Bad: Begins with uppercase letter
586 function DoSomething() {
587 // code
588 }
589
590 // Bad: Begins with noun
591 function car() {
592 // code
593 }
594
595 // Bad: Uses underscores
596 function do_something() {
597 // code
598 }
599
600 Constructor functions, those functions used with the `new` operator to create new objects, should be formatted in camel case but must begin with an uppercase letter. Constructor function names should begin with a non-verb because `new` is the action of creating an object instance.
601
602 // Good
603 function MyObject() {
604 // code
605 }
606
607 // Bad: Begins with lowercase letter
608 function myObject() {
609 // code
610 }
611
612 // Bad: Uses underscores
613 function My_Object() {
614 // code
615 }
616
617 // Bad: Begins with verb
618 function getMyObject() {
619 // code
620 }
621
622 Variables that act as constants (values that won't be changed) should be formatted using all uppercase letters with words separated by a single underscore.
623
624 // Good
625 var TOTAL_COUNT = 10;
626
627 // Bad: Camel case
628 var totalCount = 10;
629
630 // Bad: Mixed case
631 var total_COUNT = 10;
632
633 Object properties follow the same naming conventions as variables. Object methods follow the same naming conventions as functions. If a property or method is meant to be private, then it should be prefixed with an underscore character.
634
635 // Good
636 var object = {
637 _count: 10,
638
639 _getCount: function () {
640 return this._count;
641 }
642 };
643
644 ## Strict Mode
645
646 Strict mode should be used in all modules, specified below the file overview comment and above everything else:
647
648 // Bad: Strict mode in functions
649 function doSomething() {
650 "use strict";
651
652 // code
653 }
654
655 // Bad: Strict mode in global scope and redundant strict mode directive in function
656 "use strict"; // This one is good
657
658 function doSomething() {
659 "use strict"; // This one is bad
660
661 // code
662 }
663
664 // Good: Global strict mode
665 "use strict";
666
667 function doSomething() {
668 // no "use strict" here
669
670 // code
671 }
672
673 ## Assignments
674
675 When assigning a value to a variable, use parentheses around a right-side expression that contains a comparison.
676
677 // Good
678 var flag = (i < count);
679
680 // Bad: Missing parentheses
681 var flag = i < count;
682
683 ## Equality Operators
684
685 Use `===` and `!==` instead of `==` and `!=`. This avoids type coercion errors.
686
687 // Good
688 var same = (a === b);
689
690 // Bad: Using ==
691 var same = (a == b);
692
693 ## Ternary Operator
694
695 The ternary operator should be used only for assigning values conditionally and never as a shortcut for an `if` statement.
696
697 // Good
698 var value = condition ? value1 : value2;
699
700 // Bad: no assignment, should be an if statement
701 condition ? doSomething() : doSomethingElse();
702
703 ## Statements
704
705 ### Simple Statements
706
707 Each line should contain at most one statement. All simple statements should end with a semicolon (`;`).
708
709 // Good
710 count++;
711 a = b;
712
713 // Bad: Multiple statements on one line
714 count++; a = b;
715
716 ### return Statement
717
718 A return statement with a value should not use parentheses unless they make the return value more obvious in some way. Example:
719
720 return;
721
722 return collection.size();
723
724 return (size > 0 ? size : defaultSize);
725
726 ### Compound Statements
727
728 Compound statements are lists of statements enclosed inside of braces.
729
730 * The enclosed statements should be indented one more level than the compound statement.
731 * The opening brace should be at the end of the line that begins the compound statement; the closing brace should begin a line and be indented to the beginning of the compound statement.
732 * Braces are used around all statements, even single statements, when they are part of a control structure, such as a `if` or `for` statement. This makes it easier to add statements without accidentally introducing bugs due to forgetting to add braces.
733 * The statement beginning keyword, such as `if`, should be followed by one space and the opening brace should be preceded by a space.
734
735 ### if Statement
736
737 The `if` class of statements should have the following form:
738
739 if (condition) {
740 statements
741 }
742
743 if (condition) {
744 statements
745 } else {
746 statements
747 }
748
749 if (condition) {
750 statements
751 } else if (condition) {
752 statements
753 } else {
754 statements
755 }
756
757 It is never permissible to omit the braces in any part of an `if` statement.
758
759 // Good
760 if (condition) {
761 doSomething();
762 }
763
764 // Bad: Improper spacing
765 if(condition){
766 doSomething();
767 }
768
769 // Bad: Missing braces
770 if (condition)
771 doSomething();
772
773 // Bad: All on one line
774 if (condition) { doSomething(); }
775
776 // Bad: All on one line without braces
777 if (condition) doSomething();
778
779 ### for Statement
780
781 The `for` class of statements should have the following form:
782
783 for (initialization; condition; update) {
784 statements
785 }
786
787 for (variable in object) {
788 statements
789 }
790
791 Variables should not be declared in the initialization section of a `for` statement.
792
793 // Good
794 var i,
795 len;
796
797 for (i=0, len=10; i < len; i++) {
798 // code
799 }
800
801 // Bad: Variables declared during initialization
802 for (var i=0, len=10; i < len; i++) {
803 // code
804 }
805
806 // Bad: Variables declared during initialization
807 for (var prop in object) {
808 // code
809 }
810
811 When using a `for-in` statement, double-check whether or not you need to use `hasOwnProperty()` to filter out object members.
812
813 ### while Statement
814
815 The `while` class of statements should have the following form:
816
817 while (condition) {
818 statements
819 }
820
821 ### do Statement
822
823 The `do` class of statements should have the following form:
824
825 do {
826 statements
827 } while (condition);
828
829 Note the use of a semicolon as the final part of this statement. There should be a space before and after the `while` keyword.
830
831 ### switch Statement
832
833 The `switch` class of statements should have the following form:
834
835 switch (expression) {
836 case expression:
837 statements
838
839 default:
840 statements
841 }
842
843 Each `case` is indented one level under the `switch`. Each `case` after the first, including `default`, should be preceded by a single empty line.
844
845 Each group of statements (except the default) should end with `break`, `return`, `throw`, or a comment indicating fall through.
846
847 // Good
848 switch (value) {
849 case 1:
850 /* falls through */
851
852 case 2:
853 doSomething();
854 break;
855
856 case 3:
857 return true;
858
859 default:
860 throw new Error("This shouldn't happen.);
861 }
862
863 If a `switch` doesn't have a `default` case, then it should be indicated with a comment.
864
865 // Good
866 switch (value) {
867 case 1:
868 /*falls through*/
869
870 case 2:
871 doSomething();
872 break;
873
874 case 3:
875 return true;
876
877 // no default
878 }
879
880 ### try Statement
881
882 The `try` class of statements should have the following form:
883
884 try {
885 statements
886 } catch (variable) {
887 statements
888 }
889
890 try {
891 statements
892 } catch (variable) {
893 statements
894 } finally {
895 statements
896 }
897
898 ## Whitespace
899
900 Blank lines improve readability by setting off sections of code that are logically related.
901
902 Two blank lines should always be used in the following circumstances:
903
904 * Between sections of a source file
905 * Between class and interface definitions
906
907 One blank line should always be used in the following circumstances:
908
909 * Between methods
910 * Between the local variables in a method and its first statement
911 * Before a multi-line or single-line comment
912 * Between logical sections inside a method to improve readability
913
914 Blank spaces should be used in the following circumstances:
915
916 * A keyword followed by a parenthesis should be separated by a space.
917 * A blank space should appear after commas in argument lists.
918 * All binary operators except dot (`.`) should be separated from their operands by spaces. Blank spaces should never separate unary operators such as unary minus, increment (`++`), and decrement (`--`) from their operands.
919 * The expressions in a `for` statement should be separated by blank spaces. Blank spaces should only be used after semicolons, not before.
920
921 ## Things to Avoid
922
923 * Never use the primitive wrapper types, such as `String`, to create new objects.
924 * Never use `eval()`.
925 * Never use the `with` statement. This statement isn't available in strict mode and likely won't be available in future ECMAScript editions.