mirror of
https://github.com/twiglet/cs2j.git
synced 2025-01-18 13:15:17 +01:00
Support for Partial Types.
Reworked earlier attempt that tried to collect them after JavaMaker phase. Realised it is better to go all the way through to generating strings because we need the original token stream to do that and partial types can be splity across different files. Its actually simpler this way.
This commit is contained in:
parent
930db5d588
commit
d855f757ae
@ -209,7 +209,7 @@ namespace Twiglet.CS2J.Translator
|
|||||||
foreach (string r in csDir)
|
foreach (string r in csDir)
|
||||||
doFile(r, ".cs", translateFile, cfg.Exclude); // translate it
|
doFile(r, ".cs", translateFile, cfg.Exclude); // translate it
|
||||||
|
|
||||||
if (cfg.DebugLevel >= 1) Console.Out.WriteLine("Writing out collected partial types");
|
if (cfg.DebugLevel >= 1 && partialTypes.Count > 0) Console.Out.WriteLine("Writing out collected partial types");
|
||||||
foreach (KeyValuePair<string, ClassDescriptorSerialized> entry in partialTypes)
|
foreach (KeyValuePair<string, ClassDescriptorSerialized> entry in partialTypes)
|
||||||
emitPartialType(entry.Key, entry.Value);
|
emitPartialType(entry.Key, entry.Value);
|
||||||
|
|
||||||
@ -537,8 +537,8 @@ namespace Twiglet.CS2J.Translator
|
|||||||
|
|
||||||
outputMaker.Cfg = cfg;
|
outputMaker.Cfg = cfg;
|
||||||
outputMaker.EmittedCommentTokenIdx = saveEmittedCommentTokenIdx;
|
outputMaker.EmittedCommentTokenIdx = saveEmittedCommentTokenIdx;
|
||||||
outputMaker.IsPartial = javaMaker.CUMap[typeName].IsPartial;
|
bool isPartial = javaMaker.CUMap[typeName].IsPartial;
|
||||||
if (outputMaker.IsPartial)
|
if (isPartial)
|
||||||
{
|
{
|
||||||
if (!partialTypes.ContainsKey(typeName))
|
if (!partialTypes.ContainsKey(typeName))
|
||||||
{
|
{
|
||||||
@ -550,7 +550,7 @@ namespace Twiglet.CS2J.Translator
|
|||||||
|
|
||||||
outputMaker.IsLast = i == (javaMaker.CUKeys.Count - 1);
|
outputMaker.IsLast = i == (javaMaker.CUKeys.Count - 1);
|
||||||
|
|
||||||
if (!outputMaker.IsPartial)
|
if (!isPartial)
|
||||||
{
|
{
|
||||||
if (cfg.DebugLevel >= 1) Console.Out.WriteLine("Writing out {0}", javaFName);
|
if (cfg.DebugLevel >= 1) Console.Out.WriteLine("Writing out {0}", javaFName);
|
||||||
StreamWriter javaW = new StreamWriter(javaFName);
|
StreamWriter javaW = new StreamWriter(javaFName);
|
||||||
@ -574,25 +574,17 @@ namespace Twiglet.CS2J.Translator
|
|||||||
|
|
||||||
public static void emitPartialType(string name, ClassDescriptorSerialized serTy)
|
public static void emitPartialType(string name, ClassDescriptorSerialized serTy)
|
||||||
{
|
{
|
||||||
|
JavaPrettyPrint outputMaker = new JavaPrettyPrint(null);
|
||||||
// Pretty print as text
|
outputMaker.Filename = serTy.FileName;
|
||||||
Dictionary<string,object> args = new Dictionary<string,object>();
|
outputMaker.TraceDestination = Console.Error;
|
||||||
args["now"] = DateTime.Now;
|
outputMaker.TemplateLib = templates;
|
||||||
args["includeDate"] = cfg.TranslatorAddTimeStamp;
|
outputMaker.Cfg = cfg;
|
||||||
args["packageName"] = serTy.Package;
|
|
||||||
args["imports"] = serTy.Imports;
|
|
||||||
args["modifiers"] = serTy.Mods;
|
|
||||||
args["name"] = serTy.Identifier;
|
|
||||||
args["extends"] = serTy.ClassBase;
|
|
||||||
args["imps"] = serTy.ClassImplements;
|
|
||||||
args["body"] = serTy.ClassBody;
|
|
||||||
|
|
||||||
StringTemplate st = templates.GetInstanceOf("partial_type", args);
|
StringTemplate pkgST = outputMaker.emitPackage(serTy);
|
||||||
|
|
||||||
// new STAttrMap().Add("now", DateTime.Now).Add("includeDate", Cfg.TranslatorAddTimeStamp).Add("packageName", (((nm != null) ? nm.Text : null) != null && ((nm != null) ? nm.Text : null).Length > 0 ? ((nm != null) ? nm.Text : null) : null)).Add("imports", ((imports1 != null) ? imports1.ST : null)).Add("type", ((type_declaration2 != null) ? type_declaration2.ST : null)).Add("endComments", CollectedComments ));
|
|
||||||
if (cfg.DebugLevel >= 1) Console.Out.WriteLine("Writing out {0}", serTy.FileName);
|
if (cfg.DebugLevel >= 1) Console.Out.WriteLine("Writing out {0}", serTy.FileName);
|
||||||
StreamWriter javaW = new StreamWriter(serTy.FileName);
|
StreamWriter javaW = new StreamWriter(serTy.FileName);
|
||||||
javaW.Write(limit(st.ToString()));
|
javaW.Write(limit(pkgST.ToString()));
|
||||||
javaW.Close();
|
javaW.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,37 +46,16 @@ import_list(nss) ::= <<
|
|||||||
|
|
||||||
import_template(ns) ::= ""import <ns>;""
|
import_template(ns) ::= ""import <ns>;""
|
||||||
|
|
||||||
// ****** output partial type ******
|
|
||||||
partial_type(now, includeDate, packageName, imports, modifiers, comments, attributes, name, typeparams, extends, imps, body) ::= <<
|
|
||||||
<itsmine(now=now,includeDate=includeDate)>
|
|
||||||
<if(packageName)>package <packageName>;<endif>
|
|
||||||
|
|
||||||
<comments; separator=""\n"">
|
|
||||||
<import_list(imports)>
|
|
||||||
|
|
||||||
<modifiers(modifiers)>class <name> <typeparams> <extends><if(imps)> implements <imps; separator="",""><endif>
|
|
||||||
{
|
|
||||||
<body>
|
|
||||||
}
|
|
||||||
|
|
||||||
>>
|
|
||||||
|
|
||||||
// ******* CLASSES ***********
|
// ******* CLASSES ***********
|
||||||
|
|
||||||
class(modifiers, comments, attributes, name, typeparams, extends, imps, body) ::= <<
|
class(modifiers, comments, attributes, type, name, typeparams, extends, imps, body, partial_types, end_comments) ::= <<
|
||||||
<comments; separator=""\n"">
|
<comments; separator=""\n"">
|
||||||
<modifiers(modifiers)>class <name> <typeparams> <extends> <imps>
|
<modifiers><if(type)><type><else>class<endif> <name> <typeparams> <extends> <imps>
|
||||||
{
|
|
||||||
<body>
|
|
||||||
}
|
|
||||||
>>
|
|
||||||
|
|
||||||
iface(modifiers, comments, attributes, name, typeparams, imps, body) ::= <<
|
|
||||||
<comments; separator=""\n"">
|
|
||||||
<modifiers(modifiers)>interface <name> <typeparams> <imps>
|
|
||||||
{
|
{
|
||||||
<body>
|
<body>
|
||||||
|
<partial_types>
|
||||||
}
|
}
|
||||||
|
<end_comments; separator=""\n"">
|
||||||
>>
|
>>
|
||||||
|
|
||||||
class_body(entries) ::= <<
|
class_body(entries) ::= <<
|
||||||
@ -89,7 +68,7 @@ class_member(comments, member) ::= <<
|
|||||||
>>
|
>>
|
||||||
|
|
||||||
constructor(modifiers, name, params, exceptions, body, bodyIsSemi) ::= <<
|
constructor(modifiers, name, params, exceptions, body, bodyIsSemi) ::= <<
|
||||||
<modifiers(modifiers)><name>(<params; separator="", "">)<if(exceptions)> throws <exceptions; separator="", ""><endif> <if(bodyIsSemi)>;
|
<modifiers><name>(<params; separator="", "">)<if(exceptions)> throws <exceptions; separator="", ""><endif> <if(bodyIsSemi)>;
|
||||||
<else>
|
<else>
|
||||||
<body>
|
<body>
|
||||||
<endif>
|
<endif>
|
||||||
@ -97,7 +76,7 @@ constructor(modifiers, name, params, exceptions, body, bodyIsSemi) ::= <<
|
|||||||
>>
|
>>
|
||||||
|
|
||||||
static_constructor(modifiers, body, bodyIsSemi) ::= <<
|
static_constructor(modifiers, body, bodyIsSemi) ::= <<
|
||||||
<modifiers(modifiers)><if(bodyIsSemi)>;
|
<modifiers><if(bodyIsSemi)>;
|
||||||
<else>
|
<else>
|
||||||
<body>
|
<body>
|
||||||
<endif>
|
<endif>
|
||||||
@ -105,14 +84,14 @@ static_constructor(modifiers, body, bodyIsSemi) ::= <<
|
|||||||
>>
|
>>
|
||||||
|
|
||||||
method(modifiers, typeparams, type, name, params, exceptions, body, bodyIsSemi) ::= <<
|
method(modifiers, typeparams, type, name, params, exceptions, body, bodyIsSemi) ::= <<
|
||||||
<modifiers(modifiers)><typeparams> <type> <name>(<params; separator="", "">)<if(exceptions)> throws <exceptions; separator="", ""><endif> <if(bodyIsSemi)>;
|
<modifiers><typeparams><type> <name>(<params>)<if(exceptions)> throws <exceptions; separator="", ""><endif> <if(bodyIsSemi)>;
|
||||||
<else>
|
<else>
|
||||||
<body>
|
<body>
|
||||||
<endif>
|
<endif>
|
||||||
<\n>
|
<\n>
|
||||||
>>
|
>>
|
||||||
|
|
||||||
field(modifiers, type, field, comments, init) ::= ""<comments><modifiers(modifiers)><type> <field>;""
|
field(modifiers, type, field, comments, init) ::= ""<comments><modifiers><type> <field>;""
|
||||||
|
|
||||||
variable_declarators(varinits) ::= ""<varinits; separator=\"", \"">""
|
variable_declarators(varinits) ::= ""<varinits; separator=\"", \"">""
|
||||||
variable_declarator(typename,init) ::= ""<typename><if(init)> = <init><endif>""
|
variable_declarator(typename,init) ::= ""<typename><if(init)> = <init><endif>""
|
||||||
@ -122,7 +101,7 @@ primary_expression_start_parts(start,follows) ::= ""<start><follows>""
|
|||||||
type_param_constraint(param, constraints) ::= ""<param> extends <constraints; separator=\"" & \"">""
|
type_param_constraint(param, constraints) ::= ""<param> extends <constraints; separator=\"" & \"">""
|
||||||
|
|
||||||
fixed_parameter(mod,type,name,def) ::= <<
|
fixed_parameter(mod,type,name,def) ::= <<
|
||||||
<mod> <type> <name><if(def)> = <def><endif>
|
<mod><type> <name><if(def)> = <def><endif>
|
||||||
>>
|
>>
|
||||||
|
|
||||||
varargs(type,name) ::= <<
|
varargs(type,name) ::= <<
|
||||||
@ -141,7 +120,7 @@ statement(statement) ::= <<
|
|||||||
|
|
||||||
annotation(modifiers, comments, attributes, name, body) ::= <<
|
annotation(modifiers, comments, attributes, name, body) ::= <<
|
||||||
<comments; separator=""\n"">
|
<comments; separator=""\n"">
|
||||||
<modifiers(modifiers)>@interface <name>
|
<modifiers>@interface <name>
|
||||||
{
|
{
|
||||||
<body>
|
<body>
|
||||||
}
|
}
|
||||||
@ -159,7 +138,7 @@ throw(exp) ::= ""throw <exp>;""
|
|||||||
|
|
||||||
enum(modifiers,comments, attributes, name, body) ::= <<
|
enum(modifiers,comments, attributes, name, body) ::= <<
|
||||||
<comments; separator=""\n"">
|
<comments; separator=""\n"">
|
||||||
<modifiers(modifiers)>enum <name>
|
<modifiers>enum <name>
|
||||||
{
|
{
|
||||||
<body>
|
<body>
|
||||||
}
|
}
|
||||||
@ -175,7 +154,9 @@ enum_member(comments, value) ::= <<
|
|||||||
type(name, rs, stars, opt) ::= ""<name><rs><stars><opt>""
|
type(name, rs, stars, opt) ::= ""<name><rs><stars><opt>""
|
||||||
namespace_or_type(type1, type2, types) ::= ""<type1><if(type2)>::<type2><endif><if(types)>.<types; separator=\"".\""><endif>""
|
namespace_or_type(type1, type2, types) ::= ""<type1><if(type2)>::<type2><endif><if(types)>.<types; separator=\"".\""><endif>""
|
||||||
|
|
||||||
modifiers(mods) ::= ""<if(mods)><mods; separator=\"" \""> <endif>""
|
modifiers(mods) ::= <<
|
||||||
|
<if(mods)><mods; separator="" ""> <endif>
|
||||||
|
>>
|
||||||
|
|
||||||
type_parameter_list(items) ::= <<
|
type_parameter_list(items) ::= <<
|
||||||
\<<items; separator="", "">\>
|
\<<items; separator="", "">\>
|
||||||
|
@ -258,45 +258,24 @@ namespace Twiglet.CS2J.Translator.Transform
|
|||||||
public bool IsPartial {get; set;}
|
public bool IsPartial {get; set;}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ClassDescriptor {
|
// This structure holds (serialized) consolidated strings describing
|
||||||
public IToken Token { get;set; }
|
// partial classes and interfaces
|
||||||
public String Comments { get;set; }
|
|
||||||
public CommonTree Atts { get;set; }
|
|
||||||
public CommonTree Mods { get;set; }
|
|
||||||
public CommonTree Identifier { get;set; }
|
|
||||||
public CommonTree TypeParameterList { get;set; }
|
|
||||||
public CommonTree ClassBase { get;set; }
|
|
||||||
public CommonTree TypeParameterConstraintsClauses { get;set; }
|
|
||||||
public CommonTree ClassBody { get;set; }
|
|
||||||
public Dictionary<String, ClassDescriptor> PartialTypes { get;set; }
|
|
||||||
|
|
||||||
public ClassDescriptor(IToken inToken, String inComments, CommonTree inAtts, CommonTree inMods, CommonTree inIdentifier, CommonTree inTypeParameterList, CommonTree inClassBase, CommonTree inTypeParameterConstraintsClauses, CommonTree inClassBody, Dictionary<String, ClassDescriptor> inPartialTypes) {
|
|
||||||
Token = inToken;
|
|
||||||
Comments = inComments;
|
|
||||||
Atts = inAtts;
|
|
||||||
Mods = inMods;
|
|
||||||
Identifier = inIdentifier;
|
|
||||||
TypeParameterList = inTypeParameterList;
|
|
||||||
ClassBase = inClassBase;
|
|
||||||
TypeParameterConstraintsClauses = inTypeParameterConstraintsClauses;
|
|
||||||
ClassBody = inClassBody;
|
|
||||||
PartialTypes = inPartialTypes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ClassDescriptorSerialized {
|
public class ClassDescriptorSerialized {
|
||||||
public String FileName { get;set; }
|
public String FileName { get;set; }
|
||||||
public List<String> Imports { get;set; }
|
public List<String> Imports { get;set; }
|
||||||
public String Package { get;set; }
|
public String Package { get;set; }
|
||||||
|
public String Type { get;set; }
|
||||||
public String Comments { get;set; }
|
public String Comments { get;set; }
|
||||||
public String Atts { get;set; }
|
public String Atts { get;set; }
|
||||||
public List<String> Mods { get;set; }
|
public List<String> Mods { get;set; }
|
||||||
public String Identifier { get;set; }
|
public String Identifier { get;set; }
|
||||||
public String TypeParameterList { get;set; }
|
public String TypeParameterList { get;set; }
|
||||||
public String ClassBase { get;set; }
|
public List<String> ClassExtends { get;set; } // Can have multiple extends in an interface
|
||||||
public List<String> ClassImplements { get;set; }
|
public List<String> ClassImplements { get;set; }
|
||||||
public String TypeParameterConstraintsClauses { get;set; }
|
|
||||||
public String ClassBody { get;set; }
|
public String ClassBody { get;set; }
|
||||||
|
public String EndComments { get;set; }
|
||||||
|
|
||||||
|
public Dictionary<String,ClassDescriptorSerialized> PartialTypes { get;set; }
|
||||||
|
|
||||||
public ClassDescriptorSerialized(string name)
|
public ClassDescriptorSerialized(string name)
|
||||||
{
|
{
|
||||||
@ -304,14 +283,16 @@ namespace Twiglet.CS2J.Translator.Transform
|
|||||||
Comments = "";
|
Comments = "";
|
||||||
Imports = new List<String>();
|
Imports = new List<String>();
|
||||||
Package = "";
|
Package = "";
|
||||||
|
Type = "class";
|
||||||
Atts = "";
|
Atts = "";
|
||||||
Mods = new List<String>();
|
Mods = new List<String>();
|
||||||
Identifier = name;
|
Identifier = name;
|
||||||
TypeParameterList = "";
|
TypeParameterList = "";
|
||||||
ClassBase = "";
|
ClassExtends = new List<String>();
|
||||||
ClassImplements = new List<String>();
|
ClassImplements = new List<String>();
|
||||||
TypeParameterConstraintsClauses = "";
|
|
||||||
ClassBody = "";
|
ClassBody = "";
|
||||||
|
EndComments = "";
|
||||||
|
PartialTypes = new Dictionary<String,ClassDescriptorSerialized>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,6 @@ scope NSContext {
|
|||||||
// A scope to keep track of the current type context
|
// A scope to keep track of the current type context
|
||||||
scope TypeContext {
|
scope TypeContext {
|
||||||
string typeName;
|
string typeName;
|
||||||
Dictionary<String,ClassDescriptor> partialTypes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@namespace { Twiglet.CS2J.Translator.Transform }
|
@namespace { Twiglet.CS2J.Translator.Transform }
|
||||||
@ -56,10 +55,6 @@ scope TypeContext {
|
|||||||
public IDictionary<string, CUnit> CUMap { get; set; }
|
public IDictionary<string, CUnit> CUMap { get; set; }
|
||||||
public IList<string> CUKeys { get; set; }
|
public IList<string> CUKeys { get; set; }
|
||||||
|
|
||||||
// we keep track of the end position of the previous class / struct member
|
|
||||||
// so that we can collect comments for a partial type definition
|
|
||||||
private int prevMemberEndTokenIndex = -1;
|
|
||||||
|
|
||||||
protected string snaffleComments(int startIndex, int endIndex) {
|
protected string snaffleComments(int startIndex, int endIndex) {
|
||||||
StringBuilder ret = new StringBuilder();
|
StringBuilder ret = new StringBuilder();
|
||||||
List<IToken> toks = ((CommonTokenStream)this.GetTreeNodeStream().TokenStream).GetTokens(startIndex,endIndex);
|
List<IToken> toks = ((CommonTokenStream)this.GetTreeNodeStream().TokenStream).GetTokens(startIndex,endIndex);
|
||||||
@ -507,56 +502,56 @@ scope TypeContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Merges part into combined
|
// Merges part into combined
|
||||||
protected void mergePartialTypes(ClassDescriptor combined, ClassDescriptor part) {
|
// protected void mergePartialTypes(ClassDescriptor combined, ClassDescriptor part) {
|
||||||
|
//
|
||||||
// append comments
|
// // append comments
|
||||||
combined.Comments += part.Comments;
|
// combined.Comments += part.Comments;
|
||||||
|
//
|
||||||
// union all attributes
|
// // union all attributes
|
||||||
CommonTree attRoot = (CommonTree)adaptor.Nil;
|
// CommonTree attRoot = (CommonTree)adaptor.Nil;
|
||||||
adaptor.AddChild(attRoot, combined.Atts);
|
// adaptor.AddChild(attRoot, combined.Atts);
|
||||||
adaptor.AddChild(attRoot, part.Atts);
|
// adaptor.AddChild(attRoot, part.Atts);
|
||||||
combined.Atts = (CommonTree)adaptor.RulePostProcessing(attRoot);
|
// combined.Atts = (CommonTree)adaptor.RulePostProcessing(attRoot);
|
||||||
|
//
|
||||||
// merge all modifiers
|
// // merge all modifiers
|
||||||
combined.Mods = mergeModifiers(combined.Mods, part.Mods);
|
// combined.Mods = mergeModifiers(combined.Mods, part.Mods);
|
||||||
|
//
|
||||||
// type parameter list must be the same on all parts
|
// // type parameter list must be the same on all parts
|
||||||
|
//
|
||||||
// all parts that have a TypeParameterConstraintsClauses must agree
|
// // all parts that have a TypeParameterConstraintsClauses must agree
|
||||||
if (combined.TypeParameterConstraintsClauses == null)
|
// if (combined.TypeParameterConstraintsClauses == null)
|
||||||
combined.TypeParameterConstraintsClauses = part.TypeParameterConstraintsClauses;
|
// combined.TypeParameterConstraintsClauses = part.TypeParameterConstraintsClauses;
|
||||||
|
//
|
||||||
// merge all base classes, interfaces
|
// // merge all base classes, interfaces
|
||||||
combined.ClassBase = mergeModifiers(combined.ClassBase, part.ClassBase);
|
// combined.ClassBase = mergeModifiers(combined.ClassBase, part.ClassBase);
|
||||||
|
//
|
||||||
// union all class_body
|
// // union all class_body
|
||||||
CommonTree bodyRoot = (CommonTree)adaptor.Nil;
|
// CommonTree bodyRoot = (CommonTree)adaptor.Nil;
|
||||||
adaptor.AddChild(bodyRoot, combined.ClassBody);
|
// adaptor.AddChild(bodyRoot, combined.ClassBody);
|
||||||
adaptor.AddChild(bodyRoot, part.ClassBody);
|
// adaptor.AddChild(bodyRoot, part.ClassBody);
|
||||||
combined.ClassBody = (CommonTree)adaptor.RulePostProcessing(bodyRoot);
|
// combined.ClassBody = (CommonTree)adaptor.RulePostProcessing(bodyRoot);
|
||||||
|
//
|
||||||
// merge partial sub-types
|
// // merge partial sub-types
|
||||||
foreach (string key in combined.PartialTypes.Keys) {
|
// foreach (string key in combined.PartialTypes.Keys) {
|
||||||
if (part.PartialTypes.ContainsKey(key)) {
|
// if (part.PartialTypes.ContainsKey(key)) {
|
||||||
mergePartialTypes(combined.PartialTypes[key], part.PartialTypes[key]);
|
// mergePartialTypes(combined.PartialTypes[key], part.PartialTypes[key]);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
// Add types in part but not combined
|
// // Add types in part but not combined
|
||||||
foreach (string key in part.PartialTypes.Keys) {
|
// foreach (string key in part.PartialTypes.Keys) {
|
||||||
if (!combined.PartialTypes.ContainsKey(key)) {
|
// if (!combined.PartialTypes.ContainsKey(key)) {
|
||||||
combined.PartialTypes[key] = part.PartialTypes[key];
|
// combined.PartialTypes[key] = part.PartialTypes[key];
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
protected CommonTree emitPartialTypes(Dictionary<string,ClassDescriptor> partialTypes) {
|
// protected CommonTree emitPartialTypes(Dictionary<string,ClassDescriptor> partialTypes) {
|
||||||
CommonTree root = (CommonTree)adaptor.Nil;
|
// CommonTree root = (CommonTree)adaptor.Nil;
|
||||||
foreach (ClassDescriptor part in partialTypes.Values) {
|
// foreach (ClassDescriptor part in partialTypes.Values) {
|
||||||
root.AddChild((CommonTree)magicClassFromDescriptor(part.Token, part).Tree);
|
// root.AddChild((CommonTree)magicClassFromDescriptor(part.Token, part).Tree);
|
||||||
}
|
// }
|
||||||
return (CommonTree)adaptor.RulePostProcessing(root);
|
// return (CommonTree)adaptor.RulePostProcessing(root);
|
||||||
}
|
// }
|
||||||
|
|
||||||
protected void mergeCompUnits(CUnit cu, List<string> searchPath, List<string> aliasKeys, List<string> aliasNamespaces) {
|
protected void mergeCompUnits(CUnit cu, List<string> searchPath, List<string> aliasKeys, List<string> aliasNamespaces) {
|
||||||
foreach (string s in searchPath) {
|
foreach (string s in searchPath) {
|
||||||
@ -590,7 +585,6 @@ scope NSContext, TypeContext;
|
|||||||
$NSContext::aliasNamespaces = new List<string>();
|
$NSContext::aliasNamespaces = new List<string>();
|
||||||
|
|
||||||
$TypeContext::typeName = null;
|
$TypeContext::typeName = null;
|
||||||
$TypeContext::partialTypes = new Dictionary<String,ClassDescriptor>();
|
|
||||||
}
|
}
|
||||||
:
|
:
|
||||||
namespace_body;
|
namespace_body;
|
||||||
@ -636,7 +630,6 @@ scope TypeContext;
|
|||||||
bool isCompUnit = false;
|
bool isCompUnit = false;
|
||||||
CommonTree atts = null;
|
CommonTree atts = null;
|
||||||
CommonTree mods = null;
|
CommonTree mods = null;
|
||||||
$TypeContext::partialTypes = new Dictionary<string, ClassDescriptor>();
|
|
||||||
}
|
}
|
||||||
@after {
|
@after {
|
||||||
if (isCompUnit) {
|
if (isCompUnit) {
|
||||||
@ -647,21 +640,11 @@ scope TypeContext;
|
|||||||
Warning(treeEntry.Value.Token.Line, "[UNSUPPORTED] Cannot have a class with multiple generic type overloadings: " + fqn);
|
Warning(treeEntry.Value.Token.Line, "[UNSUPPORTED] Cannot have a class with multiple generic type overloadings: " + fqn);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CUMap.Add(fqn, new CUnit(mkPackage(treeEntry.Value.Token, treeEntry.Value, ns),CollectSearchPath,CollectAliasKeys,CollectAliasNamespaces));
|
CUMap.Add(fqn, new CUnit(mkPackage(treeEntry.Value.Token, treeEntry.Value, ns),CollectSearchPath,CollectAliasKeys,CollectAliasNamespaces, $ty.isPartial));
|
||||||
CUKeys.Add(fqn);
|
CUKeys.Add(fqn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (KeyValuePair<String, ClassDescriptor> partialEntry in $TypeContext::partialTypes) {
|
|
||||||
string fqn = ns+(String.IsNullOrEmpty(ns) ? "" : ".")+partialEntry.Key;
|
|
||||||
if (CUKeys.Contains(fqn)) {
|
|
||||||
Warning(partialEntry.Value.Token.Line, "[UNSUPPORTED] Cannot have a class with multiple generic type overloadings: " + fqn);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
CUMap.Add(fqn, new CUnit(mkPackage(partialEntry.Value.Token, (CommonTree)magicClassFromDescriptor(partialEntry.Value.Token, partialEntry.Value).Tree, ns), CollectSearchPath, CollectAliasKeys, CollectAliasNamespaces, true));
|
|
||||||
CUKeys.Add(fqn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}:
|
}:
|
||||||
namespace_declaration
|
namespace_declaration
|
||||||
@ -669,17 +652,19 @@ scope TypeContext;
|
|||||||
;
|
;
|
||||||
// type_declaration is only called at the top level, so each of the types declared
|
// type_declaration is only called at the top level, so each of the types declared
|
||||||
// here will become a Java compilation unit (and go to its own file)
|
// here will become a Java compilation unit (and go to its own file)
|
||||||
type_declaration[CommonTree atts, CommonTree mods] returns [Dictionary<String,CommonTree> compUnits]
|
type_declaration[CommonTree atts, CommonTree mods] returns [Dictionary<String,CommonTree> compUnits, bool isPartial]
|
||||||
@init {
|
@init {
|
||||||
$compUnits = new Dictionary<String,CommonTree>();
|
$compUnits = new Dictionary<String,CommonTree>();
|
||||||
|
$isPartial = false;
|
||||||
}
|
}
|
||||||
:
|
:
|
||||||
('partial') => p='partial'! (pc=class_declaration[$atts, $mods, true /* toplevel */, true /* isPartial */]
|
('partial') => p='partial' { $isPartial = true; }
|
||||||
| ps=struct_declaration[$atts, $mods, true /* toplevel */, true /* isPartial */]
|
(pc=class_declaration[$atts, $mods, $p, true /* toplevel */] { $compUnits.Add($pc.name, $pc.tree); }
|
||||||
| pi=interface_declaration[$atts, $mods] { $compUnits.Add($pi.name, $pi.tree); } )
|
| ps=struct_declaration[$atts, $mods, $p, true /* toplevel */] { $compUnits.Add($ps.name, $ps.tree); }
|
||||||
| c=class_declaration[$atts, $mods, true /* toplevel */, false /* isPartial */] { $compUnits.Add($c.name, $c.tree); }
|
| pi=interface_declaration[$atts, $mods, $p] { $compUnits.Add($pi.name, $pi.tree); } )
|
||||||
| s=struct_declaration[$atts, $mods, true /* toplevel */, false /* isPartial */] { $compUnits.Add($s.name, $s.tree); }
|
| c=class_declaration[$atts, $mods, null, true /* toplevel */] { $compUnits.Add($c.name, $c.tree); }
|
||||||
| i=interface_declaration[$atts, $mods] { $compUnits.Add($i.name, $i.tree); }
|
| s=struct_declaration[$atts, $mods, null, true /* toplevel */] { $compUnits.Add($s.name, $s.tree); }
|
||||||
|
| i=interface_declaration[$atts, $mods, null] { $compUnits.Add($i.name, $i.tree); }
|
||||||
| e=enum_declaration[$atts, $mods] { $compUnits.Add($e.name, $e.tree); }
|
| e=enum_declaration[$atts, $mods] { $compUnits.Add($e.name, $e.tree); }
|
||||||
| d=delegate_declaration[$atts, $mods, true /* toplevel */] { $compUnits = $d.compUnits; }
|
| d=delegate_declaration[$atts, $mods, true /* toplevel */] { $compUnits = $d.compUnits; }
|
||||||
;
|
;
|
||||||
@ -698,22 +683,17 @@ modifier:
|
|||||||
'new' -> /* No new in Java*/ | 'public' | 'protected' | 'private' | 'internal' -> /* translate to package-private */| 'unsafe' -> | 'abstract' | 'sealed' -> FINAL["final"] | 'static'
|
'new' -> /* No new in Java*/ | 'public' | 'protected' | 'private' | 'internal' -> /* translate to package-private */| 'unsafe' -> | 'abstract' | 'sealed' -> FINAL["final"] | 'static'
|
||||||
| 'readonly' -> /* no equivalent in C# (this is like a const that can be initialized separately in the constructor) */ | 'volatile' | e='extern' { Warning($e.line, "[UNSUPPORTED] 'extern' modifier"); } | 'virtual' -> | 'override' -> /* not in Java, maybe convert to override annotation */;
|
| 'readonly' -> /* no equivalent in C# (this is like a const that can be initialized separately in the constructor) */ | 'volatile' | e='extern' { Warning($e.line, "[UNSUPPORTED] 'extern' modifier"); } | 'virtual' -> | 'override' -> /* not in Java, maybe convert to override annotation */;
|
||||||
|
|
||||||
class_member_declaration
|
class_member_declaration:
|
||||||
@after {
|
|
||||||
this.prevMemberEndTokenIndex = adaptor.GetTokenStopIndex($class_member_declaration.tree);
|
|
||||||
}:
|
|
||||||
a=attributes?
|
a=attributes?
|
||||||
m=modifiers?
|
m=modifiers?
|
||||||
( c='const' ct=type constant_declarators ';' -> ^(FIELD[$c.token, "FIELD"] $a? $m? { addConstModifiers($c.token, $m.modList) } $ct constant_declarators)
|
( c='const' ct=type constant_declarators ';' -> ^(FIELD[$c.token, "FIELD"] $a? $m? { addConstModifiers($c.token, $m.modList) } $ct constant_declarators)
|
||||||
| ev=event_declaration[$a.tree, $m.tree] -> $ev
|
| ev=event_declaration[$a.tree, $m.tree] -> $ev
|
||||||
| p='partial' (v1=void_type m3=method_declaration[$a.tree, $m.tree, $m.modList, $v1.tree, $v1.text, true /* isPartial */] -> { $m3.tree != null}? $m3
|
| p='partial' (v1=void_type m3=method_declaration[$a.tree, $m.tree, $m.modList, $v1.tree, $v1.text, true /* isPartial */] -> { $m3.tree != null}? $m3
|
||||||
->
|
->
|
||||||
| pi=interface_declaration[$a.tree, $m.tree] -> $pi
|
| pi=interface_declaration[$a.tree, $m.tree, $p] -> $pi
|
||||||
| pc=class_declaration[$a.tree, $m.tree, false /* toplevel */, true /* isPartial */] -> { $pc.tree != null}? $pc
|
| pc=class_declaration[$a.tree, $m.tree, $p, false /* toplevel */] -> $pc
|
||||||
->
|
| ps=struct_declaration[$a.tree, $m.tree, $p, false /* toplevel */] -> $ps)
|
||||||
| ps=struct_declaration[$a.tree, $m.tree, false /* toplevel */, true /* isPartial */] -> { ps.tree != null}? $ps
|
| i=interface_declaration[$a.tree, $m.tree, null] -> $i
|
||||||
-> )
|
|
||||||
| i=interface_declaration[$a.tree, $m.tree] -> $i
|
|
||||||
| v2=void_type m1=method_declaration[$a.tree, $m.tree, $m.modList, $v2.tree, $v2.text, false /* isPartial */] -> $m1
|
| v2=void_type m1=method_declaration[$a.tree, $m.tree, $m.modList, $v2.tree, $v2.text, false /* isPartial */] -> $m1
|
||||||
| t=type ( (member_name type_parameter_list? '(') => m2=method_declaration[$a.tree, $m.tree, $m.modList, $t.tree, $t.text, false /* isPartial */] -> $m2
|
| t=type ( (member_name type_parameter_list? '(') => m2=method_declaration[$a.tree, $m.tree, $m.modList, $t.tree, $t.text, false /* isPartial */] -> $m2
|
||||||
| (member_name '{') => pd=property_declaration[$a.tree, $m.tree, $t.tree] -> $pd
|
| (member_name '{') => pd=property_declaration[$a.tree, $m.tree, $t.tree] -> $pd
|
||||||
@ -724,8 +704,8 @@ class_member_declaration
|
|||||||
)
|
)
|
||||||
// common_modifiers// (method_modifiers | field_modifiers)
|
// common_modifiers// (method_modifiers | field_modifiers)
|
||||||
|
|
||||||
| cd=class_declaration[$a.tree, $m.tree, false /* toplevel */, false /* isPartial */] -> $cd
|
| cd=class_declaration[$a.tree, $m.tree, null, false /* toplevel */] -> $cd
|
||||||
| sd=struct_declaration[$a.tree, $m.tree, false /* toplevel */, false /* isPartial */] -> $sd
|
| sd=struct_declaration[$a.tree, $m.tree, null, false /* toplevel */] -> $sd
|
||||||
| ed=enum_declaration[$a.tree, $m.tree] -> $ed
|
| ed=enum_declaration[$a.tree, $m.tree] -> $ed
|
||||||
| dd=delegate_declaration[$a.tree, $m.tree, false /* toplevel */] -> { mkFlattenDictionary($dd.tree.Token,$dd.compUnits) }
|
| dd=delegate_declaration[$a.tree, $m.tree, false /* toplevel */] -> { mkFlattenDictionary($dd.tree.Token,$dd.compUnits) }
|
||||||
| co3=conversion_operator_declaration -> ^(CONVERSION_OPERATOR[$co3.start.Token, "CONVERSION"] $a? $m? $co3)
|
| co3=conversion_operator_declaration -> ^(CONVERSION_OPERATOR[$co3.start.Token, "CONVERSION"] $a? $m? $co3)
|
||||||
@ -1258,42 +1238,11 @@ attribute_argument_expression:
|
|||||||
// Class Section
|
// Class Section
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
|
|
||||||
class_declaration[CommonTree atts, CommonTree mods, bool toplevel, bool isPartial] returns [string name]
|
class_declaration[CommonTree atts, CommonTree mods, CommonTree partial, bool toplevel] returns [string name]
|
||||||
scope TypeContext;
|
scope TypeContext;
|
||||||
@init{
|
|
||||||
$TypeContext::partialTypes = new Dictionary<String,ClassDescriptor>();
|
|
||||||
int prevMemberEndIndex = this.prevMemberEndTokenIndex;
|
|
||||||
IToken endToken = null;
|
|
||||||
}
|
|
||||||
:
|
:
|
||||||
c='class' identifier { $TypeContext::typeName = $identifier.thetext; } type_parameter_list? { $name = mkGenericTypeAlias($identifier.thetext, $type_parameter_list.names); } class_base? type_parameter_constraints_clauses? class_body[$isPartial] { endToken = $class_body.endToken; } (s=';' { endToken = $s.token; })?
|
c='class' identifier { $TypeContext::typeName = $identifier.thetext; } type_parameter_list? { $name = mkGenericTypeAlias($identifier.thetext, $type_parameter_list.names); } class_base? type_parameter_constraints_clauses? class_body ';'?
|
||||||
{
|
-> ^(CLASS[$c.token, "class"] { dupTree($partial) } { dupTree($atts) } { toplevel ? dupTree($mods) : addModifier($mods, (CommonTree)adaptor.Create(STATIC, $c.token, "static")) } identifier type_parameter_constraints_clauses? type_parameter_list? class_base? class_body );
|
||||||
if ($isPartial) {
|
|
||||||
|
|
||||||
// Strip off braces
|
|
||||||
CommonTree newClassBody = dupTree($class_body.tree);
|
|
||||||
int bodyChildren = adaptor.GetChildCount(newClassBody);
|
|
||||||
if (bodyChildren >= 2 && ((CommonTree)adaptor.GetChild(newClassBody, 0)).Type == OPEN_BRACE && ((CommonTree)adaptor.GetChild(newClassBody, bodyChildren - 1)).Type == CLOSE_BRACE) {
|
|
||||||
adaptor.DeleteChild(newClassBody, bodyChildren - 1);
|
|
||||||
adaptor.DeleteChild(newClassBody, 0);
|
|
||||||
newClassBody = (CommonTree)adaptor.RulePostProcessing(newClassBody);
|
|
||||||
}
|
|
||||||
if (!toplevel) {
|
|
||||||
$mods = addModifier($mods, (CommonTree)adaptor.Create(STATIC, $c.token, "static"));
|
|
||||||
}
|
|
||||||
ClassDescriptor klass = new ClassDescriptor($c.token, snaffleComments(prevMemberEndIndex, $c.token.TokenIndex), $atts, $mods, $identifier.tree, $type_parameter_list.tree, $class_base.tree, $type_parameter_constraints_clauses.tree, newClassBody, $TypeContext::partialTypes);
|
|
||||||
// add to parent's context
|
|
||||||
Dictionary<String,ClassDescriptor> parentPartialTypes = ((TypeContext_scope)$TypeContext.ToArray()[1]).partialTypes;
|
|
||||||
if (parentPartialTypes.ContainsKey($identifier.thetext)) {
|
|
||||||
mergePartialTypes(parentPartialTypes[$identifier.thetext], klass);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
parentPartialTypes[$identifier.thetext] = klass;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-> {$isPartial}?
|
|
||||||
-> ^(CLASS[$c.Token] { dupTree($atts) } { toplevel ? dupTree($mods) : addModifier($mods, (CommonTree)adaptor.Create(STATIC, $c.token, "static")) } identifier type_parameter_constraints_clauses? type_parameter_list? class_base? class_body );
|
|
||||||
|
|
||||||
type_parameter_list returns [List<string> names]
|
type_parameter_list returns [List<string> names]
|
||||||
@init {
|
@init {
|
||||||
@ -1311,10 +1260,8 @@ class_base:
|
|||||||
//interface_type_list:
|
//interface_type_list:
|
||||||
// ts+=type (',' ts+=type)* -> $ts+;
|
// ts+=type (',' ts+=type)* -> $ts+;
|
||||||
|
|
||||||
class_body[bool isPartial] returns [IToken endToken]:
|
class_body:
|
||||||
'{' class_member_declarations? e='}' { $endToken = $e.token; }
|
'{' class_member_declarations? '}' ;
|
||||||
-> {!$isPartial}? '{' class_member_declarations? { emitPartialTypes($TypeContext::partialTypes) } '}'
|
|
||||||
-> '{' class_member_declarations? '}' ;
|
|
||||||
class_member_declarations:
|
class_member_declarations:
|
||||||
class_member_declaration+ ;
|
class_member_declaration+ ;
|
||||||
|
|
||||||
@ -1664,12 +1611,12 @@ parameter_array:
|
|||||||
;
|
;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
interface_declaration[CommonTree atts, CommonTree mods] returns [string name]
|
interface_declaration[CommonTree atts, CommonTree mods, CommonTree partial] returns [string name]
|
||||||
scope TypeContext;
|
scope TypeContext;
|
||||||
:
|
:
|
||||||
c='interface' identifier { $name = $identifier.thetext; $TypeContext::typeName = $identifier.thetext; } variant_generic_parameter_list?
|
c='interface' identifier { $name = $identifier.thetext; $TypeContext::typeName = $identifier.thetext; } variant_generic_parameter_list?
|
||||||
interface_base? type_parameter_constraints_clauses? interface_body ';'?
|
interface_base? type_parameter_constraints_clauses? interface_body ';'?
|
||||||
-> ^(INTERFACE[$c.Token, "interface"] { dupTree($atts) } { dupTree($mods) } identifier type_parameter_constraints_clauses? variant_generic_parameter_list? interface_base? interface_body );
|
-> ^(INTERFACE[$c.token, "interface"] { dupTree($partial) } { dupTree($atts) } { dupTree($mods) } identifier type_parameter_constraints_clauses? variant_generic_parameter_list? interface_base? interface_body );
|
||||||
|
|
||||||
interface_base:
|
interface_base:
|
||||||
c=':' ts+=type (',' ts+=type)* -> ^(EXTENDS[$c.token,"extends"] $ts)*;
|
c=':' ts+=type (',' ts+=type)* -> ^(EXTENDS[$c.token,"extends"] $ts)*;
|
||||||
@ -1713,47 +1660,14 @@ interface_accessor_declaration [CommonTree atts, CommonTree mods, CommonTree typ
|
|||||||
;
|
;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
struct_declaration[CommonTree atts, CommonTree mods, bool toplevel, bool isPartial] returns [string name]
|
struct_declaration[CommonTree atts, CommonTree mods, CommonTree partial, bool toplevel] returns [string name]
|
||||||
scope TypeContext;
|
scope TypeContext;
|
||||||
@init {
|
|
||||||
$TypeContext::partialTypes = new Dictionary<String,ClassDescriptor>();
|
|
||||||
IToken endToken = null;
|
|
||||||
}
|
|
||||||
:
|
:
|
||||||
c='struct' identifier { $TypeContext::typeName = $identifier.thetext; } type_parameter_list? { $name = mkGenericTypeAlias($identifier.thetext, $type_parameter_list.names); } class_base? type_parameter_constraints_clauses? struct_body[$isPartial, $identifier.thetext] { endToken = $struct_body.endToken; } (s=';' { endToken = $s.token; })?
|
c='struct' identifier { $TypeContext::typeName = $identifier.thetext; } type_parameter_list? { $name = mkGenericTypeAlias($identifier.thetext, $type_parameter_list.names); } class_base? type_parameter_constraints_clauses? struct_body[$identifier.thetext] ';'?
|
||||||
{
|
-> ^(CLASS[$c.token, "class"] { dupTree($partial) } { dupTree($atts) } { toplevel ? dupTree($mods) : addModifier($mods, (CommonTree)adaptor.Create(STATIC, $c.token, "static")) } identifier type_parameter_constraints_clauses? type_parameter_list? class_base? struct_body );
|
||||||
if ($isPartial) {
|
|
||||||
|
|
||||||
// Strip off braces
|
struct_body [string structName]:
|
||||||
CommonTree newClassBody = dupTree($struct_body.tree);
|
o='{' magicDefaultConstructor[$o.token, structName] class_member_declarations? e='}'
|
||||||
int bodyChildren = adaptor.GetChildCount(newClassBody);
|
|
||||||
if (bodyChildren >= 2 && ((CommonTree)adaptor.GetChild(newClassBody, 0)).Type == OPEN_BRACE && ((CommonTree)adaptor.GetChild(newClassBody, bodyChildren - 1)).Type == CLOSE_BRACE) {
|
|
||||||
adaptor.DeleteChild(newClassBody, bodyChildren - 1);
|
|
||||||
adaptor.DeleteChild(newClassBody, 0);
|
|
||||||
newClassBody = (CommonTree)adaptor.RulePostProcessing(newClassBody);
|
|
||||||
}
|
|
||||||
if (!toplevel) {
|
|
||||||
$mods = addModifier($mods, (CommonTree)adaptor.Create(STATIC, $c.token, "static"));
|
|
||||||
}
|
|
||||||
|
|
||||||
ClassDescriptor klass = new ClassDescriptor($c.token, snaffleComments(this.prevMemberEndTokenIndex, $c.token.TokenIndex), $atts, $mods, $identifier.tree, $type_parameter_list.tree, $class_base.tree, $type_parameter_constraints_clauses.tree, newClassBody, $TypeContext::partialTypes);
|
|
||||||
|
|
||||||
// add to parent's context
|
|
||||||
Dictionary<String,ClassDescriptor> parentPartialTypes = ((TypeContext_scope)$TypeContext.ToArray()[1]).partialTypes;
|
|
||||||
if (!parentPartialTypes.ContainsKey($identifier.thetext)) {
|
|
||||||
mergePartialTypes(parentPartialTypes[$identifier.thetext], klass);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
parentPartialTypes[$identifier.thetext] = klass;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-> {$isPartial}?
|
|
||||||
-> ^(CLASS[$c.Token, "class"] { dupTree($atts) } { toplevel ? dupTree($mods) : addModifier($mods, (CommonTree)adaptor.Create(STATIC, $c.token, "static")) } identifier type_parameter_constraints_clauses? type_parameter_list? class_base? struct_body );
|
|
||||||
|
|
||||||
struct_body [bool isPartial, string structName] returns [IToken endToken]:
|
|
||||||
o='{' magicDefaultConstructor[$o.token, structName] class_member_declarations? e='}' { $endToken = $e.token; }
|
|
||||||
-> {$isPartial}? '{' magicDefaultConstructor class_member_declarations? { emitPartialTypes($TypeContext::partialTypes) } '}'
|
|
||||||
-> '{' magicDefaultConstructor class_member_declarations? '}' ;
|
-> '{' magicDefaultConstructor class_member_declarations? '}' ;
|
||||||
|
|
||||||
|
|
||||||
@ -2352,5 +2266,5 @@ magicMultiDelClass[IToken tok, CommonTree atts, CommonTree mods, string classNam
|
|||||||
OPEN_BRACE[tok, "{"] {dupTree(invokeMethod)} { dupTree(members) } CLOSE_BRACE[tok, "}"])
|
OPEN_BRACE[tok, "{"] {dupTree(invokeMethod)} { dupTree(members) } CLOSE_BRACE[tok, "}"])
|
||||||
;
|
;
|
||||||
|
|
||||||
magicClassFromDescriptor[IToken tok, ClassDescriptor klass]:
|
//magicClassFromDescriptor[IToken tok, ClassDescriptor klass]:
|
||||||
-> ^(CLASS[tok] PAYLOAD[tok, klass.Comments] { dupTree(klass.Atts) } { dupTree(klass.Mods) } { dupTree(klass.Identifier) } { dupTree(klass.TypeParameterConstraintsClauses) } { dupTree(klass.TypeParameterList) } { dupTree(klass.ClassBase) } OPEN_BRACE[tok, "{"] { dupTree(klass.ClassBody) } { emitPartialTypes(klass.PartialTypes) } CLOSE_BRACE[tok, "}"] );
|
//-> ^(CLASS[tok] PAYLOAD[tok, klass.Comments] { dupTree(klass.Atts) } { dupTree(klass.Mods) } { dupTree(klass.Identifier) } { dupTree(klass.TypeParameterConstraintsClauses) } { dupTree(klass.TypeParameterList) } { dupTree(klass.ClassBase) } OPEN_BRACE[tok, "{"] { dupTree(klass.ClassBody) } { emitPartialTypes(klass.PartialTypes) } CLOSE_BRACE[tok, "}"] );
|
||||||
|
@ -12,6 +12,11 @@ options {
|
|||||||
output=template;
|
output=template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We don't emit partial types as soon as we generate them, we merge them unti we know we hve seen all parts
|
||||||
|
scope TypeContext {
|
||||||
|
Dictionary<string,ClassDescriptorSerialized> partialTypes;
|
||||||
|
}
|
||||||
|
|
||||||
@namespace { Twiglet.CS2J.Translator.Transform }
|
@namespace { Twiglet.CS2J.Translator.Transform }
|
||||||
|
|
||||||
@header
|
@header
|
||||||
@ -25,9 +30,9 @@ options {
|
|||||||
@members
|
@members
|
||||||
{
|
{
|
||||||
|
|
||||||
public bool IsPartial { get; set; }
|
|
||||||
public bool IsLast { get; set; }
|
public bool IsLast { get; set; }
|
||||||
public int EmittedCommentTokenIdx { get; set; }
|
public int EmittedCommentTokenIdx { get; set; }
|
||||||
|
// If top level is partial then this will contain the components so that we can mere with other parts down the line
|
||||||
public ClassDescriptorSerialized PartialDescriptor { get; set; }
|
public ClassDescriptorSerialized PartialDescriptor { get; set; }
|
||||||
|
|
||||||
private List<string> collectedComments = null;
|
private List<string> collectedComments = null;
|
||||||
@ -293,20 +298,139 @@ options {
|
|||||||
protected string mkString(object s) {
|
protected string mkString(object s) {
|
||||||
return (s == null ? String.Empty : s.ToString());
|
return (s == null ? String.Empty : s.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void mergeParts(ClassDescriptorSerialized master, ClassDescriptorSerialized part) {
|
||||||
|
// Merge into existing descriptor
|
||||||
|
if (!String.IsNullOrEmpty(part.Comments)) {
|
||||||
|
master.Comments += "\n" + part.Comments;
|
||||||
|
}
|
||||||
|
if (!String.IsNullOrEmpty(part.EndComments)) {
|
||||||
|
master.EndComments += "\n" + part.EndComments;
|
||||||
|
}
|
||||||
|
|
||||||
|
// So that we can set "class" as default an doverride it when we see its an interface
|
||||||
|
master.Type = part.Type;
|
||||||
|
|
||||||
|
// Union all attributes
|
||||||
|
// we don't push through attributes yet
|
||||||
|
master.Atts += part.Atts;
|
||||||
|
|
||||||
|
// Merge modifiers
|
||||||
|
foreach (string m in part.Mods) {
|
||||||
|
if (!master.Mods.Contains(m)) {
|
||||||
|
master.Mods.Add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (String.IsNullOrEmpty(master.TypeParameterList)) {
|
||||||
|
master.TypeParameterList = part.TypeParameterList;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string m in part.ClassExtends) {
|
||||||
|
if (!master.ClassExtends.Contains(m)) {
|
||||||
|
master.ClassExtends.Add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string m in part.ClassImplements) {
|
||||||
|
if (!master.ClassImplements.Contains(m)) {
|
||||||
|
master.ClassImplements.Add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Union the class bodies
|
||||||
|
if (!String.IsNullOrEmpty(part.ClassBody)) {
|
||||||
|
master.ClassBody += "\n" + part.ClassBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (KeyValuePair<String,ClassDescriptorSerialized> d in part.PartialTypes) {
|
||||||
|
if (master.PartialTypes.ContainsKey(d.Key)) {
|
||||||
|
mergeParts(master.PartialTypes[d.Key], part.PartialTypes[d.Key]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
master.PartialTypes[d.Key] = part.PartialTypes[d.Key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringTemplate emitPackage(ClassDescriptorSerialized part)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Pretty print as text
|
||||||
|
StringTemplate pkgST = %package();
|
||||||
|
%{pkgST}.now = DateTime.Now;
|
||||||
|
%{pkgST}.includeDate = Cfg.TranslatorAddTimeStamp;
|
||||||
|
%{pkgST}.packageName = part.Package;
|
||||||
|
StringTemplate impST = %import_list();
|
||||||
|
%{impST}.nss = part.Imports;
|
||||||
|
%{pkgST}.imports = impST;
|
||||||
|
%{pkgST}.type = emitPartialType(part);
|
||||||
|
%{pkgST}.endComments = part.EndComments;
|
||||||
|
|
||||||
|
return pkgST;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringTemplate emitPartialType(ClassDescriptorSerialized part)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Pretty print as text
|
||||||
|
StringTemplate modST = %modifiers();
|
||||||
|
%{modST}.mods = part.Mods;
|
||||||
|
StringTemplate serTy = %class();
|
||||||
|
%{serTy}.comments = part.Comments;
|
||||||
|
%{serTy}.modifiers = modST;
|
||||||
|
%{serTy}.type = part.Type;
|
||||||
|
%{serTy}.name = part.Identifier;
|
||||||
|
%{serTy}.typeparams = part.TypeParameterList;
|
||||||
|
StringTemplate extTy = %extends();
|
||||||
|
%{extTy}.types = part.ClassExtends;
|
||||||
|
%{serTy}.extends = extTy;
|
||||||
|
StringTemplate impsTy = %imps();
|
||||||
|
%{impsTy}.types = part.ClassImplements;
|
||||||
|
%{serTy}.imps = impsTy;
|
||||||
|
%{serTy}.body = part.ClassBody;
|
||||||
|
%{serTy}.partial_types = emitParts(part.PartialTypes);
|
||||||
|
%{serTy}.end_comments = part.EndComments;
|
||||||
|
return serTy;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected StringTemplate emitParts(Dictionary<string, ClassDescriptorSerialized> partialTypes)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Pretty print as text
|
||||||
|
List<StringTemplate> serParts = new List<StringTemplate>();
|
||||||
|
foreach (ClassDescriptorSerialized part in partialTypes.Values) {
|
||||||
|
StringTemplate partST = emitPartialType(part);
|
||||||
|
serParts.Add(partST);
|
||||||
|
}
|
||||||
|
StringTemplate allParts = %seplist();
|
||||||
|
%{allParts}.items = serParts;
|
||||||
|
%{allParts}.sep = "\n";
|
||||||
|
|
||||||
|
return allParts;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public compilation_unit
|
public compilation_unit
|
||||||
|
scope TypeContext;
|
||||||
@init{
|
@init{
|
||||||
initPrecedence();
|
initPrecedence();
|
||||||
|
$TypeContext::partialTypes = new Dictionary<string,ClassDescriptorSerialized>();
|
||||||
}
|
}
|
||||||
:
|
:
|
||||||
^(PACKAGE nm=PAYLOAD imports? type_declaration)
|
^(PACKAGE nm=PAYLOAD imports? type_declaration)
|
||||||
|
|
||||||
{
|
{
|
||||||
if (IsLast) collectComments();
|
if (IsLast) collectComments();
|
||||||
if (IsPartial) {
|
if (PartialDescriptor != null && $TypeContext::partialTypes.Count > 0) {
|
||||||
// Merge into existing descriptor
|
// Merge into existing descriptor (must only be one)
|
||||||
|
foreach (ClassDescriptorSerialized part in $TypeContext::partialTypes.Values) {
|
||||||
|
mergeParts(PartialDescriptor, part);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is the first time we have seen thsi we must ensure Package name is there
|
||||||
PartialDescriptor.Package = ($nm.text != null && $nm.text.Length > 0 ? $nm.text : null);
|
PartialDescriptor.Package = ($nm.text != null && $nm.text.Length > 0 ? $nm.text : null);
|
||||||
if ($imports.importList != null && $imports.importList.Count > 0) {
|
if ($imports.importList != null && $imports.importList.Count > 0) {
|
||||||
foreach (string m in $imports.importList) {
|
foreach (string m in $imports.importList) {
|
||||||
@ -315,8 +439,18 @@ public compilation_unit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (IsLast) {
|
||||||
|
List<string> endComments = CollectedComments;
|
||||||
|
if (endComments != null) {
|
||||||
|
foreach (string comment in endComments) {
|
||||||
|
PartialDescriptor.EndComments += comment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
-> { PartialDescriptor != null}? // output is all collected in PartialDescriptor
|
||||||
->
|
->
|
||||||
package(now = {DateTime.Now}, includeDate = {Cfg.TranslatorAddTimeStamp}, packageName = {($nm.text != null && $nm.text.Length > 0 ? $nm.text : null)},
|
package(now = {DateTime.Now}, includeDate = {Cfg.TranslatorAddTimeStamp}, packageName = {($nm.text != null && $nm.text.Length > 0 ? $nm.text : null)},
|
||||||
imports = {$imports.st},
|
imports = {$imports.st},
|
||||||
@ -955,59 +1089,65 @@ attribute_argument_expression:
|
|||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
|
|
||||||
class_declaration[bool topLevel]
|
class_declaration[bool topLevel]
|
||||||
|
scope TypeContext;
|
||||||
@init {
|
@init {
|
||||||
List<string> preComments = null;
|
List<string> preComments = null;
|
||||||
|
String name = "";
|
||||||
|
bool isPartial = false;
|
||||||
|
$TypeContext::partialTypes = new Dictionary<string,ClassDescriptorSerialized>();
|
||||||
}:
|
}:
|
||||||
^(c=CLASS PAYLOAD?
|
^(c=CLASS ('partial' { isPartial = true; })? PAYLOAD?
|
||||||
attributes? modifiers? identifier type_parameter_constraints_clauses? type_parameter_list[$type_parameter_constraints_clauses.tpConstraints]?
|
attributes? modifiers? identifier { name = $identifier.st.ToString(); } type_parameter_constraints_clauses? type_parameter_list[$type_parameter_constraints_clauses.tpConstraints]?
|
||||||
class_extends? class_implements? { preComments = CollectedComments; preComments.Add($PAYLOAD.text); } class_body )
|
class_extends? class_implements? { preComments = CollectedComments; preComments.Add($PAYLOAD.text); } class_body )
|
||||||
{
|
{
|
||||||
if (IsPartial && topLevel) {
|
|
||||||
// Merge into existing descriptor
|
if (isPartial) {
|
||||||
|
// build a serialized descriptor and merge it
|
||||||
|
ClassDescriptorSerialized part = new ClassDescriptorSerialized(name);
|
||||||
|
|
||||||
if (preComments != null) {
|
if (preComments != null) {
|
||||||
foreach (String comment in preComments) {
|
foreach (String comment in preComments) {
|
||||||
PartialDescriptor.Comments += comment ;
|
part.Comments += comment ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Union all attributes
|
// Union all attributes
|
||||||
// we don't push through attributes yet
|
part.Atts += mkString($attributes.st);
|
||||||
PartialDescriptor.Atts += mkString($attributes.st);
|
|
||||||
|
|
||||||
// Merge modifiers
|
// Merge modifiers
|
||||||
if ($modifiers.modList != null && $modifiers.modList.Count > 0) {
|
if ($modifiers.modList != null && $modifiers.modList.Count > 0) {
|
||||||
foreach (string m in $modifiers.modList) {
|
foreach (string m in $modifiers.modList) {
|
||||||
if (!PartialDescriptor.Mods.Contains(m)) {
|
part.Mods.Add(m);
|
||||||
PartialDescriptor.Mods.Add(m);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
part.TypeParameterList = mkString($type_parameter_list.st);
|
||||||
|
|
||||||
if (String.IsNullOrEmpty(PartialDescriptor.TypeParameterList)) {
|
if ($class_extends.extendList != null && $class_extends.extendList.Count > 0) {
|
||||||
PartialDescriptor.TypeParameterList = mkString($type_parameter_list.st);
|
foreach (string m in $class_extends.extendList) {
|
||||||
|
part.ClassExtends.Add(m);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (String.IsNullOrEmpty(PartialDescriptor.TypeParameterConstraintsClauses)) {
|
|
||||||
PartialDescriptor.TypeParameterConstraintsClauses = mkString($type_parameter_constraints_clauses.st);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($class_implements.implementList != null && $class_implements.implementList.Count > 0) {
|
if ($class_implements.implementList != null && $class_implements.implementList.Count > 0) {
|
||||||
foreach (string m in $class_implements.implementList) {
|
foreach (string m in $class_implements.implementList) {
|
||||||
if (!PartialDescriptor.ClassImplements.Contains(m)) {
|
part.ClassImplements.Add(m);
|
||||||
PartialDescriptor.ClassImplements.Add(m);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (String.IsNullOrEmpty(PartialDescriptor.ClassBase)) {
|
part.ClassBody += mkString($class_body.st);
|
||||||
PartialDescriptor.ClassBase = mkString($class_extends.st);
|
part.PartialTypes = $TypeContext::partialTypes;
|
||||||
}
|
|
||||||
|
|
||||||
// Union the class bodies
|
// Place this in our parent's scope
|
||||||
PartialDescriptor.ClassBody += mkString($class_body.st);
|
Dictionary<string,ClassDescriptorSerialized> parentPartialTypes = ((TypeContext_scope)$TypeContext.ToArray()[1]).partialTypes;
|
||||||
|
if (!parentPartialTypes.ContainsKey(name)) {
|
||||||
|
parentPartialTypes[name] = part;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mergeParts(parentPartialTypes[name], part);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
-> {isPartial}?
|
||||||
-> class(modifiers = { $modifiers.st }, name={ $identifier.st }, typeparams= {$type_parameter_list.st}, comments = { preComments },
|
-> class(modifiers = { $modifiers.st }, name={ $identifier.st }, typeparams= {$type_parameter_list.st}, comments = { preComments },
|
||||||
extends = { $class_extends.st }, imps = { $class_implements.st }, body={$class_body.st}) ;
|
extends = { $class_extends.st }, imps = { $class_implements.st }, body={$class_body.st}, partial_types = { emitParts($TypeContext::partialTypes) }) ;
|
||||||
|
|
||||||
type_parameter_list [Dictionary<string,StringTemplate> tpConstraints]:
|
type_parameter_list [Dictionary<string,StringTemplate> tpConstraints]:
|
||||||
(attributes? t+=type_parameter[tpConstraints])+ -> type_parameter_list(items={ $t });
|
(attributes? t+=type_parameter[tpConstraints])+ -> type_parameter_list(items={ $t });
|
||||||
@ -1018,15 +1158,18 @@ type_parameter [Dictionary<string,StringTemplate> tpConstraints]
|
|||||||
}:
|
}:
|
||||||
identifier {if (tpConstraints == null || !tpConstraints.TryGetValue($identifier.text, out mySt)) {mySt = $identifier.st;}; } -> { mySt } ;
|
identifier {if (tpConstraints == null || !tpConstraints.TryGetValue($identifier.text, out mySt)) {mySt = $identifier.st;}; } -> { mySt } ;
|
||||||
|
|
||||||
class_extends:
|
class_extends returns [List<String> extendList]
|
||||||
ts+=class_extend+ -> extends(types = { $ts }) ;
|
@init {
|
||||||
class_extend:
|
$extendList = new List<String>();
|
||||||
^(EXTENDS ts=type) -> { $ts.st } ;
|
}:
|
||||||
|
(class_extend { $extendList.Add($class_extend.extend); })+ -> extends(types = { $extendList }) ;
|
||||||
|
class_extend returns [string extend]:
|
||||||
|
^(EXTENDS ts=type { $extend = $ts.st.ToString(); }) -> { $ts.st } ;
|
||||||
class_implements returns [List<String> implementList]
|
class_implements returns [List<String> implementList]
|
||||||
@init {
|
@init {
|
||||||
$implementList = new List<String>();
|
$implementList = new List<String>();
|
||||||
}:
|
}:
|
||||||
(class_implement {$implementList.Add($class_implement.st.ToString()); })+ -> imps(types = { $implementList }) ;
|
(class_implement {$implementList.Add($class_implement.implement); })+ -> imps(types = { $implementList }) ;
|
||||||
class_implement returns [string implement]:
|
class_implement returns [string implement]:
|
||||||
^(IMPLEMENTS ts=type) { $implement = $ts.st.ToString(); } -> { $ts.st };
|
^(IMPLEMENTS ts=type) { $implement = $ts.st.ToString(); } -> { $ts.st };
|
||||||
|
|
||||||
@ -1186,11 +1329,53 @@ parameter_array:
|
|||||||
interface_declaration
|
interface_declaration
|
||||||
@init {
|
@init {
|
||||||
List<string> preComments = null;
|
List<string> preComments = null;
|
||||||
|
String name = "";
|
||||||
|
bool isPartial = false;
|
||||||
}:
|
}:
|
||||||
^(c=INTERFACE attributes? modifiers?
|
^(c=INTERFACE ('partial' { isPartial = true; })? attributes? modifiers?
|
||||||
identifier type_parameter_constraints_clauses? variant_generic_parameter_list[$type_parameter_constraints_clauses.tpConstraints]?
|
identifier { name = $identifier.st.ToString(); } type_parameter_constraints_clauses? variant_generic_parameter_list[$type_parameter_constraints_clauses.tpConstraints]?
|
||||||
class_extends? { preComments = CollectedComments; } interface_body )
|
class_extends? { preComments = CollectedComments; } interface_body )
|
||||||
-> iface(modifiers = { $modifiers.st }, name={ $identifier.st }, typeparams={$variant_generic_parameter_list.st} ,comments = { preComments },
|
{
|
||||||
|
|
||||||
|
if (isPartial) {
|
||||||
|
// build a serialized descriptor and merge it
|
||||||
|
ClassDescriptorSerialized part = new ClassDescriptorSerialized(name);
|
||||||
|
|
||||||
|
if (preComments != null) {
|
||||||
|
foreach (String comment in preComments) {
|
||||||
|
part.Comments += comment ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
part.Type = "interface";
|
||||||
|
// Union all attributes
|
||||||
|
part.Atts += mkString($attributes.st);
|
||||||
|
// Merge modifiers
|
||||||
|
if ($modifiers.modList != null && $modifiers.modList.Count > 0) {
|
||||||
|
foreach (string m in $modifiers.modList) {
|
||||||
|
part.Mods.Add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
part.TypeParameterList = mkString($variant_generic_parameter_list.st);
|
||||||
|
|
||||||
|
if ($class_extends.extendList != null && $class_extends.extendList.Count > 0) {
|
||||||
|
foreach (string m in $class_extends.extendList) {
|
||||||
|
part.ClassExtends.Add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
part.ClassBody += mkString($interface_body.st);
|
||||||
|
|
||||||
|
// Place this in our parent's scope (We don't declare a TypeContext scope because interfaces don't have nested types)
|
||||||
|
if (!$TypeContext::partialTypes.ContainsKey(name)) {
|
||||||
|
$TypeContext::partialTypes[name] = part;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mergeParts($TypeContext::partialTypes[name], part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
-> {isPartial}?
|
||||||
|
-> class(type={ "interface" }, modifiers = { $modifiers.st }, name={ $identifier.st }, typeparams={$variant_generic_parameter_list.st} ,comments = { preComments },
|
||||||
imps = { $class_extends.st }, body = { $interface_body.st }) ;
|
imps = { $class_extends.st }, body = { $interface_body.st }) ;
|
||||||
//interface_base:
|
//interface_base:
|
||||||
// ':' interface_type_list ;
|
// ':' interface_type_list ;
|
||||||
|
@ -2212,7 +2212,7 @@ scope NSContext,SymTab;
|
|||||||
$SymTab::symtab = new Dictionary<string, TypeRepTemplate>();
|
$SymTab::symtab = new Dictionary<string, TypeRepTemplate>();
|
||||||
}
|
}
|
||||||
:
|
:
|
||||||
^(c=CLASS PAYLOAD? attributes? modifiers? identifier type_parameter_constraints_clauses?
|
^(c=CLASS 'partial'? PAYLOAD? attributes? modifiers? identifier type_parameter_constraints_clauses?
|
||||||
type_parameter_list?
|
type_parameter_list?
|
||||||
{ $NSContext::currentNS = NSPrefix(ParentNameSpace) + mkGenericTypeAlias($identifier.thetext, $type_parameter_list.tyParams); if (CompUnitName == null) CompUnitName = $NSContext::currentNS; }
|
{ $NSContext::currentNS = NSPrefix(ParentNameSpace) + mkGenericTypeAlias($identifier.thetext, $type_parameter_list.tyParams); if (CompUnitName == null) CompUnitName = $NSContext::currentNS; }
|
||||||
class_implements?
|
class_implements?
|
||||||
@ -2251,7 +2251,7 @@ scope NSContext,SymTab;
|
|||||||
}
|
}
|
||||||
class_body magicAnnotation[$modifiers.tree, $identifier.tree, null, $c.token])
|
class_body magicAnnotation[$modifiers.tree, $identifier.tree, null, $c.token])
|
||||||
-> {$class_implements.hasExtends && $class_implements.extendDotNetType.IsA(AppEnv.Search("System.Attribute", new UnknownRepTemplate("System.Attribute")), AppEnv)}? magicAnnotation
|
-> {$class_implements.hasExtends && $class_implements.extendDotNetType.IsA(AppEnv.Search("System.Attribute", new UnknownRepTemplate("System.Attribute")), AppEnv)}? magicAnnotation
|
||||||
-> ^($c PAYLOAD? attributes? modifiers? identifier type_parameter_constraints_clauses? type_parameter_list? class_implements? class_body);
|
-> ^($c 'partial'? PAYLOAD? attributes? modifiers? identifier type_parameter_constraints_clauses? type_parameter_list? class_implements? class_body);
|
||||||
|
|
||||||
type_parameter_list returns [List<string> tyParams]
|
type_parameter_list returns [List<string> tyParams]
|
||||||
@init {
|
@init {
|
||||||
@ -2467,7 +2467,7 @@ parameter_array:
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
interface_declaration:
|
interface_declaration:
|
||||||
^(INTERFACE attributes? modifiers? identifier type_parameter_constraints_clauses? variant_generic_parameter_list?
|
^(INTERFACE 'partial'? attributes? modifiers? identifier type_parameter_constraints_clauses? variant_generic_parameter_list?
|
||||||
class_extends? interface_body ) ;
|
class_extends? interface_body ) ;
|
||||||
interface_modifiers:
|
interface_modifiers:
|
||||||
modifier+ ;
|
modifier+ ;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user