Comparison

doc/coding_style.md @ 9939:3a7f822f6edd

doc/coding_style: apply consistent semi-colon usage Make all "good" statements in the coding style document use consistent statement-separator semi-colon
author marc0s <marcos@tenak.net>
date Sat, 30 Mar 2019 18:44:34 +0100
parent 9900:f2104b36f673
child 11000:d9aae4734f38
comparison
equal deleted inserted replaced
9938:4e8ba156738b 9939:3a7f822f6edd
11 11
12 ```lua 12 ```lua
13 for i, pkg in ipairs(packages) do 13 for i, pkg in ipairs(packages) do
14 for name, version in pairs(pkg) do 14 for name, version in pairs(pkg) do
15 if name == searched then 15 if name == searched then
16 print(version) 16 print(version);
17 end 17 end
18 end 18 end
19 end 19 end
20 ``` 20 ```
21 21
67 67
68 * Use `_` for ignored variables (e.g. in for loops:) 68 * Use `_` for ignored variables (e.g. in for loops:)
69 69
70 ```lua 70 ```lua
71 for _, item in ipairs(items) do 71 for _, item in ipairs(items) do
72 do_something_with_item(item) 72 do_something_with_item(item);
73 end 73 end
74 ``` 74 ```
75 75
76 * Generally all identifiers (variables and function names) should use `snake_case`, 76 * Generally all identifiers (variables and function names) should use `snake_case`,
77 i.e. lowercase words joined by `_`. 77 i.e. lowercase words joined by `_`.
83 local c = function() 83 local c = function()
84 -- ...stuff... 84 -- ...stuff...
85 end 85 end
86 86
87 -- good 87 -- good
88 local this_is_my_object = {} 88 local this_is_my_object = {};
89 89
90 local function do_that_thing() 90 local function do_that_thing()
91 -- ...stuff... 91 -- ...stuff...
92 end 92 end
93 ``` 93 ```
111 return alignment < 100 111 return alignment < 100
112 end 112 end
113 113
114 -- good 114 -- good
115 local function is_evil(alignment) 115 local function is_evil(alignment)
116 return alignment < 100 116 return alignment < 100;
117 end 117 end
118 ``` 118 ```
119 119
120 * `UPPER_CASE` is to be used sparingly, with "constants" only. 120 * `UPPER_CASE` is to be used sparingly, with "constants" only.
121 121
128 ## Tables 128 ## Tables
129 129
130 * When creating a table, prefer populating its fields all at once, if possible: 130 * When creating a table, prefer populating its fields all at once, if possible:
131 131
132 ```lua 132 ```lua
133 local player = { name = "Jack", class = "Rogue" } 133 local player = { name = "Jack", class = "Rogue" };
134 ``` 134 ```
135 135
136 * Items should be separated by commas. If there are many items, put each 136 * Items should be separated by commas. If there are many items, put each
137 key/value on a separate line and use a semi-colon after each item (including 137 key/value on a separate line and use a semi-colon after each item (including
138 the last one): 138 the last one):
143 class = "Rogue"; 143 class = "Rogue";
144 } 144 }
145 ``` 145 ```
146 146
147 > **Rationale:** This makes the structure of your tables more evident at a glance. 147 > **Rationale:** This makes the structure of your tables more evident at a glance.
148 Trailing commas make it quicker to add new fields and produces shorter diffs. 148 Trailing semi-colons make it quicker to add new fields and produces shorter diffs.
149 149
150 * Use plain `key` syntax whenever possible, use `["key"]` syntax when using names 150 * Use plain `key` syntax whenever possible, use `["key"]` syntax when using names
151 that can't be represented as identifiers and avoid mixing representations in 151 that can't be represented as identifiers and avoid mixing representations in
152 a declaration: 152 a declaration:
153 153
154 ```lua 154 ```lua
155 local mytable = { 155 local mytable = {
156 ["1394-E"] = val1, 156 ["1394-E"] = val1;
157 ["UTF-8"] = val2, 157 ["UTF-8"] = val2;
158 ["and"] = val2, 158 ["and"] = val2;
159 } 159 }
160 ``` 160 ```
161 161
162 ## Strings 162 ## Strings
163 163
164 * Use `"double quotes"` for strings; use `'single quotes'` when writing strings 164 * Use `"double quotes"` for strings; use `'single quotes'` when writing strings
165 that contain double quotes. 165 that contain double quotes.
166 166
167 ```lua 167 ```lua
168 local name = "Prosody" 168 local name = "Prosody";
169 local sentence = 'The name of the program is "Prosody"' 169 local sentence = 'The name of the program is "Prosody"';
170 ``` 170 ```
171 171
172 > **Rationale:** Double quotes are used as string delimiters in a larger number of 172 > **Rationale:** Double quotes are used as string delimiters in a larger number of
173 programming languages. Single quotes are useful for avoiding escaping when 173 programming languages. Single quotes are useful for avoiding escaping when
174 using double quotes in literals. 174 using double quotes in literals.
216 end 216 end
217 217
218 -- good 218 -- good
219 local function is_good_name(name, options, args) 219 local function is_good_name(name, options, args)
220 if #name < 3 or #name > 30 then 220 if #name < 3 or #name > 30 then
221 return false 221 return false;
222 end 222 end
223 223
224 -- ...stuff... 224 -- ...stuff...
225 225
226 return true 226 return true;
227 end 227 end
228 ``` 228 ```
229 229
230 ## Function calls 230 ## Function calls
231 231
234 234
235 ```lua 235 ```lua
236 -- bad 236 -- bad
237 local data = get_data"KRP"..tostring(area_number) 237 local data = get_data"KRP"..tostring(area_number)
238 -- good 238 -- good
239 local data = get_data("KRP"..tostring(area_number)) 239 local data = get_data("KRP"..tostring(area_number));
240 local data = get_data("KRP")..tostring(area_number) 240 local data = get_data("KRP")..tostring(area_number);
241 ``` 241 ```
242 242
243 > **Rationale:** It is not obvious at a glace what the precedence rules are 243 > **Rationale:** It is not obvious at a glace what the precedence rules are
244 when omitting the parentheses in a function call. Can you quickly tell which 244 when omitting the parentheses in a function call. Can you quickly tell which
245 of the two "good" examples in equivalent to the "bad" one? (It's the second 245 of the two "good" examples in equivalent to the "bad" one? (It's the second
249 argument on a single line. You may do so for table arguments that span several 249 argument on a single line. You may do so for table arguments that span several
250 lines. 250 lines.
251 251
252 ```lua 252 ```lua
253 local an_instance = a_module.new { 253 local an_instance = a_module.new {
254 a_parameter = 42, 254 a_parameter = 42;
255 another_parameter = "yay", 255 another_parameter = "yay";
256 } 256 }
257 ``` 257 ```
258 258
259 > **Rationale:** The use as in `a_module.new` above occurs alone in a statement, 259 > **Rationale:** The use as in `a_module.new` above occurs alone in a statement,
260 so there are no precedence issues. 260 so there are no precedence issues.
263 263
264 * Use dot notation when accessing known properties. 264 * Use dot notation when accessing known properties.
265 265
266 ```lua 266 ```lua
267 local luke = { 267 local luke = {
268 jedi = true, 268 jedi = true;
269 age = 28, 269 age = 28;
270 } 270 }
271 271
272 -- bad 272 -- bad
273 local is_jedi = luke["jedi"] 273 local is_jedi = luke["jedi"]
274 274
275 -- good 275 -- good
276 local is_jedi = luke.jedi 276 local is_jedi = luke.jedi;
277 ``` 277 ```
278 278
279 * Use subscript notation `[]` when accessing properties with a variable or if using a table as a list. 279 * Use subscript notation `[]` when accessing properties with a variable or if using a table as a list.
280 280
281 ```lua 281 ```lua
282 local vehicles = load_vehicles_from_disk("vehicles.dat") 282 local vehicles = load_vehicles_from_disk("vehicles.dat")
283 283
284 if vehicles["Porsche"] then 284 if vehicles["Porsche"] then
285 porsche_handler(vehicles["Porsche"]) 285 porsche_handler(vehicles["Porsche"]);
286 vehicles["Porsche"] = nil 286 vehicles["Porsche"] = nil;
287 end 287 end
288 for name, cars in pairs(vehicles) do 288 for name, cars in pairs(vehicles) do
289 regular_handler(cars) 289 regular_handler(cars);
290 end 290 end
291 ``` 291 ```
292 292
293 > **Rationale:** Using dot notation makes it clearer that the given key is meant 293 > **Rationale:** Using dot notation makes it clearer that the given key is meant
294 to be used as a record/object field. 294 to be used as a record/object field.
296 ## Functions in tables 296 ## Functions in tables
297 297
298 * When declaring modules and classes, declare functions external to the table definition: 298 * When declaring modules and classes, declare functions external to the table definition:
299 299
300 ```lua 300 ```lua
301 local my_module = {} 301 local my_module = {};
302 302
303 function my_module.a_function(x) 303 function my_module.a_function(x)
304 -- code 304 -- code
305 end 305 end
306 ``` 306 ```
335 ```lua 335 ```lua
336 -- bad 336 -- bad
337 superpower = get_superpower() 337 superpower = get_superpower()
338 338
339 -- good 339 -- good
340 local superpower = get_superpower() 340 local superpower = get_superpower();
341 ``` 341 ```
342 342
343 > **Rationale:** Not doing so will result in global variables to avoid polluting 343 > **Rationale:** Not doing so will result in global variables to avoid polluting
344 the global namespace. 344 the global namespace.
345 345
364 return name 364 return name
365 end 365 end
366 366
367 -- good 367 -- good
368 local bad = function() 368 local bad = function()
369 test() 369 test();
370 print("doing stuff..") 370 print("doing stuff..");
371 371
372 --...other stuff... 372 --...other stuff...
373 373
374 local name = get_name() 374 local name = get_name();
375 375
376 if name == "test" then 376 if name == "test" then
377 return false 377 return false;
378 end 378 end
379 379
380 return name 380 return name;
381 end 381 end
382 ``` 382 ```
383 383
384 > **Rationale:** Lua has proper lexical scoping. Declaring the function later means that its 384 > **Rationale:** Lua has proper lexical scoping. Declaring the function later means that its
385 scope is smaller, so this makes it easier to check for the effects of a variable. 385 scope is smaller, so this makes it easier to check for the effects of a variable.
408 easier to scan visually: 408 easier to scan visually:
409 409
410 ```lua 410 ```lua
411 local function default_name(name) 411 local function default_name(name)
412 -- return the default "Waldo" if name is nil 412 -- return the default "Waldo" if name is nil
413 return name or "Waldo" 413 return name or "Waldo";
414 end 414 end
415 415
416 local function brew_coffee(machine) 416 local function brew_coffee(machine)
417 return (machine and machine.is_loaded) and "coffee brewing" or "fill your water" 417 return (machine and machine.is_loaded) and "coffee brewing" or "fill your water";
418 end 418 end
419 ``` 419 ```
420 420
421 Note that the `x and y or z` as a substitute for `x ? y : z` does not work if 421 Note that the `x and y or z` as a substitute for `x ? y : z` does not work if
422 `y` may be `nil` or `false` so avoid it altogether for returning booleans or 422 `y` may be `nil` or `false` so avoid it altogether for returning booleans or
432 432
433 -- good 433 -- good
434 if not ok then return nil, "this failed for this reason: " .. reason end 434 if not ok then return nil, "this failed for this reason: " .. reason end
435 435
436 -- good 436 -- good
437 use_callback(x, function(k) return k.last end) 437 use_callback(x, function(k) return k.last end);
438 438
439 -- good 439 -- good
440 if test then 440 if test then
441 return false 441 return false
442 end 442 end
444 -- bad 444 -- bad
445 if test < 1 and do_complicated_function(test) == false or seven == 8 and nine == 10 then do_other_complicated_function() end 445 if test < 1 and do_complicated_function(test) == false or seven == 8 and nine == 10 then do_other_complicated_function() end
446 446
447 -- good 447 -- good
448 if test < 1 and do_complicated_function(test) == false or seven == 8 and nine == 10 then 448 if test < 1 and do_complicated_function(test) == false or seven == 8 and nine == 10 then
449 do_other_complicated_function() 449 do_other_complicated_function();
450 return false 450 return false;
451 end 451 end
452 ``` 452 ```
453 453
454 * Separate statements onto multiple lines. Use semicolons as statement terminators. 454 * Separate statements onto multiple lines. Use semicolons as statement terminators.
455 455
489 age="1 year", 489 age="1 year",
490 breed="Bernese Mountain Dog" 490 breed="Bernese Mountain Dog"
491 }) 491 })
492 492
493 -- good 493 -- good
494 local x = y * 9 494 local x = y * 9;
495 local numbers = {1, 2, 3} 495 local numbers = {1, 2, 3};
496 local strings = { 496 local strings = {
497 "hello"; 497 "hello";
498 "Lua"; 498 "Lua";
499 "world"; 499 "world";
500 } 500 }
501 dog.set("attr", { 501 dog.set("attr", {
502 age = "1 year", 502 age = "1 year";
503 breed = "Bernese Mountain Dog", 503 breed = "Bernese Mountain Dog";
504 }) 504 });
505 ``` 505 ```
506 506
507 * Indent tables and functions according to the start of the line, not the construct: 507 * Indent tables and functions according to the start of the line, not the construct:
508 508
509 ```lua 509 ```lua
520 local my_table = { 520 local my_table = {
521 "hello"; 521 "hello";
522 "world"; 522 "world";
523 } 523 }
524 using_a_callback(x, function(...) 524 using_a_callback(x, function(...)
525 print("hello") 525 print("hello");
526 end) 526 end)
527 ``` 527 ```
528 528
529 > **Rationale:** This keep indentation levels aligned at predictable places. You don't 529 > **Rationale:** This keep indentation levels aligned at predictable places. You don't
530 need to realign the entire block if something in the first line changes (such as 530 need to realign the entire block if something in the first line changes (such as
532 532
533 * The concatenation operator gets a pass for avoiding spaces: 533 * The concatenation operator gets a pass for avoiding spaces:
534 534
535 ```lua 535 ```lua
536 -- okay 536 -- okay
537 local message = "Hello, "..user.."! This is your day # "..day.." in our platform!" 537 local message = "Hello, "..user.."! This is your day # "..day.." in our platform!";
538 ``` 538 ```
539 539
540 > **Rationale:** Being at the baseline, the dots already provide some visual spacing. 540 > **Rationale:** Being at the baseline, the dots already provide some visual spacing.
541 541
542 * No spaces after the name of a function in a declaration or in its arguments: 542 * No spaces after the name of a function in a declaration or in its arguments:
580 -- bad 580 -- bad
581 local a = 1 581 local a = 1
582 local long_identifier = 2 582 local long_identifier = 2
583 583
584 -- good 584 -- good
585 local a = 1 585 local a = 1;
586 local long_identifier = 2 586 local long_identifier = 2;
587 ``` 587 ```
588 588
589 > **Rationale:** This produces extra diffs which add noise to `git blame`. 589 > **Rationale:** This produces extra diffs which add noise to `git blame`.
590 590
591 * Alignment is occasionally useful when logical correspondence is to be highlighted: 591 * Alignment is occasionally useful when logical correspondence is to be highlighted:
592 592
593 ```lua 593 ```lua
594 -- okay 594 -- okay
595 sys_command(form, UI_FORM_UPDATE_NODE, "a", FORM_NODE_HIDDEN, false) 595 sys_command(form, UI_FORM_UPDATE_NODE, "a", FORM_NODE_HIDDEN, false);
596 sys_command(form, UI_FORM_UPDATE_NODE, "sample", FORM_NODE_VISIBLE, false) 596 sys_command(form, UI_FORM_UPDATE_NODE, "sample", FORM_NODE_VISIBLE, false);
597 ``` 597 ```
598 598
599 ## Typing 599 ## Typing
600 600
601 * In non-performance critical code, it can be useful to add type-checking assertions 601 * In non-performance critical code, it can be useful to add type-checking assertions
602 for function arguments: 602 for function arguments:
603 603
604 ```lua 604 ```lua
605 function manif.load_manifest(repo_url, lua_version) 605 function manif.load_manifest(repo_url, lua_version)
606 assert(type(repo_url) == "string") 606 assert(type(repo_url) == "string");
607 assert(type(lua_version) == "string" or not lua_version) 607 assert(type(lua_version) == "string" or not lua_version);
608 608
609 -- ... 609 -- ...
610 end 610 end
611 ``` 611 ```
612 612
615 ```lua 615 ```lua
616 -- bad 616 -- bad
617 local total_score = review_score .. "" 617 local total_score = review_score .. ""
618 618
619 -- good 619 -- good
620 local total_score = tostring(review_score) 620 local total_score = tostring(review_score);
621 ``` 621 ```
622 622
623 ## Errors 623 ## Errors
624 624
625 * Functions that can fail for reasons that are expected (e.g. I/O) should 625 * Functions that can fail for reasons that are expected (e.g. I/O) should
634 Follow [these guidelines](http://hisham.hm/2014/01/02/how-to-write-lua-modules-in-a-post-module-world/) for writing modules. In short: 634 Follow [these guidelines](http://hisham.hm/2014/01/02/how-to-write-lua-modules-in-a-post-module-world/) for writing modules. In short:
635 635
636 * Always require a module into a local variable named after the last component of the module’s full name. 636 * Always require a module into a local variable named after the last component of the module’s full name.
637 637
638 ```lua 638 ```lua
639 local bar = require("foo.bar") -- requiring the module 639 local bar = require("foo.bar"); -- requiring the module
640 640
641 bar.say("hello") -- using the module 641 bar.say("hello"); -- using the module
642 ``` 642 ```
643 643
644 * Don’t rename modules arbitrarily: 644 * Don’t rename modules arbitrarily:
645 645
646 ```lua 646 ```lua
655 name that will be used to require it. You may use an LDoc comment to identify 655 name that will be used to require it. You may use an LDoc comment to identify
656 the whole module path. 656 the whole module path.
657 657
658 ```lua 658 ```lua
659 --- @module foo.bar 659 --- @module foo.bar
660 local bar = {} 660 local bar = {};
661 ``` 661 ```
662 662
663 * Try to use names that won't clash with your local variables. For instance, don't 663 * Try to use names that won't clash with your local variables. For instance, don't
664 name your module something like “size”. 664 name your module something like “size”.
665 665
670 670
671 * Public functions are declared in the module table, with dot syntax: 671 * Public functions are declared in the module table, with dot syntax:
672 672
673 ```lua 673 ```lua
674 function bar.say(greeting) 674 function bar.say(greeting)
675 print(greeting) 675 print(greeting);
676 end 676 end
677 ``` 677 ```
678 678
679 > **Rationale:** Visibility rules are made explicit through syntax. 679 > **Rationale:** Visibility rules are made explicit through syntax.
680 680
700 700
701 and do something like this instead: 701 and do something like this instead:
702 702
703 ```lua 703 ```lua
704 -- good 704 -- good
705 local messagepack = require("messagepack") 705 local messagepack = require("messagepack");
706 local mpack = messagepack.new({integer = "unsigned"}) 706 local mpack = messagepack.new({integer = "unsigned"});
707 ``` 707 ```
708 708
709 * The invocation of require may omit parentheses around the module name: 709 * The invocation of require may omit parentheses around the module name:
710 710
711 ```lua 711 ```lua
712 local bla = require "bla" 712 local bla = require "bla";
713 ``` 713 ```
714 714
715 ## Metatables, classes and objects 715 ## Metatables, classes and objects
716 716
717 If creating a new type of object that has a metatable and methods, the 717 If creating a new type of object that has a metatable and methods, the
737 ``` 737 ```
738 -- bad 738 -- bad
739 my_object.my_method(my_object) 739 my_object.my_method(my_object)
740 740
741 -- good 741 -- good
742 my_object:my_method() 742 my_object:my_method();
743 ``` 743 ```
744 744
745 > **Rationale:** This makes it explicit that the intent is to use the function as a method. 745 > **Rationale:** This makes it explicit that the intent is to use the function as a method.
746 746
747 * Do not rely on the `__gc` metamethod to release resources other than memory. 747 * Do not rely on the `__gc` metamethod to release resources other than memory.
778 reasons (e.g. a callback that follows a given format) but doesn't use some of 778 reasons (e.g. a callback that follows a given format) but doesn't use some of
779 its arguments; it's better to spell out in the argument what the API the 779 its arguments; it's better to spell out in the argument what the API the
780 function implements is, instead of adding `_` variables. 780 function implements is, instead of adding `_` variables.
781 781
782 ``` 782 ```
783 local foo, bar = some_function() --luacheck: ignore 212/foo 783 local foo, bar = some_function(); --luacheck: ignore 212/foo
784 print(bar) 784 print(bar);
785 ``` 785 ```
786 786
787 * luacheck warning 542 (empty if branch) can also be ignored, when a sequence 787 * luacheck warning 542 (empty if branch) can also be ignored, when a sequence
788 of `if`/`elseif`/`else` blocks implements a "switch/case"-style list of cases, 788 of `if`/`elseif`/`else` blocks implements a "switch/case"-style list of cases,
789 and one of the cases is meant to mean "pass". For example: 789 and one of the cases is meant to mean "pass". For example:
790 790
791 ```lua 791 ```lua
792 if warning >= 600 and warning <= 699 then 792 if warning >= 600 and warning <= 699 then
793 print("no whitespace warnings") 793 print("no whitespace warnings");
794 elseif warning == 542 then --luacheck: ignore 542 794 elseif warning == 542 then --luacheck: ignore 542
795 -- pass 795 -- pass
796 else 796 else
797 print("got a warning: "..warning) 797 print("got a warning: "..warning);
798 end 798 end
799 ``` 799 ```
800 800
801 > **Rationale:** This avoids writing negated conditions in the final fallback 801 > **Rationale:** This avoids writing negated conditions in the final fallback
802 case, and it's easy to add another case to the construct without having to 802 case, and it's easy to add another case to the construct without having to