Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 11 additions & 30 deletions tools/generator/CodeGenerationOptions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand All @@ -10,29 +11,6 @@ namespace MonoDroid.Generation
{
public class CodeGenerationOptions
{
Stack<GenBase> context_types = new Stack<GenBase> ();
public Stack<GenBase> ContextTypes {
get { return context_types; }
}
public List<Method> ContextGeneratedMethods { get; set; } = new List<Method> ();
public GenBase ContextType {
get { return context_types.Any () ? context_types.Peek () : null; }
}
public Field ContextField { get; set; }
string ContextFieldString {
get { return ContextField != null ? "in field " + ContextField.Name + " " : null; }
}
public MethodBase ContextMethod { get; set; }
string ContextMethodString {
get { return ContextMethod != null ? "in method " + ContextMethod.Name + " " : null; }
}
string ContextTypeString {
get { return ContextType != null ? "in managed type " + ContextType.FullName : null; }
}
public string ContextString {
get { return ContextFieldString + ContextMethodString + ContextTypeString; }
}

CodeGenerationTarget codeGenerationTarget;
public CodeGenerationTarget CodeGenerationTarget {
get { return codeGenerationTarget; }
Expand Down Expand Up @@ -134,20 +112,23 @@ public string GetSafeIdentifier (string name)
return name.Replace ('$', '_');
}

Dictionary<string,string> short_file_names = new Dictionary<string, string> ();
readonly Dictionary<string,string> short_file_names = new Dictionary<string, string> ();

public string GetFileName (string fullName)
{
if (!UseShortFileNames)
return fullName;
string s;
if (short_file_names.TryGetValue (fullName, out s))

lock (short_file_names) {
if (short_file_names.TryGetValue (fullName, out var s))
return s;

s = short_file_names.Count.ToString ();
short_file_names [fullName] = s;

return s;
s = short_file_names.Count.ToString ();
short_file_names [fullName] = s;
return s;
}
}
}

}

7 changes: 4 additions & 3 deletions tools/generator/CodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ static void Run (CodeGeneratorOptions options, DirectoryAssemblyResolver resolve
AddTypeToTable (opt, gen);
}

Validate (gens, opt);
Validate (gens, opt, new CodeGeneratorContext ());

if (api_versions_xml != null)
ApiVersionsSupport.AssignApiLevels (gens, api_versions_xml);
Expand Down Expand Up @@ -175,6 +175,7 @@ static void Run (CodeGeneratorOptions options, DirectoryAssemblyResolver resolve
if (gen.IsGeneratable)
gen.Generate (opt, gen_info);


ClassGen.GenerateTypeRegistrations (opt, gen_info);
ClassGen.GenerateEnumList (gen_info);

Expand Down Expand Up @@ -211,7 +212,7 @@ static IEnumerable<GenBase> FlattenNestedTypes (IEnumerable<GenBase> gens)
}
}

