Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dottydoc #1453

Merged
merged 100 commits into from
Aug 23, 2016
Merged

Add dottydoc #1453

merged 100 commits into from
Aug 23, 2016

Conversation

felixmulder
Copy link
Contributor

@felixmulder felixmulder commented Aug 15, 2016

Dottydoc - GSoC

In all ways and means dottydoc is a compiler. It uses the dotty frontend phase to do parsing and typing - after this the documentation phases take over. Similarly to dotty, dottydoc uses fused phases as a way of transforming the documentation AST.

The new scaladoc alias dottydoc is comprised of two parts: a documentation hook and a front end hook.

There are still a few missing features to dottydoc - and this PR was opened now due to the GSoC project coming to an end as well as the limitations of the CI (100 commits - will it pass the tests!?).

The missing parts are currently AFAIK:

  • Grouping
  • Usecase

Scaladoc has a long history, and as such features may have been overlooked, the missing parts as listed will be implemented in the coming weeks together with any missing features reported and vital.

Architecture

                         source files
                               |
                               v
                       +--------------+
 (template) -------->  |              |
                       |   dottydoc   | -----> JSON/html
[resources] -------->  |              |
                       +--------------+

(...) == optional file
[...] == optional list of files

Because dotty needs to bootstrap, we cannot have the client UI be part of the repository if we want to use external scala dependencies. This obstacle became an incentive to do something better - and the idea of third party templates was born. Currently dottydoc supports a specific frontend format which enables users to replace the frontend if they so choose (maybe they don't like the defaults, maybe they can do better - diversity is good).

To build your own frontend this is what you'll need:

.
├── template.html
├── resource1.js
└── resource2.css

The templating engine supported is currently mustache

The template will be given an instance of Entity for each top-level object (traits, objects, classes, packages). Entity has the following signature:

trait Entity {
  def name: String
  /** Path from root, i.e. `scala.Option$` */
  def path: List[String]
  def comment: Option[Comment]
  def kind: String
  def parent: Entity
}

The template is then used to create a collection of static HTML pages à la the old scaladoc. Each template is also given the path to assets (directory) and index (javascript file). As such it is quite easy to build your own template. Example:

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Dottydoc - {{name}}</title>
        <script type="text/javascript" src="{{index}}"></script>
        <script type="text/javascript" src="{{assets}}/dottydoc.js"></script>
        <link rel="stylesheet" href="{{assets}}/index.css">
    </head>
    <body>
        <div id="main-container">
            <h1>{{name}}</h1>
        </div>
        <script>
            (function() {
                Index.currentEntity = {{&currentEntity}};

                var addMember = function(entry) {
                    document.getElementById("main-container").innerHTML += entry.name + "</br>";
                };

                if (Index.currentEntity.members !== undefined)
                    Index.currentEntity.members.forEach(addMember);
            })();
        </script>
    </body>
</html>

The Index object will look like this after the template has been written:

{
    "packages": {
        "scala": { ... },
        "scala.collection": { ... },
        ...
    }
    "currentEntity": {
        "name": ...
    }
}

There is of course already a default front end in place dottydoc-client. This one will be used by default by sbt. This project is available here: https://github.com/lampepfl/dottydoc-client

To view the documentation rendered by the 100th commit in this PR: https://dl.dropboxusercontent.com/u/358427/gsoc-dottydoc/docs/scala/Option.html

There are parts in dottydoc that have been developed for the previous scaladoc and adapted to dottydoc most prominently by @odersky, @VladUreche @manojo - thank you for your hard work.

There is still a ton to do and I will make a small list here of things I plan to work on, and that I'd be happy to receive help on.

The great aftermath of the dottydoc PR

  • @usecase
  • @group
  • Better search that displays members (client)
  • Rename docs -> API and add support for documentation as reference
  • Prototype markdown in doc-comments
  • Properly handle synthetically added methods (argument names are mangled)

@xeno-by
Copy link

xeno-by commented Aug 16, 2016

This is an impressive contribution. Congratulations!

There have always been two things about scaladoc that I thought could be improved. I wonder if you could comment on whether they can be potentially addressed in dottydoc.

  1. Incremental compilation. If I change just one file in the project, I'd like to also regenerate at most one page in the documentation. At the moment, if I'm not mistaken, scaladoc needs a full recompilation. Can something be done about that?

  2. Separate compilation. If I want to include N projects in my documentation, then I need to compile all of them in one compilation run. I think this is pretty inconvenient, and also not always feasible is macros are in play. What do you think about this one?

@felixmulder
Copy link
Contributor Author

Thank you @xeno-by, much appreciated.

  1. Incremental compilation. If I change just one file in the project, I'd like to also regenerate at most one page in the documentation. At the moment, if I'm not mistaken, scaladoc needs a full recompilation. Can something be done about that?

It is not something that has been taken into consideration thus far - but it is definitely something worth investing in further down the line.

Furthermore, I do believe it is possible to preserve the index and mutate it between runs - the API could be made to handle this in some convenient way that works well with the build tools.

  1. Separate compilation. If I want to include N projects in my documentation, then I need to compile all of them in one compilation run. I think this is pretty inconvenient, and also not always feasible is macros are in play. What do you think about this one?

My first reaction is that this could/should be solved using TASTY - but I'm not currently 100% confident in what has been included in the spec (i.e - does TASTY serialize comments attached to their corresponding entity?).

An other alternative would perhaps be to define some form of lookup using the scaladex - but perhaps the tools are better kept separate.

@VladUreche
Copy link
Contributor

It is not something that has been taken into consideration thus far - but it is definitely something worth investing in further down the line.

The problem is changes are not local but ripple out -- e.g. adding a new class means its superclasses get another subclass listed on their pages.

@retronym
Copy link
Member

The problem is changes are not local but ripple out -- e.g. adding a new class means its superclasses get another subclass listed on their pages.

It might be useful to think about this in terms of a compiler + linker. The compiler extracts information from a single .scala file into a corresponding output file (perhaps attributes in the .class file?). References to external data should be expressed symbolically. This could be resolved by a linker (that generates the entire site). The linker itself could be incremental in manner of ScalaJS's linker (ie: "I know that I need to rebuild this section of the page in all superclasses"). The "linker" might even be implemented as Javascript in the view itself.

@felixmulder
Copy link
Contributor Author

/rebuild

* The tool can also generate JSON from the created index using "indexToJson"
* or directly using "createJsonIndex"
*/
trait Dottydoc extends DocDriver {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you have both Dottydoc.java and Dottydoc.scala ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is to have a Java interface for when the time comes that releases are compiled with dotty. As such, tools compiled with dotty should be able to use the Scala interface, while incompatible projects (such as sbt on 2.10) will still be able to use the Java interface.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, should this interface be part of dotty-interfaces ?

Copy link
Contributor Author

@felixmulder felixmulder Aug 22, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm okay with that as long as it's on the same classpath available to the bridge as dotty 😄

Let me know and I'll make it happen.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, let's keep it as is for now

@odersky
Copy link
Contributor

odersky commented Aug 23, 2016

Any objection to merge this now?

@odersky odersky merged commit 265ade0 into scala:master Aug 23, 2016
OlivierBlanvillain pushed a commit to OlivierBlanvillain/dotty that referenced this pull request Dec 12, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants