* Makefile: Run "make run-test" or "make run-test-ondotnet" to
[mono.git] / mcs / CodingStyle
1 * Coding Style for the Mono C# source code.
2
3 * Class Libraries and Assembly Layout
4
5         The class libraries are grouped together in the assemblies
6         they belong.
7         
8         Each directory here represents an assembly, and inside each
9         directory we divide the code based on the namespace they
10         implement.
11         
12         In addition, each assembly directory contains a Test directory
13         that holds the NUnit tests for that assembly.
14         
15         We use a new build system which is described by various README
16         files in mcs/build
17         
18         The build process typically builds an assembly, but in some
19         cases it also builds special versions of the assemblies
20         intended to be used for testing.
21
22 * Missing implementation bits
23
24         If you implement a class and you are missing implementation bits,
25         please use the attribute [MonoTODO].  This attribute can be used
26         to programatically generate our status web pages:
27
28         [MonoTODO]
29         int MyFunction ()
30         {
31                 throw new NotImplementedException ();
32         }
33
34 * Supporting .NET 1.2, .NET 1.1 and .NET 1.0 builds
35
36         The defines NET_1_1 and NET_2_0 are used to include
37         features.   When NET_2_0 is defined, it also implies that the
38         NET_1_1 is defined.
39
40         To have code which is only available in an old version, use ONLY_1_0,
41         ONLY_1_1
42
43 * Tagging buggy code
44
45         If there is a bug in your implementation tag the problem by using
46         the word "FIXME" in the code, together with a description of the 
47         problem.
48
49         Do not use XXX or obscure descriptions, because otherwise people
50         will not be able to understand what you mean.
51
52 * Tagging Problematic specs.
53
54         If the documentation and the Microsoft implementation do
55         differ (you wrote a test case to prove this), I suggest that you edit
56         the file `mcs/class/doc/API-notes' so we can keep track of these problems
57         and submit our comments to ECMA or Microsoft and seek clarification.
58
59         Sometimes the documentation might be buggy, and sometimes the implementation
60         might be buggy.  Lets try to identify and pinpoint which one
61         is the correct one.
62
63         Sometimes the specification will be lame (consider Version.ToString (fieldCount)
64         where there is no way of knowing how many fields are available, making the API
65         not only stupid, but leading to unreliable code).
66
67         In those cases, use the keyword "LAMESPEC".
68         
69
70 * Coding considerations and style.
71
72         In order to keep the code consistent, please use the following
73         conventions.  From here on `good' and `bad' are used to attribute
74         things that would make the coding style match, or not match.  It is not
75         a judgement call on your coding abilities, but more of a style and 
76         look call.  Please try to follow these guidelines to ensure prettiness.
77
78         Use 8 space tabs for writing your code (hopefully we can keep
79         this consistent).  If you are modifying someone else's code, try
80         to keep the coding style similar.
81
82         Since we are using 8-space tabs, you might want to consider the Linus
83         Torvals trick to reduce code nesting.  Many times in a loop, you will
84         find yourself doing a test, and if the test is true, you will nest.
85         Many times this can be changed.  Example:
86
87
88                 for (i = 0; i < 10; i++) {
89                         if (something (i)) {
90                                 do_more ();
91                         }
92                 }
93
94         This take precious space, instead write it like this:
95
96                 for (i = 0; i < 10; i++) {
97                         if (!something (i))
98                                 continue;
99                         do_more ();
100                 }
101
102 * Performance and readability
103
104         It is more important to be correct than to be fast.
105
106         It is more important to be maintainable than to be fast.
107
108         Fast code that is difficult to maintain is likely going to
109         be looked down upon.
110
111 * Style Guidelines
112
113                 * Use a space before an opening parenthesis when calling
114                   functions, or indexing, like this:
115
116                         method (a);
117                         b [10];
118
119                 * Do not put a space after the opening parenthesis and the 
120                   closing one, ie:
121
122                         good: method (a);       array [10];
123
124                         bad:  method ( a );     array[ 10 ];
125
126                 * Inside a code block, put the opening brace on the same line
127                   as the statement:
128
129                         good:
130                                 if (a) {
131                                         code ();
132                                         code ();
133                                 }
134
135                         bad:
136                                 if (a) 
137                                 {
138                                         code ();
139                                         code ();
140                                 }
141
142                 * Avoid using unecessary open/close braces, vertical space
143                   is usually limited:
144
145                         good:
146                                 if (a)
147                                         code ();
148
149                         bad:
150                                 if (a) {
151                                         code ();
152                                 }
153
154                 * When defining a method, use the C style for brace placement, 
155                   that means, use a new line for the brace, like this:
156
157                         good:
158                                 void Method ()
159                                 {
160                                 }
161
162                         bad:
163                                 void Method () {
164                                 }
165
166                 * Properties and indexers are an exception, keep the
167                   brace on the same line as the property declaration.
168                   Rationale: this makes it visually
169                   simple to distinguish them.
170
171                         good:
172                                 int Property {
173                                         get {
174                                                 return value;
175                                         }
176                                 }
177
178                         bad:
179                                 int Property 
180                                 {
181                                         get {
182                                                 return value;
183                                         }
184                                 }
185
186                   Notice how the accessor "get" also keeps its brace on the same
187                   line.
188
189                   For very small properties, you can compress things:
190
191                         ok:
192                                 int Property {
193                                         get { return value; }
194                                         set { x = value; }
195                                 }
196
197                 * Use white space in expressions liberally, except in the presence
198                   of parenthesis:
199
200                         good:
201
202                                 if (a + 5 > method (blah () + 4))
203
204                         bad:
205                                 if (a+5>method(blah()+4))
206
207                 * For any new files, please use a descriptive introduction, like
208                   this:
209
210                         //
211                         // System.Comment.cs: Handles comments in System files.
212                         //
213                         // Author:
214                         //   Juan Perez (juan@address.com)
215                         //
216                         // (C) 2002 Address, Inc (http://www.address.com)
217                         //
218
219                 * If you are modyfing someone else's code, and your contribution
220                   is significant, please add yourself to the Authors list.
221
222                 * Switch statements have the case at the same indentation as the
223                   switch:
224
225                         switch (x) {
226                         case 'a':
227                                 ...
228                         case 'b':
229                                 ...
230                         }
231
232                 * Argument names should use the camel casing for
233                   identifiers, like this:
234
235                         good:
236                                 void Method (string myArgument)
237
238                         bad:
239                                 void Method (string lpstrArgument)
240                                 void Method (string my_string)
241
242                 * Empty methods: They should have the body of code using two    
243                   lines, in consistency with the rest:
244
245                         good:
246                                 void EmptyMethod ()
247                                 {
248                                 }
249
250                         bad:
251                                 void EmptyMethod () {}
252
253                                 void EmptyMethod () 
254                                 {}
255                 
256                 * Line length: The line length for C# source code is 134 columns.
257
258
259                   If your function declaration arguments go beyond
260                   this point, please align your arguments to match the
261                   opening brace, like this:
262
263                         void Function (int arg, string argb,
264                                        int argc)
265                         {
266                         }
267          
268                   When invoking functions, the rule is different, the
269                   arguments are not aligned with the previous
270                   argument, instead they begin at the tabbed position,
271                   like this:
272           
273                         void M ()
274                         {
275                                 MethodCall ("Very long string that will force",
276                                         "Next argument on the 8-tab pos",
277                                         "Just like this one")
278                 
279                         }
280
281                 * Variable declaration indentation.
282
283                   Sometimes it is convenient to indent the variables to make the code
284                   look pretier, but do not add gratuitous space, try to use the minimally
285                   necessary space, for example:
286
287                   Good:
288
289                         void Method ()
290                         {
291                                 string b;
292                                 int    a;
293                                 byte   c;
294                         }
295
296                   Bad:
297
298                         void Method ()
299                         {
300                                 string          b;
301                                 int             a;
302                                 byte            c;
303                         }
304
305                 * Braces and the `else' clause
306
307                   If there are braces closing or opening next to the else clause,
308                   they go on the same line as the word `else', for example:
309
310                   Good:
311
312                         if (..) {
313
314                         } else {
315                 
316                         }
317         
318                   Bad:
319
320                         if (..) {
321
322                         } 
323                         else {
324                 
325                         }
326
327                   Bad:
328
329                         if (..) {
330
331                         } else 
332                         {               
333                         }
334
335                   Bad:
336
337                         if (..) {
338
339                         } 
340                         else 
341                         {
342                 
343                         }
344
345 * RCS and CVS tags
346
347         Some users like to use the special RCS/CVS tags in their
348         source code: $id$, $log$ and so on.  
349
350         The use of these is not permitted on the Mono source code
351         repository.   This metadata belongs on a ChangeLog or in the
352         SVN metadata. 
353
354 * File formats
355
356         Historically our repository has used a mix of line-endings,
357         this is a mistake that we are trying hard to fix.
358
359         For existing files, please make sure that you do not convert 
360         the file, as that causes us to loose precious history (the
361         full file is commited).
362
363         For new files that you create, please make sure that you use
364         Subversion's support for mapping the line endings
365         automatically, after adding your file:
366
367                 $ svn add file.cs
368
369         Execute this command:
370
371                 $ svn propset svn:eol-style native file.cs
372
373         Which will make the file automatically receive the proper
374         treatment from that point on.
375
376         Please verify before commiting that your changes wont loose
377         history, you can do this by running:
378
379                 $ svn diff
380
381         And examining the output.
382
383 * ChangeLogs
384
385         ChangeLogs are the files that we use to track the project
386         history.  ChangeLogs are found one per directory, or in small
387         projects, one per project.
388
389         The format looks like this:
390
391         2004-11-19  Raja R Harinath  <rharinath@novell.com>
392
393                 * Makefile (%-profiles): Go through an intermediate
394                 set of rules.  Move body to ...
395                 (profiles-do--%): ... this.
396                 (profiles-do--run-test): Customized rule that usefully
397                 runs with 'make -j' and 'make -k'.
398                 (profiles-do--all, profile-do--%--all): Orchestrate
399                 the bootstrap process.
400
401                 * file.cs (MainForm): Updated version.
402
403         The date, author, email address in the first line.
404
405         From that point on a list of changes in a file-by-file basis,
406         describing what changes were done.
407                 
408 * Warnings
409
410         Avoid commiting code with warnings to the repository, the use
411         of #pragmas to disable warnings is strongly discouraged, but
412         can be used on unique cases.  Please justify the use of the
413         warning ignore clause on a comment.
414
415         Do not commit changes to the Makefiles that removes warnings,
416         if anything warnings should be eliminated one at a time, and
417         if not possible, they must be flagged.
418
419
420 * Examples:
421
422 class X : Y {
423
424         bool Method (int argument_1, int argument_2)
425         {
426                 if (argument_1 == argument_2)
427                         throw new Exception (Locale.GetText ("They are equal!");
428
429                 if (argument_1 < argument_2) {
430                         if (argument_1 * 3 > 4)
431                                 return true;
432                         else
433                                 return false;
434                 }
435
436                 //
437                 // This sample helps keep your sanity while using 8-spaces for tabs
438                 // 
439                 VeryLongIdentifierWhichTakesManyArguments (
440                         Argument1, Argument2, Argument3,
441                         NestedCallHere (
442                                 MoreNested));
443         }
444
445         bool MyProperty {
446                 get {
447                         return x;
448                 }
449
450                 set {
451                         x = value;
452                 }
453         }
454
455         void AnotherMethod () 
456         {
457                 if ((a + 5) != 4) {
458                 }
459
460                 while (blah) {
461                         if (a)
462                                 continue;
463                         b++;
464                 }
465         }
466 }
467