CompilationUnits
Organization
Fantom source code for pods is organized into one or more directories on the file system. By convention the source tree of a pod is structured as follows:
podxyz/ +- fan/ // ".fan" source files +- java/ // ".java" Java native peers +- js/ // ".js" JavaScript native peers +- dotnet/ // ".cs" C# native peers +- res/ // resources to bundle with pod +- locale/ // localization files +- test/ // ".fan" unit tests +- build.fan // build script for pod +- pod.fandoc // pod level documentation
Each of those directories may contain arbitrary sub-directories under it, although it is not required.
Fantom source code is stored in plain text files using a ".fan" extension. Each source file can contain one or more class or mixin definitions. Unlike Java, there is no restriction that each type must be in its own source file. Although by convention we put each class into a source file with a matching name. However if you have lots of little classes, then it is best to combine them intelligently.
Char Encoding
There is only one simple rule to follow - all Fantom source files must be in UTF-8 encoding. Even better, if you want to ensure that your source code is drop-dead easy to use in any editor then use standard 7-bit ASCII characters (which is a clean subset of UTF-8). End of story, enough said.
Anatomy of Source File
Compiler writers like to use the fancy term compilation unit to describe the text of a source file. A compilation unit has a pretty simple structure:
- Zero or more
using
statements - One or more type definitions
The using statements import types from external pods into the compilation unit's namespace. The type definitions are the actual classes and mixins.
Using
Every compilation unit can specify zero or more using
statements to import types into the unit's namespace. Importing types into the namespace lets you use simple type names in your type signatures instead of qualified names.
The simplest form of the using
statement is to import all the types of a pod into your namespace:
using inet
The statement above allows you to use any type defined in the inet
pod via its simple name. For example the simple type name TcpSocket
will now resolve to inet::TcpSocket
.
We can also import a single type into the namespace. For example to just import inet::TcpSocket
without importing all the other types from the inet
pod we use this syntax:
using inet::TcpSocket
In large scale projects it is inevitable that two different pods will reuse the same type name. If we need to use both types in a compilation unit, then we could use the qualified name - although it can be a bit verbose. Another option is to use the using as
statement. For example, given a naming collision between red::Foo
and blue::Foo
, we can import blue::Foo
as BlueFoo
with this syntax:
using blue::Foo as BlueFoo
The using as
statement is for naming collisions - don't use it for bone-headed things like importing sys::Str
as S
(we've tried to keep key type names short to being with).
The sys
pod is automatically imported into every compilation unit - in fact it is a compiler error if you try to import sys
explicitly.
Comments
Fantom supports three styles of comments:
/* */
block comments are used to comment out a block of text which can span multiple lines. You can nest/* */
comments as a handy way to comment out large sections of code//
end of line comments ignore everything to the end of the line**
fandoc comments
The **
comment is used for documentation. Like //
comments, it comments everything to the end of the line. Fandoc comments are similar to /** */
Javadoc or ///
C# documentation comments. You prefix one more lines of **
comments to specify the documentation for a type or slot definition:
** This class is really cool class Cool { ** When you gotta just do it! Void justDoIt() {} }
The documentation is written in plain text using a special set of rules for structure called fandoc. Fandoc allows you to write documentation that looks good in plain text source files, but can be translated into other formats such as nicely formatted HTML.