/// <summary>
        /// Returns node icon id looked up from the provided base string plus the protection
        /// attribute (and, optionally, the staticness) of node.
        /// </summary>
        private static Core.IconId iconIdWithProtectionAttr(DNode n, string image,
                                                            bool allow_static = false)
        {
            string attr = "";

            if (allow_static && n.ContainsAttribute(DTokens.Static))
            {
                attr += "static_";
            }

            if (n.ContainsAttribute(DTokens.Package))
            {
                return(DCodeCompletionSupport.GetNodeImage(attr + image + "_internal"));
            }
            else if (n.ContainsAttribute(DTokens.Protected))
            {
                return(DCodeCompletionSupport.GetNodeImage(attr + image + "_protected"));
            }
            else if (n.ContainsAttribute(DTokens.Private))
            {
                return(DCodeCompletionSupport.GetNodeImage(attr + image + "_private"));
            }
            return(DCodeCompletionSupport.GetNodeImage(attr + image));
        }
        public static Core.IconId GetNodeIcon(DNode n)
        {
            try
            {
                if (n == null)
                {
                    return(null);
                }

                if (n is DClassLike)
                {
                    switch ((n as DClassLike).ClassType)
                    {
                    case DTokens.Template:
                        return(iconIdWithProtectionAttr(n, "template"));

                    case DTokens.Class:
                        return(classIconIdWithProtectionAttr(n));

                    case DTokens.Union:
                        return(iconIdWithProtectionAttr(n, "union"));

                    case DTokens.Struct:
                        return(iconIdWithProtectionAttr(n, "struct"));

                    case DTokens.Interface:
                        return(iconIdWithProtectionAttr(n, "interface"));
                    }
                }
                else if (n is DEnum)
                {
                    // TODO: does declaring an enum private/protected/package actually have a meaning?
                    return(iconIdWithProtectionAttr(n, "enum"));
                }
                else if (n is DEnumValue)
                {
                    return(DCodeCompletionSupport.GetNodeImage("literal"));
                }
                else if (n is DMethod)
                {
                    //TODO: Getter or setter functions should be declared as a >single< property only
                    if (n.ContainsPropertyAttribute())
                    {
                        return(iconIdWithProtectionAttr(n, "property"));
                    }

                    return(methodIconIdWithProtectionAttr(n));
                }
                else if (n is DVariable)
                {
                    if (((DVariable)n).IsAlias)
                    {
                        // TODO: does declaring an alias private/protected/package actually have a meaning?
                        return(iconIdWithProtectionAttr(n, "alias"));
                    }

                    if (n.ContainsPropertyAttribute())
                    {
                        return(iconIdWithProtectionAttr(n, "property"));
                    }

                    if (n.Type is DelegateDeclaration)
                    {
                        return(iconIdWithProtectionAttr(n, "delegate"));
                    }

                    if (n.ContainsAttribute(DTokens.Const))
                    {
                        return(iconIdWithProtectionAttr(n, "literal", true));
                    }

                    var realParent = n.Parent as DNode;

                    if (realParent == null)
                    {
                        return(DCodeCompletionSupport.GetNodeImage("local"));
                    }

                    if (realParent is DClassLike || n.Parent is IAbstractSyntaxTree)
                    {
                        return(iconIdWithProtectionAttr(n, "field", true));
                    }

                    if (realParent is DMethod)
                    {
                        // FIXME: first parameter of class constructors is always displayed as a local, not a parameter
                        if ((realParent as DMethod).Parameters.Contains(n))
                        {
                            if (n.ContainsAttribute(DTokens.Ref))
                            {
                                return(DCodeCompletionSupport.GetNodeImage("ref_parameter"));
                            }
                            else if (n.ContainsAttribute(DTokens.Lazy))
                            {
                                return(DCodeCompletionSupport.GetNodeImage("lazy_parameter"));
                            }
                            else if (n.ContainsAttribute(DTokens.Out))
                            {
                                return(DCodeCompletionSupport.GetNodeImage("out_parameter"));
                            }
                            else
                            {
                                return(DCodeCompletionSupport.GetNodeImage("parameter"));
                            }
                            // TODO: immutable, scope?
                        }
                        return(DCodeCompletionSupport.GetNodeImage("local"));
                    }

                    // FIXME: looks like this is supposed to handle template parameters, but
                    // it doesn't seem to work
                    if (realParent.ContainsTemplateParameter(n.Name))
                    {
                        return(DCodeCompletionSupport.GetNodeImage("parameter"));
                    }
                }
            }
            catch (Exception ex) { LoggingService.LogError("Error while getting node icon", ex); }
            return(null);
        }
        public static Core.IconId GetNodeIcon(DNode n)
        {
            try
            {
                if (n == null)
                {
                    return(null);
                }

                if (n is DClassLike)
                {
                    switch ((n as DClassLike).ClassType)
                    {
                    case DTokens.Template:
                    case DTokens.Class:
                        if (n.ContainsAttribute(DTokens.Package))
                        {
                            return(DCodeCompletionSupport.GetNodeImage("class_internal"));
                        }
                        else if (n.ContainsAttribute(DTokens.Protected))
                        {
                            return(DCodeCompletionSupport.GetNodeImage("class_protected"));
                        }
                        else if (n.ContainsAttribute(DTokens.Private))
                        {
                            return(DCodeCompletionSupport.GetNodeImage("class_private"));
                        }
                        return(DCodeCompletionSupport.GetNodeImage("class"));

                    case DTokens.Union:
                    case DTokens.Struct:
                        if (n.ContainsAttribute(DTokens.Package))
                        {
                            return(DCodeCompletionSupport.GetNodeImage("struct_internal"));
                        }
                        else if (n.ContainsAttribute(DTokens.Protected))
                        {
                            return(DCodeCompletionSupport.GetNodeImage("struct_protected"));
                        }
                        else if (n.ContainsAttribute(DTokens.Private))
                        {
                            return(DCodeCompletionSupport.GetNodeImage("struct_private"));
                        }
                        return(DCodeCompletionSupport.GetNodeImage("struct"));

                    case DTokens.Interface:
                        if (n.ContainsAttribute(DTokens.Package))
                        {
                            return(DCodeCompletionSupport.GetNodeImage("interface_internal"));
                        }
                        else if (n.ContainsAttribute(DTokens.Protected))
                        {
                            return(DCodeCompletionSupport.GetNodeImage("interface_protected"));
                        }
                        else if (n.ContainsAttribute(DTokens.Private))
                        {
                            return(DCodeCompletionSupport.GetNodeImage("interface_private"));
                        }
                        return(DCodeCompletionSupport.GetNodeImage("interface"));
                    }
                }
                else if (n is DEnum)
                {
                    if (n.ContainsAttribute(DTokens.Package))
                    {
                        return(DCodeCompletionSupport.GetNodeImage("enum_internal"));
                    }
                    else if (n.ContainsAttribute(DTokens.Protected))
                    {
                        return(DCodeCompletionSupport.GetNodeImage("enum_protected"));
                    }
                    else if (n.ContainsAttribute(DTokens.Private))
                    {
                        return(DCodeCompletionSupport.GetNodeImage("enum_private"));
                    }
                    return(DCodeCompletionSupport.GetNodeImage("enum"));
                }
                else if (n is DMethod)
                {
                    //TODO: Getter or setter functions should be declared as a >single< property only
                    if (n.ContainsPropertyAttribute())
                    {
                        if (n.ContainsAttribute(DTokens.Package))
                        {
                            return(DCodeCompletionSupport.GetNodeImage("property_internal"));
                        }
                        else if (n.ContainsAttribute(DTokens.Protected))
                        {
                            return(DCodeCompletionSupport.GetNodeImage("property_protected"));
                        }
                        else if (n.ContainsAttribute(DTokens.Private))
                        {
                            return(DCodeCompletionSupport.GetNodeImage("property_private"));
                        }
                        return(DCodeCompletionSupport.GetNodeImage("property"));
                    }

                    if (n.ContainsAttribute(DTokens.Package))
                    {
                        return(DCodeCompletionSupport.GetNodeImage("method_internal"));
                    }
                    else if (n.ContainsAttribute(DTokens.Protected))
                    {
                        return(DCodeCompletionSupport.GetNodeImage("method_protected"));
                    }
                    else if (n.ContainsAttribute(DTokens.Private))
                    {
                        return(DCodeCompletionSupport.GetNodeImage("method_private"));
                    }
                    return(DCodeCompletionSupport.GetNodeImage("method"));
                }
                else if (n is DEnumValue)
                {
                    return(DCodeCompletionSupport.GetNodeImage("literal"));
                }
                else if (n is DVariable)
                {
                    if (n.ContainsPropertyAttribute())
                    {
                        if (n.ContainsAttribute(DTokens.Package))
                        {
                            return(DCodeCompletionSupport.GetNodeImage("property_internal"));
                        }
                        else if (n.ContainsAttribute(DTokens.Protected))
                        {
                            return(DCodeCompletionSupport.GetNodeImage("property_protected"));
                        }
                        else if (n.ContainsAttribute(DTokens.Private))
                        {
                            return(DCodeCompletionSupport.GetNodeImage("property_private"));
                        }
                        return(DCodeCompletionSupport.GetNodeImage("property"));
                    }

                    if (n.Type is DelegateDeclaration)
                    {
                        if (n.ContainsAttribute(DTokens.Package))
                        {
                            return(DCodeCompletionSupport.GetNodeImage("delegate_internal"));
                        }
                        else if (n.ContainsAttribute(DTokens.Protected))
                        {
                            return(DCodeCompletionSupport.GetNodeImage("delegate_protected"));
                        }
                        else if (n.ContainsAttribute(DTokens.Private))
                        {
                            return(DCodeCompletionSupport.GetNodeImage("delegate_private"));
                        }
                        return(DCodeCompletionSupport.GetNodeImage("delegate"));
                    }

                    if (n.ContainsAttribute(DTokens.Const))
                    {
                        return(DCodeCompletionSupport.GetNodeImage("literal"));
                    }

                    var realParent = n.Parent as DNode;

                    if (n.Parent is IAbstractSyntaxTree && !(n as DVariable).IsAlias)
                    {
                        return(DCodeCompletionSupport.GetNodeImage("field"));
                    }

                    if (realParent == null)
                    {
                        return(DCodeCompletionSupport.GetNodeImage("local"));
                    }

                    if (realParent is DClassLike)
                    {
                        if (n.ContainsAttribute(DTokens.Package))
                        {
                            return(DCodeCompletionSupport.GetNodeImage("field_internal"));
                        }
                        else if (n.ContainsAttribute(DTokens.Protected))
                        {
                            return(DCodeCompletionSupport.GetNodeImage("field_protected"));
                        }
                        else if (n.ContainsAttribute(DTokens.Private))
                        {
                            return(DCodeCompletionSupport.GetNodeImage("field_private"));
                        }
                        return(DCodeCompletionSupport.GetNodeImage("field"));
                    }

                    if (realParent is DMethod)
                    {
                        if ((realParent as DMethod).Parameters.Contains(n))
                        {
                            return(DCodeCompletionSupport.GetNodeImage("parameter"));
                        }
                        return(DCodeCompletionSupport.GetNodeImage("local"));
                    }

                    if (realParent.ContainsTemplateParameter(n.Name))
                    {
                        return(DCodeCompletionSupport.GetNodeImage("parameter"));
                    }
                }
            }
            catch (Exception ex) { LoggingService.LogError("Error while getting node icon", ex); }
            return(null);
        }