Esempio n. 1
0
        void Add(Dictionary <string, HierarchyElement> index, string indexName, string typeName, HierarchyElement type)
        {
            if (String.IsNullOrEmpty(typeName))
            {
                throw new ArgumentException("must not be null or empty", nameof(typeName));
            }

            if (String.Compare("java.lang.Comparable", typeName, StringComparison.OrdinalIgnoreCase) == 0)
            {
                Logger.Debug($"java.lang.Comparable being added: {type} ({type.FullName})");
            }

            //Logger.Verbose ($"Index: trying to add '{typeName}' ({type.GetType ().FullName}), parent: {type.ParentElement?.FullName} ({type.ParentElement?.GetType ()?.FullName})");
            HierarchyElement t;

            if (index.TryGetValue(typeName, out t) && t != null)
            {
                // if (t.GetType () == type.GetType ()) // TODO: implement IEquatable<T> on namespaces,
                //                   // classes and indexes and don't throw if the two
                //                   // objects have actually equal contents
                //  throw new InvalidOperationException ($"Duplicate type entry for type '{typeName}' ({type.GetType ().FullName})' in {indexName} index");

                string prefix = TypeToPrefix(type);
                Logger.Warning($"Duplicate type name '{typeName}' in {indexName} index. Existing entry is of type {t.GetType ().FullName}, new entry of type {type.GetType ().FullName}");
                Logger.Debug($"Prefixing new type entry with '{prefix}:'");
                // This is necessary because Xamarin.Android adds invoker classes for deprecated
                // interfaces and, initially, the class has exactly the same Java name as the interface
                // and only later in the process the interface name is prefixed with 'I' creating a
                // unique managed type name
                typeName = $"{prefix}:{typeName}";
            }

            index [typeName] = type;
        }
Esempio n. 2
0
        protected virtual void GenerateNamespaceMember(HierarchyNamespace ns, HierarchyElement element, string outputDirectory)
        {
            FilesystemPath path = Context.OutputPathProvider.GetPathFor(outputDirectory, element);

            if (String.IsNullOrEmpty(path?.FullPath))
            {
                Logger.Warning($"Unable to generate output for element {element.GetType ().FullName} ({element.GetManagedName (true) ?? element.FullName}) since no full path was given (at {element.GetLocation ()})");
                return;
            }

            if (path.IsDirectory)
            {
                throw new InvalidOperationException($"Namespace member must be written to a file ({ns.FullName})");
            }

            EnsureDirectory(Path.GetDirectoryName(path.FullPath));
            CheckOverwrite(path.FullPath);

            using (Stream fs = File.Open(path.FullPath, FileMode.Create)) {
                using (StreamWriter writer = new StreamWriter(fs, Context.FileEncoding)) {
                    WriteFileHeader(ns, writer);
                    OutputNamespaceMember(element, writer, path.FullPath);
                    WriteFileFooter(ns, writer);
                }
            }
        }
Esempio n. 3
0
        // Walks up the parent chain and calculates the namespace based on the parent types instead of just
        // reading the full managed name which can lead to invalid results
        public virtual string GetNamespace()
        {
            if (Parent == null)
            {
                return(null);
            }

            HierarchyElement parent         = ParentElement;
            HierarchyBase    previousParent = parent;
            var segments = new List <string> ();

            while (parent != null)
            {
                var ns = parent as HierarchyNamespace;
                if (ns != null)
                {
                    if (!(previousParent is HierarchyNamespace))
                    {
                        throw new InvalidOperationException("Parent namespaces must not be interlaced with other types");
                    }
                    segments.Add(ns.GetManagedName());
                }
                previousParent = parent;
                parent         = parent.ParentElement;
            }

            if (segments.Count == 0)
            {
                throw new InvalidOperationException($"A type must be a child of at least one namespace");
            }

            return(String.Join(".", segments));
        }
