Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733
  1. # Lua Style Guide
  2. This style guide contains a list of guidelines that we try to follow for Rspamd.
  3. This guide is forked from https://github.com/Olivine-Labs/lua-style-guide
  4. ## <a name='TOC'>Table of Contents</a>
  5. 1. [Types](#types)
  6. 1. [Tables](#tables)
  7. 1. [Strings](#strings)
  8. 1. [Functions](#functions)
  9. 1. [Properties](#properties)
  10. 1. [Variables](#variables)
  11. 1. [Conditional Expressions & Equality](#conditionals)
  12. 1. [Blocks](#blocks)
  13. 1. [Whitespace](#whitespace)
  14. 1. [Commas](#commas)
  15. 1. [Semicolons](#semicolons)
  16. 1. [Type Casting & Coercion](#type-coercion)
  17. 1. [Naming Conventions](#naming-conventions)
  18. 1. [Accessors](#accessors)
  19. 1. [Constructors](#constructors)
  20. 1. [Modules](#modules)
  21. 1. [Testing](#testing)
  22. 1. [License](#license)
  23. ## <a name='types'>Types</a>
  24. - **Primitives**: When you access a primitive type you work directly on its value
  25. + `string`
  26. + `number`
  27. + `boolean`
  28. + `nil`
  29. ```lua
  30. local foo = 1
  31. local bar = foo
  32. bar = 9
  33. print(foo, bar) -- => 1 9
  34. ```
  35. - **Complex**: When you access a complex type you work on a reference to its value
  36. + `table`
  37. + `function`
  38. + `userdata`
  39. ```lua
  40. local foo = { 1, 2 }
  41. local bar = foo
  42. bar[0] = 9
  43. foo[1] = 3
  44. print(foo[0], bar[0]) -- => 9 9
  45. print(foo[1], bar[1]) -- => 3 3
  46. print(foo[2], bar[2]) -- => 2 2
  47. ```
  48. **[[⬆]](#TOC)**
  49. ## <a name='tables'>Tables</a>
  50. - Use the constructor syntax for table property creation where possible.
  51. ```lua
  52. -- bad
  53. local player = {}
  54. player.name = 'Jack'
  55. player.class = 'Rogue'
  56. -- good
  57. local player = {
  58. name = 'Jack',
  59. class = 'Rogue'
  60. }
  61. ```
  62. - Define functions externally to table definition.
  63. ```lua
  64. -- bad
  65. local player = {
  66. attack = function()
  67. -- ...stuff...
  68. end
  69. }
  70. -- good
  71. local function attack()
  72. end
  73. local player = {
  74. attack = attack
  75. }
  76. ```
  77. **[[⬆]](#TOC)**
  78. ## <a name='strings'>Strings</a>
  79. - Use single quotes `''` for strings.
  80. ```lua
  81. -- bad
  82. local name = "Bob Parr"
  83. -- good
  84. local name = 'Bob Parr'
  85. -- bad
  86. local fullName = "Bob " .. self.lastName
  87. -- good
  88. local fullName = 'Bob ' .. self.lastName
  89. ```
  90. - Strings longer than 80 characters should be written across multiple lines
  91. using concatenation. This allows you to indent nicely.
  92. ```lua
  93. -- bad
  94. local errorMessage = 'This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.'
  95. -- bad
  96. local errorMessage = 'This is a super long error that \
  97. was thrown because of Batman. \
  98. When you stop to think about \
  99. how Batman had anything to do \
  100. with this, you would get nowhere \
  101. fast.'
  102. -- bad
  103. local errorMessage = [[This is a super long error that
  104. was thrown because of Batman.
  105. When you stop to think about
  106. how Batman had anything to do
  107. with this, you would get nowhere
  108. fast.]]
  109. -- good
  110. local errorMessage = 'This is a super long error that ' ..
  111. 'was thrown because of Batman. ' ..
  112. 'When you stop to think about ' ..
  113. 'how Batman had anything to do ' ..
  114. 'with this, you would get nowhere ' ..
  115. 'fast.'
  116. ```
  117. **[[⬆]](#TOC)**
  118. ## <a name='functions'>Functions</a>
  119. - Prefer lots of small functions to large, complex functions. [Smalls Functions Are Good For The Universe](http://kikito.github.io/blog/2012/03/16/small-functions-are-good-for-the-universe/).
  120. - Prefer function syntax over variable syntax. This helps differentiate
  121. between named and anonymous functions.
  122. ```lua
  123. -- bad
  124. local nope = function(name, options)
  125. -- ...stuff...
  126. end
  127. -- good
  128. local function yup(name, options)
  129. -- ...stuff...
  130. end
  131. ```
  132. - Never name a parameter `arg`, this will take precendence over the `arg` object that is given to every function scope in older versions of Lua.
  133. ```lua
  134. -- bad
  135. local function nope(name, options, arg)
  136. -- ...stuff...
  137. end
  138. -- good
  139. local function yup(name, options, ...)
  140. -- ...stuff...
  141. end
  142. ```
  143. - Perform validation early and return as early as possible.
  144. ```lua
  145. -- bad
  146. local is_good_name = function(name, options, arg)
  147. local is_good = #name > 3
  148. is_good = is_good and #name < 30
  149. -- ...stuff...
  150. return is_bad
  151. end
  152. -- good
  153. local is_good_name = function(name, options, args)
  154. if #name < 3 or #name > 30 then return false end
  155. -- ...stuff...
  156. return true
  157. end
  158. ```
  159. **[[⬆]](#TOC)**
  160. ## <a name='properties'>Properties</a>
  161. - Use dot notation when accessing known properties.
  162. ```lua
  163. local luke = {
  164. jedi = true,
  165. age = 28
  166. }
  167. -- bad
  168. local isJedi = luke['jedi']
  169. -- good
  170. local isJedi = luke.jedi
  171. ```
  172. - Use subscript notation `[]` when accessing properties with a variable
  173. or if using a table as a list.
  174. ```lua
  175. local luke = {
  176. jedi = true,
  177. age = 28
  178. }
  179. local function getProp(prop)
  180. return luke[prop]
  181. end
  182. local isJedi = getProp('jedi')
  183. ```
  184. **[[⬆]](#TOC)**
  185. ## <a name='variables'>Variables</a>
  186. - Always use `local` to declare variables. Not doing so will result in
  187. global variables to avoid polluting the global namespace.
  188. ```lua
  189. -- bad
  190. superPower = SuperPower()
  191. -- good
  192. local superPower = SuperPower()
  193. ```
  194. - Assign variables at the top of their scope where possible. This makes it
  195. easier to check for existing variables.
  196. ```lua
  197. -- bad
  198. local bad = function()
  199. test()
  200. print('doing stuff..')
  201. //..other stuff..
  202. local name = getName()
  203. if name == 'test' then
  204. return false
  205. end
  206. return name
  207. end
  208. -- good
  209. local function good()
  210. local name = getName()
  211. test()
  212. print('doing stuff..')
  213. //..other stuff..
  214. if name == 'test' then
  215. return false
  216. end
  217. return name
  218. end
  219. ```
  220. **[[⬆]](#TOC)**
  221. ## <a name='conditionals'>Conditional Expressions & Equality</a>
  222. - False and nil are *falsy* in conditional expressions. All else is true.
  223. ```lua
  224. local str = ''
  225. if str then
  226. -- true
  227. end
  228. ```
  229. - Use shortcuts when you can, unless you need to know the difference between
  230. false and nil.
  231. ```lua
  232. -- bad
  233. if name ~= nil then
  234. -- ...stuff...
  235. end
  236. -- good
  237. if name then
  238. -- ...stuff...
  239. end
  240. ```
  241. - Prefer *true* statements over *false* statements where it makes sense.
  242. Prioritize truthy conditions when writing multiple conditions.
  243. ```lua
  244. --bad
  245. if not thing then
  246. -- ...stuff...
  247. else
  248. -- ...stuff...
  249. end
  250. --good
  251. if thing then
  252. -- ...stuff...
  253. else
  254. -- ...stuff...
  255. end
  256. ```
  257. - Prefer defaults to `else` statements where it makes sense. This results in
  258. less complex and safer code at the expense of variable reassignment, so
  259. situations may differ.
  260. ```lua
  261. --bad
  262. local function full_name(first, last)
  263. local name
  264. if first and last then
  265. name = first .. ' ' .. last
  266. else
  267. name = 'John Smith'
  268. end
  269. return name
  270. end
  271. --good
  272. local function full_name(first, last)
  273. local name = 'John Smith'
  274. if first and last then
  275. name = first .. ' ' .. last
  276. end
  277. return name
  278. end
  279. ```
  280. - Short ternaries are okay.
  281. ```lua
  282. local function default_name(name)
  283. -- return the default 'Waldo' if name is nil
  284. return name or 'Waldo'
  285. end
  286. local function brew_coffee(machine)
  287. return machine and machine.is_loaded and 'coffee brewing' or 'fill your water'
  288. end
  289. ```
  290. **[[⬆]](#TOC)**
  291. ## <a name='blocks'>Blocks</a>
  292. - Single line blocks are okay for *small* statements. Try to keep lines to 80 characters.
  293. Indent lines if they overflow past the limit.
  294. ```lua
  295. -- good
  296. if test then return false end
  297. -- good
  298. if test then
  299. return false
  300. end
  301. -- bad
  302. if test < 1 and do_complicated_function(test) == false or seven == 8 and nine == 10 then do_other_complicated_function()end
  303. -- good
  304. if test < 1 and do_complicated_function(test) == false or
  305. seven == 8 and nine == 10 then
  306. do_other_complicated_function()
  307. return false
  308. end
  309. ```
  310. **[[⬆]](#TOC)**
  311. ## <a name='whitespace'>Whitespace</a>
  312. - Use soft tabs set to 2 spaces.
  313. ```lua
  314. -- bad
  315. function()
  316. ∙∙∙∙local name
  317. end
  318. -- bad
  319. function()
  320. ∙local name
  321. end
  322. -- good
  323. function()
  324. ∙∙local name
  325. end
  326. ```
  327. - Place 1 space before opening and closing braces. Place no spaces around parens.
  328. ```lua
  329. -- bad
  330. local test = {one=1}
  331. -- good
  332. local test = { one = 1 }
  333. -- bad
  334. dog.set('attr',{
  335. age = '1 year',
  336. breed = 'Bernese Mountain Dog'
  337. })
  338. -- good
  339. dog.set('attr', {
  340. age = '1 year',
  341. breed = 'Bernese Mountain Dog'
  342. })
  343. ```
  344. - Place an empty newline at the end of the file.
  345. ```lua
  346. -- bad
  347. (function(global)
  348. -- ...stuff...
  349. end)(self)
  350. ```
  351. ```lua
  352. -- good
  353. (function(global)
  354. -- ...stuff...
  355. end)(self)
  356. ```
  357. - Surround operators with spaces.
  358. ```lua
  359. -- bad
  360. local thing=1
  361. thing = thing-1
  362. thing = thing*1
  363. thing = 'string'..'s'
  364. -- good
  365. local thing = 1
  366. thing = thing - 1
  367. thing = thing * 1
  368. thing = 'string' .. 's'
  369. ```
  370. - Use one space after commas.
  371. ```lua
  372. --bad
  373. local thing = {1,2,3}
  374. thing = {1 , 2 , 3}
  375. thing = {1 ,2 ,3}
  376. --good
  377. local thing = {1, 2, 3}
  378. ```
  379. - Add a line break after multiline blocks.
  380. ```lua
  381. --bad
  382. if thing then
  383. -- ...stuff...
  384. end
  385. function derp()
  386. -- ...stuff...
  387. end
  388. local wat = 7
  389. --good
  390. if thing then
  391. -- ...stuff...
  392. end
  393. function derp()
  394. -- ...stuff...
  395. end
  396. local wat = 7
  397. ```
  398. - Delete unnecessary whitespace at the end of lines.
  399. **[[⬆]](#TOC)**
  400. ## <a name='commas'>Commas</a>
  401. - Leading commas aren't okay. An ending comma on the last item is okay but discouraged.
  402. ```lua
  403. -- bad
  404. local thing = {
  405. once = 1
  406. , upon = 2
  407. , aTime = 3
  408. }
  409. -- good
  410. local thing = {
  411. once = 1,
  412. upon = 2,
  413. aTime = 3
  414. }
  415. -- okay
  416. local thing = {
  417. once = 1,
  418. upon = 2,
  419. aTime = 3,
  420. }
  421. ```
  422. **[[⬆]](#TOC)**
  423. ## <a name='semicolons'>Semicolons</a>
  424. - **Nope.** Separate statements onto multiple lines.
  425. ```lua
  426. -- bad
  427. local whatever = 'sure';
  428. a = 1; b = 2
  429. -- good
  430. local whatever = 'sure'
  431. a = 1
  432. b = 2
  433. ```
  434. **[[⬆]](#TOC)**
  435. ## <a name='type-coercion'>Type Casting & Coercion</a>
  436. - Perform type coercion at the beginning of the statement. Use the built-in functions. (`tostring`, `tonumber`, etc.)
  437. - Use `tostring` for strings if you need to cast without string concatenation.
  438. ```lua
  439. -- bad
  440. local totalScore = reviewScore .. ''
  441. -- good
  442. local totalScore = tostring(reviewScore)
  443. ```
  444. - Use `tonumber` for Numbers.
  445. ```lua
  446. local inputValue = '4'
  447. -- bad
  448. local val = inputValue * 1
  449. -- good
  450. local val = tonumber(inputValue)
  451. ```
  452. **[[⬆]](#TOC)**
  453. ## <a name='naming-conventions'>Naming Conventions</a>
  454. - Avoid single letter names. Be descriptive with your naming. You can get
  455. away with single-letter names when they are variables in loops.
  456. ```lua
  457. -- bad
  458. local function q()
  459. -- ...stuff...
  460. end
  461. -- good
  462. local function query()
  463. -- ..stuff..
  464. end
  465. ```
  466. - Use underscores for ignored variables in loops.
  467. ```lua
  468. --good
  469. for _, name in pairs(names) do
  470. -- ...stuff...
  471. end
  472. ```
  473. - Use snake_case when naming objects, functions, and instances. Tend towards
  474. verbosity if unsure about naming.
  475. ```lua
  476. -- bad
  477. local OBJEcttsssss = {}
  478. local thisIsMyObject = {}
  479. local c = function()
  480. -- ...stuff...
  481. end
  482. -- good
  483. local this_is_my_object = {}
  484. local function do_that_thing()
  485. -- ...stuff...
  486. end
  487. ```
  488. - Use PascalCase for factories.
  489. ```lua
  490. -- bad
  491. local player = require('player')
  492. -- good
  493. local Player = require('player')
  494. local me = Player({ name = 'Jack' })
  495. ```
  496. **[[⬆]](#TOC)**
  497. - Use `is` or `has` for boolean-returning functions that are part of tables.
  498. ```lua
  499. --bad
  500. local function evil(alignment)
  501. return alignment < 100
  502. end
  503. --good
  504. local function is_evil(alignment)
  505. return alignment < 100
  506. end
  507. ```
  508. ## <a name='modules'>Modules</a>
  509. - The module should return a table or function.
  510. - The module should not use the global namespace for anything ever. The
  511. module should be a closure.
  512. - The file should be named like the module.
  513. ```lua
  514. -- thing.lua
  515. local thing = { }
  516. local meta = {
  517. __call = function(self, key, vars)
  518. print key
  519. end
  520. }
  521. return setmetatable(thing, meta)
  522. ```
  523. - Note that modules are [loaded as singletons](http://lua-users.org/wiki/TheEssenceOfLoadingCode)
  524. and therefore should usually be factories (a function returning a new instance of a table)
  525. unless static (like utility libraries.)
  526. **[[⬆]](#TOC)**
  527. ## <a name='testing'>Testing</a>
  528. - Use [telescope](https://github.com/norman/telescope) for unit tests and Robot framework for functional testing.
  529. Unit tests can rely on LuaJIT ffi module if C function testing is required.
  530. **[[⬆]](#TOC)**
  531. ## <a name='license'>License</a>
  532. - Released under CC0 (Public Domain).
  533. Information can be found at [http://creativecommons.org/publicdomain/zero/1.0/](http://creativecommons.org/publicdomain/zero/1.0/).
  534. **[[⬆]](#TOC)**