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

Foundations of a Modern IDE

Foundations of a Modern IDE

Developers may take for granted many features in a modern IDE, but it was not long ago when there was just the command line. Today with the growing complexity of software stacks and frameworks, the importance of effective developer tools has only followed. This talk will cover the basics of static analysis, parsing, debugging, code comprehension, and how we can leverage all these features to develop powerful, integrated language tools and plugins.

Breandan Considine

December 05, 2015
Tweet

More Decks by Breandan Considine

Other Decks in Programming

Transcript

  1. Welcome to Houston TechFest • Please turn off all electronic

    devices or set them to vibrate. • If you must take a phone call, please do so in the lobby so as not to disturb others. • Thanks to our Diamond Sponsors: Thank you for being a part of the 8th Annual Houston TechFest!
  2. Traditional IDE • Rapid navigation (declarations, find usages) • Code

    assistance (completions, refactoring) • Program analysis (validation, inspections) • Build automation (dependencies, compiling)
  3. Today’s IDE • Plugin support • Debugging & profiling •

    Version control • Framework support • Cloud enabled • Visual programming • Device simulation
  4. Back to the basics! Why use an IDE? • Minimizes

    ad-hoc configuration • Provides scaffolding for common tasks • Allows you to focus on writing new code • Accelerates feedback by detecting issues early • Assembles and deploys complex applications
  5. Usability requirements • Keystroke to response under 100ms • Handles

    arbitrarily large projects smoothly • Robust parsing, most of the time code is broken • Any loss of work is unacceptable
  6. http://www.eclipse.org/articles/article.php?file=Article-JavaCodeManipulation_AST/index.html Language parsing • Error recovery is key • Incremental

    parsing ◦ Parsing deltas is much more efficient ◦ Queues enable seamless editing and analysis of code ◦ Once we have an AST, we can expose the code to IDE
  7. From [E]BNF to [A]ST <try> ::= try [resources] <block> <catches>;

    <resources> ::= ( <resource> {';' <resource>} ); <resource> ::= [modifier] <res type> <id> '=' <exprs>; <catches> ::= <catch> | <catch> <catches> | <finally>; <catch> ::= catch( <throwable> <identifier> ) <block>; <throwable> ::= <throw type> {'|' <throw type>}; <finally> ::= finally <block>; <block> ::= {…} *<exprs> ::= extra credit
  8. try (Connection c = getC()) {...} catch (SQLException e) {...}

    finally {...} ___________try_____________ / | \ ___resources____ block \ / | \ ? catches ( ___resource__ ? ? / | | \ res type: ? ? ? Connection ? ? ? <try> ::= try [resources] <block> <catches>;
  9. try (Connection c = getC()) {...} catch (SQLException e) {...}

    finally {...} ___________try_____________ / | \ ___resources____ block \ / | \ ? catches ( ___resource__ ? ? ? <resources> ::= ( <resource> {';' <resource>} );
  10. try (Connection c = getC()) {...} catch (SQLException e) {...}

    finally {...} ___________try_____________ / | \ ___resources____ block \ / | \ ? catches ( ___resource__ ? ? / | | \ res type: ?d: ? exp?s: Connection c getC() <resource> ::= [modifier] <res type> <id> '=' <exprs>;
  11. try (Connection c = getC()) {...} catch (SQLException e) {...}

    finally {...} ___________try_____________ / | \ ___resources____ block \ / | \ ? catches ( ___resource__ ? ? / | | \ res type: id: ? exp?s: Connection c getC() <resource> ::= [modifier] <res type> <id> '=' <exprs>;
  12. try (Connection c = getC()) {...} catch (SQLException e) {...}

    finally {...} ___________try_____________ / | \ ___resources____ block \ / | \ ? catches ( ___resource__ ? ? / | | \ res type: id: = exp?s: Connection c <resource> ::= [modifier] <res type> <id> '=' <exprs>;
  13. try (Connection c = getC()) {...} catch (SQLException e) {...}

    finally {...} ___________try_____________ / | \ ___resources____ block \ / | \ ? catches ( ___resource__ ? ? / | | \ res type: id: = exprs: Connection c getC() <resource> ::= [modifier] <res type> <id> '=' <exprs>;
  14. try (Connection c = getC()) {...} catch (SQLException e) {...}

    finally {...} ___________try_____________ / | \ ___resources____ block \ / | \ ? catches ( ___resource__ ) ? / | | \ res type: id: = exprs: Connection c getC() <resources> ::= ( <resource> {';' <resource>} );
  15. try (Connection c = getC()) {...} catch (SQLException e) {...}

    finally {...} ___________try_____________ / | \ ___resources____ block \ / | \ {…} catches ( ___resource__ ) ? / | | \ res type: id: = exprs: Connection c getC() <try> ::= try [resources] <block> <catches>;
  16. try (Connection c = getC()) {...} catch (SQLException e) {...}

    finally {...} ___________try_____________ / | \ ___resources____ block \ / | \ {…} catches ( ___resource__ ) ? / | | \ res type: id: = exprs: Connection c getC() <try> ::= try [resources] <block> <catches>;
  17. try (Connection c = getC()) {...} catch (SQLException e) {...}

    finally {...} ___________try_____________ / | \ ___resources____ block \ / | \ {…} catches ( ___resource__ ) ? / | | \ res type: id: = exprs: Connection c getC() <catches> ::= <catch> | <catch> <catches> | <finally>;
  18. try (Connection c = getC()) {...} catch (SQLException e) {...}

    finally {...} ___________try_____________ / | \ ___resources____ block \ / | \ {…} ____catches ( ___resource__ ) / / | | \ ______catch________ finally res type: id: = exprs: / | | \ \ Connection c getC() ? throwable id: ? block block ? ? ? <catch> ::= catch( <throwable> <identifier> ) <block>;
  19. try (Connection c = getC()) {...} catch (SQLException e) {...}

    finally {...} ___________try_____________ / | \ ___resources____ block \ / | \ {…} ____catches ( ___resource__ ) / / | | \ ______catch________ finally res type: id: = exprs: / | | \ \ Connection c getC() ? throwable id: ? block block ? ? ? <catches> ::= <catch> | <catch> <catches> | <finally>;
  20. try (Connection c = getC()) {...} catch (SQLException e) {...}

    finally {...} ___________try_____________ / | \ ___resources____ block \ / | \ {…} ____catches ( ___resource__ ) / / | | \ ______catch________ finally res type: id: = exprs: / | | \ \ Connection c getC() ( throwable id: ? block block ? ? ? <catch> ::= catch( <throwable> <identifier> ) <block>;
  21. try (Connection c = getC()) {...} catch (SQLException e) {...}

    finally {...} ___________try_____________ / | \ ___resources____ block \ / | \ {…} ____catches ( ___resource__ ) / / | | \ ______catch________ finally res type: id: = exprs: / | | \ \ Connection c getC() ( throwable id: ? block block / ? ? throw type: SQLException <throwable> ::= <throw type> {'|' <throw type>};
  22. try (Connection c = getC()) {...} catch (SQLException e) {...}

    finally {...} ___________try_____________ / | \ ___resources____ block \ / | \ {…} ____catches ( ___resource__ ) / / | | \ ______catch________ finally res type: id: = exprs: / | | \ \ Connection c getC() ( throwable id: ? block block / e ? throw type: SQLException <catch> ::= catch( <throwable> <identifier> ) <block>;
  23. try (Connection c = getC()) {...} catch (SQLException e) {...}

    finally {...} ___________try_____________ / | \ ___resources____ block \ / | \ {…} ____catches ( ___resource__ ) / / | | \ ______catch________ finally res type: id: = exprs: / | | \ \ Connection c getC() ( throwable id: ) block block / e ? throw type: SQLException <catch> ::= catch( <throwable> <identifier> ) <block>;
  24. try (Connection c = getC()) {...} catch (SQLException e) {...}

    finally {...} ___________try_____________ / | \ ___resources____ block \ / | \ {…} ____catches ( ___resource__ ) / / | | \ ______catch________ finally res type: id: = exprs: / | | \ \ Connection c getC() ( throwable id: ) block block / e {…} throw type: SQLException <catch> ::= catch( <throwable> <identifier> ) <block>;
  25. try (Connection c = getC()) {...} catch (SQLException e) {...}

    finally {...} ___________try_____________ / | \ ___resources____ block \ / | \ {…} ____catches ( ___resource__ ) / / | | \ ______catch________ finally res type: id: = exprs: / | | \ \ Connection c getC() ( throwable id: ) block block / e {…} throw type: SQLException <catches> ::= <catch> | <catch> <catches> | <finally>;
  26. try (Connection c = getC()) {...} catch (SQLException e) {...}

    finally {...} ___________try_____________ / | \ ___resources____ block \ / | \ {…} ____catches____ ( ___resource__ ) / \ / | | \ ______catch________ finally res type: id: = exprs: / | | \ \ \ Connection c getC() ( throwable id: ) block block / e {…} {?} throw type: SQLException <finally> ::= finally <block>;
  27. try (Connection c = getC()) {...} catch (SQLException e) {...}

    finally {...} ___________try_____________ / | \ ___resources____ block \ / | \ {…} ____catches____ ( ___resource__ ) / \ / | | \ ______catch________ finally res type: id: = exprs: / | | \ \ \ Connection c getC() ( throwable id: ) block block / e {…} {…} throw type: SQLException <finally> ::= finally <block>;
  28. Parser generators • Writing parsers is fun • Debugging them

    is not • Most plugins just use generators • Correct by construction • Easier to maintain
  29. Code Awareness and Comprehension • Understanding how your code is

    organized ◦ Code Quality: documentation, cleanliness, complexity ◦ Static Analysis: runtime, dataflow, security, concurrency • Understands how to diagnose and fix issues ◦ Debugging, refactoring, intentions ◦ Framework support and device/platform specific
  30. Static analysis and debugging • Bugs are difficult to detect

    ◦ Obvious bugs are the most harmless ◦ Many bugs are hidden in plain sight • Static analysis catches runtime errors ◦ Checks for syntax then employs more advanced heuristics • Hot swap debugging
  31. Dependency Resolution • Directed acyclic graph • Each dependency is

    represented by an edge • How do we build an application? • Using a topological sort!
  32. An IDE’s work is never done • There are uncountably

    many possible features • Languages & frameworks are constantly evolving • Hardware & platforms are constantly evolving • Programmers are constantly iterating software • Static analysis ⇔ Halting problem, cf. Rice
  33. Too many features, too little time • Each feature has

    uncountably many use cases • Each feature needs to be tested for side effects • Each feature must be supported indefinitely • Hurray for plugin developers!
  34. • Records a complete stack at each instant • Review

    the full trace after program has run
  35. • Headless indexing and code review • Static analysis tools

    • Works with Maven/IDEA builds • Repository browser •