Esempio n. 4
0
        public void ResolveBaseTypes(HierarchyIndex typeIndex)
        {
            if (DoNotAddBaseTypes || baseTypes != null)
            {
                return;
            }

            if (typeIndex == null)
            {
                throw new ArgumentNullException(nameof(typeIndex));
            }

            if (baseTypeNames != null && baseTypeNames.Count > 0)
            {
                string kindHint = HierarchyIndex.TypeToPrefix <HierarchyInterface> ();
                foreach (string typeName in baseTypeNames)
                {
                    HierarchyElement e = typeIndex.Lookup(typeName, kindHint, this);
                }
            }

            AddBaseTypes(typeIndex);

            if (baseTypes == null)
            {
                AddDefaultBaseType(typeIndex);
            }
        }
Esempio n. 5
0
        // Builds, possibly nested, type name excluding any and all namespaces. Nested type name will have its
        // parent class names separated with dots.
        public virtual string GetNameWithoutNamespace()
        {
            if (Parent == null)
            {
                return(GetManagedName());
            }

            HierarchyElement parent = ParentElement;
            var segments            = new List <string> {
                GetManagedName()
            };

            while (parent != null)
            {
                if (parent is HierarchyNamespace)
                {
                    break;
                }

                segments.Add(parent.GetManagedName());
                parent = parent.ParentElement;
            }

            return(String.Join(".", segments));
        }
Esempio n. 6
0
        protected void NestElements(Action <Dictionary <HierarchyElement, HierarchyElement> > looper)
        {
            if (looper == null)
            {
                throw new ArgumentNullException(nameof(looper));
            }

            var toReparent = new Dictionary <HierarchyElement, HierarchyElement> ();

            looper(toReparent);

            if (toReparent.Count == 0)
            {
                return;
            }

            foreach (var kvp in toReparent)
            {
                HierarchyElement element   = kvp.Key;
                HierarchyElement newParent = kvp.Value;

                element.ParentElement?.RemoveMember(element);
                newParent.AddMember(element);
            }
        }
Esempio n. 7
0
        protected FilesystemPath GetPathFor_Single(string rootDirectory, HierarchyElement element)
        {
            if (element is HierarchyNamespace)
            {
                return(null);
            }

            throw new NotImplementedException();
        }
Esempio n. 8
0
        public void AddNative(HierarchyElement type)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            Add(nativeIndex, "native", type.FullName, type);
        }
Esempio n. 9
0
        public void AddMember(HierarchyElement member)
        {
            if (member == null)
            {
                throw new ArgumentNullException(nameof(member));
            }

            Helpers.AddToList(member, ref members);
            member.Parent = this;
            MemberAdded(member);
        }
Esempio n. 10
0
 public void RemoveMember(HierarchyElement member)
 {
     if (member == null)
     {
         throw new ArgumentNullException(nameof(member));
     }
     if (members == null || members.Count == 0)
     {
         return;
     }
     members.Remove(member);
 }
Esempio n. 11
0
        public void AddManaged(HierarchyElement type)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (!String.IsNullOrEmpty(type.FullManagedName))
            {
                Add(managedIndex, "managed", type.FullManagedName, type);
            }
        }
Esempio n. 12
0
        public HierarchyElement Lookup(string typeName, string kindHint = null, HierarchyElement context = null)
        {
            HierarchyElement ret = Lookup(nativeIndex, "native", typeName, kindHint, context);

            if (ret == null)
            {
                ret = Lookup(managedIndex, "managed", typeName, kindHint, context);
            }

            if (ret == null)
            {
                throw new InvalidOperationException($"Type '{typeName}' not found in index.{GetContextLocation (context)}");
            }

            return(ret);
        }
