// The Nova Project by Ken Beckett.
// Copyright (C) 2007-2012 Inevitable Software, all rights reserved.
// Released under the Common Development and Distribution License, CDDL-1.0: http://opensource.org/licenses/cddl1.php
using System;
using System.Collections.Generic;
using Nova.Rendering;
namespace Nova.CodeDOM
{
/// <summary>
/// These modifiers are usable on various code objects to specify access and special behaviors.
/// </summary>
/// <remarks>
/// The order of appearance in this enum determines the display order of the modifiers.
/// </remarks>
[Flags]
public enum Modifiers
{
// * = only if nested Event,
None = 0x00000000, // Class Struct Interface Delegate Enum Method Property Indexer Field Constant Ctor Operator Accessor Destructor
Public = 0x00000001, // Y Y Y Y Y Y Y Y Y Y Y Y
Protected = 0x00000002, // * * * * * Y Y Y Y Y Y Y
Internal = 0x00000004, // Y Y Y Y Y Y Y Y Y Y Y Y
// Protected + Internal // * * * * * Y Y Y Y Y Y Y
Private = 0x00000008, // * * * * * Y Y Y Y Y Y Y
Static = 0x00000010, // Y Y Y Y Y Y
New = 0x00000020, // * * * Y Y Y Y Y
Abstract = 0x00000040, // Y Y Y Y
Sealed = 0x00000080, // Y Y Y Y
Virtual = 0x00000100, // Y Y Y
Override = 0x00000200, // Y Y Y
Extern = 0x00000400, // Y Y Y Y Y Y
Unsafe = 0x00000800, // Y Y Y Y Y Y Y Y Y Y Y Y
// NOTE: Partial must appear as the last modifier for both types and methods.
Partial = 0x00001000, // Y Y Y Y
Implicit = 0x00004000, // Y (conv ops only)
Explicit = 0x00008000, // Y (conv ops only)
Const = 0x00010000, // Y (also local vars)
ReadOnly = 0x00020000, // Y
Volatile = 0x00040000, // Y
Event = 0x00100000 // Y
// RULES:
// - Namespaces have no access modifiers (they are implicitly public).
// - Top-level type declarations can be only 'internal' or 'public', and default to 'internal'.
// - Nested type declarations in a class or struct default to 'private'.
// - Interface and enum members are implicitly 'public' (no access modifiers are allowed).
// - Class can't be both 'abstract' and 'sealed'.
// - If any method of a class is 'abstract', the class must be 'abstract'.
// - A non-abstract Class with an 'abstract' base must implement all 'abstract' members.
// - An 'abstract' class must implement all interface members, although it may map them onto 'abstract' methods.
// - Structs are implicitly 'sealed', and can't have default constructors or a destructor.
// - Struct members can't have 'protected' or 'protected internal' access.
// - An 'abstract' method can't be 'static', 'virtual' (it's implicitly virtual), or 'extern'.
// - An 'abstract' or 'extern' method has no body.
// - An 'abstract' property behaves like an 'abstract' method.
// - An 'abstract' property can't be 'static'.
// - Nested types can access 'private' members of their parent.
// - A 'readonly' field may only be assigned in the declaration or in a constructor of the parent class.
// - 'const' or type declaration members of a class are implicitly 'static'.
// - 'const' reference types can only be null or a string.
// - 'virtual' can't be used with 'static', 'abstract', or 'override'.
// - 'volatile' fields must be a reference type, or an integral type (excluding long/ulong), or a float.
}
#region /* STATIC HELPER CLASS */
/// <summary>
/// Static helper methods for Modifiers.
/// </summary>
public static class ModifiersHelpers
{
#region /* STATIC FIELDS */
private static readonly string[] _names;
private static readonly Array _values;
private static readonly Dictionary<string, Modifiers> _nameToModifierMap = new Dictionary<string, Modifiers>();
#endregion
#region /* STATIC CONSTRUCTOR */
// Setup arrays of names, values, and a map of names to values.
static ModifiersHelpers()
{
_names = Enum.GetNames(typeof(Modifiers));
_values = Enum.GetValues(typeof(Modifiers));
for (int i = 0; i < _values.Length; ++i)
{
_names[i] = _names[i].ToLower();
_nameToModifierMap.Add(_names[i], (Modifiers)_values.GetValue(i));
}
}
#endregion
#region /* STATIC HELPER METHODS */
/// <summary>
/// Format Modifiers as a string.
/// </summary>
public static string AsString(Modifiers modifiers)
{
if (modifiers == Modifiers.None)
return "";
using (CodeWriter writer = new CodeWriter())
{
AsText(modifiers, writer);
return writer.ToString();
}
}
/// <summary>
/// Convert Modifiers to text.
/// </summary>
public static void AsText(Modifiers modifiers, CodeWriter writer)
{
if (modifiers != Modifiers.None)
{
for (int i = 1; i < _values.Length; ++i)
{
if (modifiers.HasFlag((Modifiers)_values.GetValue(i)))
writer.Write(_names[i] + ' ');
}
}
}
/// <summary>
/// Returns true if the specified text is a valid modifier name.
/// </summary>
public static bool IsModifier(string modifier)
{
return (modifier != null && _nameToModifierMap.ContainsKey(modifier));
}
#endregion
}
#endregion
}