193 строки
4.4 KiB
C#
193 строки
4.4 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
|
|
using Mono.Cecil;
|
|
|
|
namespace Xamarin.Bundler
|
|
{
|
|
public enum SymbolType
|
|
{
|
|
Function,
|
|
ObjectiveCClass,
|
|
Field,
|
|
}
|
|
|
|
public enum SymbolMode
|
|
{
|
|
Default,
|
|
Linker, // pass "-u symbol" to the native linker
|
|
Code, // generate code
|
|
Ignore, // do nothing and hope for the best
|
|
}
|
|
|
|
public class Symbol
|
|
{
|
|
public SymbolType Type;
|
|
public bool Ignore;
|
|
|
|
string name;
|
|
public string Name {
|
|
get {
|
|
if (name != null)
|
|
return name;
|
|
if (ObjectiveCName != null) {
|
|
var prefix = Driver.SupportsModernObjectiveC ? "OBJC_CLASS_$_" : ".objc_class_name_";
|
|
return prefix + ObjectiveCName;
|
|
}
|
|
throw ErrorHelper.CreateError (99, $"Internal error: symbol without a name (type: {Type}). Please file a bug report with a test case (https://bugzilla.xamarin.com).");
|
|
}
|
|
set {
|
|
name = value;
|
|
}
|
|
}
|
|
public string ObjectiveCName;
|
|
|
|
public string Prefix {
|
|
get {
|
|
if (ObjectiveCName != null && !Driver.SupportsModernObjectiveC)
|
|
return string.Empty;
|
|
return "_";
|
|
}
|
|
}
|
|
|
|
List<MemberReference> members = new List<MemberReference> ();
|
|
public IEnumerable<MemberReference> Members { get { return members; } }
|
|
|
|
public HashSet<AssemblyDefinition> Assemblies { get; private set; } = new HashSet<AssemblyDefinition> ();
|
|
|
|
public void AddMember (MemberReference member)
|
|
{
|
|
members.Add (member);
|
|
Assemblies.Add (member.Module.Assembly);
|
|
}
|
|
|
|
public void AddAssembly (AssemblyDefinition assembly)
|
|
{
|
|
Assemblies.Add (assembly);
|
|
}
|
|
}
|
|
|
|
public class Symbols : IEnumerable<Symbol>
|
|
{
|
|
Dictionary<string, Symbol> store = new Dictionary<string, Symbol> (StringComparer.Ordinal);
|
|
|
|
public int Count {
|
|
get {
|
|
return store.Count;
|
|
}
|
|
}
|
|
|
|
public void Add (Symbol symbol)
|
|
{
|
|
store.Add (symbol.Name, symbol);
|
|
}
|
|
|
|
public Symbol AddObjectiveCClass (string class_name)
|
|
{
|
|
var symbol = new Symbol {
|
|
Type = SymbolType.ObjectiveCClass,
|
|
ObjectiveCName = class_name,
|
|
};
|
|
var existing = Find (symbol.Name);
|
|
if (existing != null)
|
|
return existing;
|
|
Add (symbol);
|
|
return symbol;
|
|
}
|
|
|
|
public Symbol AddField (string name)
|
|
{
|
|
Symbol rv = Find (name);
|
|
if (rv == null) {
|
|
rv = new Symbol { Name = name, Type = SymbolType.Field };
|
|
Add (rv);
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
public Symbol AddFunction (string name)
|
|
{
|
|
Symbol rv = Find (name);
|
|
if (rv == null) {
|
|
rv = new Symbol { Name = name, Type = SymbolType.Function };
|
|
Add (rv);
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
public void Remove (Func<Symbol, bool> condition)
|
|
{
|
|
foreach (var symbol in this) {
|
|
if (condition (symbol))
|
|
store.Remove (symbol.Name);
|
|
}
|
|
}
|
|
|
|
public IEnumerator<Symbol> GetEnumerator ()
|
|
{
|
|
return store.Values.GetEnumerator ();
|
|
}
|
|
|
|
IEnumerator IEnumerable.GetEnumerator ()
|
|
{
|
|
return store.Values.GetEnumerator ();
|
|
}
|
|
|
|
public Symbol Find (string name)
|
|
{
|
|
Symbol rv;
|
|
store.TryGetValue (name, out rv);
|
|
return rv;
|
|
}
|
|
|
|
public bool Contains (string name)
|
|
{
|
|
return store.ContainsKey (name);
|
|
}
|
|
|
|
public Symbol this [string name] {
|
|
get {
|
|
return store [name];
|
|
}
|
|
}
|
|
|
|
public void Load (string filename, Target target)
|
|
{
|
|
using (var reader = new StreamReader (filename)) {
|
|
string line;
|
|
Symbol current = null;
|
|
while ((line = reader.ReadLine ()) != null) {
|
|
if (line.Length == 0)
|
|
continue;
|
|
if (line [0] == '\t') {
|
|
var asm = line.Substring (1);
|
|
Assembly assembly;
|
|
if (!target.Assemblies.TryGetValue (Assembly.GetIdentity (asm), out assembly))
|
|
throw ErrorHelper.CreateError (99, $"Internal error: serialized assembly {asm} for symbol {current.Name}, but no such assembly loaded. Please file a bug report with a test case (https://bugzilla.xamarin.com).");
|
|
current.AddAssembly (assembly.AssemblyDefinition);
|
|
} else {
|
|
var eq = line.IndexOf ('=');
|
|
var typestr = line.Substring (0, eq);
|
|
var name = line.Substring (eq + 1);
|
|
current = new Symbol { Name = name, Type = (SymbolType) Enum.Parse (typeof (SymbolType), typestr) };
|
|
Add (current);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Save (string filename)
|
|
{
|
|
using (var writer = new StreamWriter (filename)) {
|
|
foreach (var symbol in store.Values) {
|
|
writer.WriteLine ("{0}={1}", symbol.Type, symbol.Name);
|
|
foreach (var asm in symbol.Assemblies)
|
|
writer.WriteLine ($"\t{asm.MainModule.FileName}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|