This is a hack - need to investigate using Sourcekit http://www.jpsim.com/uncovering-sourcekit/ possibly entire code base is a bin job.
For now - the translation requires user to specify workspace / project inside Chime project this uses the clang parser.
I will simplify this so a single header / implementation file can be specified to help automate batch processing.
scheduledTask / MRWorker schema > trawler - IN PROGRESS.
TODO / Task Tracker https://docs.google.com/spreadsheets/d/1gUvHCqdPyH-yAt5W_2pmDOVsgBVtAzqfeMnoTJRTgFQ/edit#gid=738774835
This attached sourcecode is a stop gap until Xcode has a button to convert an objective-c project over to swift. There are potential commercial opportunities worth exploring. To discuss.
The most important first step is to run Apple's "Convert to Modern Objective-C Syntax" refactoring, so that you're using array/dictionary literals and bracket-accesses; these will then be usable in Swift.
Detected pattern | Will be Replaced by this | STATUS |
---|---|---|
Module | ||
@interface newType : superType <protocol1, protocol2> | class newType : superType, protocol1, protocol2 | OK |
@implementation OR @synthesize OR @end | Delete | OK |
Properties | ||
property(…) TypeName * varName; | var varName:TypeName | OK |
property (readonly...) TypeName * varName; | let varName:TypeName | OK |
property(…) TypeName * IBOutlet varName; | @IBOutlet var varName:TypeName | TODO |
_property | self.property | |
Compiler Directives | ||
#import module.h | Obj-C modules: Include in ...-Bridging-Header.h Project modules: DeleteFrameworks: import module | OK |
#define macroName value | let macroName = value | TODO |
More complex#define / #ifdef / #ifndef | N/A | OK |
#elif value | #elseif value | OK |
#pragma mark sectionName | // MARK: sectionName (not implemented yet) | OK |
NSAssert(conditon,description) | assert(condition, description) | TODO |
Types | ||
NSString * | String | TODO |
NSArray * arrayName = arrayValue | let arrayName = arrayValue ORlet arrayName: Array = arrayValue OR let arrayName: TypeName[] = arrayValue | DRAFTED |
NSDictionary * | Dictionary | TODO |
NSMutableArray OR NSMutableDictionary ... | var arrayName... | OK |
id | AnyObject | OK |
TypeName * | TypeName | OK |
c types, e.g. uint32 OR float | Titlecase , e.g. UInt32 or Float | OK |
NSInteger OR NSUInteger | Int OR UInt | OK |
Method Definitions | OK | |
-(void) methodName | func methodName() | OK |
-(TypeName) methodName | func methodName() -> TypeName | OK |
-(IBAction) methodName | @IBAction func methodName | TODO |
#ERROR! | class func methodName() -> TypeName | OK |
...methodName: (Type1) param1 b: (Type2) param2 | ...methodName(param: Type1 b param2: Typ2) | DRAFTED |
method overriden from superclass | add override | TODO |
Variables | ||
TypeName varName = value | var (OR let) name = value OR var (OR let) name: TypeName if necessary | OK |
Object Creation | ||
TypeName * varName = [[TypeName alloc] init] | varName = TypeName() | OK |
[[TypeName alloc] initWithA: value1 B: value2] | TypeName(a: value1, b: value2) | DRAFTED |
[TypeName TypeNameWithA: value] | TypeName(a: value) | OK |
Statements | ||
break in switch statements | not necessary, except for empty cases,but add fallthrough where needed | |
if/while (expr) | if/while expr, parentheses optional,but expr must now be a boolean | |
for ( ... ) | for ..., optional | TODO |
Method Calls | ||
[object method] | object.method() | OK |
[object method: param1 b: param2 …] | object.method(param1, b: param2, …) | DRAFTED |
Expressions | ||
YES | TRUE | OK |
NO | FALSE | OK |
(TypeName) value to recast | value as TypeName OR TypeName(value) | TODO |
stringName.length | stringName.utf16 ORstringName.countElements | TODO |
stringName isEqualToString: string2Name | stringName == string2Name | TODO |
NSString stringWithFormat@"...%@..%d",obj,int) | ...(obj)...(int) | TODO |
Miscellaneous | ||
semicolons at end of line | Optionally delete | OK |
@ for literals | Delete | OK |
Jens Alfke crafted this ruby hack with regex code https://github.com/snej/swiftier Be sure to point it to a wildcard /project/*.m files and watch it fly.
Here's a more refined hack. It's leveraging clang + and an objective-c wrapper called chime. fire it up app - point it to an existing workspace / or project and it will start processing.
Any .m files a Currently it's creating swift files -> and ripping out every comment from objective-c file. It knows your classes / methods / functions / globals. The entire sourcecode file is being parsed - and I have all the variables / methods / types at disposal thanks to sourcecodekit + clang introspection.
You can step into more detail inside SCKSyntaxHighlighter
- (NSString*)convertToSwiftSource:(SCKClangSourceFile *)file; // inside your .m file -> be sure to step through the attributes
NSLog(@"attrs:%@",attrs); NSLog(@"attributedSubstringFromRange:%@",[source attributedSubstringFromRange:range] );
There's two directions this project can take -
-
Regex pattern matching / ruby hack method in combitation with SourceCodeKit attributed string conversion
-
ChimeTranslationUnit / clang parser
Inside IndexDocument
N.B.
BOOL useClangParser = NO;
if(useClangParser){
SCKSourceFile *implementation = [sourceCollection sourceFileForPath: fileURL.path]; //.m files
NSMutableString *headerFile = [NSMutableString stringWithFormat:@"%@",fileURL.path];
[headerFile replaceOccurrencesOfString:@".m" withString:@".h" options:0 range:NSMakeRange(0, headerFile.length)];
SCKSourceFile *hFile = [sourceCollection sourceFileForPath: headerFile]; //.h files -
}else{
ChimeTranslationUnit *tu = [[ChimeTranslationUnit alloc] initWithFileURL:fileURL arguments:arguments index:self.index];
if (tu == nil) {
// TODO: provide error
NSLog(@"Couldn't create translation unit for file \"%@\"", [fileURL path]);
} else {
[result addObject:tu];
}
}
[sourceCollection.files enumerateKeysAndObjectsUsingBlock:^(NSString *key, SCKClangSourceFile *file, BOOL * __nonnull stop) {
if ([file isKindOfClass:[SCKClangSourceFile class]]) {
DDFileReader *reader = [[DDFileReader alloc]initWithFilePath:file.fileName];
NSLog(@"file.fileName:%@",file.fileName);
[reader createSwiftFileFrom:file];
}
}];
C wrappers in clang ->
Obectivej-C to Swift Syntax Translation https://gist.github.com/mackworth/81e81bcc0e2dc281e1a4