static void Validate (List<GenBase> gens, CodeGenerationOptions opt)
static void Validate (List<GenBase> gens, CodeGenerationOptions opt, CodeGeneratorContext context)
{
//int cycle = 1;
List<GenBase> removed = new List<GenBase> ();
Expand All @@ -229,7 +230,7 @@ static void Validate (List<GenBase> gens, CodeGenerationOptions opt)
foreach (GenBase gen in gens)
if ((opt.IgnoreNonPublicType &&
(gen.RawVisibility != "public" && gen.RawVisibility != "internal"))
|| !gen.Validate (opt, null)) {
|| !gen.Validate (opt, null, context)) {
foreach (GenBase nest in gen.NestedTypes) {
foreach (var nt in nest.Invalidate ())
removed.Add (nt);
Expand Down
20 changes: 20 additions & 0 deletions tools/generator/CodeGeneratorContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace MonoDroid.Generation
{
public class CodeGeneratorContext
{
public Stack<GenBase> ContextTypes { get; } = new Stack<GenBase> ();
public List<Method> ContextGeneratedMethods { get; set; } = new List<Method> ();
public Field ContextField { get; set; }
public MethodBase ContextMethod { get; set; }

public GenBase ContextType => ContextTypes.Any () ? ContextTypes.Peek () : null;
string ContextFieldString => ContextField != null ? "in field " + ContextField.Name + " " : null;
string ContextMethodString => ContextMethod != null ? "in method " + ContextMethod.Name + " " : null;
string ContextTypeString => ContextType != null ? "in managed type " + ContextType.FullName : null;
public string ContextString => ContextFieldString + ContextMethodString + ContextTypeString;
}
}
72 changes: 16 additions & 56 deletions tools/generator/GenerationInfo.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand All @@ -13,77 +14,36 @@ public class GenerationInfo {

public GenerationInfo (string csdir, string javadir, string assembly)
{
this.csdir = csdir;
this.javadir = javadir;
this.assembly = assembly;
CSharpDir = csdir;
JavaDir = javadir;
Assembly = assembly;
}

string assembly;
public string Assembly {
get { return assembly; }
}

string csdir;
public string CSharpDir {
get { return csdir; }
}

string javadir;
public string JavaDir {
get { return javadir; }
}

string member;
public string CurrentMember {
get { return typename + "." + member; }
set { member = value; }
}

string typename;
public string CurrentType {
get { return typename; }
set { typename = value; }
}

StreamWriter sw;
public StreamWriter Writer {
get { return sw; }
set { sw = value; }
}

List<string> generated_files = new List<string> ();
public IEnumerable<string> GeneratedFiles {
get { return generated_files; }
}
public string Assembly { get; }
public string CSharpDir { get; }
public string JavaDir { get; }
public ConcurrentBag<string> GeneratedFiles { get; } = new ConcurrentBag<string> ();
public ConcurrentBag<string> Enums { get; } = new ConcurrentBag<string> ();
public ConcurrentBag<KeyValuePair<string, string>> TypeRegistrations { get; } = new ConcurrentBag<KeyValuePair<string, string>> ();

public StreamWriter OpenStream (string name)
{
if (!Directory.Exists(csdir))
Directory.CreateDirectory (csdir);
string filename = Path.Combine (csdir, name + ".cs");
if (!Directory.Exists (CSharpDir))
Directory.CreateDirectory (CSharpDir);
string filename = Path.Combine (CSharpDir, name + ".cs");

sw = new StreamWriter (File.Create (filename));
generated_files.Add (filename);
var sw = new StreamWriter (File.Create (filename));
GeneratedFiles.Add (filename);
return sw;
}

List<string> enums = new List<string> ();
public ICollection<string> Enums {
get { return enums; }
}

List<KeyValuePair<string, string>> type_registrations = new List<KeyValuePair<string, string>> ();
public ICollection<KeyValuePair<string, string>> TypeRegistrations {
get { return type_registrations; }
}

internal void GenerateLibraryProjectFile (CodeGeneratorOptions options, IEnumerable<string> enumFiles, string path = null)
{
if (path == null) {
var name = Assembly ?? "GeneratedFiles";
int idx = name.IndexOf (',');
name = idx < 0 ? name : name.Substring (0, idx);
path = Path.Combine (csdir, name + ".projitems");
path = Path.Combine (CSharpDir, name + ".projitems");
}

var msbuild = XNamespace.Get ("http://schemas.microsoft.com/developer/msbuild/2003");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
Expand All @@ -13,6 +14,8 @@ abstract class CodeGenerator
protected TextWriter writer;
protected CodeGenerationOptions opt;

public CodeGeneratorContext Context { get; } = new CodeGeneratorContext ();

protected CodeGenerator (TextWriter writer, CodeGenerationOptions options)
{
this.writer = writer;
Expand All @@ -38,8 +41,8 @@ protected CodeGenerator (TextWriter writer, CodeGenerationOptions options)

public void WriteClass (ClassGen @class, string indent, GenerationInfo gen_info)
{
opt.ContextTypes.Push (@class);
opt.ContextGeneratedMethods = new List<Method> ();
Context.ContextTypes.Push (@class);
Context.ContextGeneratedMethods = new List<Method> ();

gen_info.TypeRegistrations.Add (new KeyValuePair<string, string> (@class.RawJniName, @class.AssemblyQualifiedName));
bool is_enum = @class.base_symbol != null && @class.base_symbol.FullName == "Java.Lang.Enum";
Expand Down Expand Up @@ -186,9 +189,9 @@ public void WriteClass (ClassGen @class, string indent, GenerationInfo gen_info)
WriteClassInvoker (@class, indent);
}

opt.ContextGeneratedMethods.Clear ();
Context.ContextGeneratedMethods.Clear ();

opt.ContextTypes.Pop ();
Context.ContextTypes.Pop ();
}

public void WriteClassAbstractMembers (ClassGen @class, string indent)
Expand Down Expand Up @@ -289,7 +292,7 @@ public void WriteClassMethods (ClassGen @class, string indent)
WriteMethodAbstractDeclaration (m, indent, null, @class);
else
WriteMethod (m, indent, @class, true);
opt.ContextGeneratedMethods.Add (m);
Context.ContextGeneratedMethods.Add (m);
m.IsVirtual = virt;
}

Expand Down Expand Up @@ -393,7 +396,7 @@ public bool WriteFields (List<Field> fields, string indent, GenBase gen, HashSet
Report.Warning (0, Report.WarningDuplicateField, "Skipping {0}.{1}, due to a duplicate field. (Field) (Java type: {2})", gen.FullName, f.Name, gen.JavaName);
continue;
}
if (f.Validate (opt, gen.TypeParameters)) {
if (f.Validate (opt, gen.TypeParameters, Context)) {
if (seen != null)
seen.Add (f.Name);
needsProperty = needsProperty || f.NeedsProperty;
Expand Down Expand Up @@ -440,7 +443,7 @@ internal virtual void WriteField (Field field, string indent, GenBase type)

public void WriteInterface (InterfaceGen @interface, string indent, GenerationInfo gen_info)
{
opt.ContextTypes.Push (@interface);
Context.ContextTypes.Push (@interface);

// interfaces don't nest, so generate as siblings
foreach (GenBase nest in @interface.NestedTypes) {
Expand All @@ -465,7 +468,7 @@ public void WriteInterface (InterfaceGen @interface, string indent, GenerationIn
WriteInterfaceExtensionsDeclaration (@interface, indent, null);
WriteInterfaceInvoker (@interface, indent);
WriteInterfaceEventHandler (@interface, indent);
opt.ContextTypes.Pop ();
Context.ContextTypes.Pop ();
}

// For each interface, generate either an abstract method or an explicit implementation method.
Expand All @@ -474,7 +477,7 @@ public void WriteInterfaceAbstractMembers (InterfaceGen @interface, ClassGen gen
foreach (Method m in @interface.Methods.Where (m => !m.IsInterfaceDefaultMethod && !m.IsStatic)) {
bool mapped = false;
string sig = m.GetSignature ();
if (opt.ContextGeneratedMethods.Any (_ => _.Name == m.Name && _.JniSignature == m.JniSignature))
if (Context.ContextGeneratedMethods.Any (_ => _.Name == m.Name && _.JniSignature == m.JniSignature))
continue;
for (var cls = gen; cls != null; cls = cls.BaseGen)
if (cls.ContainsMethod (m, false) || cls != gen && gen.ExplicitlyImplementedInterfaceMethods.Contains (sig)) {
Expand All @@ -487,7 +490,7 @@ public void WriteInterfaceAbstractMembers (InterfaceGen @interface, ClassGen gen
WriteMethodExplicitInterfaceImplementation (m, indent, @interface);
else
WriteMethodAbstractDeclaration (m, indent, @interface, gen);
opt.ContextGeneratedMethods.Add (m);
Context.ContextGeneratedMethods.Add (m);
}
foreach (Property prop in @interface.Properties.Where (p => !p.Getter.IsStatic)) {
if (gen.ContainsProperty (prop.Name, false))
Expand Down Expand Up @@ -777,7 +780,7 @@ public void WriteInterfaceInvoker (InterfaceGen @interface, string indent)
writer.WriteLine ();
writer.WriteLine ("{0}\tpublic {1}Invoker (IntPtr handle, JniHandleOwnership transfer) : base (Validate (handle), transfer)", indent, @interface.Name);
writer.WriteLine ("{0}\t{{", indent);
writer.WriteLine ("{0}\t\tIntPtr local_ref = JNIEnv.GetObjectClass ({1});", indent, opt.ContextType.GetObjectHandleProperty ("this"));
writer.WriteLine ("{0}\t\tIntPtr local_ref = JNIEnv.GetObjectClass ({1});", indent, Context.ContextType.GetObjectHandleProperty ("this"));
writer.WriteLine ("{0}\t\tthis.class_ref = JNIEnv.NewGlobalRef (local_ref);", indent);
writer.WriteLine ("{0}\t\tJNIEnv.DeleteLocalRef (local_ref);", indent);
writer.WriteLine ("{0}\t}}", indent);
Expand Down Expand Up @@ -1176,7 +1179,7 @@ public void WriteMethodInvokerBody (Method method, string indent)
WriteParameterListCallArgs (method.Parameters, indent, invoker: true);
string env_method = "Call" + method.RetVal.CallMethodPrefix + "Method";
string call = "JNIEnv." + env_method + " (" +
opt.ContextType.GetObjectHandleProperty ("this") + ", " + method.EscapedIdName + method.Parameters.GetCallArgs (opt, invoker: true) + ")";
Context.ContextType.GetObjectHandleProperty ("this") + ", " + method.EscapedIdName + method.Parameters.GetCallArgs (opt, invoker: true) + ")";
if (method.IsVoid)
writer.WriteLine ("{0}{1};", indent, call);
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ internal override void WriteConstructorBody (Ctor ctor, string indent, System.Co
? "(" + ctor.Parameters.JniNestedDerivedSignature + ")V"
: ctor.JniSignature);
writer.WriteLine ();
writer.WriteLine ("{0}if ({1} != IntPtr.Zero)", indent, opt.ContextType.GetObjectHandleProperty ("this"));
writer.WriteLine ("{0}if ({1} != IntPtr.Zero)", indent, Context.ContextType.GetObjectHandleProperty ("this"));
writer.WriteLine ("{0}\treturn;", indent);
writer.WriteLine ();
foreach (string prep in ctor.Parameters.GetCallPrep (opt))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.ComponentModel.Design;
using System.IO;

namespace MonoDroid.Generation {
Expand Down Expand Up @@ -65,7 +66,7 @@ internal override void WriteConstructorIdField (Ctor ctor, string indent)

internal override void WriteConstructorBody (Ctor ctor, string indent, System.Collections.Specialized.StringCollection call_cleanup)
{
writer.WriteLine ("{0}if ({1} != IntPtr.Zero)", indent, opt.ContextType.GetObjectHandleProperty ("this"));
writer.WriteLine ("{0}if ({1} != IntPtr.Zero)", indent, Context.ContextType.GetObjectHandleProperty ("this"));
writer.WriteLine ("{0}\treturn;", indent);
writer.WriteLine ();
foreach (string prep in ctor.Parameters.GetCallPrep (opt))
Expand All @@ -83,7 +84,7 @@ internal override void WriteConstructorBody (Ctor ctor, string indent, System.Co
writer.WriteLine ("{0}\t\t\tJniHandleOwnership.TransferLocalRef);", indent);
writer.WriteLine ("{0}\tglobal::Android.Runtime.JNIEnv.FinishCreateInstance ({1}, \"{2}\"{3});",
indent,
opt.ContextType.GetObjectHandleProperty ("this"),
Context.ContextType.GetObjectHandleProperty ("this"),
ctor.IsNonStaticNestedType ? "(" + ctor.Parameters.JniNestedDerivedSignature + ")V" : ctor.JniSignature,
ctor.Parameters.GetCallArgs (opt, invoker:false));
writer.WriteLine ("{0}\treturn;", indent);
Expand All @@ -97,7 +98,7 @@ internal override void WriteConstructorBody (Ctor ctor, string indent, System.Co
writer.WriteLine ("{0}\t\tJniHandleOwnership.TransferLocalRef);", indent);
writer.WriteLine ("{0}JNIEnv.FinishCreateInstance ({1}, class_ref, {2}{3});",
indent,
opt.ContextType.GetObjectHandleProperty ("this"),
Context.ContextType.GetObjectHandleProperty ("this"),
ctor.ID,
ctor.Parameters.GetCallArgs (opt, invoker:false));
indent = oldindent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,11 @@ public override string Name {
set { name = value; }
}

protected override bool OnValidate (CodeGenerationOptions opt, GenericParameterDefinitionList tps)
protected override bool OnValidate (CodeGenerationOptions opt, GenericParameterDefinitionList tps, CodeGeneratorContext context)
{
if (missing_enclosing_class)
return false;
return base.OnValidate (opt, tps);
return base.OnValidate (opt, tps, context);
}

public override string CustomAttributes {
Expand Down
Loading