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)
|
||||
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)
|
||||
emitPartialType(entry.Key, entry.Value);
|
||||
|
||||
@ -537,8 +537,8 @@ namespace Twiglet.CS2J.Translator
|
||||
|
||||
outputMaker.Cfg = cfg;
|
||||
outputMaker.EmittedCommentTokenIdx = saveEmittedCommentTokenIdx;
|
||||
outputMaker.IsPartial = javaMaker.CUMap[typeName].IsPartial;
|
||||
if (outputMaker.IsPartial)
|
||||
bool isPartial = javaMaker.CUMap[typeName].IsPartial;
|
||||
if (isPartial)
|
||||
{
|
||||
if (!partialTypes.ContainsKey(typeName))
|
||||
{
|
||||
@ -550,7 +550,7 @@ namespace Twiglet.CS2J.Translator
|
||||
|
||||
outputMaker.IsLast = i == (javaMaker.CUKeys.Count - 1);
|
||||
|
||||
if (!outputMaker.IsPartial)
|
||||
if (!isPartial)
|
||||
{
|
||||
if (cfg.DebugLevel >= 1) Console.Out.WriteLine("Writing out {0}", javaFName);
|
||||
StreamWriter javaW = new StreamWriter(javaFName);
|
||||
@ -574,25 +574,17 @@ namespace Twiglet.CS2J.Translator
|
||||
|
||||
public static void emitPartialType(string name, ClassDescriptorSerialized serTy)
|
||||
{
|
||||
|
||||
// Pretty print as text
|
||||
Dictionary<string,object> args = new Dictionary<string,object>();
|
||||
args["now"] = DateTime.Now;
|
||||
args["includeDate"] = cfg.TranslatorAddTimeStamp;
|
||||
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;
|
||||
JavaPrettyPrint outputMaker = new JavaPrettyPrint(null);
|
||||
outputMaker.Filename = serTy.FileName;
|
||||
outputMaker.TraceDestination = Console.Error;
|
||||
outputMaker.TemplateLib = templates;
|
||||
outputMaker.Cfg = cfg;
|
||||
|
||||
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);
|
||||
StreamWriter javaW = new StreamWriter(serTy.FileName);
|
||||
javaW.Write(limit(st.ToString()));
|
||||
javaW.Write(limit(pkgST.ToString()));
|
||||
javaW.Close();
|
||||
}
|
||||
}
|
||||
|
@ -46,37 +46,16 @@ import_list(nss) ::= <<
|
||||
|
||||
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 ***********
|
||||
|
||||
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"">
|
||||
<modifiers(modifiers)>class <name> <typeparams> <extends> <imps>
|
||||
{
|
||||
<body>
|
||||
}
|
||||
>>
|
||||
|
||||
iface(modifiers, comments, attributes, name, typeparams, imps, body) ::= <<
|
||||
<comments; separator=""\n"">
|
||||
<modifiers(modifiers)>interface <name> <typeparams> <imps>
|
||||
<modifiers><if(type)><type><else>class<endif> <name> <typeparams> <extends> <imps>
|
||||
{
|
||||
<body>
|
||||
<partial_types>
|
||||
}
|
||||
<end_comments; separator=""\n"">
|
||||
>>
|
||||
|
||||
class_body(entries) ::= <<
|
||||
@ -89,7 +68,7 @@ class_member(comments, member) ::= <<
|
||||
>>
|
||||
|
||||
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>
|
||||
<body>
|
||||
<endif>
|
||||
@ -97,7 +76,7 @@ constructor(modifiers, name, params, exceptions, body, bodyIsSemi) ::= <<
|
||||
>>
|
||||
|
||||
static_constructor(modifiers, body, bodyIsSemi) ::= <<
|
||||
<modifiers(modifiers)><if(bodyIsSemi)>;
|
||||
<modifiers><if(bodyIsSemi)>;
|
||||
<else>
|
||||
<body>
|
||||
<endif>
|
||||
@ -105,14 +84,14 @@ static_constructor(modifiers, 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>
|
||||
<body>
|
||||
<endif>
|
||||
<\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_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=\"" & \"">""
|
||||
|
||||
fixed_parameter(mod,type,name,def) ::= <<
|
||||
<mod> <type> <name><if(def)> = <def><endif>
|
||||
<mod><type> <name><if(def)> = <def><endif>
|
||||
>>
|
||||
|
||||
varargs(type,name) ::= <<
|
||||
@ -141,7 +120,7 @@ statement(statement) ::= <<
|
||||
|
||||
annotation(modifiers, comments, attributes, name, body) ::= <<
|
||||
<comments; separator=""\n"">
|
||||
<modifiers(modifiers)>@interface <name>
|
||||
<modifiers>@interface <name>
|
||||
{
|
||||
<body>
|
||||
}
|
||||
@ -159,7 +138,7 @@ throw(exp) ::= ""throw <exp>;""
|
||||
|
||||
enum(modifiers,comments, attributes, name, body) ::= <<
|
||||
<comments; separator=""\n"">
|
||||
<modifiers(modifiers)>enum <name>
|
||||
<modifiers>enum <name>
|
||||
{
|
||||
<body>
|
||||
}
|
||||
@ -175,7 +154,9 @@ enum_member(comments, value) ::= <<
|
||||
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>""
|
||||
|
||||
modifiers(mods) ::= ""<if(mods)><mods; separator=\"" \""> <endif>""
|
||||
modifiers(mods) ::= <<
|
||||
<if(mods)><mods; separator="" ""> <endif>
|
||||
>>
|
||||
|
||||
type_parameter_list(items) ::= <<
|
||||
\<<items; separator="", "">\>
|
||||
|
@ -258,45 +258,24 @@ namespace Twiglet.CS2J.Translator.Transform
|
||||
public bool IsPartial {get; set;}
|
||||
}
|
||||
|
||||
public class ClassDescriptor {
|
||||
public IToken Token { get;set; }
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// This structure holds (serialized) consolidated strings describing
|
||||
// partial classes and interfaces
|
||||
public class ClassDescriptorSerialized {
|
||||
public String FileName { get;set; }
|
||||
public List<String> Imports { get;set; }
|
||||
public String Package { get;set; }
|
||||
public String Type { get;set; }
|
||||
public String Comments { get;set; }
|
||||
public String Atts { get;set; }
|
||||
public List<String> Mods { get;set; }
|
||||
public String Identifier { 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 String TypeParameterConstraintsClauses { get;set; }
|
||||
public String ClassBody { get;set; }
|
||||
public String EndComments { get;set; }
|
||||
|
||||
public Dictionary<String,ClassDescriptorSerialized> PartialTypes { get;set; }
|
||||
|
||||
public ClassDescriptorSerialized(string name)
|
||||
{
|
||||
@ -304,14 +283,16 @@ namespace Twiglet.CS2J.Translator.Transform
|
||||
Comments = "";
|
||||
Imports = new List<String>();
|
||||
Package = "";
|
||||
Type = "class";
|
||||
Atts = "";
|
||||
Mods = new List<String>();
|
||||
Identifier = name;
|
||||
TypeParameterList = "";
|
||||
ClassBase = "";
|
||||
ClassExtends = new List<String>();
|
||||
ClassImplements = new List<String>();
|
||||
TypeParameterConstraintsClauses = "";
|
||||
ClassBody = "";
|
||||
EndComments = "";
|
||||
PartialTypes = new Dictionary<String,ClassDescriptorSerialized>();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,6 @@ scope NSContext {
|
||||
// A scope to keep track of the current type context
|
||||
scope TypeContext {
|
||||
string typeName;
|
||||
Dictionary<String,ClassDescriptor> partialTypes;
|
||||
}
|
||||
|
||||
@namespace { Twiglet.CS2J.Translator.Transform }
|
||||
@ -56,10 +55,6 @@ scope TypeContext {
|
||||
public IDictionary<string, CUnit> CUMap { 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) {
|
||||
StringBuilder ret = new StringBuilder();
|
||||
List<IToken> toks = ((CommonTokenStream)this.GetTreeNodeStream().TokenStream).GetTokens(startIndex,endIndex);
|
||||
@ -507,56 +502,56 @@ scope TypeContext {
|
||||
}
|
||||
|
||||
// Merges part into combined
|
||||
protected void mergePartialTypes(ClassDescriptor combined, ClassDescriptor part) {
|
||||
|
||||
// append comments
|
||||
combined.Comments += part.Comments;
|
||||
|
||||
// union all attributes
|
||||
CommonTree attRoot = (CommonTree)adaptor.Nil;
|
||||
adaptor.AddChild(attRoot, combined.Atts);
|
||||
adaptor.AddChild(attRoot, part.Atts);
|
||||
combined.Atts = (CommonTree)adaptor.RulePostProcessing(attRoot);
|
||||
|
||||
// merge all modifiers
|
||||
combined.Mods = mergeModifiers(combined.Mods, part.Mods);
|
||||
|
||||
// type parameter list must be the same on all parts
|
||||
|
||||
// all parts that have a TypeParameterConstraintsClauses must agree
|
||||
if (combined.TypeParameterConstraintsClauses == null)
|
||||
combined.TypeParameterConstraintsClauses = part.TypeParameterConstraintsClauses;
|
||||
|
||||
// merge all base classes, interfaces
|
||||
combined.ClassBase = mergeModifiers(combined.ClassBase, part.ClassBase);
|
||||
|
||||
// union all class_body
|
||||
CommonTree bodyRoot = (CommonTree)adaptor.Nil;
|
||||
adaptor.AddChild(bodyRoot, combined.ClassBody);
|
||||
adaptor.AddChild(bodyRoot, part.ClassBody);
|
||||
combined.ClassBody = (CommonTree)adaptor.RulePostProcessing(bodyRoot);
|
||||
|
||||
// merge partial sub-types
|
||||
foreach (string key in combined.PartialTypes.Keys) {
|
||||
if (part.PartialTypes.ContainsKey(key)) {
|
||||
mergePartialTypes(combined.PartialTypes[key], part.PartialTypes[key]);
|
||||
}
|
||||
}
|
||||
// Add types in part but not combined
|
||||
foreach (string key in part.PartialTypes.Keys) {
|
||||
if (!combined.PartialTypes.ContainsKey(key)) {
|
||||
combined.PartialTypes[key] = part.PartialTypes[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected CommonTree emitPartialTypes(Dictionary<string,ClassDescriptor> partialTypes) {
|
||||
CommonTree root = (CommonTree)adaptor.Nil;
|
||||
foreach (ClassDescriptor part in partialTypes.Values) {
|
||||
root.AddChild((CommonTree)magicClassFromDescriptor(part.Token, part).Tree);
|
||||
}
|
||||
return (CommonTree)adaptor.RulePostProcessing(root);
|
||||
}
|
||||
// protected void mergePartialTypes(ClassDescriptor combined, ClassDescriptor part) {
|
||||
//
|
||||
// // append comments
|
||||
// combined.Comments += part.Comments;
|
||||
//
|
||||
// // union all attributes
|
||||
// CommonTree attRoot = (CommonTree)adaptor.Nil;
|
||||
// adaptor.AddChild(attRoot, combined.Atts);
|
||||
// adaptor.AddChild(attRoot, part.Atts);
|
||||
// combined.Atts = (CommonTree)adaptor.RulePostProcessing(attRoot);
|
||||
//
|
||||
// // merge all modifiers
|
||||
// combined.Mods = mergeModifiers(combined.Mods, part.Mods);
|
||||
//
|
||||
// // type parameter list must be the same on all parts
|
||||
//
|
||||
// // all parts that have a TypeParameterConstraintsClauses must agree
|
||||
// if (combined.TypeParameterConstraintsClauses == null)
|
||||
// combined.TypeParameterConstraintsClauses = part.TypeParameterConstraintsClauses;
|
||||
//
|
||||
// // merge all base classes, interfaces
|
||||
// combined.ClassBase = mergeModifiers(combined.ClassBase, part.ClassBase);
|
||||
//
|
||||
// // union all class_body
|
||||
// CommonTree bodyRoot = (CommonTree)adaptor.Nil;
|
||||
// adaptor.AddChild(bodyRoot, combined.ClassBody);
|
||||
// adaptor.AddChild(bodyRoot, part.ClassBody);
|
||||
// combined.ClassBody = (CommonTree)adaptor.RulePostProcessing(bodyRoot);
|
||||
//
|
||||
// // merge partial sub-types
|
||||
// foreach (string key in combined.PartialTypes.Keys) {
|
||||
// if (part.PartialTypes.ContainsKey(key)) {
|
||||
// mergePartialTypes(combined.PartialTypes[key], part.PartialTypes[key]);
|
||||
// }
|
||||
// }
|
||||
// // Add types in part but not combined
|
||||
// foreach (string key in part.PartialTypes.Keys) {
|
||||
// if (!combined.PartialTypes.ContainsKey(key)) {
|
||||
// combined.PartialTypes[key] = part.PartialTypes[key];
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// protected CommonTree emitPartialTypes(Dictionary<string,ClassDescriptor> partialTypes) {
|
||||
// CommonTree root = (CommonTree)adaptor.Nil;
|
||||
// foreach (ClassDescriptor part in partialTypes.Values) {
|
||||
// root.AddChild((CommonTree)magicClassFromDescriptor(part.Token, part).Tree);
|
||||
// }
|
||||
// return (CommonTree)adaptor.RulePostProcessing(root);
|
||||
// }
|
||||
|
||||
protected void mergeCompUnits(CUnit cu, List<string> searchPath, List<string> aliasKeys, List<string> aliasNamespaces) {
|
||||
foreach (string s in searchPath) {
|
||||
@ -590,7 +585,6 @@ scope NSContext, TypeContext;
|
||||
$NSContext::aliasNamespaces = new List<string>();
|
||||
|
||||
$TypeContext::typeName = null;
|
||||
$TypeContext::partialTypes = new Dictionary<String,ClassDescriptor>();
|
||||
}
|
||||
:
|
||||
namespace_body;
|
||||
@ -636,7 +630,6 @@ scope TypeContext;
|
||||
bool isCompUnit = false;
|
||||
CommonTree atts = null;
|
||||
CommonTree mods = null;
|
||||
$TypeContext::partialTypes = new Dictionary<string, ClassDescriptor>();
|
||||
}
|
||||
@after {
|
||||
if (isCompUnit) {
|
||||
@ -647,21 +640,11 @@ scope TypeContext;
|
||||
Warning(treeEntry.Value.Token.Line, "[UNSUPPORTED] Cannot have a class with multiple generic type overloadings: " + fqn);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
@ -669,17 +652,19 @@ scope TypeContext;
|
||||
;
|
||||
// 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)
|
||||
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 {
|
||||
$compUnits = new Dictionary<String,CommonTree>();
|
||||
$isPartial = false;
|
||||
}
|
||||
:
|
||||
('partial') => p='partial'! (pc=class_declaration[$atts, $mods, true /* toplevel */, true /* isPartial */]
|
||||
| ps=struct_declaration[$atts, $mods, true /* toplevel */, true /* isPartial */]
|
||||
| pi=interface_declaration[$atts, $mods] { $compUnits.Add($pi.name, $pi.tree); } )
|
||||
| c=class_declaration[$atts, $mods, true /* toplevel */, false /* isPartial */] { $compUnits.Add($c.name, $c.tree); }
|
||||
| s=struct_declaration[$atts, $mods, true /* toplevel */, false /* isPartial */] { $compUnits.Add($s.name, $s.tree); }
|
||||
| i=interface_declaration[$atts, $mods] { $compUnits.Add($i.name, $i.tree); }
|
||||
('partial') => p='partial' { $isPartial = true; }
|
||||
(pc=class_declaration[$atts, $mods, $p, true /* toplevel */] { $compUnits.Add($pc.name, $pc.tree); }
|
||||
| ps=struct_declaration[$atts, $mods, $p, true /* toplevel */] { $compUnits.Add($ps.name, $ps.tree); }
|
||||
| pi=interface_declaration[$atts, $mods, $p] { $compUnits.Add($pi.name, $pi.tree); } )
|
||||
| c=class_declaration[$atts, $mods, null, true /* toplevel */] { $compUnits.Add($c.name, $c.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); }
|
||||
| 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'
|
||||
| '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
|
||||
@after {
|
||||
this.prevMemberEndTokenIndex = adaptor.GetTokenStopIndex($class_member_declaration.tree);
|
||||
}:
|
||||
class_member_declaration:
|
||||
a=attributes?
|
||||
m=modifiers?
|
||||
( 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
|
||||
| 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
|
||||
| pc=class_declaration[$a.tree, $m.tree, false /* toplevel */, true /* isPartial */] -> { $pc.tree != null}? $pc
|
||||
->
|
||||
| ps=struct_declaration[$a.tree, $m.tree, false /* toplevel */, true /* isPartial */] -> { ps.tree != null}? $ps
|
||||
-> )
|
||||
| i=interface_declaration[$a.tree, $m.tree] -> $i
|
||||
| pi=interface_declaration[$a.tree, $m.tree, $p] -> $pi
|
||||
| pc=class_declaration[$a.tree, $m.tree, $p, false /* toplevel */] -> $pc
|
||||
| ps=struct_declaration[$a.tree, $m.tree, $p, false /* toplevel */] -> $ps)
|
||||
| i=interface_declaration[$a.tree, $m.tree, null] -> $i
|
||||
| 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
|
||||
| (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)
|
||||
|
||||
| cd=class_declaration[$a.tree, $m.tree, false /* toplevel */, false /* isPartial */] -> $cd
|
||||
| sd=struct_declaration[$a.tree, $m.tree, false /* toplevel */, false /* isPartial */] -> $sd
|
||||
| cd=class_declaration[$a.tree, $m.tree, null, false /* toplevel */] -> $cd
|
||||
| sd=struct_declaration[$a.tree, $m.tree, null, false /* toplevel */] -> $sd
|
||||
| ed=enum_declaration[$a.tree, $m.tree] -> $ed
|
||||
| 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)
|
||||
@ -1258,42 +1238,11 @@ attribute_argument_expression:
|
||||
// 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;
|
||||
@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; })?
|
||||
{
|
||||
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 );
|
||||
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 );
|
||||
|
||||
type_parameter_list returns [List<string> names]
|
||||
@init {
|
||||
@ -1311,10 +1260,8 @@ class_base:
|
||||
//interface_type_list:
|
||||
// ts+=type (',' ts+=type)* -> $ts+;
|
||||
|
||||
class_body[bool isPartial] returns [IToken endToken]:
|
||||
'{' class_member_declarations? e='}' { $endToken = $e.token; }
|
||||
-> {!$isPartial}? '{' class_member_declarations? { emitPartialTypes($TypeContext::partialTypes) } '}'
|
||||
-> '{' class_member_declarations? '}' ;
|
||||
class_body:
|
||||
'{' class_member_declarations? '}' ;
|
||||
class_member_declarations:
|
||||
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;
|
||||
:
|
||||
c='interface' identifier { $name = $identifier.thetext; $TypeContext::typeName = $identifier.thetext; } variant_generic_parameter_list?
|
||||
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:
|
||||
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;
|
||||
@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; })?
|
||||
{
|
||||
if ($isPartial) {
|
||||
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 );
|
||||
|
||||
// Strip off braces
|
||||
CommonTree newClassBody = dupTree($struct_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(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) } '}'
|
||||
struct_body [string structName]:
|
||||
o='{' magicDefaultConstructor[$o.token, structName] class_member_declarations? e='}'
|
||||
-> '{' 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, "}"])
|
||||
;
|
||||
|
||||
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, "}"] );
|
||||
//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, "}"] );
|
||||
|
@ -12,6 +12,11 @@ options {
|
||||
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 }
|
||||
|
||||
@header
|
||||
@ -25,9 +30,9 @@ options {
|
||||
@members
|
||||
{
|
||||
|
||||
public bool IsPartial { get; set; }
|
||||
public bool IsLast { 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; }
|
||||
|
||||
private List<string> collectedComments = null;
|
||||
@ -293,20 +298,139 @@ options {
|
||||
protected string mkString(object s) {
|
||||
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
|
||||
scope TypeContext;
|
||||
@init{
|
||||
initPrecedence();
|
||||
$TypeContext::partialTypes = new Dictionary<string,ClassDescriptorSerialized>();
|
||||
}
|
||||
:
|
||||
^(PACKAGE nm=PAYLOAD imports? type_declaration)
|
||||
|
||||
{
|
||||
if (IsLast) collectComments();
|
||||
if (IsPartial) {
|
||||
// Merge into existing descriptor
|
||||
if (PartialDescriptor != null && $TypeContext::partialTypes.Count > 0) {
|
||||
// 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);
|
||||
if ($imports.importList != null && $imports.importList.Count > 0) {
|
||||
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)},
|
||||
imports = {$imports.st},
|
||||
@ -955,59 +1089,65 @@ attribute_argument_expression:
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
class_declaration[bool topLevel]
|
||||
scope TypeContext;
|
||||
@init {
|
||||
List<string> preComments = null;
|
||||
String name = "";
|
||||
bool isPartial = false;
|
||||
$TypeContext::partialTypes = new Dictionary<string,ClassDescriptorSerialized>();
|
||||
}:
|
||||
^(c=CLASS PAYLOAD?
|
||||
attributes? modifiers? identifier type_parameter_constraints_clauses? type_parameter_list[$type_parameter_constraints_clauses.tpConstraints]?
|
||||
^(c=CLASS ('partial' { isPartial = true; })? PAYLOAD?
|
||||
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 )
|
||||
{
|
||||
if (IsPartial && topLevel) {
|
||||
// Merge into existing descriptor
|
||||
|
||||
if (isPartial) {
|
||||
// build a serialized descriptor and merge it
|
||||
ClassDescriptorSerialized part = new ClassDescriptorSerialized(name);
|
||||
|
||||
if (preComments != null) {
|
||||
foreach (String comment in preComments) {
|
||||
PartialDescriptor.Comments += comment ;
|
||||
part.Comments += comment ;
|
||||
}
|
||||
}
|
||||
// Union all attributes
|
||||
// we don't push through attributes yet
|
||||
PartialDescriptor.Atts += mkString($attributes.st);
|
||||
|
||||
part.Atts += mkString($attributes.st);
|
||||
// Merge modifiers
|
||||
if ($modifiers.modList != null && $modifiers.modList.Count > 0) {
|
||||
foreach (string m in $modifiers.modList) {
|
||||
if (!PartialDescriptor.Mods.Contains(m)) {
|
||||
PartialDescriptor.Mods.Add(m);
|
||||
}
|
||||
part.Mods.Add(m);
|
||||
}
|
||||
}
|
||||
part.TypeParameterList = mkString($type_parameter_list.st);
|
||||
|
||||
if (String.IsNullOrEmpty(PartialDescriptor.TypeParameterList)) {
|
||||
PartialDescriptor.TypeParameterList = mkString($type_parameter_list.st);
|
||||
if ($class_extends.extendList != null && $class_extends.extendList.Count > 0) {
|
||||
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) {
|
||||
foreach (string m in $class_implements.implementList) {
|
||||
if (!PartialDescriptor.ClassImplements.Contains(m)) {
|
||||
PartialDescriptor.ClassImplements.Add(m);
|
||||
}
|
||||
part.ClassImplements.Add(m);
|
||||
}
|
||||
}
|
||||
|
||||
if (String.IsNullOrEmpty(PartialDescriptor.ClassBase)) {
|
||||
PartialDescriptor.ClassBase = mkString($class_extends.st);
|
||||
}
|
||||
part.ClassBody += mkString($class_body.st);
|
||||
part.PartialTypes = $TypeContext::partialTypes;
|
||||
|
||||
// Union the class bodies
|
||||
PartialDescriptor.ClassBody += mkString($class_body.st);
|
||||
// Place this in our parent's scope
|
||||
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 },
|
||||
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]:
|
||||
(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 } ;
|
||||
|
||||
class_extends:
|
||||
ts+=class_extend+ -> extends(types = { $ts }) ;
|
||||
class_extend:
|
||||
^(EXTENDS ts=type) -> { $ts.st } ;
|
||||
class_extends returns [List<String> extendList]
|
||||
@init {
|
||||
$extendList = new List<String>();
|
||||
}:
|
||||
(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]
|
||||
@init {
|
||||
$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]:
|
||||
^(IMPLEMENTS ts=type) { $implement = $ts.st.ToString(); } -> { $ts.st };
|
||||
|
||||
@ -1186,11 +1329,53 @@ parameter_array:
|
||||
interface_declaration
|
||||
@init {
|
||||
List<string> preComments = null;
|
||||
String name = "";
|
||||
bool isPartial = false;
|
||||
}:
|
||||
^(c=INTERFACE attributes? modifiers?
|
||||
identifier type_parameter_constraints_clauses? variant_generic_parameter_list[$type_parameter_constraints_clauses.tpConstraints]?
|
||||
^(c=INTERFACE ('partial' { isPartial = true; })? attributes? modifiers?
|
||||
identifier { name = $identifier.st.ToString(); } type_parameter_constraints_clauses? variant_generic_parameter_list[$type_parameter_constraints_clauses.tpConstraints]?
|
||||
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 }) ;
|
||||
//interface_base:
|
||||
// ':' interface_type_list ;
|
||||
|
@ -2212,7 +2212,7 @@ scope NSContext,SymTab;
|
||||
$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?
|
||||
{ $NSContext::currentNS = NSPrefix(ParentNameSpace) + mkGenericTypeAlias($identifier.thetext, $type_parameter_list.tyParams); if (CompUnitName == null) CompUnitName = $NSContext::currentNS; }
|
||||
class_implements?
|
||||
@ -2251,7 +2251,7 @@ scope NSContext,SymTab;
|
||||
}
|
||||
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
|
||||
-> ^($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]
|
||||
@init {
|
||||
@ -2467,7 +2467,7 @@ parameter_array:
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
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 ) ;
|
||||
interface_modifiers:
|
||||
modifier+ ;
|
||||
|
Loading…
x
Reference in New Issue
Block a user