Esempio n. 13
0
        protected virtual T SelectNewParent <T> (HierarchyElement element) where T : HierarchyElement
        {
            if (element == null)
            {
                return(null);
            }

            if (String.IsNullOrEmpty(element.FullName))
            {
                throw new InvalidOperationException("Each element must have a full name");
            }

            if (TypeIndex.Count == 0)
            {
                Logger.Warning($"Unable to select new parent for element {element.Name}, type index does not exist");
                return(null);
            }

            // The way API description is constructed we can check whether a class/interface/enum is nested
            // by simply looking at its "namespace" name and checking whether it corresponds to another
            // class or interfaces
            string nsOrTypeName = Helpers.GetTypeNamespace(element.FullName);

            if (String.IsNullOrEmpty(nsOrTypeName))
            {
                return(null);
            }

            try {
                HierarchyElement maybeParent = TypeIndex.Lookup(nsOrTypeName);
                if (maybeParent == null)
                {
                    return(null);
                }

                var ret = maybeParent as T;
                if (ret == null)
                {
                    return(null);
                }

                return(ret);
            } catch {
                Logger.Fatal($"Error selecting new parent for element '{element.FullName}' ({element.GetLocation ()})");
                throw;
            }
        }
Esempio n. 14
0
        static string GetContextLocation(HierarchyElement context)
        {
            if (context == null)
            {
                return(String.Empty);
            }

            string ret      = $" Called on behalf of: {context.FullName}";
            string location = context.GetLocation();

            if (!String.IsNullOrEmpty(location))
            {
                ret += $" at {location}";
            }

            return(ret);
        }
Esempio n. 15
0
        protected void GenerateManagedNames(HierarchyElement root)
        {
            if (root == null)
            {
                return;
            }

            root.SetManagedNames();
            if (root is HierarchyObject || root is HierarchyNamespace)
            {
                TypeIndex.AddManaged(root);
            }
            if (!root.HasMembers)
            {
                return;
            }

            Helpers.ForEachNotNull(root.Members, (HierarchyElement element) => GenerateManagedNames(element));
        }
Esempio n. 16
0
        void AddLocationComment(ApiElement element, HierarchyElement hierarchyElement)
        {
            if (String.IsNullOrEmpty(element.DocumentPath) || element.SourceLine < 0)
            {
                return;
            }

            var sb = new StringBuilder();

            sb.Append(element.DocumentPath);
            if (element.SourceColumn > 0)
            {
                sb.Append($" [{element.SourceLine}:{element.SourceColumn}]");
            }
            else
            {
                sb.Append($":{element.SourceLine}");
            }
            hierarchyElement.AddComment(sb.ToString());
        }
Esempio n. 17
0
 protected virtual void GenerateNamespaceMember(HierarchyElement element, TextWriter writer, string outputFileName)
 {
     Logger.Debug($"Generating {element.GetManagedName (true)} in namespace output file: {outputFileName}");
     OutputNamespaceMember(element, writer, outputFileName);
 }
Esempio n. 18
0
 protected FilesystemPath GetPathFor_Deep(string rootDirectory, HierarchyElement element)
 {
     throw new NotImplementedException();
 }
Esempio n. 19
0
        protected FilesystemPath GetPathFor_FirstLevelThenFullShallow(string rootDirectory, HierarchyElement element)
        {
            string fullManagedName = element.GetManagedName(true);
            bool   isDirectory;
            string path = GetFirstNameSegment(fullManagedName);

            Logger.Debug($"Element: {element.FullName} (managed: {fullManagedName})");
            Logger.Debug($"Initial path: {path}");
            if (element is HierarchyNamespace)
            {
                Logger.Debug("Is namespace");
                isDirectory = true;
                path        = Path.Combine(path, fullManagedName);
            }
            else
            {
                var obj = element as HierarchyObject;
                if (obj == null)
                {
                    throw new InvalidOperationException("Only HierarchyObject and HierarchyNamespace instances can be used to compute output file name");
                }
                Logger.Debug("Is type");
                isDirectory = false;
                path        = Path.Combine(path, obj.GetNamespace(), obj.GetNameWithoutNamespace());
            }
            Logger.Debug($"Final relative path: {path}");
            Logger.Debug(String.Empty);
            return(GetFilePath(rootDirectory, path, isDirectory));
        }
Esempio n. 20
0
 public HierarchyInterface(GeneratorContext context, HierarchyElement parent) : base(context, parent)
 {
 }
