Upgrade to Pro — share decks privately, control downloads, hide ads and more …

AppCode under the hood

Aydar
January 10, 2022

AppCode under the hood

Each developer sooner or later thinks about how his IDE is arranged. Features such as auto-completion, navigation to the declaration, syntax highlighting, search for call points no longer seem magic when you use them. But the development of these important features is challenging and exciting activity. Don't forget that this is about supporting several languages at once.
AppCode is an IDE for development under macOS and iOS with a very rich history and interesting technological solutions. In this talk, we will find out what problems await you if you decide to write your development environment, how to solve some of them and what undocumented features of Xcode will help you in this difficult task.
Agenda:
1. Introduction and history;
2. How AppCode works with code: code modifications, indexing, SourceKit usage, etc;
3. Building, running, and debugging;
4. Conclusion.

Aydar

January 10, 2022
Tweet

More Decks by Aydar

Other Decks in Programming

Transcript

  1. AppCode history From the idea to the implementation 2008 idea

    of an IDE for Objective-C 2009 Objective-C parser
  2. Intentions if (b > 0 ? b * 4 :

    b / 5) != a { //... if a != (b > 0 ? b * 4 : b / 5) { //... Cmd+C, Cmd+V, Cmd+C, Cmd+V
  3. if (b > 0 ? b * 4 : b

    / 5) != a { //... 😰 Intentions
  4. Code processing Intro if (b > 0 ? b *

    4 : b / 5) != a { //... Text if ( b > 0 ? b * 4 … Lexems Abstract syntax tree if expression if condition code block parenthesised expression != a
  5. Intentions if (b > 0 ? b * 4 :

    b / 5) != a { //... 1. Update PSI 2. Apply formatting settings 3. Generate text Code processing
  6. Inspections class MyObject: AnotherObject { @objc override func foo() {}

    @objc override func bar() {} } Alt+Enter —> Remove redundant @objc attribute Code processing
  7. Inspections class MyObject: AnotherObject { @objc override func foo() {}

    @objc override func bar() {} } class AnotherObject: NSObject { @objc func foo() {} func bar() {} } Code processing
  8. ❓❓❓ 😞 
 PSI class MyObject: AnotherObject { @objc override

    func foo() {} @objc override func bar() {} } ❓ Code processing Inspections
  9. Building symbol tables class Person { let name = "John"

    let surname = "Doe" let age = 42 !// Very important function func greet() { print("Hi \(name)!") } } class Person let name: String let surname: String let age: Int func greet() #-> Void Symbol table Finding declarations
  10. CoreAudio SwiftUI Accelerate StoreKit Foundation MapKit UIKit AdSupport Modules symbol

    tables cache import Foundation import StoreKit import CoreAudio import Accelerate import SwiftUI import MapKit import AdSupport … Finding declarations Building symbol tables
  11. Symbol tables invalidation class Person { let name = "John"

    let surname = "Doe" let age = 42 !// Very important function func greet() { print("Hi \(name)!") } } class Person let name: String let surname: String let age: Int func greet() #-> Void Symbol table Finding declarations
  12. class Person { let name = "John" let surname =

    "Doe" let dateOfBirth: Date? = nil !// Very important function func sayHello() { print("Hi \(name)!") } } class Person let name: String let surname: String let age: Int func greet() #-> Void Symbol table 🕸 🕷 Finding declarations Symbol tables invalidation
  13. A C B F D E G H K L

    N O P Q M D C A Finding declarations Symbol tables invalidation
  14. Finding type declarations ❓❓❓ class MyObject: AnotherObject { @objc override

    func foo() {} @objc override func bar() {} } Finding declarations
  15. func someFunction() { !// !!... class MyObject: AnotherObject { @objc

    override func foo() {} @objc override func bar() {} } !// !!... } Finding declarations Finding type declarations
  16. class SomeClass { !// !!... func someFunction() {##...} !// !!...

    } extension SomeClass { !// !!... } Finding declarations Finding type declarations
  17. !// !!... class SomeClass {} !// !!... extension SomeClass {}

    !// !!... MyFile.swift Finding declarations Finding type declarations
  18. import Foundation import StoreKit import CoreAudio import Accelerate import SwiftUI

    import MapKit import MyLibrary Finding declarations Finding type declarations
  19. func bar() {} func bar(_ v: Int = 0) {}

    bar() Finding declarations Finding function declarations
  20. func bar(_ v: String = "") {} private func someFunction()

    { func bar(_ v: Int) {} bar("hello") } extension Int: ExpressibleByStringLiteral {##...} Finding declarations Finding function declarations
  21. Swift and Objective-C class MyObject: AnotherObject {} @interface AnotherObject :

    NSObject !//!!... @end objc class AnotherObject: NSObject Finding declarations
  22. Swift and Objective-C class MyObject: AnotherObject {} @interface AnotherObject :

    NSObject !//!!... @end objc @interface MyObject : NSObject objc Finding declarations
  23. class MyObject: AnotherObject { @objc override func foo() {} @objc

    override func bar() {} } Finding declarations
  24. 2020-04-02 15:46:10.180 Xcode[94422:5859798] SourceKit-client: [2:request:112131: 7.4167] [31] { key.request: source.request.codecomplete,

    key.compilerargs: [<...>], key.offset: 0, key.sourcefile: "/Users/aydar.mukhametzyanov/Documents/iOS/EmptyMac/EmptyMac/main.swift", key.sourcetext: "le", key.toolchains: [ "com.apple.dt.toolchain.XcodeDefault" ] } SourceKit usage Completion
  25. 2020-04-02 15:46:11.664 Xcode[94422:5859799] SourceKit-client: [2:response:112131: 8.7030] [31] { key.results: [

    { key.kind: source.lang.swift.keyword, key.name: "let", key.sourcetext: "let", key.description: "let", key.typename: "", key.context: source.codecompletion.context.none, key.num_bytes_to_erase: 0, key.substructure: { key.nameoffset: 0, key.namelength: 3 } }, <...> ] SourceKit usage Completion
  26. key.kind: source.lang.swift.decl.function.method.instance, key.name: "addChild(:)", key.sourcetext: "?.addChild(<#T##childController: UIViewController##UIViewController#>)", key.description: "addChild(childController: UIViewController)",

    key.typename: "Void", key.modulename: "UIKit.UIViewController", key.context: source.codecompletion.context.thisclass, key.num_bytes_to_erase: 1, key.associated_usrs: "c:objc(cs)UIViewController(im)addChildViewController:" SourceKit usage Completion
  27. Derived Data Derived Data Xcode 10 “This is prohibited to

    prevent build state inconsistencies.” Build
  28. How we develop AppCode Kotlin, Java, C++, Objective-C IDEA, AppCode,

    CLion Monorepo 3 releases per year YouTrack Upsource TeamCity
  29. Tests, tests, tests TeamCity duty Push to trunk Release branches

    for EAP (Early Access Program) How we develop AppCode
  30. Switch from iOS development: personal experience 🍏 🍏 + ☕

    Huge project Longer release cycle Big research tasks null 🤔 nil Who develops AppCode
  31. QA engineers Manual testing experience Ability to move a project

    forward independently Who develops AppCode
  32. 👤 Team and processes • How we develop AppCode •

    Who develops AppCode 👋 Introduction and AppCode history • Introduction • AppCode history ⌨ Programming language support • Code processing • Finding declarations • SourceKit usage 🛠 Build, run and debug • Build • Run on simulator • Run on device • Debug
  33. Conclusion Making an IDE is hard, but possible AppCode doesn’t

    contain black magic Everybody can help to make AppCode better