Commit 0ee3da6c authored by Bruno Coelho's avatar Bruno Coelho Committed by Xianwen Chen

Implement comments support (#379)

* Implement comments support, tests and readme documentation

* improve code comments and documents comments parser when the two types of comments are one after the other

* improve tests
parent a8325df7
......@@ -55,6 +55,10 @@ Djinni's input is an interface description file. Here's an example:
store: set<string>;
hash: map<string, i32>;
// You can generate two types of comments
// - Code comments by using "// comment" in djinni files which will generate "// comment"
// - Code documentation by using "# comment" in djinni files which will generate "/** comment */"
// Both of those types support single and multi line comments
values: list<another_record>;
# Comments can also be put here
......
......@@ -9,7 +9,7 @@ sort_order = enum {
}
sort_items = interface +c {
# For the iOS / Android demo
// For the iOS / Android demo
sort(order: sort_order, items: item_list);
static create_with_listener(listener: textbox_listener): sort_items;
......
......@@ -15,7 +15,7 @@ class SortItems {
public:
virtual ~SortItems() {}
/** For the iOS / Android demo */
// For the iOS / Android demo
virtual void sort(sort_order order, const ItemList & items) = 0;
static std::shared_ptr<SortItems> create_with_listener(const std::shared_ptr<TextboxListener> & listener);
......
......@@ -8,7 +8,7 @@ import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
/*package*/ interface SortItems {
/** For the iOS / Android demo */
// For the iOS / Android demo
public void sort(@Nonnull SortOrder order, @Nonnull ItemList items);
@CheckForNull
......
......@@ -10,7 +10,7 @@
@interface TXSSortItems : NSObject
/** For the iOS / Android demo */
// For the iOS / Android demo
- (void)sort:(TXSSortOrder)order
items:(nonnull TXSItemList *)items;
......
......@@ -35,7 +35,13 @@ class EnumValue(val ty: Ident, ident: Ident) extends Ident(ident.name, ident.fil
case class TypeParam(ident: Ident)
case class Doc(lines: Seq[String])
case class Doc(comments: Seq[Comment])
abstract sealed class Comment {
val lines: Seq[String]
}
case class CodeComment(override val lines: Seq[String]) extends Comment
case class DocComment(override val lines: Seq[String]) extends Comment
sealed abstract class TypeDecl {
val ident: Ident
......
......@@ -18,12 +18,15 @@ package djinni
import djinni.ast._
import java.io._
import djinni.generatorTools._
import djinni.meta._
import djinni.syntax.Error
import djinni.writer.IndentWriter
import scala.language.implicitConversions
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
import scala.util.matching.Regex
package object generatorTools {
......@@ -425,22 +428,44 @@ abstract class Generator(spec: Spec)
def writeMethodDoc(w: IndentWriter, method: Interface.Method, ident: IdentConverter) {
val paramReplacements = method.params.map(p => (s"\\b${Regex.quote(p.ident.name)}\\b", s"${ident(p.ident.name)}"))
val newDoc = Doc(method.doc.lines.map(l => {
paramReplacements.foldLeft(l)((line, rep) =>
line.replaceAll(rep._1, rep._2))
}))
val comments = ArrayBuffer[Comment]()
method.doc.comments.foreach({
case DocComment(lines) =>
val newDocComment = DocComment(lines.map(l => {
paramReplacements.foldLeft(l)((line, rep) =>
line.replaceAll(rep._1, rep._2))
}))
comments += newDocComment
case CodeComment(lines) =>
comments += CodeComment(lines)
})
val newDoc = Doc(comments)
writeDoc(w, newDoc)
}
def writeDoc(w: IndentWriter, doc: Doc) {
doc.lines.length match {
case 0 =>
case 1 =>
w.wl(s"/**${doc.lines.head} */")
case _ =>
w.wl("/**")
doc.lines.foreach (l => w.wl(s" *$l"))
w.wl(" */")
}
doc.comments.foreach({
case DocComment(lines) =>
lines.length match {
case 0 =>
case 1 =>
w.wl(s"/**${lines.head} */")
case _ =>
w.wl("/**")
lines.foreach (l => w.wl(s" *$l"))
w.wl(" */")
}
case CodeComment(lines) =>
lines.foreach (l => w.wl(s"//$l"))
})
}
}
......@@ -16,16 +16,19 @@
package djinni
import java.io.{File, FileNotFoundException, InputStreamReader, FileInputStream, Writer}
import java.io.{File, FileInputStream, FileNotFoundException, InputStreamReader, Writer}
import djinni.ast.Interface.Method
import djinni.ast.Record.DerivingType.DerivingType
import djinni.syntax._
import djinni.ast._
import java.util.{Map => JMap}
import org.yaml.snakeyaml.Yaml
import scala.collection.JavaConversions._
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
import scala.util.control.Breaks._
import scala.util.parsing.combinator.RegexParsers
import scala.util.parsing.input.{Position, Positional}
......@@ -205,7 +208,57 @@ private object IdlParser extends RegexParsers {
case (s, p) => Ident(s, fileStack.top, p)
}
def doc: Parser[Doc] = rep(regex("""#[^\n\r]*""".r) ^^ (_.substring(1))) ^^ Doc
def doc: Parser[Doc] = rep(regex("""#[^\n\r]*""".r) | regex("""\/\/[^\n\r]*""".r)) ^^ { commentLines =>
val docCommentPrefix = "#"
val codeCommentPrefix = "//"
val comments = ArrayBuffer[Comment]()
commentLines.foreach( commentLine => {
if (commentLine.startsWith(docCommentPrefix)) { // DocComment
val commentText = commentLine.substring(docCommentPrefix.length)
if (comments.isEmpty) {
comments += DocComment(Seq(commentText))
} else {
comments.last match {
case DocComment(lines) =>
val newLines = lines :+ commentText
comments.remove(comments.length-1)
comments += DocComment(newLines)
case CodeComment(_) =>
comments += DocComment(Seq(commentText))
}
}
} else if (commentLine.startsWith(codeCommentPrefix)) { // CodeComment
val commentText = commentLine.substring(codeCommentPrefix.length)
if (comments.isEmpty) {
comments += CodeComment(Seq(commentText))
} else {
val commentText = commentLine.substring(codeCommentPrefix.length)
comments.last match {
case DocComment(_) =>
comments += CodeComment(Seq(commentText))
case CodeComment(lines) =>
val newLines = lines :+ commentText
comments.remove(comments.length-1)
comments += CodeComment(newLines)
}
}
}
})
Doc(comments)
}
def parens[T](inner: Parser[T]): Parser[T] = surround("(", ")", inner)
def typeList[T](inner: Parser[T]): Parser[Seq[T]] = surround("<", ">", rep1sepend(inner, ",")) | success(Seq.empty)
......
# Record returned by a client
// Record returned by a client
client_returned_record = record {
record_id: i64;
content: string;
misc: optional<string>;
}
# Client interface
// Client interface
client_interface = interface +j +o {
// Testing code comments before documentation comments
# Returns record of given string
get_record(record_id: i64, utf8string: string, misc: optional<string>): client_returned_record;
identifier_check(data: binary, r: i32, jret: i64): f64;
return_str(): string;
# Testing documentation comments before code comments
// This method takes an interface
meth_taking_interface(i: client_interface): string;
meth_taking_optional_interface(i: optional<client_interface>): string;
}
......@@ -19,7 +22,20 @@ client_interface = interface +j +o {
reverse_client_interface = interface +c {
const return_str(): string;
// Testing code comments before documentation comments
// with multiple lines
// and another line
# Testing documentation comments after code comments
# with multiple lines
# and another line
meth_taking_interface(i: reverse_client_interface): string;
# Testing documentation comments before code comments
# with multiple lines
# and another line
// Testing code comments after documentation comments
// with multiple lines
// and another line
meth_taking_optional_interface(i: optional<reverse_client_interface>): string;
static create(): reverse_client_interface;
......
# enum for use in constants
// enum for use in constants
constant_enum = enum {
some_value;
some_other_value;
......
......@@ -8,10 +8,14 @@ constant_record = record {
constants = record {
# bool_constant has documentation.
const bool_constant: bool = true;
// i8_constant has a comment
const i8_constant: i8 = 1;
const i16_constant: i16 = 2;
const i32_constant: i32 = 3;
const i64_constant: i64 = 4;
// f64_constant has a long comment.
// (Second line of multi-line comment.
// Indented third line of multi-line comment.)
const f32_constant: f32 = 5.0;
# f64_constant has long documentation.
# (Second line of multi-line documentation.
......@@ -39,7 +43,7 @@ constants = record {
};
# No support for null optional constants
# No support for optional constant records
// No support for optional constant records
# No support for constant binary, list, set, map
const dummy: bool = false;
......@@ -79,9 +83,9 @@ constants_interface = interface +c {
some_string = string_constant
};
# No support for null optional constants
// No support for null optional constants
# No support for optional constant records
# No support for constant binary, list, set, map
// No support for constant binary, list, set, map
dummy();
}
......@@ -2,6 +2,9 @@ color = enum {
red;
orange;
yellow;
// "It is customary to list indigo as a color lying between blue and violet, but it has
// never seemed to me that indigo is worth the dignity of being considered a separate
// color. To my eyes it seems merely deep blue." --Isaac Asimov
green;
blue;
# "It is customary to list indigo as a color lying between blue and violet, but it has
......
......@@ -3,7 +3,7 @@ first_listener = interface +o {
first();
}
# Used for ObjC multiple inheritance tests
// Used for ObjC multiple inheritance tests
second_listener = interface +o {
second();
}
......@@ -25,7 +25,7 @@ return_one = interface +c {
return_one(): i8;
}
# Used for C++ multiple inheritance tests
// Used for C++ multiple inheritance tests
return_two = interface +c {
static get_instance(): return_two;
return_two(): i8;
......
......@@ -8,6 +8,8 @@ extern_record_with_derivings = record
e: test_color;
} deriving(eq, ord)
// This file tests YAML dumped by Djinni can be parsed back in
extern_interface_1 = interface +c
{
foo(i: test_client_interface): test_client_returned_record;
......
......@@ -13,11 +13,12 @@ namespace testsuite {
struct ClientReturnedRecord;
/** Client interface */
// Client interface
class ClientInterface {
public:
virtual ~ClientInterface() {}
// Testing code comments before documentation comments
/** Returns record of given string */
virtual ClientReturnedRecord get_record(int64_t record_id, const std::string & utf8string, const std::experimental::optional<std::string> & misc) = 0;
......@@ -25,6 +26,8 @@ public:
virtual std::string return_str() = 0;
/** Testing documentation comments before code comments */
// This method takes an interface
virtual std::string meth_taking_interface(const std::shared_ptr<ClientInterface> & i) = 0;
virtual std::string meth_taking_optional_interface(const std::shared_ptr<ClientInterface> & i) = 0;
......
......@@ -10,7 +10,7 @@
namespace testsuite {
/** Record returned by a client */
// Record returned by a client
struct ClientReturnedRecord final {
int64_t record_id;
std::string content;
......
......@@ -11,6 +11,9 @@ enum class color : int {
RED,
ORANGE,
YELLOW,
// "It is customary to list indigo as a color lying between blue and violet, but it has
// never seemed to me that indigo is worth the dignity of being considered a separate
// color. To my eyes it seems merely deep blue." --Isaac Asimov
GREEN,
BLUE,
/**
......
......@@ -17,6 +17,7 @@ struct Constants final {
/** bool_constant has documentation. */
static constexpr bool BOOL_CONSTANT = true;
// i8_constant has a comment
static constexpr int8_t I8_CONSTANT = 1;
static constexpr int16_t I16_CONSTANT = 2;
......@@ -25,6 +26,9 @@ struct Constants final {
static constexpr int64_t I64_CONSTANT = 4;
// f64_constant has a long comment.
// (Second line of multi-line comment.
// Indented third line of multi-line comment.)
static constexpr float F32_CONSTANT = 5.0f;
/**
......@@ -60,11 +64,9 @@ struct Constants final {
static ConstantRecord const OBJECT_CONSTANT;
/**
* No support for null optional constants
* No support for optional constant records
* No support for constant binary, list, set, map
*/
/** No support for null optional constants */
// No support for optional constant records
/** No support for constant binary, list, set, map */
static constexpr bool DUMMY = false;
};
......
......@@ -62,11 +62,9 @@ public:
static ConstantRecord const OBJECT_CONSTANT;
/**
* No support for null optional constants
* No support for optional constant records
* No support for constant binary, list, set, map
*/
// No support for null optional constants
/** No support for optional constant records */
// No support for constant binary, list, set, map
virtual void dummy() = 0;
};
......
......@@ -7,6 +7,7 @@
#include "client_returned_record.hpp"
#include <memory>
// This file tests YAML dumped by Djinni can be parsed back in
class ExternInterface1 {
public:
virtual ~ExternInterface1() {}
......
......@@ -8,7 +8,7 @@
namespace testsuite {
/** Used for C++ multiple inheritance tests */
// Used for C++ multiple inheritance tests
class ReturnTwo {
public:
virtual ~ReturnTwo() {}
......
......@@ -15,8 +15,24 @@ public:
virtual std::string return_str() const = 0;
// Testing code comments before documentation comments
// with multiple lines
// and another line
/**
* Testing documentation comments after code comments
* with multiple lines
* and another line
*/
virtual std::string meth_taking_interface(const std::shared_ptr<ReverseClientInterface> & i) = 0;
/**
* Testing documentation comments before code comments
* with multiple lines
* and another line
*/
// Testing code comments after documentation comments
// with multiple lines
// and another line
virtual std::string meth_taking_optional_interface(const std::shared_ptr<ReverseClientInterface> & i) = 0;
static std::shared_ptr<ReverseClientInterface> create();
......
......@@ -5,7 +5,7 @@
namespace testsuite {
/** Used for ObjC multiple inheritance tests */
// Used for ObjC multiple inheritance tests
class SecondListener {
public:
virtual ~SecondListener() {}
......
......@@ -6,8 +6,9 @@ package com.dropbox.djinni.test;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
/** Client interface */
// Client interface
public interface ClientInterface {
// Testing code comments before documentation comments
/** Returns record of given string */
@Nonnull
public ClientReturnedRecord getRecord(long recordId, @Nonnull String utf8string, @CheckForNull String misc);
......@@ -17,6 +18,8 @@ public interface ClientInterface {
@Nonnull
public String returnStr();
/** Testing documentation comments before code comments */
// This method takes an interface
@Nonnull
public String methTakingInterface(@CheckForNull ClientInterface i);
......
......@@ -6,7 +6,7 @@ package com.dropbox.djinni.test;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
/** Record returned by a client */
// Record returned by a client
public class ClientReturnedRecord {
......
......@@ -10,6 +10,9 @@ public enum Color {
RED,
ORANGE,
YELLOW,
// "It is customary to list indigo as a color lying between blue and violet, but it has
// never seemed to me that indigo is worth the dignity of being considered a separate
// color. To my eyes it seems merely deep blue." --Isaac Asimov
GREEN,
BLUE,
/**
......
......@@ -6,7 +6,7 @@ package com.dropbox.djinni.test;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
/** enum for use in constants */
// enum for use in constants
public enum ConstantEnum {
SOME_VALUE,
SOME_OTHER_VALUE,
......
......@@ -12,6 +12,7 @@ public class Constants {
/** bool_constant has documentation. */
public static final boolean BOOL_CONSTANT = true;
// i8_constant has a comment
public static final byte I8_CONSTANT = 1;
public static final short I16_CONSTANT = 2;
......@@ -20,6 +21,9 @@ public class Constants {
public static final long I64_CONSTANT = 4l;
// f64_constant has a long comment.
// (Second line of multi-line comment.
// Indented third line of multi-line comment.)
public static final float F32_CONSTANT = 5.0f;
/**
......@@ -67,11 +71,9 @@ public class Constants {
I32_CONSTANT /* mSomeInteger */ ,
STRING_CONSTANT /* mSomeString */ );
/**
* No support for null optional constants
* No support for optional constant records
* No support for constant binary, list, set, map
*/
/** No support for null optional constants */
// No support for optional constant records
/** No support for constant binary, list, set, map */
public static final boolean DUMMY = false;
......
......@@ -67,11 +67,9 @@ public interface ConstantsInterface {
I32_CONSTANT /* mSomeInteger */ ,
STRING_CONSTANT /* mSomeString */ );
/**
* No support for null optional constants
* No support for optional constant records
* No support for constant binary, list, set, map
*/
// No support for null optional constants
/** No support for optional constant records */
// No support for constant binary, list, set, map
public void dummy();
static final class CppProxy implements ConstantsInterface
......
......@@ -5,6 +5,7 @@ package com.dropbox.djinni.test;
import java.util.concurrent.atomic.AtomicBoolean;
// This file tests YAML dumped by Djinni can be parsed back in
public interface ExternInterface1 {
public com.dropbox.djinni.test.ClientReturnedRecord foo(com.dropbox.djinni.test.ClientInterface i);
......
......@@ -7,7 +7,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
/** Used for C++ multiple inheritance tests */
// Used for C++ multiple inheritance tests
public interface ReturnTwo {
public byte returnTwo();
......
......@@ -11,9 +11,25 @@ public interface ReverseClientInterface {
@Nonnull
public String returnStr();
// Testing code comments before documentation comments
// with multiple lines
// and another line
/**
* Testing documentation comments after code comments
* with multiple lines
* and another line
*/
@Nonnull
public String methTakingInterface(@CheckForNull ReverseClientInterface i);
/**
* Testing documentation comments before code comments
* with multiple lines
* and another line
*/
// Testing code comments after documentation comments
// with multiple lines
// and another line
@Nonnull
public String methTakingOptionalInterface(@CheckForNull ReverseClientInterface i);
......
......@@ -6,7 +6,7 @@ package com.dropbox.djinni.test;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
/** Used for ObjC multiple inheritance tests */
// Used for ObjC multiple inheritance tests
public interface SecondListener {
public void second();
}
......@@ -6,9 +6,10 @@
@protocol DBClientInterface;
/** Client interface */
// Client interface
@protocol DBClientInterface
// Testing code comments before documentation comments
/** Returns record of given string */
- (nonnull DBClientReturnedRecord *)getRecord:(int64_t)recordId
utf8string:(nonnull NSString *)utf8string
......@@ -20,6 +21,8 @@
- (nonnull NSString *)returnStr;
/** Testing documentation comments before code comments */
// This method takes an interface
- (nonnull NSString *)methTakingInterface:(nullable id<DBClientInterface>)i;
- (nonnull NSString *)methTakingOptionalInterface:(nullable id<DBClientInterface>)i;
......
......@@ -3,7 +3,7 @@
#import <Foundation/Foundation.h>
/** Record returned by a client */
// Record returned by a client
@interface DBClientReturnedRecord : NSObject
- (nonnull instancetype)initWithRecordId:(int64_t)recordId
content:(nonnull NSString *)content
......
......@@ -8,6 +8,9 @@ typedef NS_ENUM(NSInteger, DBColor)
DBColorRed,
DBColorOrange,
DBColorYellow,
// "It is customary to list indigo as a color lying between blue and violet, but it has
// never seemed to me that indigo is worth the dignity of being considered a separate
// color. To my eyes it seems merely deep blue." --Isaac Asimov
DBColorGreen,
DBColorBlue,
/**
......
......@@ -3,7 +3,7 @@
#import <Foundation/Foundation.h>
/** enum for use in constants */
// enum for use in constants
typedef NS_ENUM(NSInteger, DBConstantEnum)
{
DBConstantEnumSomeValue,
......
......@@ -27,10 +27,14 @@
/** bool_constant has documentation. */
extern BOOL const DBConstantsBoolConstant;
// i8_constant has a comment
extern int8_t const DBConstantsI8Constant;
extern int16_t const DBConstantsI16Constant;
extern int32_t const DBConstantsI32Constant;
extern int64_t const DBConstantsI64Constant;
// f64_constant has a long comment.
// (Second line of multi-line comment.
// Indented third line of multi-line comment.)
extern float const DBConstantsF32Constant;
/**
* f64_constant has long documentation.
......@@ -40,9 +44,7 @@ extern float const DBConstantsF32Constant;
extern double const DBConstantsF64Constant;
extern NSString * __nonnull const DBConstantsStringConstant;
extern NSString * __nullable const DBConstantsOptStringConstant;
/**
* No support for null optional constants
* No support for optional constant records
* No support for constant binary, list, set, map
*/
/** No support for null optional constants */
// No support for optional constant records
/** No support for constant binary, list, set, map */
extern BOOL const DBConstantsDummy;
......@@ -23,11 +23,9 @@ extern NSString * __nullable const DBConstantsInterfaceOptStringConstant;
/** Interface containing constants */
@interface DBConstantsInterface : NSObject
/**
* No support for null optional constants
* No support for optional constant records
* No support for constant binary, list, set, map
*/
// No support for null optional constants
/** No support for optional constant records */
// No support for constant binary, list, set, map
- (void)dummy;
+ (NSNumber * __nullable)optBoolConstant;
......
......@@ -6,6 +6,7 @@
#import <Foundation/Foundation.h>
// This file tests YAML dumped by Djinni can be parsed back in
@interface DBExternInterface1 : NSObject
- (nonnull DBClientReturnedRecord *)foo:(nullable id<DBClientInterface>)i;
......
......@@ -5,7 +5,7 @@
@class DBReturnTwo;
/** Used for C++ multiple inheritance tests */
// Used for C++ multiple inheritance tests
@interface DBReturnTwo : NSObject
+ (nullable DBReturnTwo *)getInstance;
......
......@@ -9,8 +9,24 @@
- (nonnull NSString *)returnStr;
// Testing code comments before documentation comments
// with multiple lines
// and another line
/**
* Testing documentation comments after code comments
* with multiple lines
* and another line
*/
- (nonnull NSString *)methTakingInterface:(nullable DBReverseClientInterface *)i;
/**
* Testing documentation comments before code comments
* with multiple lines
* and another line
*/
// Testing code comments after documentation comments
// with multiple lines
// and another line
- (nonnull NSString *)methTakingOptionalInterface:(nullable DBReverseClientInterface *)i;
+ (nullable DBReverseClientInterface *)create;
......
......@@ -4,7 +4,7 @@
#import <Foundation/Foundation.h>
/** Used for ObjC multiple inheritance tests */
// Used for ObjC multiple inheritance tests
@protocol DBSecondListener
- (void)second;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment