Week 1: First day was a quite slow day, watching & listening to slides, just some course admin related stuff. Setting up the factory computer took a bunch of time. I'll probably install my stuff only on the factory machine, and then VNC/SSH in. As well as root access and local disks, these seem to be slightly more powerful than the identical looking ones in other computer classes. The project I'm working on is Kotlin, a JVM-based functional programming language developed by JetBrains, the company behind IntelliJ IDEA. I chose this project because I like their products and am interested in compilers in general. We had received instructions to build the source tree earlier. Like all Java projects, it was a moderately painful task. (Un)fortunately, no Maven. Instructions for compiling were quite clear, and I got it to compile after fighting for a while, but not quite all of tests pass after building. Will have to investigate that. On tuesday we had finally figured out the Facebook travel stuff, which was relieving. Our mentor had sent us some things to try after getting the thing to compile, so I tried those, while checking out the Kotlin docs on their wiki. I also took a lot of time to glance around the compiler source, mostly language frontend stuff. It has a flex-based lexer and a hand-written parser. Overall code quality seems pretty good, almost zero comments though. Also, finally got an e-mail from our mentor, with a Doodle link to decide when the first IRC meeting will be held. It's been quite quiet on that end otherwise. Wednesday was still just getting more acquainted with the langnuage. The IDE plugin has an automatic Java-to-Kotlin transformer, so I tried it out and some samples on their webpage. The Java-to-Kotlin transformer works but, but the transformed source needs some minor fixups if there are lots of calls to plain Java code, as types in Kotlin are by default not nullable. I also browsed out their bugzilla, looks like enums are kinda unfinished and need more work. I found a bunch of bugs that seemed to be fixed but not closed in the but tracker, but also some that look simple enough to fix. Still haven't heard anything else about the IRC meeting, and not everyone has even responded to the Doodle yet. By thursday I was a bit bored, and just decided to do something on my own. One of the open bugs was getting Ohloh to recognize Kotlin as a programming language. That means coding Kotlin support into Ohcount, Ohloh's programming language detector. That wasn't too difficult after all, but the Ohcount's language recognizers are written in Ragel, which is C with some quite cryptic build-in syntax for building finite state automata and the general quality of Ohcount was quite crappy. For one, the test suite seemed to be completely broken, but after fiddling with it for the day I got it to work. Also got e-mail from our mentor. We now have a Google groups mailing list and our first IRC meeting on Friday, 18:00. Week 2: So far, the work on the project has bee nmostly baby steps. Like all Java projects, getting the whole thing to build and pass all (or even most) tests took a long time. Our first two IRC meetings were mostly about discussing the various tests that were failing on each ones' setup. I think that almost none of us got all tests to pass on the first try. There's still two tests that are not passing. After installing four different versions of the Java JDK (both OpenJDK and Oracle's Java, and versions 6 and 7 of both of them), Oracle's Java 6 gives the local minima of 2 failing tests. Based on the IRC meeting logs and some of the mailing list posts, there are two other people that have the exact same tests failing as me. One common factor seems to be that we all are running Linux, so it probably is just a platform-specific bug on just Linux, possibly in the JDK itself. So much for "Write once, run anywhere". Sounds more like "Write Once, Debug Everywhere", or something like that. Last week we received a simple task (Task 0) to do so we can get familiar with the codebase. We are supposed to add a simple intention action to the IntelliJ IDEA Kotlin plugin. Intention actions automate code transformations triggered by user. In IntelliJ IDEA and Netbeans too, these are the light bulb icons that appear in the left margin when the cursor is over some code where the intention action can be invoked. For example: return if (a is String) "string" else if (a is Int) "integer" else "neither string nor integer" This if-expression could be written as a pattern match instead (an extended form of an switch statement in Java): return when (a) { is String -> "string" is Int -> "integer" else -> "neither string nor integer" } The Kotlin plugin already supports this transformation. IntelliJ IDEA has quite many of these for Java but there are just a couple of them for Kotlin. The kind of intention actions needed in Kotlin are for replacing Javaisms in Kotlin code with more preferred ways to do things. For example, Kotlin has operator overloading for the array bracket notation, so that things like getting a value from a Java ArrayList can be written as the familiar notation 'arrayList[0]' instead of 'arrayList.get(0)'. That's our first task, to add an intention action for transforming method calls to the 'get' method to the array bracket notation. Coding the feature was relatively straightforward after taking some time to carefully read the existing intention actions. Basically, the Kotlin plugin interactively parses the source code in the background and builds a syntax tree. When the user moves the cursor, the intention action code can examine the syntax tree near the user's cursor to decide whether there is something that can be done. So basically, I have to figure out if the cursor is over a function call expression, where the function name is 'get', and then replace the function call node with an array access node. It didn't take too long, and I submitted the code on friday and am waiting for it to be reviewed. Week 3: This week I had two wisdom tooth removed on tuesday, so two days of working time disappeared into resting time, and productivity for the rest of the weeks hasn't been great. Also, our team has had a bunch of problems this week. Apparently someone at JetBrains pushed "an important update" to the Kotlin repository, and now half of our team can't suddenly build the source tree again. By just looking at the others' build logs, I'll have to rant that it's always the Java projects with these completely insane errors I mean, there's someone that's missing entire class hierarchies at compile time ("package org.jetbrains.jet.lang.descriptors does not exist"), another with some classes missing at runtime ("java.lang.NoClassDefFoundError: Could not initialize class org.jetbrains.jet.lang.resolve.java.resolver.TraceBasedJavaResolverCache") and then a third one with Ant/XML issues ("/Users/pkukkapalli/kotlin/build.xml:53: taskdef class com.intellij.ant.Javac2 cannot be found"). That's just completely ridiculous! Funnily enough, I didn't get any issues except that now there's another seven tests that are not passing. Having to deal with these build problems means our mentor's been quite busy so code reviews for our Task 0 pull requests took a bit longer to take place. Combined with the working days lost to the tooth ache, I only managed to get one review cycle's worth of comments instead of the 2 I was expecting. Fortunately there were only very minor issues left, like the proper capitalization of the menu entries shown on the GUI context menus. I did discover one oddity when manually testing my code transformation: activating the transformation sometimes would sometimes add spurious parenthesis to the end result. E.g. foo.get(1, 2, 3) would properly get transformed to foo[1, 2, 3], but this.get(1, 2, 3) becomes (this)[1, 2, 3] instead. After some digging around I determined that it's due to a bug in the Kotlin IDEA plugin's operator precedence calculation: for some reason the precedence of the 'this' keyword is different from a regular identifier. And indeed when calculating the operator precedence value for a 'this' expression, the code takes a different code path than the simple variable case: if (expression instanceof JetDeclaration || expression instanceof JetStatementExpression || expression instanceof JetIfExpression) { return 0; } Specifically, the middle condition (expression instanceof JetStatementExpression) passes, so the this keyword is regarded as a 'statement expression' in the code, as the class for representing a 'this' expression (JetThisExpresssion) derives from JetLabelQualifiedInstanceExpression that in turn implements the JetStatementExpression interface. I don't have the slighest clue what a JetLabelQualifiedInstanceExpression is, but JetStatementExpression seems simple enough: /** * This is an interface to show that {@link JetExpression} is not * actually an expression (in meaning that this expression can be placed after "val x = "). ... Now this is certainly very wrong, as 'val x = this' is a perfectly valid statement, so I started to wonder if it should implement that interface at all. I took a quick look with IDEA's Find Usages tool and saw that there aren't really that many places that check for 'instanceof JetStatementExpression', and just decided to remove the 'implements JetStatementExpression' from JetLabelQualifiedInstanceExpression and see what happens. Sure enough, no extra parenthesis appear around 'this' any more and no extra tests seem to be failing either. But then I went to check other places where those 'instanceof JetStatementExpression' checks exist and yep, I now have a slight bug in the Extract Variable feature of the IDE. That code looks a bit too hairy to start messing around with, so I decide to wait until Monday when the mentors are back online. Week 5: First picture: https://fbcdn-sphotos-b-a.akamaihd.net/hphotos-ak-prn2/t1/1800316_259737357527813_363648972_n.jpg This is a picture of Scott Chacon from GitHub, giving us a talk about using the Git version control system. Chacon is an important figure behind GitHub: he's been GitHub's CIO for five years. He has also written a popular learning resource for Git: the free Pro Git book (http://git-scm.com/book). Scott gave us a talk about using Git for open source projects, which is obviously useful for all people working on the Open Academy projects. He had a some sort of existing presentation slide deck for these kinds of presentations. Though he didn't actually use the slides much since most of the audience already knew the basics of Git, and he had to sidetrack from his slides and to be honest, the talk was somewhat confusing at various times, as he jumped from topic to topic. But he did talk about various useful lesser-known Git features like the index and adding partial changes from a file to a commit. He also demonstrated GitHub's own GUI client and the GitHub's pull requests by deleting all files from some Aaron Patterson's (some semi-famous Rails developer) repository. Much hilarity ensued when Aaron actually merged the pull request for a moment (https://github.com/tenderlove/rkelly/pull/33). Also what's interesting is that he did the most of his Git demonstrations inside his clone of the actual GitHub source tree. Second picture: https://fbcdn-sphotos-c-a.akamaihd.net/hphotos-ak-prn1/t1/1625611_259737390861143_357704927_n.jpg This picture shows all the snacks available for employees (and obviously us) at Facebook's campus. This picture is from Sunday, when all teams were at the the same building. On Friday and Saturday, team Kotlin was at the other building, which didn't have as much snacks as in the picture. Our building had only 2 trolleys of snacks and they didn't have the cereal boxes as well. I'm envious of the Rails and Socket.IO teams which were in this building all the time. But on the other hand, our building's fridge had more different kinds of drinks since it didn't have all the huge milk containers taking up space. I especially liked that they had Beef Jerky, since it's really expensive in Finland. Apparently I should have tried their Turkey Jerky, since someone told me that it's a better kind of jerky. It was also nice that their fridge had some healthy drinks like apple juice (they label it apple cider, I wonder why) and some protein drinks. These snack trolleys were especially perilous for the first day at Facebook, since I was working on a Java project on my old, university-loaned Core 2 Duo laptop. That is, almost every time I'd hit the compile button in the IDE, it would take at least three minutes to build anything, and almost every single time I would go and grab some snacks or another drink. On the later days I learned to eat not as much. Though still the eating shouldn't hurt, as I weighted myself on the baggage scales at the hotel and Amtrak station, and still have some more kilos to break the 60 kg barrier. Picture of their fridge as well: https://fbcdn-sphotos-a-a.akamaihd.net/hphotos-ak-ash3/t1/1621846_259737350861147_698598144_n.jpg Week 6: Our project uses IRC and mailing lists for communication, which are both pretty primitive methods. Or well, at least I hate mailing lists with a passion. I dislike communicating with e-mail in general and mailing lists just make everything worse. I hate the fact that you have to have local copies of all messages. If you have to read messages that were sent to the list before you subscribed to the list (luckily there's no need for that in our project), the only option is to basically google the subject and crawl through all the results on the 25 different read-only web interfaces, all of which have completely terrible UIs designed by people clearly still living in the 70s. Now there are NNTP newsgroups of many mailing list archives available, which is only slightly better. If you want to search for something, you need to download all the messages, and for lists like the LKML, this causes at least Thunderbird to just collapse under the load of messages. Gmail used to have a good GUI, but now it's gotten quite bad. For instance, the buttons for the next page of search results are near the top, which is extremely annoying and unintuitive. And replying in Gmail defaults to replying just to the message's sender and not the entire list; I think I've now made that mistake at least twice. Mailing lists also have the nice property of breaking various e-mail protocol additions. If you've ever subscribed to the university's or department's mailing lists with a gmail address, you might have noticed that a lot of it goes automatically to gmail's spam folder. That's because for any message sent from a @cs.helsinki.fi address, the department's mail server adds DMARC authentication headers to all outgoing messages and as mailing lists work by munging the 'To:' header when sending the message out to the list's recipients, the DMARC signature no longer matches and gmail automatically sends the message to the spam folder, as it thinks the message's sender address was forged. And while we're at the topic of the university's mailing lists, the software that manages them (Majordomo) is probably the single most user-unfriendly software ever made; I just can't understand how someone has thought that an e-mail based command line interface is a good idea. The Google Groups isn't that much better: I had given my @helsinki.fi address to the Open Academy form, so our project mentor sent the Groups invite to that address. Then when I clicked the 'accept' link for that group, the first thing it wanted to do was to sign in to gmail, so somehow I'm now subscribed with both my university e-mail address and with my gmail address. Now I have the pleasure of getting two notifications on my tablet for each e-mail from that group, with an annoying random delay between them (as gmail sends out instant push notifications but the other account is polled via IMAP)... Week 7: It's hard to believe that we're already at the half-way point, since I have a suspicious feeling that our team's achievements haven't actually been that numerous. And looking at the Git logs for the master branch confirms this suspicion. I'm leading the merge count with 8 commits, after me is Pradyoth with 2 commits, and finally Tal and Steven with a single commit from both of them. That's still six people with no merged changes. But at least it doesn't look as bleak when I go and have a look at the open pull requests page in GitHub. There are two pull requests from both Steven and Tal, and one pending from me, Zachary, Gavin, Lingzhang and Jeremy. And there's still that one pull request from me to Ohloh's Ohcount, as it looks like those maintainers aren't really that active anymore. So except for this one guy (Ross), all are fortunately making some progress and getting their code reviewed. Still, I would have expected to see more completed tasks, since all of them except Ross were at the Facebook code sprint, and they all seemed relatively competent. I recall that our mentor was doing plenty of pull request reviews at Facebook, but maybe many of them were just still working on the practice task back there. And well, there is also a difference on the kind of things we've worked on. When I did the exercise task 0, I noticed a couple of Kotlin IDE bugs at the same time, and since the code reviewers were really busy at the time, I started to work on fixing them instead of waiting for Andrey to give out new tasks. So all others have been working on actual features instead of bugfixes, and those obviously take more time. The one pull request I have pending is for a feature and it's really taken a long time and is on its fourth review cycle already. At least the code reviewer I've had is pretty strict with what gets merged, and I guess they all are. They require not only tests, but also a clean Git history, and that's probably where people are struggling a lot. Or at least I had to help some people with the rebase-oriented Git workflow at the Facebook hackathon. I'd say working in this project requires a bit too much advanced Git knowledge from the students. There's also the problem that almost all of us are working near the same code, so you have merge conflicts during rebasing each time someone else gets their feature in. Week 8: The programming language I've used the most in this project is not so surprisingly, the Kotlin programming language itself. Now, almost all of the language core and some of the IDE plugins are still written in Java, but all the new features we have been implemented were required to be written in Kotlin. This might actually be the reason why getting the source tree to build after a git fetch is sometimes so difficult. There are two ways to build this thing, from command line using Ant, and from the IntelliJ IDEA IDE. I believe the Ant build.xml downloads a precompiled Kotlin compiler from the Internet and then rebuilds the source tree with that, wheras the IDEA build always builds with whatever compiled compiler there currently is available on the disk. So that means if either the language syntax or the Kotlin <-> Java interop has changed too much, the compiler is too old to build a newer version of itself, which is a pretty scary thought. The Kotlin language itself is pretty nice I guess. The language seems to target being a better and more statically typed Java. It primarily targets the JVM and compiles to JVM byte code, but a JavaScript backend is supposedly also available, though I've never tried it. What the language looks to me is a simplified Scala. Kotlin brings several features from functional programming languages, like lambda functions, partial type inference and null safety. By default, types in Kotlin don't allow null values but there is a nullable version of every type available by appending a question mark to the type name, like 'String?'. The Kotlin compiler performs control flow analysis and prevents potentially null values from used in contexts that would raise NullPointerExceptions or given to functions or returned from functions if the expected type is not nullable. There are also helper operators for dealing with nullable values: the null-safe property access operator '?.' which is like the ordinary '.' operator in Java but returns null if it's used on a null value. For example: var a : String = "abc" a = null is a compilation error because String is not a nullable type. When a question mark is appended to the type name to make it nullable, now it compiles: var b : String? = "abc" b = null // ok However, now method calls on a are okay but direct method calls on 'b' are not possible. val len = a.length() // ok val len = b.length() // error: variable 'b' can be null Now there are several possibilities for getting the length: val len = b?.length() Now 'len' has type Int?, i.e. a nullable integer, so if b is null, 'len' is also null. Another way around this to check with an 'if' statement: val l = if (b != null) b.length() else -1 Now, the compiler allows the call to 'b.length()' since it has performed control flow analysis and sees that 'b.length()' can be only executed when 'b' is not null, since the if statement checks for that. Week 9: Classes in Kotlin have actually diverged quite a bit from Java. Let's start with an example of a class declaration: class Foo(param: String) { private val bar = param val uppercased = param.toUpperCase() fun shout() : String { return bar + "!" } } Then we can use it like this: val foo = Foo("bar") println(foo.shout()) // prints "bar!" println(foo.uppercased) // prints "BAR" So we can see that the class itself and a single constructor were declared at the same time. I believe Kotlin currently supports only a single constructor. I think there have been plans for constructor overloading but they were scrapped at some point. As we can see, the constructor parameter's scope seems to be the entire class body, and we can use it in property initializers, but not directly inside methods. When we look at how the class can be used, we can see the keyword 'new' is not used when creating new instances. It's kinda like going back to C++ syntax, but the 'new' keyword was just noise anyway in Java. Method calls work just like in Java, but there's a twist with properties: it doesn't create a plain public field, but instead a getter is autogenerated and the property access 'foo.uppercased' actually calls the getter under the hood. I don't think there's a way to make an explicit call to the getter in Kotlin, but in Java code the property access must be written as 'foo.getUppercased()'. This autogeneration of properties removes a bunch of boilerplate code that's usually just autogenerated by the IDE in Java projects. There's also a nifty shortcut that the 'val' keyword can be used directly in the constructor parameter declaration. For example: class ImmutablePoint(val x: Int, val y: Int, val z: Int) { } This Kotlin code is all that's required for a simple immutable class that has a few fields and no logic. It accomplishes all the same that the following Java code: class ImmutablePoint { private final int x; private final int y; private final int z; ImmutablePoint(int x, int y, int z) { this.x = x; this.y = y; this.z = z; } public int getX() { return x; } public int getY() { return y; } public int getZ() { return z; } } Recall that 'val' in Kotlin is always an immutable variable, so setting the property is naturally not possible and therefore no setters are generated. If we were to want those as well, we can just use 'var': class MutablePoint(var x: Int, var y: Int, var z: Int) { } Now we'll have the equivalent of this: class MutablePoint { private int x; private int y; private int z; MutablePoint(int x, int y, int z) { this.x = x; this.y = y; this.z = z; } public int getX() { return x; } public int getY() { return y; } public int getZ() { return z; } public void setX(int x) { this.x = x; } public void setY(int y) { this.y = y; } public void setZ(int z) { this.z = z; } } Week 10: The overall architecture of the project is quite complicated and we haven't been touching most of the parts, so I'll probably learn some of it now. There is one Git repository which is quite large when it's checked out and the project is build. A fully build Kotlin tree takes 1.7 gigabytes for me. I think most of the space is taken by the IDE plugin, as the build scripts download an entire sandboxed IntelliJ IDEA installation for developing the IDE plugin. The whole thing can be opened in IDEA as it is a single IDEA project with multiple modules. That's a very useful abstraction in IDEA that a single project file can have multiple modules with, and I think NetBeans lacks this feature, though I think it allows projects to depend on other projects. There are 35 different modules and I don't have a clue what most of them are doing. There seem to be different modules for the compiler frontend, backend, and cli (command line interface). Then there are three projects for the JavaScript backend, a couple for the Java-to-Kotlin converter, some for the IntelliJ IDEA plugin, and some kind of vague stuff for the rest. Regarding the compile process itself and the IDE plugin stuff we've been working on, as we all know, the first step of a compiler is a lexer. A lexer takes in the textual source code and delimits it into tokens. That's located in the frontend project, in compiler/frontend/src/org/jetbrains/jet/lexer/Jet.flex. The lexer is written in a special-purpose domain-specific language called flex. The flex file contains a bunch of regular expressions and Java code to be executed when each regular expression matches a part of the input. The flex code is then translated to Java code, which implements a table-driven deterministic finite automaton (DFA) which is an efficient algorithm for matching text. The lexing phase takes in source text and produces tokens, that are instances of the class JetToken. The next step is to parse the token stream into syntax trees. The parser is in the frontend module as well, in compiler/frontend/src/org/jetbrains/jet/lang/parsing/ and is written in plain Java, as a simple top-down predictive parser. As it's a couple of thousand lines long, it's splitted into several classes. The parser produces a syntax tree of the program source, or as in JetBrains lingo, tree of PSI (Program Structure Interface) elements. The parser is very simple and stupid, it doesn't resolve types or does any semantic analysis. That's because the lexer and parser are used directly by the IDEA plugin, and they might be needed to be re-run nearly every time an editor window's contents get changed. Also, a large chunk of the IDE functionality doesn't require anything else besides the tokens or syntax tree but the lack of some of them is visible pretty soon. I'd believe syntax highlighting depends just on the lexing phase. And most of the intention actions we've been writing have actually depended just on the syntax tree. Week 11: At least for the parts that we've been touching, project Kotlin is extremely well tested. In fact, there are over 10000 individual test cases in the project, for multiple different modules. Obviously we've been required to add tests for all the things we've done. However, there are many pain points with the project's tests. There are so many of them that it takes 15 minutes to run it. That means I practically never bother to run the entire test suite. Even though the tests are split into non-monolithic per-module tests, and in theory, I could run just the IDEA plugin-specific tests, even the IDEA tests take five minutes. One thing I see is that most of the tests aren't really proper unit tests but closer to integration tests. Much of the functionality isn't directly tested by say JUnit tests that create objects, call some methods and make assertions, but instead there are invidiual source files that are used as test cases and correct behaviour is indirectly observed by what errors the compiler reports on the file. This is pretty powerful technique for testing a compiler, but I'd guess it leads to tests with more runtime overhead. I'd wish that some of the tests were replaced with more suitable and lighter unit tests. Another painful thing with the IDEA plugin tests is that most of the tests utilize generated Java code. There is a script that scans all the test case files in the project and generates a huge JUnit test class that contains a stub method for each test file located. I guess this is done to integrate with the existing JUnit functionality in the IDE, so only a part of the tests can be run and so on. But instead of being generated at compile time, this generated test file is committed into the git repository. This realy doesn't make sense as Maven at least has support for generating source files at compile time and Ant can be probably scripted to do that as well without too much difficulty. The fact that the file is in Git makes it very painful to do a rebase pull (which is what's required of us) as now I need to re-run the generation script for each local commit I've made to ensure that the automatic merge didn't do anything funky with it. So in addition to the typical build break when pulling a new version, I need a ridiculous number of interactive rebase steps. Week 13: Like in the most programming done nowadays, formal documentation is next to nonexistent. The source tree actually contains a 'docs/' directory but I have never opened that. Let's look what's inside. total 26M drwx------ 4 tmtynkky tkol 4.0K Jan 13 11:05 . drwx------ 28 tmtynkky tkol 4.0K Apr 14 08:09 .. -rw------- 1 tmtynkky tkol 3.8K Jan 13 11:05 CodeGen2012_Proposal.txt drwx------ 3 tmtynkky tkol 4.0K Jan 13 11:05 confluence.jetbrains.com -rw------- 1 tmtynkky tkol 4.1M Jan 13 11:05 CSClub_Kotlin.key -rw------- 1 tmtynkky tkol 432K Jan 13 11:05 CSClub_Kotlin.pdf -rw------- 1 tmtynkky tkol 4.2M Jan 13 11:05 Devclub_Kotlin.key -rw------- 1 tmtynkky tkol 4.2M Jan 13 11:05 Devoxx_Kotlin.key drwx------ 5 tmtynkky tkol 4.0K Jan 13 11:05 exPuzzlers -rw------- 1 tmtynkky tkol 0 Jan 13 11:05 JVMLS_12_Ktloin_Java_Interop.key -rw------- 1 tmtynkky tkol 0 Jan 13 11:05 JVMLS_12_Ktloin_Java_Interop.key.pdf -rwx------ 1 tmtynkky tkol 180K Jan 13 11:05 JVMLS_talk_2011.pdf -rwx------ 1 tmtynkky tkol 150K Jan 13 11:05 JVMLS_talk_2011.pps -rwx------ 1 tmtynkky tkol 181K Jan 13 11:05 JVMLS_talk_2011.ppt -rwx------ 1 tmtynkky tkol 200K Jan 13 11:05 JVMLS_workshop_2011.pdf -rwx------ 1 tmtynkky tkol 192K Jan 13 11:05 JVMLS_workshop_2011.pps -rwx------ 1 tmtynkky tkol 212K Jan 13 11:05 JVMLS_workshop_2011.ppt -rw------- 1 tmtynkky tkol 233K Jan 13 11:05 Kotlin_OopenSystems.pages -rw------- 1 tmtynkky tkol 2.2M Jan 13 11:05 Kotlin-RivieraDev.ppt -rwx------ 1 tmtynkky tkol 4.0M Jan 13 11:05 OSCON_Kotlin.key -rwx------ 1 tmtynkky tkol 413K Jan 13 11:05 OSCON_Kotlin.pdf -rw------- 1 tmtynkky tkol 893 Jan 13 11:05 qr.net_kotlin.png -rw------- 1 tmtynkky tkol 4.1M Jan 13 11:05 StrangeLoop_Kotlin.key -rw------- 1 tmtynkky tkol 578K Jan 13 11:05 StrangeLoop_Kotlin.pdf Yep, no real documentation to be found, just as I guessed. Just some conference slides. But apparently the build process is building javadocs so let's check those as well... Nope, the package overview page is completely blank and a random sampling of 10 classes in general shows zero documentation on the methods except for some lone methods that have a small summary. But it's not like anybody actually wants to read javadocs since the layout is so ugly, with the white background and HTML frames and everything. So for the Kotlin compiler/toolset itself, the pretty much only usable thing is the readme which contains build instructions. For the language libraries itself, there seems to be a some sort of javadoc: http://jetbrains.github.io/kotlin/versions/snapshot/apidocs/index.html which still has the awful frames but at least there's some CSS. Now at least the packages contain a summary and most of the methods in core classes like Strings have some sort of documentation, but that still looks pretty amateurish. For instance, there are apparently JVM implementation-specific things leaking into the documentation, such as KMemberFunction0, KMemberFunction1, KMemberFunction2, and so on all the way until KMemberFunction22. That kind of pollution of the class list looks really sloppy and I really wonder if it could be avoided by blacklisting those classes from the javadoc generator somehow. For the language itself, the situation is better. There is a pretty comprehensive wiki at http://confluence.jetbrains.com/display/Kotlin/Docs+Home, though it uses Confluence which I find very painful to work with. The documentation pages are mostly coherent and up-to-date Week 15: Well, I guess the project itself was fairly interesting, but a second period of this was kind of too much and I really didn't have much motivation to focus on the project for the last few weeks. I guess there were a couple of bigger things, one thing is that the IDE's Kotlin plugin has definitely been getting a lot slower in the meantime, I really don't know why. It tends to freeze for a couple of seconds without responding to any input every now and then. And getting the code completions to update regularly takes over half a minute. It also sometimes experiences a weird input bug where half of the keyboard input would get thrown away and IDEA had to be restarted. Another painful thing was the constant merge conflicts that we were getting as all of us were touching few certain central files at the same time. Also there is the annoying generated-but-checked-into-the-repository java file, which meant a merge conflict almost every single time someone else added some new functionality. Also the rebase-oriented workflow made this worse, since the merge conflict would almost always need fixing say, four times if I were working on a feature split into 4 clean commits. I think that rebasing and explicitly fiddlling with the history to make it 'clean' is a pointless waste of time and a really annoying thing to do.