Esempio n. 21
0
 protected FilesystemPath GetPathFor_FirstLevelThenShortSingle(string rootDirectory, HierarchyElement element)
 {
     throw new NotImplementedException();
 }
Esempio n. 22
0
 protected virtual void MemberAdded(HierarchyElement member)
 {
 }
Esempio n. 23
0
        public override FilesystemPath GetPathFor(string rootDirectory, HierarchyElement element)
        {
            if (String.IsNullOrEmpty(rootDirectory))
            {
                throw new ArgumentException("Must not be null or empty", nameof(rootDirectory));
            }

            if (element == null)
            {
                throw new ArgumentNullException(nameof(element));
            }

            switch (element)
            {
            case HierarchyNamespace ns:
            case HierarchyClass klass:
            case HierarchyInterface iface:
            case HierarchyEnum enm:
                break;

            default:
                throw new InvalidOperationException($"Unsupported hierarchy type '{element.GetType ()}'");
            }

            Func <string, HierarchyElement, FilesystemPath> getter = null;

            switch (TreeLayout.NamespaceTreeStyle)
            {
            case OutputNamespaceTreeStyle.Single:
                getter = GetPathFor_Single;
                break;

            case OutputNamespaceTreeStyle.Shallow:
                getter = GetPathFor_Shallow;
                break;

            case OutputNamespaceTreeStyle.Deep:
                getter = GetPathFor_Deep;
                break;

            case OutputNamespaceTreeStyle.FirstLevelThenFullShallow:
                getter = GetPathFor_FirstLevelThenFullShallow;
                break;

            case OutputNamespaceTreeStyle.FirstLevelThenFullSingle:
                getter = GetPathFor_FirstLevelThenFullSingle;
                break;

            case OutputNamespaceTreeStyle.FirstLevelThenShortShallow:
                getter = GetPathFor_FirstLevelThenShortShallow;
                break;

            case OutputNamespaceTreeStyle.FirstLevelThenShortSingle:
                getter = GetPathFor_FirstLevelThenShortSingle;
                break;

            default:
                throw new InvalidOperationException($"Unsupported namespace tree style {TreeLayout.NamespaceTreeStyle}");
            }

            return(getter(rootDirectory, element));
        }
Esempio n. 24
0
        HierarchyElement Lookup(Dictionary <string, HierarchyElement> index, string indexName, string typeName, string kindHint, HierarchyElement context)
        {
            if (!index.TryGetValue(typeName, out HierarchyElement ret))
            {
                string caller = GetContextLocation(context);

                Logger.Debug($"Type '{typeName}' not found in {indexName} index.{caller}");
                if (!String.IsNullOrEmpty(kindHint))
                {
                    typeName = $"{kindHint}:{typeName}";
                    Logger.Debug($"Trying to look up using prefixed name: '{typeName}'.{caller}");
                    if (!index.TryGetValue(typeName, out ret))
                    {
                        Logger.Debug($"Prefixed type name not found in {indexName} index either.{caller}");
                    }
                }
            }

            return(ret);
        }
Esempio n. 25
0
 public abstract FilesystemPath GetPathFor(string rootDirectory, HierarchyElement element);
Esempio n. 26
0
 protected virtual void OutputNamespaceMember(HierarchyElement element, TextWriter writer, string fileName)
 {
 }
Esempio n. 27
0
 public void Add(HierarchyElement type)
 {
     AddNative(type);
     AddManaged(type);
 }
Esempio n. 28
0
 public HierarchyInterfaceInvoker(GeneratorContext context, HierarchyElement parent, HierarchyInterface invokedInterface) : base(context, parent)
 {
     InvokedInterface = invokedInterface ?? throw new ArgumentNullException(nameof(invokedInterface));
     Visibility       = ApiVisibility.Internal;
 }
Esempio n. 29
0
 public HierarchyClass(GeneratorContext context, HierarchyElement parent) : base(context, parent)
 {
 }