-
Notifications
You must be signed in to change notification settings - Fork 394
Mogenerator internals
A quick introduction and reference for anyone who wants to hack on mogenerator
itself.
mogenerator
has been around for a long time. Go check the commit history if you like. It's been around since the iPhone was just a glimmer in Steve Jobs' eye. Parts of it are older than Mac OS X. As such it's written entirely in Objective-C, and will continue to be so until some highly motivated person finds a reason to rewrite it.
Code is grouped as follows:
-
mogenerator.[hm]
: The Core ofmogenerator
. Everything about combining a data model with templates to produce model classes happens here. It includes-
MOGeneratorApp
, the core ofmogenerator
's operations - Numerous categories on Core Data classes (see below under "template variables" for a discussion of these).
-
-
momcom
: A collection of classes implementing a Core Data model compiler. Used bymogenerator
to compile a data model into anNSManagedObjectModel
. Derived from this repo. -
MiscMerge
: Template engine used to process template source code files. This comes from Don Yactman and Carl Lindberg's old MiscKit project, and can now also be found in thisrepo. -
ponso
: No longer used. -
ddcli
: Dave Dribin's ddcli, which is used to parse command line arguments.
Arguments are processed by ddcli
. This happens in main
, which is a single line that calls DDCliAppRunWithClass
.
Any new or updated command line arguments should update all of the following:
- Argument names (long and short) plus argument type are listed in
-[MOGeneratorApp application:willParseOptions:]
. "Type" here means the command-line argument type, not the data type. Things like whether the argument requires a value or can stand on its own, for example. - Each argument corresponds to an instance variable declared on
MOGeneratorApp
, which in turn is declared inmogenerator.h
. This is where the data type for the argument is declared. For example the--model
argument corresponds to the instance variableNSManagedObjectModel *model
. Mapping from argument to instance var isddcli
's job. - Usage descriptions are found in strings in
-[MOGeneratorApp printUsage]
.
Once arguments have been processed, the main mogenerator
work is kicked off by a call to -[MOGeneratorApp application:runWithArguments:]
. Instance variables on MOGeneratorApp
will have values dereived from command line arguments.
Most template variables correspond to properties or methods on the relevant Core Data class. For example,
- The value of
managedObjectClassName
template variable on an entity is found by calling themanagedObjectClassName
method on theNSEntityDescription
instance for the entity. - When iterating over an entity's attributes, the value of the
usesRawValueEnumType
template variable comes from callingusesRawValueEnumType
on theNSAttributeDescription
instance for the attribute.
Lookups use both built-in Core Data methods and any methods implemented in categories on those classes. Categories with such methods are found in mogenerator.m
.
There are a lot of extra methods defined in categories of Core Data classes for the sole purpose of providing template variables. One side effect of this is that many methods declared in code are apparently never called-- because the only reference to them is in a template file. Don't remove a category method without checking template files to see if it's used there.
Template variables can also be declared via command line aguments using the syntax --template-var KEY=VALUE
. These key-value pairs are copied to the templateVar
property of MOGeneratorApp
. That dictionary is passed on to the template engine (MiscMerge), and the variables are available when processing templates.
Templates can also use loop variables when iterating over collections. For example, consider the following template code
<$foreach Attribute noninheritedAttributes do$>
<$if Attribute.hasDefinedAttributeType$>
<$if Attribute.hasScalarAttributeType$>
...
<$endforeach do$>
- The
foreach
loop calls thenoninheritedAttributes
method on the current entity to get an array of attributes. This method is implemented in a category onNSEntityDescription
found inmogenerator.m
. -
Attribute
is a loop variable which represents each attribute in turn. SincenoninheritedAttributes
returns an array ofNSAttributeDescription
, its template variables correspond to properties or methods on that class. - The
hasDefinedAttributeType
andhasScalarAttributeType
template variables are looked up using methods of the same name onNSAttributeDescription
. Both of these are defined in a category onNSAttributeDescription
.
Custom userInfo
keys configured in data models are available in code via the userInfo
property on NSEntityDescription
, NSAttributeDescription
, and NSRelationshipDescription
. These may be mapped to template variables but the names don't need to match. User info variables do not automatically become template variables.
For example, attribute descriptions may use a key named attributeValueScalarType
. There's a category method on NSAttributeDescription
that looks up the value of this user info key. The method is called usesCustomScalarAttributeType
, so that's also the name of the corresponding template variable.