mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-09-03 09:23:40 +00:00
478 lines
10 KiB
Markdown
478 lines
10 KiB
Markdown
Contributing
|
|
------------
|
|
|
|
As an open source project, your contributions are important to the future of Cappuccino. Whether you're looking to write code, add new documentation, or just report a bug, you'll be helping everyone who uses Cappuccino in the future.
|
|
|
|
## Reporting Bugs
|
|
|
|
We use [GitHub to track issues](https://github.com/cappuccino/cappuccino/issues). You might be interested in our [issue life cycle](http://www.cappuccino-project.org/community/contribute/the-issue-lifecycle/) which explains the process of how an issue is taken from new to resolved.
|
|
|
|
## Patches
|
|
|
|
To contribute a patch or a fix, fork Cappuccino and then clone your fork and make the changes to a branch of your fork:
|
|
|
|
git clone https://github.com/<your username>/cappuccino.git
|
|
git checkout -b descriptive-branch-name master
|
|
|
|
# Check that the unit tests work.
|
|
jake test
|
|
|
|
# Make changes. Make sure you follow the coding style guidelines and write unit tests.
|
|
|
|
# Check that everything is still working, then commit.
|
|
jake test
|
|
git commit
|
|
|
|
git push origin descriptive-branch-name
|
|
|
|
Now you can go to GitHub and [make a pull request](https://help.github.com/articles/using-pull-requests).
|
|
|
|
Some things are difficult to unit test in a way that's worthwhile. For instance a change to the mouse interaction of a `CPButton`. In this case a manual test is fine instead. Find the closest related manual test in `Tests/Manual` and add whatever it takes to easily reproduce the patched behavior, ideally with some labels describing how someone running the manual test should exercise it.
|
|
|
|
## Cappuccino Coding Style Guidelines
|
|
|
|
### Indentation
|
|
|
|
Use spaces, not tabs. Tabs should only appear in files that require them for semantic meaning, like Makefiles (which there are currently none of). The indent size is 4 spaces.
|
|
|
|
##### Right:
|
|
|
|
function main()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
##### Wrong:
|
|
|
|
function main()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
---
|
|
|
|
A case label should be indented once from its switch statement. The case statement is indented out from the longest label.
|
|
|
|
##### Right:
|
|
|
|
switch (condition)
|
|
{
|
|
case fooCondition:
|
|
case barCondition: i++;
|
|
break;
|
|
|
|
default: i--;
|
|
}
|
|
|
|
##### Wrong:
|
|
|
|
switch (condition) {
|
|
case fooCondition:
|
|
case barCondition:
|
|
i++;
|
|
break;
|
|
default:
|
|
i--;
|
|
}
|
|
|
|
### Spacing
|
|
|
|
Do not place spaces around unary operators.
|
|
|
|
##### Right:
|
|
|
|
i++
|
|
|
|
##### Wrong:
|
|
|
|
i ++
|
|
|
|
---
|
|
|
|
Do place spaces around binary and ternary operators.
|
|
|
|
##### Right:
|
|
|
|
y = m * x + b;
|
|
f(a, b);
|
|
c = a | b;
|
|
return condition ? 1 : 0;
|
|
|
|
##### Wrong:
|
|
|
|
y=m*x+b;
|
|
f(a,b);
|
|
c = a|b;
|
|
return condition ? 1:0;
|
|
|
|
---
|
|
|
|
Place spaces between control statements and their parentheses.
|
|
|
|
##### Right:
|
|
|
|
if (condition)
|
|
doIt();
|
|
|
|
##### Wrong:
|
|
|
|
if(condition)
|
|
doIt();
|
|
|
|
---
|
|
|
|
Do not place spaces between a function and its parentheses, or between a parenthesis and its content.
|
|
|
|
##### Right:
|
|
|
|
f(a, b);
|
|
|
|
##### Wrong:
|
|
|
|
f (a, b);
|
|
f( a, b );
|
|
|
|
---
|
|
|
|
Do not place spaces between the return type of an Objective-J method and the selector name. DO place spaces between the method type and the method return type.
|
|
|
|
##### Right:
|
|
|
|
- (void)method;
|
|
|
|
##### Wrong:
|
|
|
|
- (void) method;
|
|
-(void)method;
|
|
|
|
---
|
|
|
|
Do not place spaces between Objective-J selectors and arguments.
|
|
|
|
##### Right:
|
|
|
|
[myNumber addNumber:5]
|
|
|
|
##### Wrong:
|
|
|
|
[myNumber addNumber: 5]
|
|
|
|
### Line breaking
|
|
|
|
Each statement should get its own line.
|
|
|
|
##### Right:
|
|
|
|
var x,
|
|
y;
|
|
x++;
|
|
y++;
|
|
if (condition)
|
|
doIt();
|
|
|
|
##### Wrong:
|
|
|
|
var x, y;
|
|
x++; y++;
|
|
if (condition) doIt();
|
|
|
|
### Braces
|
|
|
|
Every brace gets its own line, very simple to remember:
|
|
|
|
##### Right:
|
|
|
|
int main()
|
|
{
|
|
//...
|
|
}
|
|
|
|
if (condition)
|
|
{
|
|
//...
|
|
}
|
|
else if (condition)
|
|
{
|
|
//...
|
|
}
|
|
|
|
@implementation MyObject : CPObject
|
|
{
|
|
}
|
|
|
|
@end
|
|
|
|
##### Wrong:
|
|
|
|
int main() {
|
|
...
|
|
}
|
|
|
|
if (condition) {
|
|
...
|
|
} else if (condition) {
|
|
...
|
|
}
|
|
|
|
@implementation MyObject : CPObject {}
|
|
@end
|
|
|
|
### Null, false and 0
|
|
|
|
In JavaScript, the null object value should be written as null. In Objective-J, it should be written as `nil` when the variable refers to an object, and `Nil` when it refers to a `Class`. Objective-J `BOOL` values should be written as `YES` and `NO`.
|
|
|
|
Tests for `true/false`, `null/non-null`, and zero/non-zero should all be done without equality comparisons, except for cases when a value could be both 0 or `null` (or another "falsey" value). In this case, the comparison should be preceded by a comment explaining the distinction.
|
|
|
|
##### Right:
|
|
|
|
if (condition)
|
|
doIt();
|
|
|
|
if (!ptr)
|
|
return;
|
|
|
|
if (!count)
|
|
return;
|
|
|
|
// object is an ID number, so 0 is OK, but null is not.
|
|
if (object === null)
|
|
return;
|
|
|
|
##### Wrong:
|
|
|
|
if (condition == true)
|
|
doIt();
|
|
|
|
if (ptr == NULL)
|
|
return;
|
|
|
|
if (count == 0)
|
|
return;
|
|
|
|
if (object == null)
|
|
return;
|
|
|
|
---
|
|
|
|
In Objective-J, instance variables are initialized to `nil` automatically. Don't add explicit initializations to `nil` or `NO` in an init method.
|
|
|
|
### Names
|
|
|
|
Use CamelCase. Capitalize the first letter of a class. Lower-case the first letter of a variable or function name. Fully capitalize acronyms.
|
|
|
|
##### Right:
|
|
|
|
@implementation Data : //...
|
|
@implementation HTMLDocument : //...
|
|
|
|
##### Wrong:
|
|
|
|
@implementation data : //...
|
|
@implementation HtmlDocument : //...
|
|
|
|
---
|
|
|
|
Multiple var declarations should be collapsed with commas.
|
|
|
|
##### Right:
|
|
|
|
var index = 0,
|
|
count = 5;
|
|
|
|
##### Wrong:
|
|
|
|
var index = 0;
|
|
var count = 5;
|
|
|
|
---
|
|
|
|
Variable declarations should be created as needed, rather than up front ("hoisted").
|
|
|
|
##### Right:
|
|
|
|
- (BOOL)doSomething:(id)aFoo
|
|
{
|
|
var importantVariable = [aFoo message];
|
|
if (!importantVariable)
|
|
return;
|
|
|
|
var index = [aFoo count];
|
|
while (index--)
|
|
{
|
|
var innerVariable = [aFoo objectAtIndex:index];
|
|
//do something;
|
|
}
|
|
}
|
|
|
|
##### Wrong:
|
|
|
|
- (BOOL)doSomething:(id)aFoo
|
|
{
|
|
var importantVariable = [aFoo message],
|
|
index = [aFoo count],
|
|
innerVariable;
|
|
|
|
if (!importantVariable)
|
|
return;
|
|
|
|
while (index--)
|
|
{
|
|
innerVariable = [aFoo objectAtIndex:index];
|
|
//do something;
|
|
}
|
|
}
|
|
|
|
---
|
|
|
|
Use full words, except in the rare case where an abbreviation would be more canonical and easier to understand.
|
|
|
|
##### Right:
|
|
|
|
var characterSize,
|
|
length,
|
|
tabIndex; // more canonical
|
|
|
|
##### Wrong:
|
|
|
|
var charSize,
|
|
len,
|
|
tabulationIndex; // bizarre
|
|
|
|
---
|
|
|
|
Prefix Objective-J instance variables with `_`, but only when writing code for the Cappuccino frameworks. User level (application) code should not prefix variables with `_`. This prevents conflicts between the two scopes.
|
|
|
|
##### Right:
|
|
|
|
@implementation CPString
|
|
{
|
|
unsigned _length;
|
|
}
|
|
@end
|
|
|
|
##### Wrong:
|
|
|
|
@implementation CPString
|
|
{
|
|
unsigned length;
|
|
}
|
|
@end
|
|
|
|
---
|
|
|
|
Precede boolean values with words like "is" and "did".
|
|
|
|
##### Right:
|
|
|
|
var isValid;
|
|
var didSendData;
|
|
- (BOOL)isEditable;
|
|
- (BOOL)didReceiveResponse;
|
|
|
|
##### Wrong:
|
|
|
|
var valid;
|
|
var sentData;
|
|
- (BOOL)editable;
|
|
- (BOOL)receivedResponse;
|
|
|
|
---
|
|
|
|
Precede setters with the word "set". Use bare words for getters. Setter and getter names should match the names of the variables being set/gotten.
|
|
|
|
##### Right:
|
|
|
|
- (void)setCount:(unsigned)aCount; // sets _count
|
|
- (unsigned)count; // returns _count
|
|
|
|
##### Wrong:
|
|
|
|
- (unsigned)getCount;
|
|
|
|
---
|
|
|
|
Use descriptive verbs in function names, and place desired types in comments.
|
|
|
|
##### Right:
|
|
|
|
function convertToASCII(/*String*/ aString)
|
|
|
|
##### Wrong:
|
|
|
|
function toASCII(str)
|
|
|
|
---
|
|
|
|
Use descriptive parameter names that are not abbreviated.
|
|
|
|
##### Right:
|
|
|
|
- (void)convertString:(CPString)aString toFormat:(Format)aFormat;
|
|
- (void)appendSubviews:(CPArray)subviews inOrder:(BOOL)shouldBeInOrder;
|
|
|
|
##### Wrong:
|
|
|
|
- (void)convertString:(CPString)str toFormat:(Format)f;
|
|
- (void)appendSubviews:(CPArray)s inOrder:(BOOL)flag;
|
|
|
|
---
|
|
|
|
Use descriptive parameter types, despite not being fully supported in JavaScript. At some point we will be adding optional static typing, and even until then this serves as a much better indicator of what the method expects. Of course, if the method can truly take any input or return any output, it is perfectly acceptable to use `id`, `CPObject`, or `var`.
|
|
|
|
##### Right:
|
|
|
|
- (char)characterAtIndex:(unsigned)anIndex;
|
|
- (void)insertObject:(id)anObject;
|
|
|
|
##### Wrong:
|
|
|
|
- (String)characterAtIndex:(var)index;
|
|
|
|
---
|
|
|
|
Objective-J method names should follow the Cocoa naming guidelines — they should read like a phrase and each piece of the selector should start with a lowercase letter and use intercaps.
|
|
|
|
Enum members should user InterCaps with an initial capital letter.
|
|
|
|
`#defined` constants should use all uppercase names with words separated by underscores.
|
|
|
|
Macros that expand to function calls or other non-constant computation: these should be named like functions, and should have parentheses at the end, even if they take no arguments (with the exception of some special macros like ASSERT).
|
|
|
|
##### Right:
|
|
|
|
#define StopButtonTitle() \
|
|
CPLocalizedString(@"Stop", @"Stop button title")
|
|
|
|
##### Wrong:
|
|
|
|
#define STOP_BUTTON_TITLE \
|
|
CPLocalizedString(@"Stop", @"Stop button title")
|
|
|
|
#define StopButtontitle \
|
|
CPLocalizedString(@"Stop", @"Stop button title")
|
|
|
|
### import Statements
|
|
|
|
1. Include external frameworks first.
|
|
2. Include Foundation classes before AppKit classes.
|
|
3. Include files in alphabetical order.
|
|
4. Use local imports whenever possible.
|
|
|
|
##### Right:
|
|
|
|
// (Within AppKit)
|
|
import <Foundation/CPObject.j>
|
|
import <Foundation/CPArray.j>
|
|
|
|
import "CPTabViewItem.j"
|
|
import "CPTabView.j"
|
|
|
|
##### Wrong:
|
|
|
|
// (Within AppKit)
|
|
import "CPTabView.j"
|
|
import <AppKit/CPTabViewItem.j>
|
|
|
|
import <Foundation/CPArray.j>
|
|
import <Foundation/CPObject.j>
|