diff --git a/src/Artemis.Core/Events/PropertyGroupUpdatingEventArgs.cs b/src/Artemis.Core/Events/PropertyGroupUpdatingEventArgs.cs index a1f4c3b6c..cb6b81529 100644 --- a/src/Artemis.Core/Events/PropertyGroupUpdatingEventArgs.cs +++ b/src/Artemis.Core/Events/PropertyGroupUpdatingEventArgs.cs @@ -14,7 +14,7 @@ namespace Artemis.Core.Events OverrideTime = overrideTime; } - public double DeltaTime { get; } - public TimeSpan OverrideTime { get; } + public double DeltaTime { get; } + public TimeSpan OverrideTime { get; } } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs index 4c72f6010..e456e3d64 100644 --- a/src/Artemis.Core/Models/Profile/Layer.cs +++ b/src/Artemis.Core/Models/Profile/Layer.cs @@ -164,7 +164,7 @@ namespace Artemis.Core.Models.Profile LayerEntity.LayerEffects.Clear(); foreach (var layerEffect in LayerEffects) { - var layerEffectEntity = new LayerEffectEntity() + var layerEffectEntity = new LayerEffectEntity { PluginGuid = layerEffect.PluginInfo.Guid, EffectType = layerEffect.GetType().Name, @@ -505,7 +505,7 @@ namespace Artemis.Core.Models.Profile { if (LayerBrush == null) return; - + var brush = LayerBrush; DeactivateLayerBrush(); LayerEntity.PropertyEntities.RemoveAll(p => p.PluginGuid == brush.PluginInfo.Guid && p.Path.StartsWith("LayerBrush.")); diff --git a/src/Artemis.Core/Models/Profile/LayerGeneralProperties.cs b/src/Artemis.Core/Models/Profile/LayerGeneralProperties.cs index fe819758d..e0a2b46d4 100644 --- a/src/Artemis.Core/Models/Profile/LayerGeneralProperties.cs +++ b/src/Artemis.Core/Models/Profile/LayerGeneralProperties.cs @@ -17,7 +17,7 @@ namespace Artemis.Core.Models.Profile [PropertyDescription(Name = "Brush type", Description = "The type of brush to use for this layer")] public LayerBrushReferenceLayerProperty BrushReference { get; set; } - + protected override void PopulateDefaults() { ShapeType.DefaultValue = LayerShapeType.Rectangle; diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs index 7c5115364..27ed19c4c 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs @@ -10,15 +10,15 @@ namespace Artemis.Core.Models.Profile.LayerProperties /// public abstract class BaseLayerProperty { - private bool _keyframesEnabled; private bool _isHidden; + private bool _keyframesEnabled; internal BaseLayerProperty() { } /// - /// The layer this property applies to + /// The layer this property applies to /// public Layer Layer { get; internal set; } @@ -84,7 +84,9 @@ namespace Artemis.Core.Models.Profile.LayerProperties internal PropertyEntity PropertyEntity { get; set; } internal LayerPropertyGroup LayerPropertyGroup { get; set; } - + + public abstract void ApplyDefaultValue(); + /// /// Applies the provided property entity to the layer property by deserializing the JSON base value and keyframe values @@ -113,12 +115,12 @@ namespace Artemis.Core.Models.Profile.LayerProperties public event EventHandler BaseValueChanged; /// - /// Occurs when the value of the layer property was updated + /// Occurs when the value of the layer property was updated /// public event EventHandler VisibilityChanged; /// - /// Occurs when keyframes are enabled/disabled + /// Occurs when keyframes are enabled/disabled /// public event EventHandler KeyframesToggled; @@ -163,9 +165,5 @@ namespace Artemis.Core.Models.Profile.LayerProperties } #endregion - - public abstract void ApplyDefaultValue(); - - } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs index c2c4e84d8..82ae2aa34 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs @@ -56,7 +56,8 @@ namespace Artemis.Core.Models.Profile.LayerProperties } /// - /// Gets or sets the default value of this layer property. If set, this value is automatically applied if the property has no + /// Gets or sets the default value of this layer property. If set, this value is automatically applied if the property + /// has no /// value in storage /// public T DefaultValue { get; set; } @@ -166,6 +167,12 @@ namespace Artemis.Core.Models.Profile.LayerProperties RemoveKeyframe(layerPropertyKeyframe); } + public override void ApplyDefaultValue() + { + BaseValue = DefaultValue; + CurrentValue = DefaultValue; + } + /// /// Called every update (if keyframes are both supported and enabled) to determine the new /// based on the provided progress @@ -284,11 +291,5 @@ namespace Artemis.Core.Models.Profile.LayerProperties EasingFunction = (int) k.EasingFunction })); } - - public override void ApplyDefaultValue() - { - BaseValue = DefaultValue; - CurrentValue = DefaultValue; - } } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/Types/ColorGradientLayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/Types/ColorGradientLayerProperty.cs index 483fb2c05..f326a8ca4 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/Types/ColorGradientLayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/Types/ColorGradientLayerProperty.cs @@ -12,6 +12,11 @@ namespace Artemis.Core.Models.Profile.LayerProperties.Types KeyframesSupported = false; } + public static implicit operator ColorGradient(ColorGradientLayerProperty p) + { + return p.CurrentValue; + } + protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased) { throw new ArtemisCoreException("Color Gradients do not support keyframes."); @@ -24,7 +29,5 @@ namespace Artemis.Core.Models.Profile.LayerProperties.Types // Don't allow color gradients to be null BaseValue ??= DefaultValue ?? new ColorGradient(); } - - public static implicit operator ColorGradient(ColorGradientLayerProperty p) => p.CurrentValue; } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/Types/EnumLayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/Types/EnumLayerProperty.cs index ce1edb251..00132833b 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/Types/EnumLayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/Types/EnumLayerProperty.cs @@ -11,12 +11,19 @@ namespace Artemis.Core.Models.Profile.LayerProperties.Types KeyframesSupported = false; } + public static implicit operator T(EnumLayerProperty p) + { + return p.CurrentValue; + } + + public static implicit operator int(EnumLayerProperty p) + { + return Convert.ToInt32(p.CurrentValue); + } + protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased) { throw new ArtemisCoreException("Enum properties do not support keyframes."); } - - public static implicit operator T(EnumLayerProperty p) => p.CurrentValue; - public static implicit operator int(EnumLayerProperty p) => Convert.ToInt32(p.CurrentValue); } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/Types/FloatLayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/Types/FloatLayerProperty.cs index 1d5a09c9c..64206f7fc 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/Types/FloatLayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/Types/FloatLayerProperty.cs @@ -1,19 +1,26 @@ namespace Artemis.Core.Models.Profile.LayerProperties.Types { - /// + /// public class FloatLayerProperty : LayerProperty { internal FloatLayerProperty() { } + public static implicit operator float(FloatLayerProperty p) + { + return p.CurrentValue; + } + + public static implicit operator double(FloatLayerProperty p) + { + return p.CurrentValue; + } + protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased) { var diff = NextKeyframe.Value - CurrentKeyframe.Value; CurrentValue = CurrentKeyframe.Value + diff * keyframeProgressEased; } - - public static implicit operator float(FloatLayerProperty p) => p.CurrentValue; - public static implicit operator double(FloatLayerProperty p) => p.CurrentValue; } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/Types/IntLayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/Types/IntLayerProperty.cs index 4ec1e3e8d..eca8b15ae 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/Types/IntLayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/Types/IntLayerProperty.cs @@ -2,21 +2,32 @@ namespace Artemis.Core.Models.Profile.LayerProperties.Types { - /// + /// public class IntLayerProperty : LayerProperty { internal IntLayerProperty() { } + public static implicit operator int(IntLayerProperty p) + { + return p.CurrentValue; + } + + public static implicit operator float(IntLayerProperty p) + { + return p.CurrentValue; + } + + public static implicit operator double(IntLayerProperty p) + { + return p.CurrentValue; + } + protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased) { var diff = NextKeyframe.Value - CurrentKeyframe.Value; CurrentValue = (int) Math.Round(CurrentKeyframe.Value + diff * keyframeProgressEased, MidpointRounding.AwayFromZero); } - - public static implicit operator int(IntLayerProperty p) => p.CurrentValue; - public static implicit operator float(IntLayerProperty p) => p.CurrentValue; - public static implicit operator double(IntLayerProperty p) => p.CurrentValue; } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/Types/LayerBrushReferenceLayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/Types/LayerBrushReferenceLayerProperty.cs index e7e4e2023..6df2e1723 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/Types/LayerBrushReferenceLayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/Types/LayerBrushReferenceLayerProperty.cs @@ -3,7 +3,7 @@ namespace Artemis.Core.Models.Profile.LayerProperties.Types { /// - /// A special layer property used to configure the selected layer brush + /// A special layer property used to configure the selected layer brush /// public class LayerBrushReferenceLayerProperty : LayerProperty { @@ -12,11 +12,14 @@ namespace Artemis.Core.Models.Profile.LayerProperties.Types KeyframesSupported = false; } + public static implicit operator LayerBrushReference(LayerBrushReferenceLayerProperty p) + { + return p.CurrentValue; + } + protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased) { throw new ArtemisCoreException("Layer brush references do not support keyframes."); } - - public static implicit operator LayerBrushReference(LayerBrushReferenceLayerProperty p) => p.CurrentValue; } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKColorLayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKColorLayerProperty.cs index 1b5d1359b..8c8dd2c69 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKColorLayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKColorLayerProperty.cs @@ -3,13 +3,18 @@ using SkiaSharp; namespace Artemis.Core.Models.Profile.LayerProperties.Types { - /// + /// public class SKColorLayerProperty : LayerProperty { internal SKColorLayerProperty() { } + public static implicit operator SKColor(SKColorLayerProperty p) + { + return p.CurrentValue; + } + protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased) { var redDiff = NextKeyframe.Value.Red - CurrentKeyframe.Value.Red; @@ -29,7 +34,5 @@ namespace Artemis.Core.Models.Profile.LayerProperties.Types { return (byte) Math.Max(0, Math.Min(255, value)); } - - public static implicit operator SKColor(SKColorLayerProperty p) => p.CurrentValue; } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKPointLayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKPointLayerProperty.cs index 4246cd740..b94227a7b 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKPointLayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKPointLayerProperty.cs @@ -2,20 +2,23 @@ namespace Artemis.Core.Models.Profile.LayerProperties.Types { - /// + /// public class SKPointLayerProperty : LayerProperty { internal SKPointLayerProperty() { } + public static implicit operator SKPoint(SKPointLayerProperty p) + { + return p.CurrentValue; + } + protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased) { var xDiff = NextKeyframe.Value.X - CurrentKeyframe.Value.X; var yDiff = NextKeyframe.Value.Y - CurrentKeyframe.Value.Y; CurrentValue = new SKPoint(CurrentKeyframe.Value.X + xDiff * keyframeProgressEased, CurrentKeyframe.Value.Y + yDiff * keyframeProgressEased); } - - public static implicit operator SKPoint(SKPointLayerProperty p) => p.CurrentValue; } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKSizeLayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKSizeLayerProperty.cs index 647ed68cf..11aa9c68a 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKSizeLayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKSizeLayerProperty.cs @@ -2,20 +2,23 @@ namespace Artemis.Core.Models.Profile.LayerProperties.Types { - /// + /// public class SKSizeLayerProperty : LayerProperty { internal SKSizeLayerProperty() { } + public static implicit operator SKSize(SKSizeLayerProperty p) + { + return p.CurrentValue; + } + protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased) { var widthDiff = NextKeyframe.Value.Width - CurrentKeyframe.Value.Width; var heightDiff = NextKeyframe.Value.Height - CurrentKeyframe.Value.Height; CurrentValue = new SKSize(CurrentKeyframe.Value.Width + widthDiff * keyframeProgressEased, CurrentKeyframe.Value.Height + heightDiff * keyframeProgressEased); } - - public static implicit operator SKSize(SKSizeLayerProperty p) => p.CurrentValue; } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs b/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs index 7c027d696..d26c7403f 100644 --- a/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs +++ b/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs @@ -107,6 +107,21 @@ namespace Artemis.Core.Models.Profile return _allLayerProperties; } + public void UpdateOrder(int oldOrder) + { + // Expanded state is tied to the path so save it before changing the path + var expanded = Layer.IsPropertyGroupExpanded(this); + Layer.SetPropertyGroupExpanded(this, false); + + Path = Path.Replace($"LayerEffect.{oldOrder}.", $"LayerEffect.{LayerEffect.Order}."); + // Restore the expanded state with the new path + Layer.SetPropertyGroupExpanded(this, expanded); + + // Update children + foreach (var layerPropertyGroup in LayerPropertyGroups) + layerPropertyGroup.UpdateOrder(oldOrder); + } + /// /// Called before properties are fully initialized to allow you to populate /// on the properties you want @@ -280,20 +295,5 @@ namespace Artemis.Core.Models.Profile } #endregion - - public void UpdateOrder(int oldOrder) - { - // Expanded state is tied to the path so save it before changing the path - var expanded = Layer.IsPropertyGroupExpanded(this); - Layer.SetPropertyGroupExpanded(this, false); - - Path = Path.Replace($"LayerEffect.{oldOrder}.", $"LayerEffect.{LayerEffect.Order}."); - // Restore the expanded state with the new path - Layer.SetPropertyGroupExpanded(this, expanded); - - // Update children - foreach (var layerPropertyGroup in LayerPropertyGroups) - layerPropertyGroup.UpdateOrder(oldOrder); - } } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/ProfileElement.cs b/src/Artemis.Core/Models/Profile/ProfileElement.cs index 6657ade42..92cc472b9 100644 --- a/src/Artemis.Core/Models/Profile/ProfileElement.cs +++ b/src/Artemis.Core/Models/Profile/ProfileElement.cs @@ -127,14 +127,14 @@ namespace Artemis.Core.Models.Profile } } - /// - /// Applies the profile element's properties to the underlying storage entity - /// - internal abstract void ApplyToEntity(); - public override string ToString() { return $"{nameof(EntityId)}: {EntityId}, {nameof(Order)}: {Order}, {nameof(Name)}: {Name}"; } + + /// + /// Applies the profile element's properties to the underlying storage entity + /// + internal abstract void ApplyToEntity(); } } \ No newline at end of file diff --git a/src/Artemis.Core/Ninject/CoreModule.cs b/src/Artemis.Core/Ninject/CoreModule.cs index b61a0f0c5..2d5169aad 100644 --- a/src/Artemis.Core/Ninject/CoreModule.cs +++ b/src/Artemis.Core/Ninject/CoreModule.cs @@ -63,7 +63,7 @@ namespace Artemis.Core.Ninject }).InSingletonScope(); Kernel.Bind().ToSelf().InSingletonScope(); - + // Bind all migrations as singletons Kernel.Bind(x => { diff --git a/src/Artemis.Core/Plugins/Abstract/Plugin.cs b/src/Artemis.Core/Plugins/Abstract/Plugin.cs index 0280a3057..1a27b7dd6 100644 --- a/src/Artemis.Core/Plugins/Abstract/Plugin.cs +++ b/src/Artemis.Core/Plugins/Abstract/Plugin.cs @@ -23,6 +23,11 @@ namespace Artemis.Core.Plugins.Abstract /// public bool HasConfigurationViewModel { get; protected set; } + public void Dispose() + { + DisablePlugin(); + } + /// /// Called when the plugin is activated /// @@ -59,11 +64,6 @@ namespace Artemis.Core.Plugins.Abstract } } - public void Dispose() - { - DisablePlugin(); - } - #region Events public event EventHandler PluginEnabled; diff --git a/src/Artemis.Core/Properties/Annotations.cs b/src/Artemis.Core/Properties/Annotations.cs index 718b5d4d2..c0469b60d 100644 --- a/src/Artemis.Core/Properties/Annotations.cs +++ b/src/Artemis.Core/Properties/Annotations.cs @@ -21,6 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ using System; + // ReSharper disable InheritdocConsiderUsage #pragma warning disable 1591 @@ -33,1131 +34,1349 @@ using System; namespace Artemis.Core.Annotations { - /// - /// Indicates that the value of the marked element could be null sometimes, - /// so checking for null is required before its usage. - /// - /// - /// [CanBeNull] object Test() => null; - /// - /// void UseTest() { - /// var p = Test(); - /// var s = p.ToString(); // Warning: Possible 'System.NullReferenceException' - /// } - /// - [AttributeUsage( - AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | - AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event | - AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)] - public sealed class CanBeNullAttribute : Attribute { } - - /// - /// Indicates that the value of the marked element can never be null. - /// - /// - /// [NotNull] object Foo() { - /// return null; // Warning: Possible 'null' assignment - /// } - /// - [AttributeUsage( - AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | - AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event | - AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)] - public sealed class NotNullAttribute : Attribute { } - - /// - /// Can be applied to symbols of types derived from IEnumerable as well as to symbols of Task - /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property - /// or of the Lazy.Value property can never be null. - /// - /// - /// public void Foo([ItemNotNull]List<string> books) - /// { - /// foreach (var book in books) { - /// if (book != null) // Warning: Expression is always true - /// Console.WriteLine(book.ToUpper()); - /// } - /// } - /// - [AttributeUsage( - AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | - AttributeTargets.Delegate | AttributeTargets.Field)] - public sealed class ItemNotNullAttribute : Attribute { } - - /// - /// Can be applied to symbols of types derived from IEnumerable as well as to symbols of Task - /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property - /// or of the Lazy.Value property can be null. - /// - /// - /// public void Foo([ItemCanBeNull]List<string> books) - /// { - /// foreach (var book in books) - /// { - /// // Warning: Possible 'System.NullReferenceException' - /// Console.WriteLine(book.ToUpper()); - /// } - /// } - /// - [AttributeUsage( - AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | - AttributeTargets.Delegate | AttributeTargets.Field)] - public sealed class ItemCanBeNullAttribute : Attribute { } - - /// - /// Indicates that the marked method builds string by the format pattern and (optional) arguments. - /// The parameter, which contains the format string, should be given in constructor. The format string - /// should be in -like form. - /// - /// - /// [StringFormatMethod("message")] - /// void ShowError(string message, params object[] args) { /* do something */ } - /// - /// void Foo() { - /// ShowError("Failed: {0}"); // Warning: Non-existing argument in format string - /// } - /// - [AttributeUsage( - AttributeTargets.Constructor | AttributeTargets.Method | - AttributeTargets.Property | AttributeTargets.Delegate)] - public sealed class StringFormatMethodAttribute : Attribute - { - /// - /// Specifies which parameter of an annotated method should be treated as the format string - /// - public StringFormatMethodAttribute([NotNull] string formatParameterName) - { - FormatParameterName = formatParameterName; - } - - [NotNull] public string FormatParameterName { get; } - } - - /// - /// Use this annotation to specify a type that contains static or const fields - /// with values for the annotated property/field/parameter. - /// The specified type will be used to improve completion suggestions. - /// - /// - /// namespace TestNamespace - /// { - /// public class Constants - /// { - /// public static int INT_CONST = 1; - /// public const string STRING_CONST = "1"; - /// } - /// - /// public class Class1 - /// { - /// [ValueProvider("TestNamespace.Constants")] public int myField; - /// public void Foo([ValueProvider("TestNamespace.Constants")] string str) { } - /// - /// public void Test() - /// { - /// Foo(/*try completion here*/);// - /// myField = /*try completion here*/ - /// } - /// } - /// } - /// - [AttributeUsage( - AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field, - AllowMultiple = true)] - public sealed class ValueProviderAttribute : Attribute - { - public ValueProviderAttribute([NotNull] string name) - { - Name = name; - } - - [NotNull] public string Name { get; } - } - - /// - /// Indicates that the function argument should be a string literal and match one - /// of the parameters of the caller function. For example, ReSharper annotates - /// the parameter of . - /// - /// - /// void Foo(string param) { - /// if (param == null) - /// throw new ArgumentNullException("par"); // Warning: Cannot resolve symbol - /// } - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class InvokerParameterNameAttribute : Attribute { } - - /// - /// Indicates that the method is contained in a type that implements - /// System.ComponentModel.INotifyPropertyChanged interface and this method - /// is used to notify that some property value changed. - /// - /// - /// The method should be non-static and conform to one of the supported signatures: - /// - /// NotifyChanged(string) - /// NotifyChanged(params string[]) - /// NotifyChanged{T}(Expression{Func{T}}) - /// NotifyChanged{T,U}(Expression{Func{T,U}}) - /// SetProperty{T}(ref T, T, string) - /// - /// - /// - /// public class Foo : INotifyPropertyChanged { - /// public event PropertyChangedEventHandler PropertyChanged; - /// - /// [NotifyPropertyChangedInvocator] - /// protected virtual void NotifyChanged(string propertyName) { ... } - /// - /// string _name; - /// - /// public string Name { - /// get { return _name; } - /// set { _name = value; NotifyChanged("LastName"); /* Warning */ } - /// } - /// } - /// - /// Examples of generated notifications: - /// - /// NotifyChanged("Property") - /// NotifyChanged(() => Property) - /// NotifyChanged((VM x) => x.Property) - /// SetProperty(ref myField, value, "Property") - /// - /// - [AttributeUsage(AttributeTargets.Method)] - public sealed class NotifyPropertyChangedInvocatorAttribute : Attribute - { - public NotifyPropertyChangedInvocatorAttribute() { } - public NotifyPropertyChangedInvocatorAttribute([NotNull] string parameterName) - { - ParameterName = parameterName; - } - - [CanBeNull] public string ParameterName { get; } - } - - /// - /// Describes dependency between method input and output. - /// - /// - ///

Function Definition Table syntax:

- /// - /// FDT ::= FDTRow [;FDTRow]* - /// FDTRow ::= Input => Output | Output <= Input - /// Input ::= ParameterName: Value [, Input]* - /// Output ::= [ParameterName: Value]* {halt|stop|void|nothing|Value} - /// Value ::= true | false | null | notnull | canbenull - /// - /// If the method has a single input parameter, its name could be omitted.
- /// Using halt (or void/nothing, which is the same) for the method output - /// means that the method doesn't return normally (throws or terminates the process).
- /// Value canbenull is only applicable for output parameters.
- /// You can use multiple [ContractAnnotation] for each FDT row, or use single attribute - /// with rows separated by semicolon. There is no notion of order rows, all rows are checked - /// for applicability and applied per each program state tracked by the analysis engine.
- ///
- /// - /// - /// [ContractAnnotation("=> halt")] - /// public void TerminationMethod() - /// - /// - /// [ContractAnnotation("null <= param:null")] // reverse condition syntax - /// public string GetName(string surname) - /// - /// - /// [ContractAnnotation("s:null => true")] - /// public bool IsNullOrEmpty(string s) // string.IsNullOrEmpty() - /// - /// - /// // A method that returns null if the parameter is null, - /// // and not null if the parameter is not null - /// [ContractAnnotation("null => null; notnull => notnull")] - /// public object Transform(object data) - /// - /// - /// [ContractAnnotation("=> true, result: notnull; => false, result: null")] - /// public bool TryParse(string s, out Person result) - /// - /// - [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] - public sealed class ContractAnnotationAttribute : Attribute - { - public ContractAnnotationAttribute([NotNull] string contract) - : this(contract, false) { } - - public ContractAnnotationAttribute([NotNull] string contract, bool forceFullStates) - { - Contract = contract; - ForceFullStates = forceFullStates; - } - - [NotNull] public string Contract { get; } - - public bool ForceFullStates { get; } - } - - /// - /// Indicates whether the marked element should be localized. - /// - /// - /// [LocalizationRequiredAttribute(true)] - /// class Foo { - /// string str = "my string"; // Warning: Localizable string - /// } - /// - [AttributeUsage(AttributeTargets.All)] - public sealed class LocalizationRequiredAttribute : Attribute - { - public LocalizationRequiredAttribute() : this(true) { } - - public LocalizationRequiredAttribute(bool required) - { - Required = required; - } - - public bool Required { get; } - } - - /// - /// Indicates that the value of the marked type (or its derivatives) - /// cannot be compared using '==' or '!=' operators and Equals() - /// should be used instead. However, using '==' or '!=' for comparison - /// with null is always permitted. - /// - /// - /// [CannotApplyEqualityOperator] - /// class NoEquality { } - /// - /// class UsesNoEquality { - /// void Test() { - /// var ca1 = new NoEquality(); - /// var ca2 = new NoEquality(); - /// if (ca1 != null) { // OK - /// bool condition = ca1 == ca2; // Warning - /// } - /// } - /// } - /// - [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct)] - public sealed class CannotApplyEqualityOperatorAttribute : Attribute { } - - /// - /// When applied to a target attribute, specifies a requirement for any type marked - /// with the target attribute to implement or inherit specific type or types. - /// - /// - /// [BaseTypeRequired(typeof(IComponent)] // Specify requirement - /// class ComponentAttribute : Attribute { } - /// - /// [Component] // ComponentAttribute requires implementing IComponent interface - /// class MyComponent : IComponent { } - /// - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] - [BaseTypeRequired(typeof(Attribute))] - public sealed class BaseTypeRequiredAttribute : Attribute - { - public BaseTypeRequiredAttribute([NotNull] Type baseType) - { - BaseType = baseType; - } - - [NotNull] public Type BaseType { get; } - } - - /// - /// Indicates that the marked symbol is used implicitly (e.g. via reflection, in external library), - /// so this symbol will not be reported as unused (as well as by other usage inspections). - /// - [AttributeUsage(AttributeTargets.All, Inherited = false)] - public sealed class UsedImplicitlyAttribute : Attribute - { - public UsedImplicitlyAttribute() - : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { } - - public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags) - : this(useKindFlags, ImplicitUseTargetFlags.Default) { } - - public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags) - : this(ImplicitUseKindFlags.Default, targetFlags) { } - - public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) - { - UseKindFlags = useKindFlags; - TargetFlags = targetFlags; - } - - public ImplicitUseKindFlags UseKindFlags { get; } - - public ImplicitUseTargetFlags TargetFlags { get; } - } - - /// - /// Can be applied to attributes, type parameters, and parameters of a type assignable from . - /// When applied to an attribute, the decorated attribute behaves the same as . - /// When applied to a type parameter or to a parameter of type , indicates that the corresponding type - /// is used implicitly. - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.GenericParameter | AttributeTargets.Parameter)] - public sealed class MeansImplicitUseAttribute : Attribute - { - public MeansImplicitUseAttribute() - : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { } - - public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags) - : this(useKindFlags, ImplicitUseTargetFlags.Default) { } - - public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags) - : this(ImplicitUseKindFlags.Default, targetFlags) { } - - public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) - { - UseKindFlags = useKindFlags; - TargetFlags = targetFlags; - } - - [UsedImplicitly] public ImplicitUseKindFlags UseKindFlags { get; } - - [UsedImplicitly] public ImplicitUseTargetFlags TargetFlags { get; } - } - - /// - /// Specify the details of implicitly used symbol when it is marked - /// with or . - /// - [Flags] - public enum ImplicitUseKindFlags - { - Default = Access | Assign | InstantiatedWithFixedConstructorSignature, - /// Only entity marked with attribute considered used. - Access = 1, - /// Indicates implicit assignment to a member. - Assign = 2, /// - /// Indicates implicit instantiation of a type with fixed constructor signature. - /// That means any unused constructor parameters won't be reported as such. + /// Indicates that the value of the marked element could be null sometimes, + /// so checking for null is required before its usage. /// - InstantiatedWithFixedConstructorSignature = 4, - /// Indicates implicit instantiation of a type. - InstantiatedNoFixedConstructorSignature = 8, - } - - /// - /// Specify what is considered to be used implicitly when marked - /// with or . - /// - [Flags] - public enum ImplicitUseTargetFlags - { - Default = Itself, - Itself = 1, - /// Members of entity marked with attribute are considered used. - Members = 2, - /// Entity marked with attribute and all its members considered used. - WithMembers = Itself | Members - } - - /// - /// This attribute is intended to mark publicly available API - /// which should not be removed and so is treated as used. - /// - [MeansImplicitUse(ImplicitUseTargetFlags.WithMembers)] - [AttributeUsage(AttributeTargets.All, Inherited = false)] - public sealed class PublicAPIAttribute : Attribute - { - public PublicAPIAttribute() { } - - public PublicAPIAttribute([NotNull] string comment) + /// + /// + /// [CanBeNull] object Test() => null; + /// + /// void UseTest() { + /// var p = Test(); + /// var s = p.ToString(); // Warning: Possible 'System.NullReferenceException' + /// } + /// + /// + [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | + AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event | + AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)] + public sealed class CanBeNullAttribute : Attribute { - Comment = comment; } - [CanBeNull] public string Comment { get; } - } - - /// - /// Tells code analysis engine if the parameter is completely handled when the invoked method is on stack. - /// If the parameter is a delegate, indicates that delegate is executed while the method is executed. - /// If the parameter is an enumerable, indicates that it is enumerated while the method is executed. - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class InstantHandleAttribute : Attribute { } - - /// - /// Indicates that a method does not make any observable state changes. - /// The same as System.Diagnostics.Contracts.PureAttribute. - /// - /// - /// [Pure] int Multiply(int x, int y) => x * y; - /// - /// void M() { - /// Multiply(123, 42); // Waring: Return value of pure method is not used - /// } - /// - [AttributeUsage(AttributeTargets.Method)] - public sealed class PureAttribute : Attribute { } - - /// - /// Indicates that the return value of the method invocation must be used. - /// - /// - /// Methods decorated with this attribute (in contrast to pure methods) might change state, - /// but make no sense without using their return value.
- /// Similarly to , this attribute - /// will help detecting usages of the method when the return value in not used. - /// Additionally, you can optionally specify a custom message, which will be used when showing warnings, e.g. - /// [MustUseReturnValue("Use the return value to...")]. - ///
- [AttributeUsage(AttributeTargets.Method)] - public sealed class MustUseReturnValueAttribute : Attribute - { - public MustUseReturnValueAttribute() { } - - public MustUseReturnValueAttribute([NotNull] string justification) - { - Justification = justification; - } - - [CanBeNull] public string Justification { get; } - } - - /// - /// Indicates the type member or parameter of some type, that should be used instead of all other ways - /// to get the value of that type. This annotation is useful when you have some "context" value evaluated - /// and stored somewhere, meaning that all other ways to get this value must be consolidated with existing one. - /// - /// - /// class Foo { - /// [ProvidesContext] IBarService _barService = ...; - /// - /// void ProcessNode(INode node) { - /// DoSomething(node, node.GetGlobalServices().Bar); - /// // ^ Warning: use value of '_barService' field - /// } - /// } - /// - [AttributeUsage( - AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.Method | - AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.GenericParameter)] - public sealed class ProvidesContextAttribute : Attribute { } - - /// - /// Indicates that a parameter is a path to a file or a folder within a web project. - /// Path can be relative or absolute, starting from web root (~). - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class PathReferenceAttribute : Attribute - { - public PathReferenceAttribute() { } - - public PathReferenceAttribute([NotNull, PathReference] string basePath) - { - BasePath = basePath; - } - - [CanBeNull] public string BasePath { get; } - } - - /// - /// An extension method marked with this attribute is processed by code completion - /// as a 'Source Template'. When the extension method is completed over some expression, its source code - /// is automatically expanded like a template at call site. - /// - /// - /// Template method body can contain valid source code and/or special comments starting with '$'. - /// Text inside these comments is added as source code when the template is applied. Template parameters - /// can be used either as additional method parameters or as identifiers wrapped in two '$' signs. - /// Use the attribute to specify macros for parameters. - /// - /// - /// In this example, the 'forEach' method is a source template available over all values - /// of enumerable types, producing ordinary C# 'foreach' statement and placing caret inside block: - /// - /// [SourceTemplate] - /// public static void forEach<T>(this IEnumerable<T> xs) { - /// foreach (var x in xs) { - /// //$ $END$ - /// } - /// } - /// - /// - [AttributeUsage(AttributeTargets.Method)] - public sealed class SourceTemplateAttribute : Attribute { } - - /// - /// Allows specifying a macro for a parameter of a source template. - /// - /// - /// You can apply the attribute on the whole method or on any of its additional parameters. The macro expression - /// is defined in the property. When applied on a method, the target - /// template parameter is defined in the property. To apply the macro silently - /// for the parameter, set the property value = -1. - /// - /// - /// Applying the attribute on a source template method: - /// - /// [SourceTemplate, Macro(Target = "item", Expression = "suggestVariableName()")] - /// public static void forEach<T>(this IEnumerable<T> collection) { - /// foreach (var item in collection) { - /// //$ $END$ - /// } - /// } - /// - /// Applying the attribute on a template method parameter: - /// - /// [SourceTemplate] - /// public static void something(this Entity x, [Macro(Expression = "guid()", Editable = -1)] string newguid) { - /// /*$ var $x$Id = "$newguid$" + x.ToString(); - /// x.DoSomething($x$Id); */ - /// } - /// - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method, AllowMultiple = true)] - public sealed class MacroAttribute : Attribute - { /// - /// Allows specifying a macro that will be executed for a source template - /// parameter when the template is expanded. + /// Indicates that the value of the marked element can never be null. /// - [CanBeNull] public string Expression { get; set; } + /// + /// + /// [NotNull] object Foo() { + /// return null; // Warning: Possible 'null' assignment + /// } + /// + /// + [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | + AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event | + AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)] + public sealed class NotNullAttribute : Attribute + { + } /// - /// Allows specifying which occurrence of the target parameter becomes editable when the template is deployed. + /// Can be applied to symbols of types derived from IEnumerable as well as to symbols of Task + /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property + /// or of the Lazy.Value property can never be null. + /// + /// + /// + /// public void Foo([ItemNotNull]List<string> books) + /// { + /// foreach (var book in books) { + /// if (book != null) // Warning: Expression is always true + /// Console.WriteLine(book.ToUpper()); + /// } + /// } + /// + /// + [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | + AttributeTargets.Delegate | AttributeTargets.Field)] + public sealed class ItemNotNullAttribute : Attribute + { + } + + /// + /// Can be applied to symbols of types derived from IEnumerable as well as to symbols of Task + /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property + /// or of the Lazy.Value property can be null. + /// + /// + /// + /// public void Foo([ItemCanBeNull]List<string> books) + /// { + /// foreach (var book in books) + /// { + /// // Warning: Possible 'System.NullReferenceException' + /// Console.WriteLine(book.ToUpper()); + /// } + /// } + /// + /// + [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | + AttributeTargets.Delegate | AttributeTargets.Field)] + public sealed class ItemCanBeNullAttribute : Attribute + { + } + + /// + /// Indicates that the marked method builds string by the format pattern and (optional) arguments. + /// The parameter, which contains the format string, should be given in constructor. The format string + /// should be in -like form. + /// + /// + /// + /// [StringFormatMethod("message")] + /// void ShowError(string message, params object[] args) { /* do something */ } + /// + /// void Foo() { + /// ShowError("Failed: {0}"); // Warning: Non-existing argument in format string + /// } + /// + /// + [AttributeUsage( + AttributeTargets.Constructor | AttributeTargets.Method | + AttributeTargets.Property | AttributeTargets.Delegate)] + public sealed class StringFormatMethodAttribute : Attribute + { + /// + /// Specifies which parameter of an annotated method should be treated as the format string + /// + public StringFormatMethodAttribute([NotNull] string formatParameterName) + { + FormatParameterName = formatParameterName; + } + + [NotNull] + public string FormatParameterName { get; } + } + + /// + /// Use this annotation to specify a type that contains static or const fields + /// with values for the annotated property/field/parameter. + /// The specified type will be used to improve completion suggestions. + /// + /// + /// + /// namespace TestNamespace + /// { + /// public class Constants + /// { + /// public static int INT_CONST = 1; + /// public const string STRING_CONST = "1"; + /// } + /// + /// public class Class1 + /// { + /// [ValueProvider("TestNamespace.Constants")] public int myField; + /// public void Foo([ValueProvider("TestNamespace.Constants")] string str) { } + /// + /// public void Test() + /// { + /// Foo(/*try completion here*/);// + /// myField = /*try completion here*/ + /// } + /// } + /// } + /// + /// + [AttributeUsage( + AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field, + AllowMultiple = true)] + public sealed class ValueProviderAttribute : Attribute + { + public ValueProviderAttribute([NotNull] string name) + { + Name = name; + } + + [NotNull] + public string Name { get; } + } + + /// + /// Indicates that the function argument should be a string literal and match one + /// of the parameters of the caller function. For example, ReSharper annotates + /// the parameter of . + /// + /// + /// + /// void Foo(string param) { + /// if (param == null) + /// throw new ArgumentNullException("par"); // Warning: Cannot resolve symbol + /// } + /// + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class InvokerParameterNameAttribute : Attribute + { + } + + /// + /// Indicates that the method is contained in a type that implements + /// System.ComponentModel.INotifyPropertyChanged interface and this method + /// is used to notify that some property value changed. /// /// - /// If the target parameter is used several times in the template, only one occurrence becomes editable; - /// other occurrences are changed synchronously. To specify the zero-based index of the editable occurrence, - /// use values >= 0. To make the parameter non-editable when the template is expanded, use -1. + /// The method should be non-static and conform to one of the supported signatures: + /// + /// + /// NotifyChanged(string) + /// + /// + /// NotifyChanged(params string[]) + /// + /// + /// NotifyChanged{T}(Expression{Func{T}}) + /// + /// + /// NotifyChanged{T,U}(Expression{Func{T,U}}) + /// + /// + /// SetProperty{T}(ref T, T, string) + /// + /// /// - public int Editable { get; set; } + /// + /// + /// public class Foo : INotifyPropertyChanged { + /// public event PropertyChangedEventHandler PropertyChanged; + /// + /// [NotifyPropertyChangedInvocator] + /// protected virtual void NotifyChanged(string propertyName) { ... } + /// + /// string _name; + /// + /// public string Name { + /// get { return _name; } + /// set { _name = value; NotifyChanged("LastName"); /* Warning */ } + /// } + /// } + /// + /// Examples of generated notifications: + /// + /// + /// NotifyChanged("Property") + /// + /// + /// NotifyChanged(() => Property) + /// + /// + /// NotifyChanged((VM x) => x.Property) + /// + /// + /// SetProperty(ref myField, value, "Property") + /// + /// + /// + [AttributeUsage(AttributeTargets.Method)] + public sealed class NotifyPropertyChangedInvocatorAttribute : Attribute + { + public NotifyPropertyChangedInvocatorAttribute() + { + } + + public NotifyPropertyChangedInvocatorAttribute([NotNull] string parameterName) + { + ParameterName = parameterName; + } + + [CanBeNull] + public string ParameterName { get; } + } /// - /// Identifies the target parameter of a source template if the - /// is applied on a template method. + /// Describes dependency between method input and output. /// - [CanBeNull] public string Target { get; set; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcAreaMasterLocationFormatAttribute : Attribute - { - public AspMvcAreaMasterLocationFormatAttribute([NotNull] string format) + /// + ///

Function Definition Table syntax:

+ /// + /// FDT ::= FDTRow [;FDTRow]* + /// FDTRow ::= Input => Output | Output <= Input + /// Input ::= ParameterName: Value [, Input]* + /// Output ::= [ParameterName: Value]* {halt|stop|void|nothing|Value} + /// Value ::= true | false | null | notnull | canbenull + /// + /// If the method has a single input parameter, its name could be omitted.
+ /// Using halt (or void/nothing, which is the same) for the method output + /// means that the method doesn't return normally (throws or terminates the process).
+ /// Value canbenull is only applicable for output parameters.
+ /// You can use multiple [ContractAnnotation] for each FDT row, or use single attribute + /// with rows separated by semicolon. There is no notion of order rows, all rows are checked + /// for applicability and applied per each program state tracked by the analysis engine.
+ ///
+ /// + /// + /// + /// + /// [ContractAnnotation("=> halt")] + /// public void TerminationMethod() + /// + /// + /// + /// + /// [ContractAnnotation("null <= param:null")] // reverse condition syntax + /// public string GetName(string surname) + /// + /// + /// + /// + /// [ContractAnnotation("s:null => true")] + /// public bool IsNullOrEmpty(string s) // string.IsNullOrEmpty() + /// + /// + /// + /// + /// // A method that returns null if the parameter is null, + /// // and not null if the parameter is not null + /// [ContractAnnotation("null => null; notnull => notnull")] + /// public object Transform(object data) + /// + /// + /// + /// + /// [ContractAnnotation("=> true, result: notnull; => false, result: null")] + /// public bool TryParse(string s, out Person result) + /// + /// + /// + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + public sealed class ContractAnnotationAttribute : Attribute { - Format = format; + public ContractAnnotationAttribute([NotNull] string contract) + : this(contract, false) + { + } + + public ContractAnnotationAttribute([NotNull] string contract, bool forceFullStates) + { + Contract = contract; + ForceFullStates = forceFullStates; + } + + [NotNull] + public string Contract { get; } + + public bool ForceFullStates { get; } } - [NotNull] public string Format { get; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcAreaPartialViewLocationFormatAttribute : Attribute - { - public AspMvcAreaPartialViewLocationFormatAttribute([NotNull] string format) + /// + /// Indicates whether the marked element should be localized. + /// + /// + /// + /// [LocalizationRequiredAttribute(true)] + /// class Foo { + /// string str = "my string"; // Warning: Localizable string + /// } + /// + /// + [AttributeUsage(AttributeTargets.All)] + public sealed class LocalizationRequiredAttribute : Attribute { - Format = format; + public LocalizationRequiredAttribute() : this(true) + { + } + + public LocalizationRequiredAttribute(bool required) + { + Required = required; + } + + public bool Required { get; } } - [NotNull] public string Format { get; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcAreaViewLocationFormatAttribute : Attribute - { - public AspMvcAreaViewLocationFormatAttribute([NotNull] string format) + /// + /// Indicates that the value of the marked type (or its derivatives) + /// cannot be compared using '==' or '!=' operators and Equals() + /// should be used instead. However, using '==' or '!=' for comparison + /// with null is always permitted. + /// + /// + /// + /// [CannotApplyEqualityOperator] + /// class NoEquality { } + /// + /// class UsesNoEquality { + /// void Test() { + /// var ca1 = new NoEquality(); + /// var ca2 = new NoEquality(); + /// if (ca1 != null) { // OK + /// bool condition = ca1 == ca2; // Warning + /// } + /// } + /// } + /// + /// + [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct)] + public sealed class CannotApplyEqualityOperatorAttribute : Attribute { - Format = format; } - [NotNull] public string Format { get; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcMasterLocationFormatAttribute : Attribute - { - public AspMvcMasterLocationFormatAttribute([NotNull] string format) + /// + /// When applied to a target attribute, specifies a requirement for any type marked + /// with the target attribute to implement or inherit specific type or types. + /// + /// + /// + /// [BaseTypeRequired(typeof(IComponent)] // Specify requirement + /// class ComponentAttribute : Attribute { } + /// + /// [Component] // ComponentAttribute requires implementing IComponent interface + /// class MyComponent : IComponent { } + /// + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + [BaseTypeRequired(typeof(Attribute))] + public sealed class BaseTypeRequiredAttribute : Attribute { - Format = format; + public BaseTypeRequiredAttribute([NotNull] Type baseType) + { + BaseType = baseType; + } + + [NotNull] + public Type BaseType { get; } } - [NotNull] public string Format { get; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcPartialViewLocationFormatAttribute : Attribute - { - public AspMvcPartialViewLocationFormatAttribute([NotNull] string format) + /// + /// Indicates that the marked symbol is used implicitly (e.g. via reflection, in external library), + /// so this symbol will not be reported as unused (as well as by other usage inspections). + /// + [AttributeUsage(AttributeTargets.All, Inherited = false)] + public sealed class UsedImplicitlyAttribute : Attribute { - Format = format; + public UsedImplicitlyAttribute() + : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) + { + } + + public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags) + : this(useKindFlags, ImplicitUseTargetFlags.Default) + { + } + + public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags) + : this(ImplicitUseKindFlags.Default, targetFlags) + { + } + + public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) + { + UseKindFlags = useKindFlags; + TargetFlags = targetFlags; + } + + public ImplicitUseKindFlags UseKindFlags { get; } + + public ImplicitUseTargetFlags TargetFlags { get; } } - [NotNull] public string Format { get; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcViewLocationFormatAttribute : Attribute - { - public AspMvcViewLocationFormatAttribute([NotNull] string format) + /// + /// Can be applied to attributes, type parameters, and parameters of a type assignable from + /// . + /// When applied to an attribute, the decorated attribute behaves the same as . + /// When applied to a type parameter or to a parameter of type , indicates that the + /// corresponding type + /// is used implicitly. + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.GenericParameter | AttributeTargets.Parameter)] + public sealed class MeansImplicitUseAttribute : Attribute { - Format = format; + public MeansImplicitUseAttribute() + : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) + { + } + + public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags) + : this(useKindFlags, ImplicitUseTargetFlags.Default) + { + } + + public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags) + : this(ImplicitUseKindFlags.Default, targetFlags) + { + } + + public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) + { + UseKindFlags = useKindFlags; + TargetFlags = targetFlags; + } + + [UsedImplicitly] + public ImplicitUseKindFlags UseKindFlags { get; } + + [UsedImplicitly] + public ImplicitUseTargetFlags TargetFlags { get; } } - [NotNull] public string Format { get; } - } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter - /// is an MVC action. If applied to a method, the MVC action name is calculated - /// implicitly from the context. Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcActionAttribute : Attribute - { - public AspMvcActionAttribute() { } - - public AspMvcActionAttribute([NotNull] string anonymousProperty) + /// + /// Specify the details of implicitly used symbol when it is marked + /// with or . + /// + [Flags] + public enum ImplicitUseKindFlags { - AnonymousProperty = anonymousProperty; + Default = Access | Assign | InstantiatedWithFixedConstructorSignature, + + /// Only entity marked with attribute considered used. + Access = 1, + + /// Indicates implicit assignment to a member. + Assign = 2, + + /// + /// Indicates implicit instantiation of a type with fixed constructor signature. + /// That means any unused constructor parameters won't be reported as such. + /// + InstantiatedWithFixedConstructorSignature = 4, + + /// Indicates implicit instantiation of a type. + InstantiatedNoFixedConstructorSignature = 8 } - [CanBeNull] public string AnonymousProperty { get; } - } - - /// - /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC area. - /// Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcAreaAttribute : Attribute - { - public AspMvcAreaAttribute() { } - - public AspMvcAreaAttribute([NotNull] string anonymousProperty) + /// + /// Specify what is considered to be used implicitly when marked + /// with or . + /// + [Flags] + public enum ImplicitUseTargetFlags { - AnonymousProperty = anonymousProperty; + Default = Itself, + Itself = 1, + + /// Members of entity marked with attribute are considered used. + Members = 2, + + /// Entity marked with attribute and all its members considered used. + WithMembers = Itself | Members } - [CanBeNull] public string AnonymousProperty { get; } - } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is - /// an MVC controller. If applied to a method, the MVC controller name is calculated - /// implicitly from the context. Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcControllerAttribute : Attribute - { - public AspMvcControllerAttribute() { } - - public AspMvcControllerAttribute([NotNull] string anonymousProperty) + /// + /// This attribute is intended to mark publicly available API + /// which should not be removed and so is treated as used. + /// + [MeansImplicitUse(ImplicitUseTargetFlags.WithMembers)] + [AttributeUsage(AttributeTargets.All, Inherited = false)] + public sealed class PublicAPIAttribute : Attribute { - AnonymousProperty = anonymousProperty; + public PublicAPIAttribute() + { + } + + public PublicAPIAttribute([NotNull] string comment) + { + Comment = comment; + } + + [CanBeNull] + public string Comment { get; } } - [CanBeNull] public string AnonymousProperty { get; } - } - - /// - /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC Master. Use this attribute - /// for custom wrappers similar to System.Web.Mvc.Controller.View(String, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcMasterAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC model type. Use this attribute - /// for custom wrappers similar to System.Web.Mvc.Controller.View(String, Object). - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class AspMvcModelTypeAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is an MVC - /// partial view. If applied to a method, the MVC partial view name is calculated implicitly - /// from the context. Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.RenderPartialExtensions.RenderPartial(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcPartialViewAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. Allows disabling inspections for MVC views within a class or a method. - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] - public sealed class AspMvcSuppressViewErrorAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. Indicates that a parameter is an MVC display template. - /// Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.DisplayExtensions.DisplayForModel(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcDisplayTemplateAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC editor template. - /// Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.EditorExtensions.EditorForModel(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcEditorTemplateAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC template. - /// Use this attribute for custom wrappers similar to - /// System.ComponentModel.DataAnnotations.UIHintAttribute(System.String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcTemplateAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter - /// is an MVC view component. If applied to a method, the MVC view name is calculated implicitly - /// from the context. Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Controller.View(Object). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcViewAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter - /// is an MVC view component name. - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcViewComponentAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter - /// is an MVC view component view. If applied to a method, the MVC view component view name is default. - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcViewComponentViewAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. When applied to a parameter of an attribute, - /// indicates that this parameter is an MVC action name. - /// - /// - /// [ActionName("Foo")] - /// public ActionResult Login(string returnUrl) { - /// ViewBag.ReturnUrl = Url.Action("Foo"); // OK - /// return RedirectToAction("Bar"); // Error: Cannot resolve action - /// } - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property)] - public sealed class AspMvcActionSelectorAttribute : Attribute { } - - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field)] - public sealed class HtmlElementAttributesAttribute : Attribute - { - public HtmlElementAttributesAttribute() { } - - public HtmlElementAttributesAttribute([NotNull] string name) + /// + /// Tells code analysis engine if the parameter is completely handled when the invoked method is on stack. + /// If the parameter is a delegate, indicates that delegate is executed while the method is executed. + /// If the parameter is an enumerable, indicates that it is enumerated while the method is executed. + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class InstantHandleAttribute : Attribute { - Name = name; } - [CanBeNull] public string Name { get; } - } - - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class HtmlAttributeValueAttribute : Attribute - { - public HtmlAttributeValueAttribute([NotNull] string name) + /// + /// Indicates that a method does not make any observable state changes. + /// The same as System.Diagnostics.Contracts.PureAttribute. + /// + /// + /// + /// [Pure] int Multiply(int x, int y) => x * y; + /// + /// void M() { + /// Multiply(123, 42); // Waring: Return value of pure method is not used + /// } + /// + /// + [AttributeUsage(AttributeTargets.Method)] + public sealed class PureAttribute : Attribute { - Name = name; } - [NotNull] public string Name { get; } - } - - /// - /// Razor attribute. Indicates that the marked parameter or method is a Razor section. - /// Use this attribute for custom wrappers similar to - /// System.Web.WebPages.WebPageBase.RenderSection(String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] - public sealed class RazorSectionAttribute : Attribute { } - - /// - /// Indicates how method, constructor invocation, or property access - /// over collection type affects the contents of the collection. - /// Use to specify the access type. - /// - /// - /// Using this attribute only makes sense if all collection methods are marked with this attribute. - /// - /// - /// public class MyStringCollection : List<string> - /// { - /// [CollectionAccess(CollectionAccessType.Read)] - /// public string GetFirstString() - /// { - /// return this.ElementAt(0); - /// } - /// } - /// class Test - /// { - /// public void Foo() - /// { - /// // Warning: Contents of the collection is never updated - /// var col = new MyStringCollection(); - /// string x = col.GetFirstString(); - /// } - /// } - /// - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property)] - public sealed class CollectionAccessAttribute : Attribute - { - public CollectionAccessAttribute(CollectionAccessType collectionAccessType) + /// + /// Indicates that the return value of the method invocation must be used. + /// + /// + /// Methods decorated with this attribute (in contrast to pure methods) might change state, + /// but make no sense without using their return value.
+ /// Similarly to , this attribute + /// will help detecting usages of the method when the return value in not used. + /// Additionally, you can optionally specify a custom message, which will be used when showing warnings, e.g. + /// [MustUseReturnValue("Use the return value to...")]. + ///
+ [AttributeUsage(AttributeTargets.Method)] + public sealed class MustUseReturnValueAttribute : Attribute { - CollectionAccessType = collectionAccessType; + public MustUseReturnValueAttribute() + { + } + + public MustUseReturnValueAttribute([NotNull] string justification) + { + Justification = justification; + } + + [CanBeNull] + public string Justification { get; } } - public CollectionAccessType CollectionAccessType { get; } - } - - /// - /// Provides a value for the to define - /// how the collection method invocation affects the contents of the collection. - /// - [Flags] - public enum CollectionAccessType - { - /// Method does not use or modify content of the collection. - None = 0, - /// Method only reads content of the collection but does not modify it. - Read = 1, - /// Method can change content of the collection but does not add new elements. - ModifyExistingContent = 2, - /// Method can add new elements to the collection. - UpdatedContent = ModifyExistingContent | 4 - } - - /// - /// Indicates that the marked method is assertion method, i.e. it halts the control flow if - /// one of the conditions is satisfied. To set the condition, mark one of the parameters with - /// attribute. - /// - [AttributeUsage(AttributeTargets.Method)] - public sealed class AssertionMethodAttribute : Attribute { } - - /// - /// Indicates the condition parameter of the assertion method. The method itself should be - /// marked by attribute. The mandatory argument of - /// the attribute is the assertion type. - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class AssertionConditionAttribute : Attribute - { - public AssertionConditionAttribute(AssertionConditionType conditionType) + /// + /// Indicates the type member or parameter of some type, that should be used instead of all other ways + /// to get the value of that type. This annotation is useful when you have some "context" value evaluated + /// and stored somewhere, meaning that all other ways to get this value must be consolidated with existing one. + /// + /// + /// + /// class Foo { + /// [ProvidesContext] IBarService _barService = ...; + /// + /// void ProcessNode(INode node) { + /// DoSomething(node, node.GetGlobalServices().Bar); + /// // ^ Warning: use value of '_barService' field + /// } + /// } + /// + /// + [AttributeUsage( + AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.Method | + AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.GenericParameter)] + public sealed class ProvidesContextAttribute : Attribute { - ConditionType = conditionType; } - public AssertionConditionType ConditionType { get; } - } - - /// - /// Specifies assertion type. If the assertion method argument satisfies the condition, - /// then the execution continues. Otherwise, execution is assumed to be halted. - /// - public enum AssertionConditionType - { - /// Marked parameter should be evaluated to true. - IS_TRUE = 0, - /// Marked parameter should be evaluated to false. - IS_FALSE = 1, - /// Marked parameter should be evaluated to null value. - IS_NULL = 2, - /// Marked parameter should be evaluated to not null value. - IS_NOT_NULL = 3, - } - - /// - /// Indicates that the marked method unconditionally terminates control flow execution. - /// For example, it could unconditionally throw exception. - /// - [Obsolete("Use [ContractAnnotation('=> halt')] instead")] - [AttributeUsage(AttributeTargets.Method)] - public sealed class TerminatesProgramAttribute : Attribute { } - - /// - /// Indicates that method is pure LINQ method, with postponed enumeration (like Enumerable.Select, - /// .Where). This annotation allows inference of [InstantHandle] annotation for parameters - /// of delegate type by analyzing LINQ method chains. - /// - [AttributeUsage(AttributeTargets.Method)] - public sealed class LinqTunnelAttribute : Attribute { } - - /// - /// Indicates that IEnumerable passed as a parameter is not enumerated. - /// Use this annotation to suppress the 'Possible multiple enumeration of IEnumerable' inspection. - /// - /// - /// static void ThrowIfNull<T>([NoEnumeration] T v, string n) where T : class - /// { - /// // custom check for null but no enumeration - /// } - /// - /// void Foo(IEnumerable<string> values) - /// { - /// ThrowIfNull(values, nameof(values)); - /// var x = values.ToList(); // No warnings about multiple enumeration - /// } - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class NoEnumerationAttribute : Attribute { } - - /// - /// Indicates that the marked parameter is a regular expression pattern. - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class RegexPatternAttribute : Attribute { } - - /// - /// Prevents the Member Reordering feature from tossing members of the marked class. - /// - /// - /// The attribute must be mentioned in your member reordering patterns. - /// - [AttributeUsage( - AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Enum)] - public sealed class NoReorderAttribute : Attribute { } - - /// - /// XAML attribute. Indicates the type that has ItemsSource property and should be treated - /// as ItemsControl-derived type, to enable inner items DataContext type resolve. - /// - [AttributeUsage(AttributeTargets.Class)] - public sealed class XamlItemsControlAttribute : Attribute { } - - /// - /// XAML attribute. Indicates the property of some BindingBase-derived type, that - /// is used to bind some item of ItemsControl-derived type. This annotation will - /// enable the DataContext type resolve for XAML bindings for such properties. - /// - /// - /// Property should have the tree ancestor of the ItemsControl type or - /// marked with the attribute. - /// - [AttributeUsage(AttributeTargets.Property)] - public sealed class XamlItemBindingOfItemsControlAttribute : Attribute { } - - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] - public sealed class AspChildControlTypeAttribute : Attribute - { - public AspChildControlTypeAttribute([NotNull] string tagName, [NotNull] Type controlType) + /// + /// Indicates that a parameter is a path to a file or a folder within a web project. + /// Path can be relative or absolute, starting from web root (~). + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class PathReferenceAttribute : Attribute { - TagName = tagName; - ControlType = controlType; + public PathReferenceAttribute() + { + } + + public PathReferenceAttribute([NotNull] [PathReference] string basePath) + { + BasePath = basePath; + } + + [CanBeNull] + public string BasePath { get; } } - [NotNull] public string TagName { get; } - - [NotNull] public Type ControlType { get; } - } - - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)] - public sealed class AspDataFieldAttribute : Attribute { } - - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)] - public sealed class AspDataFieldsAttribute : Attribute { } - - [AttributeUsage(AttributeTargets.Property)] - public sealed class AspMethodPropertyAttribute : Attribute { } - - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] - public sealed class AspRequiredAttributeAttribute : Attribute - { - public AspRequiredAttributeAttribute([NotNull] string attribute) + /// + /// An extension method marked with this attribute is processed by code completion + /// as a 'Source Template'. When the extension method is completed over some expression, its source code + /// is automatically expanded like a template at call site. + /// + /// + /// Template method body can contain valid source code and/or special comments starting with '$'. + /// Text inside these comments is added as source code when the template is applied. Template parameters + /// can be used either as additional method parameters or as identifiers wrapped in two '$' signs. + /// Use the attribute to specify macros for parameters. + /// + /// + /// In this example, the 'forEach' method is a source template available over all values + /// of enumerable types, producing ordinary C# 'foreach' statement and placing caret inside block: + /// + /// [SourceTemplate] + /// public static void forEach<T>(this IEnumerable<T> xs) { + /// foreach (var x in xs) { + /// //$ $END$ + /// } + /// } + /// + /// + [AttributeUsage(AttributeTargets.Method)] + public sealed class SourceTemplateAttribute : Attribute { - Attribute = attribute; } - [NotNull] public string Attribute { get; } - } - - [AttributeUsage(AttributeTargets.Property)] - public sealed class AspTypePropertyAttribute : Attribute - { - public bool CreateConstructorReferences { get; } - - public AspTypePropertyAttribute(bool createConstructorReferences) + /// + /// Allows specifying a macro for a parameter of a source template. + /// + /// + /// You can apply the attribute on the whole method or on any of its additional parameters. The macro expression + /// is defined in the property. When applied on a method, the target + /// template parameter is defined in the property. To apply the macro silently + /// for the parameter, set the property value = -1. + /// + /// + /// Applying the attribute on a source template method: + /// + /// [SourceTemplate, Macro(Target = "item", Expression = "suggestVariableName()")] + /// public static void forEach<T>(this IEnumerable<T> collection) { + /// foreach (var item in collection) { + /// //$ $END$ + /// } + /// } + /// + /// Applying the attribute on a template method parameter: + /// + /// [SourceTemplate] + /// public static void something(this Entity x, [Macro(Expression = "guid()", Editable = -1)] string newguid) { + /// /*$ var $x$Id = "$newguid$" + x.ToString(); + /// x.DoSomething($x$Id); */ + /// } + /// + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method, AllowMultiple = true)] + public sealed class MacroAttribute : Attribute { - CreateConstructorReferences = createConstructorReferences; - } - } + /// + /// Allows specifying a macro that will be executed for a source template + /// parameter when the template is expanded. + /// + [CanBeNull] + public string Expression { get; set; } - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class RazorImportNamespaceAttribute : Attribute - { - public RazorImportNamespaceAttribute([NotNull] string name) - { - Name = name; + /// + /// Allows specifying which occurrence of the target parameter becomes editable when the template is deployed. + /// + /// + /// If the target parameter is used several times in the template, only one occurrence becomes editable; + /// other occurrences are changed synchronously. To specify the zero-based index of the editable occurrence, + /// use values >= 0. To make the parameter non-editable when the template is expanded, use -1. + /// + public int Editable { get; set; } + + /// + /// Identifies the target parameter of a source template if the + /// is applied on a template method. + /// + [CanBeNull] + public string Target { get; set; } } - [NotNull] public string Name { get; } - } - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class RazorInjectionAttribute : Attribute - { - public RazorInjectionAttribute([NotNull] string type, [NotNull] string fieldName) + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcAreaMasterLocationFormatAttribute : Attribute { - Type = type; - FieldName = fieldName; + public AspMvcAreaMasterLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] + public string Format { get; } } - [NotNull] public string Type { get; } - - [NotNull] public string FieldName { get; } - } - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class RazorDirectiveAttribute : Attribute - { - public RazorDirectiveAttribute([NotNull] string directive) + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcAreaPartialViewLocationFormatAttribute : Attribute { - Directive = directive; + public AspMvcAreaPartialViewLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] + public string Format { get; } } - [NotNull] public string Directive { get; } - } + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcAreaViewLocationFormatAttribute : Attribute + { + public AspMvcAreaViewLocationFormatAttribute([NotNull] string format) + { + Format = format; + } - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class RazorPageBaseTypeAttribute : Attribute - { - public RazorPageBaseTypeAttribute([NotNull] string baseType) - { - BaseType = baseType; - } - public RazorPageBaseTypeAttribute([NotNull] string baseType, string pageName) - { - BaseType = baseType; - PageName = pageName; - } + [NotNull] + public string Format { get; } + } - [NotNull] public string BaseType { get; } - [CanBeNull] public string PageName { get; } - } + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcMasterLocationFormatAttribute : Attribute + { + public AspMvcMasterLocationFormatAttribute([NotNull] string format) + { + Format = format; + } - [AttributeUsage(AttributeTargets.Method)] - public sealed class RazorHelperCommonAttribute : Attribute { } + [NotNull] + public string Format { get; } + } - [AttributeUsage(AttributeTargets.Property)] - public sealed class RazorLayoutAttribute : Attribute { } + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcPartialViewLocationFormatAttribute : Attribute + { + public AspMvcPartialViewLocationFormatAttribute([NotNull] string format) + { + Format = format; + } - [AttributeUsage(AttributeTargets.Method)] - public sealed class RazorWriteLiteralMethodAttribute : Attribute { } + [NotNull] + public string Format { get; } + } - [AttributeUsage(AttributeTargets.Method)] - public sealed class RazorWriteMethodAttribute : Attribute { } + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcViewLocationFormatAttribute : Attribute + { + public AspMvcViewLocationFormatAttribute([NotNull] string format) + { + Format = format; + } - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class RazorWriteMethodParameterAttribute : Attribute { } + [NotNull] + public string Format { get; } + } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter + /// is an MVC action. If applied to a method, the MVC action name is calculated + /// implicitly from the context. Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcActionAttribute : Attribute + { + public AspMvcActionAttribute() + { + } + + public AspMvcActionAttribute([NotNull] string anonymousProperty) + { + AnonymousProperty = anonymousProperty; + } + + [CanBeNull] + public string AnonymousProperty { get; } + } + + /// + /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC area. + /// Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcAreaAttribute : Attribute + { + public AspMvcAreaAttribute() + { + } + + public AspMvcAreaAttribute([NotNull] string anonymousProperty) + { + AnonymousProperty = anonymousProperty; + } + + [CanBeNull] + public string AnonymousProperty { get; } + } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is + /// an MVC controller. If applied to a method, the MVC controller name is calculated + /// implicitly from the context. Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcControllerAttribute : Attribute + { + public AspMvcControllerAttribute() + { + } + + public AspMvcControllerAttribute([NotNull] string anonymousProperty) + { + AnonymousProperty = anonymousProperty; + } + + [CanBeNull] + public string AnonymousProperty { get; } + } + + /// + /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC Master. Use this attribute + /// for custom wrappers similar to System.Web.Mvc.Controller.View(String, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcMasterAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC model type. Use this attribute + /// for custom wrappers similar to System.Web.Mvc.Controller.View(String, Object). + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class AspMvcModelTypeAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is an MVC + /// partial view. If applied to a method, the MVC partial view name is calculated implicitly + /// from the context. Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.RenderPartialExtensions.RenderPartial(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcPartialViewAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. Allows disabling inspections for MVC views within a class or a method. + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] + public sealed class AspMvcSuppressViewErrorAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. Indicates that a parameter is an MVC display template. + /// Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.DisplayExtensions.DisplayForModel(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcDisplayTemplateAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC editor template. + /// Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.EditorExtensions.EditorForModel(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcEditorTemplateAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC template. + /// Use this attribute for custom wrappers similar to + /// System.ComponentModel.DataAnnotations.UIHintAttribute(System.String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcTemplateAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter + /// is an MVC view component. If applied to a method, the MVC view name is calculated implicitly + /// from the context. Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Controller.View(Object). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcViewAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter + /// is an MVC view component name. + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcViewComponentAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter + /// is an MVC view component view. If applied to a method, the MVC view component view name is default. + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcViewComponentViewAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. When applied to a parameter of an attribute, + /// indicates that this parameter is an MVC action name. + /// + /// + /// + /// [ActionName("Foo")] + /// public ActionResult Login(string returnUrl) { + /// ViewBag.ReturnUrl = Url.Action("Foo"); // OK + /// return RedirectToAction("Bar"); // Error: Cannot resolve action + /// } + /// + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property)] + public sealed class AspMvcActionSelectorAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field)] + public sealed class HtmlElementAttributesAttribute : Attribute + { + public HtmlElementAttributesAttribute() + { + } + + public HtmlElementAttributesAttribute([NotNull] string name) + { + Name = name; + } + + [CanBeNull] + public string Name { get; } + } + + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class HtmlAttributeValueAttribute : Attribute + { + public HtmlAttributeValueAttribute([NotNull] string name) + { + Name = name; + } + + [NotNull] + public string Name { get; } + } + + /// + /// Razor attribute. Indicates that the marked parameter or method is a Razor section. + /// Use this attribute for custom wrappers similar to + /// System.Web.WebPages.WebPageBase.RenderSection(String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] + public sealed class RazorSectionAttribute : Attribute + { + } + + /// + /// Indicates how method, constructor invocation, or property access + /// over collection type affects the contents of the collection. + /// Use to specify the access type. + /// + /// + /// Using this attribute only makes sense if all collection methods are marked with this attribute. + /// + /// + /// + /// public class MyStringCollection : List<string> + /// { + /// [CollectionAccess(CollectionAccessType.Read)] + /// public string GetFirstString() + /// { + /// return this.ElementAt(0); + /// } + /// } + /// class Test + /// { + /// public void Foo() + /// { + /// // Warning: Contents of the collection is never updated + /// var col = new MyStringCollection(); + /// string x = col.GetFirstString(); + /// } + /// } + /// + /// + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property)] + public sealed class CollectionAccessAttribute : Attribute + { + public CollectionAccessAttribute(CollectionAccessType collectionAccessType) + { + CollectionAccessType = collectionAccessType; + } + + public CollectionAccessType CollectionAccessType { get; } + } + + /// + /// Provides a value for the to define + /// how the collection method invocation affects the contents of the collection. + /// + [Flags] + public enum CollectionAccessType + { + /// Method does not use or modify content of the collection. + None = 0, + + /// Method only reads content of the collection but does not modify it. + Read = 1, + + /// Method can change content of the collection but does not add new elements. + ModifyExistingContent = 2, + + /// Method can add new elements to the collection. + UpdatedContent = ModifyExistingContent | 4 + } + + /// + /// Indicates that the marked method is assertion method, i.e. it halts the control flow if + /// one of the conditions is satisfied. To set the condition, mark one of the parameters with + /// attribute. + /// + [AttributeUsage(AttributeTargets.Method)] + public sealed class AssertionMethodAttribute : Attribute + { + } + + /// + /// Indicates the condition parameter of the assertion method. The method itself should be + /// marked by attribute. The mandatory argument of + /// the attribute is the assertion type. + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class AssertionConditionAttribute : Attribute + { + public AssertionConditionAttribute(AssertionConditionType conditionType) + { + ConditionType = conditionType; + } + + public AssertionConditionType ConditionType { get; } + } + + /// + /// Specifies assertion type. If the assertion method argument satisfies the condition, + /// then the execution continues. Otherwise, execution is assumed to be halted. + /// + public enum AssertionConditionType + { + /// Marked parameter should be evaluated to true. + IS_TRUE = 0, + + /// Marked parameter should be evaluated to false. + IS_FALSE = 1, + + /// Marked parameter should be evaluated to null value. + IS_NULL = 2, + + /// Marked parameter should be evaluated to not null value. + IS_NOT_NULL = 3 + } + + /// + /// Indicates that the marked method unconditionally terminates control flow execution. + /// For example, it could unconditionally throw exception. + /// + [Obsolete("Use [ContractAnnotation('=> halt')] instead")] + [AttributeUsage(AttributeTargets.Method)] + public sealed class TerminatesProgramAttribute : Attribute + { + } + + /// + /// Indicates that method is pure LINQ method, with postponed enumeration (like Enumerable.Select, + /// .Where). This annotation allows inference of [InstantHandle] annotation for parameters + /// of delegate type by analyzing LINQ method chains. + /// + [AttributeUsage(AttributeTargets.Method)] + public sealed class LinqTunnelAttribute : Attribute + { + } + + /// + /// Indicates that IEnumerable passed as a parameter is not enumerated. + /// Use this annotation to suppress the 'Possible multiple enumeration of IEnumerable' inspection. + /// + /// + /// + /// static void ThrowIfNull<T>([NoEnumeration] T v, string n) where T : class + /// { + /// // custom check for null but no enumeration + /// } + /// + /// void Foo(IEnumerable<string> values) + /// { + /// ThrowIfNull(values, nameof(values)); + /// var x = values.ToList(); // No warnings about multiple enumeration + /// } + /// + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class NoEnumerationAttribute : Attribute + { + } + + /// + /// Indicates that the marked parameter is a regular expression pattern. + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class RegexPatternAttribute : Attribute + { + } + + /// + /// Prevents the Member Reordering feature from tossing members of the marked class. + /// + /// + /// The attribute must be mentioned in your member reordering patterns. + /// + [AttributeUsage( + AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Enum)] + public sealed class NoReorderAttribute : Attribute + { + } + + /// + /// XAML attribute. Indicates the type that has ItemsSource property and should be treated + /// as ItemsControl-derived type, to enable inner items DataContext type resolve. + /// + [AttributeUsage(AttributeTargets.Class)] + public sealed class XamlItemsControlAttribute : Attribute + { + } + + /// + /// XAML attribute. Indicates the property of some BindingBase-derived type, that + /// is used to bind some item of ItemsControl-derived type. This annotation will + /// enable the DataContext type resolve for XAML bindings for such properties. + /// + /// + /// Property should have the tree ancestor of the ItemsControl type or + /// marked with the attribute. + /// + [AttributeUsage(AttributeTargets.Property)] + public sealed class XamlItemBindingOfItemsControlAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + public sealed class AspChildControlTypeAttribute : Attribute + { + public AspChildControlTypeAttribute([NotNull] string tagName, [NotNull] Type controlType) + { + TagName = tagName; + ControlType = controlType; + } + + [NotNull] + public string TagName { get; } + + [NotNull] + public Type ControlType { get; } + } + + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)] + public sealed class AspDataFieldAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)] + public sealed class AspDataFieldsAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Property)] + public sealed class AspMethodPropertyAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + public sealed class AspRequiredAttributeAttribute : Attribute + { + public AspRequiredAttributeAttribute([NotNull] string attribute) + { + Attribute = attribute; + } + + [NotNull] + public string Attribute { get; } + } + + [AttributeUsage(AttributeTargets.Property)] + public sealed class AspTypePropertyAttribute : Attribute + { + public AspTypePropertyAttribute(bool createConstructorReferences) + { + CreateConstructorReferences = createConstructorReferences; + } + + public bool CreateConstructorReferences { get; } + } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public sealed class RazorImportNamespaceAttribute : Attribute + { + public RazorImportNamespaceAttribute([NotNull] string name) + { + Name = name; + } + + [NotNull] + public string Name { get; } + } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public sealed class RazorInjectionAttribute : Attribute + { + public RazorInjectionAttribute([NotNull] string type, [NotNull] string fieldName) + { + Type = type; + FieldName = fieldName; + } + + [NotNull] + public string Type { get; } + + [NotNull] + public string FieldName { get; } + } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public sealed class RazorDirectiveAttribute : Attribute + { + public RazorDirectiveAttribute([NotNull] string directive) + { + Directive = directive; + } + + [NotNull] + public string Directive { get; } + } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public sealed class RazorPageBaseTypeAttribute : Attribute + { + public RazorPageBaseTypeAttribute([NotNull] string baseType) + { + BaseType = baseType; + } + + public RazorPageBaseTypeAttribute([NotNull] string baseType, string pageName) + { + BaseType = baseType; + PageName = pageName; + } + + [NotNull] + public string BaseType { get; } + + [CanBeNull] + public string PageName { get; } + } + + [AttributeUsage(AttributeTargets.Method)] + public sealed class RazorHelperCommonAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Property)] + public sealed class RazorLayoutAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Method)] + public sealed class RazorWriteLiteralMethodAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Method)] + public sealed class RazorWriteMethodAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class RazorWriteMethodParameterAttribute : Attribute + { + } } \ No newline at end of file diff --git a/src/Artemis.Core/Properties/AssemblyInfo.cs b/src/Artemis.Core/Properties/AssemblyInfo.cs index c5012b6bd..a31a0bfab 100644 --- a/src/Artemis.Core/Properties/AssemblyInfo.cs +++ b/src/Artemis.Core/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ -using System.Reflection; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from @@ -7,4 +6,4 @@ using System.Runtime.InteropServices; [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("9b811f9b-86b9-4771-87af-72bae7078a36")] +[assembly: Guid("9b811f9b-86b9-4771-87af-72bae7078a36")] \ No newline at end of file diff --git a/src/Artemis.Core/Services/CoreService.cs b/src/Artemis.Core/Services/CoreService.cs index 6a07ae5b1..51e92312c 100644 --- a/src/Artemis.Core/Services/CoreService.cs +++ b/src/Artemis.Core/Services/CoreService.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Threading.Tasks; using Artemis.Core.Events; using Artemis.Core.Exceptions; using Artemis.Core.JsonConverters; @@ -10,7 +9,6 @@ using Artemis.Core.Plugins.Models; using Artemis.Core.Services.Interfaces; using Artemis.Core.Services.Storage.Interfaces; using Artemis.Storage; -using Artemis.Storage.Migrations.Interfaces; using Newtonsoft.Json; using RGB.NET.Core; using Serilog; @@ -29,11 +27,11 @@ namespace Artemis.Core.Services private readonly IProfileService _profileService; private readonly IRgbService _rgbService; private readonly ISurfaceService _surfaceService; + private readonly PluginSetting _loggingLevel; private List _modules; - private PluginSetting _loggingLevel; // ReSharper disable once UnusedParameter.Local - Storage migration service is injected early to ensure it runs before anything else - internal CoreService(ILogger logger, StorageMigrationService _, ISettingsService settingsService, IPluginService pluginService, + internal CoreService(ILogger logger, StorageMigrationService _, ISettingsService settingsService, IPluginService pluginService, IRgbService rgbService, ISurfaceService surfaceService, IProfileService profileService) { _logger = logger; @@ -51,7 +49,7 @@ namespace Artemis.Core.Services _pluginService.PluginEnabled += (sender, args) => _modules = _pluginService.GetPluginsOfType(); _pluginService.PluginDisabled += (sender, args) => _modules = _pluginService.GetPluginsOfType(); - + ConfigureJsonConvert(); } @@ -66,24 +64,6 @@ namespace Artemis.Core.Services public bool IsInitialized { get; set; } - protected virtual void OnFrameRendering(FrameRenderingEventArgs e) - { - FrameRendering?.Invoke(this, e); - } - - protected virtual void OnFrameRendered(FrameRenderedEventArgs e) - { - FrameRendered?.Invoke(this, e); - } - - private void ConfigureJsonConvert() - { - JsonConvert.DefaultSettings = () => new JsonSerializerSettings - { - Converters = new List {new SKColorConverter()} - }; - } - public void Initialize() { if (IsInitialized) @@ -107,6 +87,24 @@ namespace Artemis.Core.Services OnInitialized(); } + protected virtual void OnFrameRendering(FrameRenderingEventArgs e) + { + FrameRendering?.Invoke(this, e); + } + + protected virtual void OnFrameRendered(FrameRenderedEventArgs e) + { + FrameRendered?.Invoke(this, e); + } + + private void ConfigureJsonConvert() + { + JsonConvert.DefaultSettings = () => new JsonSerializerSettings + { + Converters = new List {new SKColorConverter()} + }; + } + private void ApplyLoggingLevel() { _logger.Information("Setting logging level to {loggingLevel}", _loggingLevel.Value); diff --git a/src/Artemis.Core/Services/Interfaces/ILayerService.cs b/src/Artemis.Core/Services/Interfaces/ILayerService.cs index f30c1ded8..1cdc7fc4f 100644 --- a/src/Artemis.Core/Services/Interfaces/ILayerService.cs +++ b/src/Artemis.Core/Services/Interfaces/ILayerService.cs @@ -3,7 +3,6 @@ using Artemis.Core.Plugins.LayerBrush; using Artemis.Core.Plugins.LayerBrush.Abstract; using Artemis.Core.Plugins.LayerEffect; using Artemis.Core.Plugins.LayerEffect.Abstract; -using Artemis.Storage.Entities.Profile; namespace Artemis.Core.Services.Interfaces { diff --git a/src/Artemis.Core/Services/Interfaces/IRgbService.cs b/src/Artemis.Core/Services/Interfaces/IRgbService.cs index e7304a8c1..7f5ece69a 100644 --- a/src/Artemis.Core/Services/Interfaces/IRgbService.cs +++ b/src/Artemis.Core/Services/Interfaces/IRgbService.cs @@ -35,7 +35,7 @@ namespace Artemis.Core.Services.Interfaces ///
/// void AddDeviceProvider(IRGBDeviceProvider deviceProvider); - + void Dispose(); /// diff --git a/src/Artemis.Core/Services/LayerService.cs b/src/Artemis.Core/Services/LayerService.cs index 21a8f7586..2c844a6a0 100644 --- a/src/Artemis.Core/Services/LayerService.cs +++ b/src/Artemis.Core/Services/LayerService.cs @@ -1,18 +1,12 @@ -using System.Collections.Generic; -using System.Linq; -using System.Windows.Documents; +using System.Linq; using Artemis.Core.Exceptions; using Artemis.Core.Models.Profile; using Artemis.Core.Plugins.Abstract; -using Artemis.Core.Plugins.LayerBrush; using Artemis.Core.Plugins.LayerBrush.Abstract; using Artemis.Core.Plugins.LayerEffect; using Artemis.Core.Plugins.LayerEffect.Abstract; using Artemis.Core.Services.Interfaces; -using Artemis.Storage.Entities.Profile; using Ninject; -using Ninject.Injection; -using Ninject.Parameters; using Serilog; namespace Artemis.Core.Services @@ -63,7 +57,7 @@ namespace Artemis.Core.Services if (descriptor == null) return null; - + var brush = (BaseLayerBrush) _kernel.Get(descriptor.LayerBrushType); brush.Layer = layer; brush.Descriptor = descriptor; diff --git a/src/Artemis.Core/Services/PluginService.cs b/src/Artemis.Core/Services/PluginService.cs index 66728653d..9ef9dd508 100644 --- a/src/Artemis.Core/Services/PluginService.cs +++ b/src/Artemis.Core/Services/PluginService.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; -using System.Windows; using Artemis.Core.Events; using Artemis.Core.Exceptions; using Artemis.Core.Extensions; diff --git a/src/Artemis.Core/Services/Storage/ProfileService.cs b/src/Artemis.Core/Services/Storage/ProfileService.cs index d06ab2951..459c53b78 100644 --- a/src/Artemis.Core/Services/Storage/ProfileService.cs +++ b/src/Artemis.Core/Services/Storage/ProfileService.cs @@ -4,7 +4,6 @@ using Artemis.Core.Events; using Artemis.Core.Models.Profile; using Artemis.Core.Models.Surface; using Artemis.Core.Plugins.Abstract; -using Artemis.Core.Plugins.LayerBrush; using Artemis.Core.Services.Interfaces; using Artemis.Core.Services.Storage.Interfaces; using Artemis.Storage.Entities.Profile; @@ -214,9 +213,7 @@ namespace Artemis.Core.Services.Storage private void OnPluginLoaded(object sender, PluginEventArgs e) { if (e.PluginInfo.Instance is LayerBrushProvider) - { ActiveProfilesInstantiateProfileLayerBrushes(); - } else if (e.PluginInfo.Instance is ProfileModule profileModule) { var activeProfile = GetActiveProfile(profileModule); diff --git a/src/Artemis.Core/Services/Storage/SurfaceService.cs b/src/Artemis.Core/Services/Storage/SurfaceService.cs index f394f7068..dc4dc2145 100644 --- a/src/Artemis.Core/Services/Storage/SurfaceService.cs +++ b/src/Artemis.Core/Services/Storage/SurfaceService.cs @@ -95,7 +95,6 @@ namespace Artemis.Core.Services.Storage // Update the RGB service's graphics decorator to work with the new surface entity _rgbService.UpdateSurfaceLedGroup(); OnActiveSurfaceConfigurationChanged(new SurfaceConfigurationEventArgs(ActiveSurface)); - } public void UpdateSurfaceConfiguration(ArtemisSurface surface, bool includeDevices) diff --git a/src/Artemis.Storage/Entities/Plugins/PluginSettingEntity.cs b/src/Artemis.Storage/Entities/Plugins/PluginSettingEntity.cs index db0712c7b..ae4827426 100644 --- a/src/Artemis.Storage/Entities/Plugins/PluginSettingEntity.cs +++ b/src/Artemis.Storage/Entities/Plugins/PluginSettingEntity.cs @@ -3,7 +3,7 @@ namespace Artemis.Storage.Entities.Plugins { /// - /// Represents the setting of a plugin, a plugin can have multiple settings + /// Represents the setting of a plugin, a plugin can have multiple settings /// public class PluginSettingEntity { diff --git a/src/Artemis.Storage/Entities/Profile/LayerEntity.cs b/src/Artemis.Storage/Entities/Profile/LayerEntity.cs index f721480c2..891e651d6 100644 --- a/src/Artemis.Storage/Entities/Profile/LayerEntity.cs +++ b/src/Artemis.Storage/Entities/Profile/LayerEntity.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text.Json.Serialization; using LiteDB; namespace Artemis.Storage.Entities.Profile @@ -33,6 +32,4 @@ namespace Artemis.Storage.Entities.Profile public Guid ProfileId { get; set; } } - - } \ No newline at end of file diff --git a/src/Artemis.Storage/Entities/Profile/PropertyEntity.cs b/src/Artemis.Storage/Entities/Profile/PropertyEntity.cs index 82ef13ecc..de95b56b8 100644 --- a/src/Artemis.Storage/Entities/Profile/PropertyEntity.cs +++ b/src/Artemis.Storage/Entities/Profile/PropertyEntity.cs @@ -18,7 +18,7 @@ namespace Artemis.Storage.Entities.Profile public List KeyframeEntities { get; set; } } - + public class KeyframeEntity { public TimeSpan Position { get; set; } diff --git a/src/Artemis.Storage/Entities/Surface/DeviceEntity.cs b/src/Artemis.Storage/Entities/Surface/DeviceEntity.cs index 370aa8e45..6bc93a3ad 100644 --- a/src/Artemis.Storage/Entities/Surface/DeviceEntity.cs +++ b/src/Artemis.Storage/Entities/Surface/DeviceEntity.cs @@ -1,6 +1,4 @@ -using System; - -namespace Artemis.Storage.Entities.Surface +namespace Artemis.Storage.Entities.Surface { public class DeviceEntity { diff --git a/src/Artemis.Storage/Migrations/AttributeBasedPropertiesMigration.cs b/src/Artemis.Storage/Migrations/AttributeBasedPropertiesMigration.cs index 6fa31eb10..32c51984e 100644 --- a/src/Artemis.Storage/Migrations/AttributeBasedPropertiesMigration.cs +++ b/src/Artemis.Storage/Migrations/AttributeBasedPropertiesMigration.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Artemis.Storage.Entities.Profile; -using Artemis.Storage.Migrations.Interfaces; +using Artemis.Storage.Migrations.Interfaces; using LiteDB; namespace Artemis.Storage.Migrations @@ -10,10 +6,11 @@ namespace Artemis.Storage.Migrations public class AttributeBasedPropertiesMigration : IStorageMigration { public int UserVersion => 1; + public void Apply(LiteRepository repository) { if (repository.Database.CollectionExists("ProfileEntity")) repository.Database.DropCollection("ProfileEntity"); } } -} +} \ No newline at end of file diff --git a/src/Artemis.Storage/StorageMigrationService.cs b/src/Artemis.Storage/StorageMigrationService.cs index 35d642e09..d0105ea4c 100644 --- a/src/Artemis.Storage/StorageMigrationService.cs +++ b/src/Artemis.Storage/StorageMigrationService.cs @@ -9,8 +9,8 @@ namespace Artemis.Storage public class StorageMigrationService { private readonly ILogger _logger; - private readonly LiteRepository _repository; private readonly List _migrations; + private readonly LiteRepository _repository; public StorageMigrationService(ILogger logger, LiteRepository repository, List migrations) { diff --git a/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs b/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs index da3fdb39f..ea639c85c 100644 --- a/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs +++ b/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs @@ -8,7 +8,6 @@ using System.Windows.Media; using System.Windows.Media.Imaging; using Artemis.Core.Models.Surface; using RGB.NET.Core; -using Stylet; namespace Artemis.UI.Shared.Controls { @@ -37,19 +36,6 @@ namespace Artemis.UI.Shared.Controls Unloaded += (sender, args) => SubscribeToUpdate(false); } - private void SubscribeToUpdate(bool subscribe) - { - if (_subscribed == subscribe) - return; - - if (subscribe) - RGBSurface.Instance.Updated += RgbSurfaceOnUpdated; - else - RGBSurface.Instance.Updated -= RgbSurfaceOnUpdated; - - _subscribed = subscribe; - } - public ArtemisDevice Device { get => (ArtemisDevice) GetValue(DeviceProperty); @@ -99,6 +85,19 @@ namespace Artemis.UI.Shared.Controls drawingContext.DrawDrawing(_backingStore); } + private void SubscribeToUpdate(bool subscribe) + { + if (_subscribed == subscribe) + return; + + if (subscribe) + RGBSurface.Instance.Updated += RgbSurfaceOnUpdated; + else + RGBSurface.Instance.Updated -= RgbSurfaceOnUpdated; + + _subscribed = subscribe; + } + private static void DevicePropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) { var deviceVisualizer = (DeviceVisualizer) d; @@ -180,7 +179,7 @@ namespace Artemis.UI.Shared.Controls foreach (var deviceVisualizerLed in _deviceVisualizerLeds) deviceVisualizerLed.RenderColor(drawingContext, false); } - + drawingContext.Close(); } } diff --git a/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs b/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs index ca1bf2d31..79470d567 100644 --- a/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs +++ b/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs @@ -34,6 +34,41 @@ namespace Artemis.UI.Shared.Controls public Geometry DisplayGeometry { get; private set; } + public void RenderColor(DrawingContext drawingContext, bool isDimmed) + { + if (DisplayGeometry == null) + return; + + var r = Led.RgbLed.Color.GetR(); + var g = Led.RgbLed.Color.GetG(); + var b = Led.RgbLed.Color.GetB(); + + drawingContext.DrawRectangle(isDimmed + ? new SolidColorBrush(Color.FromArgb(100, r, g, b)) + : new SolidColorBrush(Color.FromRgb(r, g, b)), null, LedRect); + } + + public void RenderImage(DrawingContext drawingContext) + { + if (LedImage == null) + return; + + drawingContext.DrawImage(LedImage, LedRect); + } + + public void RenderOpacityMask(DrawingContext drawingContext) + { + if (DisplayGeometry == null) + return; + + var fillBrush = new SolidColorBrush(Color.FromArgb(100, 255, 255, 255)); + fillBrush.Freeze(); + var penBrush = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255)); + penBrush.Freeze(); + + drawingContext.DrawGeometry(fillBrush, new Pen(penBrush, 1), DisplayGeometry); + } + private void CreateLedGeometry() { // The minimum required size for geometry to be created @@ -105,40 +140,5 @@ namespace Artemis.UI.Shared.Controls CreateRectangleGeometry(); } } - - public void RenderColor(DrawingContext drawingContext, bool isDimmed) - { - if (DisplayGeometry == null) - return; - - var r = Led.RgbLed.Color.GetR(); - var g = Led.RgbLed.Color.GetG(); - var b = Led.RgbLed.Color.GetB(); - - drawingContext.DrawRectangle(isDimmed - ? new SolidColorBrush(Color.FromArgb(100, r, g, b)) - : new SolidColorBrush(Color.FromRgb(r, g, b)), null, LedRect); - } - - public void RenderImage(DrawingContext drawingContext) - { - if (LedImage == null) - return; - - drawingContext.DrawImage(LedImage, LedRect); - } - - public void RenderOpacityMask(DrawingContext drawingContext) - { - if (DisplayGeometry == null) - return; - - var fillBrush = new SolidColorBrush(Color.FromArgb(100, 255, 255, 255)); - fillBrush.Freeze(); - var penBrush = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255)); - penBrush.Freeze(); - - drawingContext.DrawGeometry(fillBrush, new Pen(penBrush, 1), DisplayGeometry); - } } } \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Controls/DraggableFloat.xaml.cs b/src/Artemis.UI.Shared/Controls/DraggableFloat.xaml.cs index c9adfb58d..3e5ec23a6 100644 --- a/src/Artemis.UI.Shared/Controls/DraggableFloat.xaml.cs +++ b/src/Artemis.UI.Shared/Controls/DraggableFloat.xaml.cs @@ -24,13 +24,11 @@ namespace Artemis.UI.Shared.Controls typeof(RoutedPropertyChangedEventHandler), typeof(DraggableFloat)); - public event EventHandler DragStarted; - public event EventHandler DragEnded; + private bool _calledDragStarted; private bool _inCallback; private Point _mouseDragStartPoint; private float _startValue; - private bool _calledDragStarted; public DraggableFloat() { @@ -51,11 +49,24 @@ namespace Artemis.UI.Shared.Controls public event PropertyChangedEventHandler PropertyChanged; + public event EventHandler DragStarted; + public event EventHandler DragEnded; + protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } + protected virtual void OnDragStarted() + { + DragStarted?.Invoke(this, EventArgs.Empty); + } + + protected virtual void OnDragEnded() + { + DragEnded?.Invoke(this, EventArgs.Empty); + } + private static void FloatPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) { var draggableFloat = (DraggableFloat) d; @@ -149,15 +160,5 @@ namespace Artemis.UI.Shared.Controls { return Math.Floor(amountToRound / nearstOf + fairness) * nearstOf; } - - protected virtual void OnDragStarted() - { - DragStarted?.Invoke(this, EventArgs.Empty); - } - - protected virtual void OnDragEnded() - { - DragEnded?.Invoke(this, EventArgs.Empty); - } } } \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Controls/GradientPicker.xaml b/src/Artemis.UI.Shared/Controls/GradientPicker.xaml index 43bdc3b20..d98c20444 100644 --- a/src/Artemis.UI.Shared/Controls/GradientPicker.xaml +++ b/src/Artemis.UI.Shared/Controls/GradientPicker.xaml @@ -37,9 +37,10 @@ Background="{StaticResource Checkerboard}"> - + diff --git a/src/Artemis.UI.Shared/Controls/GradientPicker.xaml.cs b/src/Artemis.UI.Shared/Controls/GradientPicker.xaml.cs index 198c77110..2ff262c80 100644 --- a/src/Artemis.UI.Shared/Controls/GradientPicker.xaml.cs +++ b/src/Artemis.UI.Shared/Controls/GradientPicker.xaml.cs @@ -1,11 +1,9 @@ using System; using System.ComponentModel; using System.Runtime.CompilerServices; -using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; -using Artemis.Core.Models.Profile; using Artemis.Core.Models.Profile.Colors; using Artemis.UI.Shared.Annotations; using Artemis.UI.Shared.Services.Interfaces; @@ -21,9 +19,6 @@ namespace Artemis.UI.Shared.Controls private static IGradientPickerService _gradientPickerService; private bool _inCallback; - public event EventHandler DialogOpened; - public event EventHandler DialogClosed; - public GradientPicker() { InitializeComponent(); @@ -63,12 +58,25 @@ namespace Artemis.UI.Shared.Controls public event PropertyChangedEventHandler PropertyChanged; + public event EventHandler DialogOpened; + public event EventHandler DialogClosed; + [NotifyPropertyChangedInvocator] protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } + protected virtual void OnDialogOpened() + { + DialogOpened?.Invoke(this, EventArgs.Empty); + } + + protected virtual void OnDialogClosed() + { + DialogClosed?.Invoke(this, EventArgs.Empty); + } + private static void ColorGradientPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) { var gradientPicker = (GradientPicker) d; @@ -102,15 +110,5 @@ namespace Artemis.UI.Shared.Controls EventManager.RegisterRoutedEvent(nameof(ColorGradient), RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler), typeof(GradientPicker)); #endregion - - protected virtual void OnDialogOpened() - { - DialogOpened?.Invoke(this, EventArgs.Empty); - } - - protected virtual void OnDialogClosed() - { - DialogClosed?.Invoke(this, EventArgs.Empty); - } } } \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Converters/ColorGradientToGradientStopsConverter.cs b/src/Artemis.UI.Shared/Converters/ColorGradientToGradientStopsConverter.cs index 67618268a..0b42719f2 100644 --- a/src/Artemis.UI.Shared/Converters/ColorGradientToGradientStopsConverter.cs +++ b/src/Artemis.UI.Shared/Converters/ColorGradientToGradientStopsConverter.cs @@ -3,7 +3,6 @@ using System.Globalization; using System.Linq; using System.Windows.Data; using System.Windows.Media; -using Artemis.Core.Models.Profile; using Artemis.Core.Models.Profile.Colors; using SkiaSharp; using Stylet; diff --git a/src/Artemis.UI.Shared/Ninject/Factories/IVMFactory.cs b/src/Artemis.UI.Shared/Ninject/Factories/IVMFactory.cs index 44ba4b651..b04a72929 100644 --- a/src/Artemis.UI.Shared/Ninject/Factories/IVMFactory.cs +++ b/src/Artemis.UI.Shared/Ninject/Factories/IVMFactory.cs @@ -1,5 +1,4 @@ -using Artemis.Core.Models.Profile; -using Artemis.Core.Models.Profile.Colors; +using Artemis.Core.Models.Profile.Colors; using Artemis.UI.Shared.Screens.GradientEditor; namespace Artemis.UI.Shared.Ninject.Factories diff --git a/src/Artemis.UI.Shared/Properties/Annotations.cs b/src/Artemis.UI.Shared/Properties/Annotations.cs index 77d9075d1..0081834f4 100644 --- a/src/Artemis.UI.Shared/Properties/Annotations.cs +++ b/src/Artemis.UI.Shared/Properties/Annotations.cs @@ -21,6 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ using System; + // ReSharper disable InheritdocConsiderUsage #pragma warning disable 1591 @@ -33,1131 +34,1349 @@ using System; namespace Artemis.UI.Shared.Annotations { - /// - /// Indicates that the value of the marked element could be null sometimes, - /// so checking for null is required before its usage. - /// - /// - /// [CanBeNull] object Test() => null; - /// - /// void UseTest() { - /// var p = Test(); - /// var s = p.ToString(); // Warning: Possible 'System.NullReferenceException' - /// } - /// - [AttributeUsage( - AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | - AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event | - AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)] - public sealed class CanBeNullAttribute : Attribute { } - - /// - /// Indicates that the value of the marked element can never be null. - /// - /// - /// [NotNull] object Foo() { - /// return null; // Warning: Possible 'null' assignment - /// } - /// - [AttributeUsage( - AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | - AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event | - AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)] - public sealed class NotNullAttribute : Attribute { } - - /// - /// Can be applied to symbols of types derived from IEnumerable as well as to symbols of Task - /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property - /// or of the Lazy.Value property can never be null. - /// - /// - /// public void Foo([ItemNotNull]List<string> books) - /// { - /// foreach (var book in books) { - /// if (book != null) // Warning: Expression is always true - /// Console.WriteLine(book.ToUpper()); - /// } - /// } - /// - [AttributeUsage( - AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | - AttributeTargets.Delegate | AttributeTargets.Field)] - public sealed class ItemNotNullAttribute : Attribute { } - - /// - /// Can be applied to symbols of types derived from IEnumerable as well as to symbols of Task - /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property - /// or of the Lazy.Value property can be null. - /// - /// - /// public void Foo([ItemCanBeNull]List<string> books) - /// { - /// foreach (var book in books) - /// { - /// // Warning: Possible 'System.NullReferenceException' - /// Console.WriteLine(book.ToUpper()); - /// } - /// } - /// - [AttributeUsage( - AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | - AttributeTargets.Delegate | AttributeTargets.Field)] - public sealed class ItemCanBeNullAttribute : Attribute { } - - /// - /// Indicates that the marked method builds string by the format pattern and (optional) arguments. - /// The parameter, which contains the format string, should be given in constructor. The format string - /// should be in -like form. - /// - /// - /// [StringFormatMethod("message")] - /// void ShowError(string message, params object[] args) { /* do something */ } - /// - /// void Foo() { - /// ShowError("Failed: {0}"); // Warning: Non-existing argument in format string - /// } - /// - [AttributeUsage( - AttributeTargets.Constructor | AttributeTargets.Method | - AttributeTargets.Property | AttributeTargets.Delegate)] - public sealed class StringFormatMethodAttribute : Attribute - { - /// - /// Specifies which parameter of an annotated method should be treated as the format string - /// - public StringFormatMethodAttribute([NotNull] string formatParameterName) - { - FormatParameterName = formatParameterName; - } - - [NotNull] public string FormatParameterName { get; } - } - - /// - /// Use this annotation to specify a type that contains static or const fields - /// with values for the annotated property/field/parameter. - /// The specified type will be used to improve completion suggestions. - /// - /// - /// namespace TestNamespace - /// { - /// public class Constants - /// { - /// public static int INT_CONST = 1; - /// public const string STRING_CONST = "1"; - /// } - /// - /// public class Class1 - /// { - /// [ValueProvider("TestNamespace.Constants")] public int myField; - /// public void Foo([ValueProvider("TestNamespace.Constants")] string str) { } - /// - /// public void Test() - /// { - /// Foo(/*try completion here*/);// - /// myField = /*try completion here*/ - /// } - /// } - /// } - /// - [AttributeUsage( - AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field, - AllowMultiple = true)] - public sealed class ValueProviderAttribute : Attribute - { - public ValueProviderAttribute([NotNull] string name) - { - Name = name; - } - - [NotNull] public string Name { get; } - } - - /// - /// Indicates that the function argument should be a string literal and match one - /// of the parameters of the caller function. For example, ReSharper annotates - /// the parameter of . - /// - /// - /// void Foo(string param) { - /// if (param == null) - /// throw new ArgumentNullException("par"); // Warning: Cannot resolve symbol - /// } - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class InvokerParameterNameAttribute : Attribute { } - - /// - /// Indicates that the method is contained in a type that implements - /// System.ComponentModel.INotifyPropertyChanged interface and this method - /// is used to notify that some property value changed. - /// - /// - /// The method should be non-static and conform to one of the supported signatures: - /// - /// NotifyChanged(string) - /// NotifyChanged(params string[]) - /// NotifyChanged{T}(Expression{Func{T}}) - /// NotifyChanged{T,U}(Expression{Func{T,U}}) - /// SetProperty{T}(ref T, T, string) - /// - /// - /// - /// public class Foo : INotifyPropertyChanged { - /// public event PropertyChangedEventHandler PropertyChanged; - /// - /// [NotifyPropertyChangedInvocator] - /// protected virtual void NotifyChanged(string propertyName) { ... } - /// - /// string _name; - /// - /// public string Name { - /// get { return _name; } - /// set { _name = value; NotifyChanged("LastName"); /* Warning */ } - /// } - /// } - /// - /// Examples of generated notifications: - /// - /// NotifyChanged("Property") - /// NotifyChanged(() => Property) - /// NotifyChanged((VM x) => x.Property) - /// SetProperty(ref myField, value, "Property") - /// - /// - [AttributeUsage(AttributeTargets.Method)] - public sealed class NotifyPropertyChangedInvocatorAttribute : Attribute - { - public NotifyPropertyChangedInvocatorAttribute() { } - public NotifyPropertyChangedInvocatorAttribute([NotNull] string parameterName) - { - ParameterName = parameterName; - } - - [CanBeNull] public string ParameterName { get; } - } - - /// - /// Describes dependency between method input and output. - /// - /// - ///

Function Definition Table syntax:

- /// - /// FDT ::= FDTRow [;FDTRow]* - /// FDTRow ::= Input => Output | Output <= Input - /// Input ::= ParameterName: Value [, Input]* - /// Output ::= [ParameterName: Value]* {halt|stop|void|nothing|Value} - /// Value ::= true | false | null | notnull | canbenull - /// - /// If the method has a single input parameter, its name could be omitted.
- /// Using halt (or void/nothing, which is the same) for the method output - /// means that the method doesn't return normally (throws or terminates the process).
- /// Value canbenull is only applicable for output parameters.
- /// You can use multiple [ContractAnnotation] for each FDT row, or use single attribute - /// with rows separated by semicolon. There is no notion of order rows, all rows are checked - /// for applicability and applied per each program state tracked by the analysis engine.
- ///
- /// - /// - /// [ContractAnnotation("=> halt")] - /// public void TerminationMethod() - /// - /// - /// [ContractAnnotation("null <= param:null")] // reverse condition syntax - /// public string GetName(string surname) - /// - /// - /// [ContractAnnotation("s:null => true")] - /// public bool IsNullOrEmpty(string s) // string.IsNullOrEmpty() - /// - /// - /// // A method that returns null if the parameter is null, - /// // and not null if the parameter is not null - /// [ContractAnnotation("null => null; notnull => notnull")] - /// public object Transform(object data) - /// - /// - /// [ContractAnnotation("=> true, result: notnull; => false, result: null")] - /// public bool TryParse(string s, out Person result) - /// - /// - [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] - public sealed class ContractAnnotationAttribute : Attribute - { - public ContractAnnotationAttribute([NotNull] string contract) - : this(contract, false) { } - - public ContractAnnotationAttribute([NotNull] string contract, bool forceFullStates) - { - Contract = contract; - ForceFullStates = forceFullStates; - } - - [NotNull] public string Contract { get; } - - public bool ForceFullStates { get; } - } - - /// - /// Indicates whether the marked element should be localized. - /// - /// - /// [LocalizationRequiredAttribute(true)] - /// class Foo { - /// string str = "my string"; // Warning: Localizable string - /// } - /// - [AttributeUsage(AttributeTargets.All)] - public sealed class LocalizationRequiredAttribute : Attribute - { - public LocalizationRequiredAttribute() : this(true) { } - - public LocalizationRequiredAttribute(bool required) - { - Required = required; - } - - public bool Required { get; } - } - - /// - /// Indicates that the value of the marked type (or its derivatives) - /// cannot be compared using '==' or '!=' operators and Equals() - /// should be used instead. However, using '==' or '!=' for comparison - /// with null is always permitted. - /// - /// - /// [CannotApplyEqualityOperator] - /// class NoEquality { } - /// - /// class UsesNoEquality { - /// void Test() { - /// var ca1 = new NoEquality(); - /// var ca2 = new NoEquality(); - /// if (ca1 != null) { // OK - /// bool condition = ca1 == ca2; // Warning - /// } - /// } - /// } - /// - [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct)] - public sealed class CannotApplyEqualityOperatorAttribute : Attribute { } - - /// - /// When applied to a target attribute, specifies a requirement for any type marked - /// with the target attribute to implement or inherit specific type or types. - /// - /// - /// [BaseTypeRequired(typeof(IComponent)] // Specify requirement - /// class ComponentAttribute : Attribute { } - /// - /// [Component] // ComponentAttribute requires implementing IComponent interface - /// class MyComponent : IComponent { } - /// - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] - [BaseTypeRequired(typeof(Attribute))] - public sealed class BaseTypeRequiredAttribute : Attribute - { - public BaseTypeRequiredAttribute([NotNull] Type baseType) - { - BaseType = baseType; - } - - [NotNull] public Type BaseType { get; } - } - - /// - /// Indicates that the marked symbol is used implicitly (e.g. via reflection, in external library), - /// so this symbol will not be reported as unused (as well as by other usage inspections). - /// - [AttributeUsage(AttributeTargets.All, Inherited = false)] - public sealed class UsedImplicitlyAttribute : Attribute - { - public UsedImplicitlyAttribute() - : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { } - - public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags) - : this(useKindFlags, ImplicitUseTargetFlags.Default) { } - - public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags) - : this(ImplicitUseKindFlags.Default, targetFlags) { } - - public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) - { - UseKindFlags = useKindFlags; - TargetFlags = targetFlags; - } - - public ImplicitUseKindFlags UseKindFlags { get; } - - public ImplicitUseTargetFlags TargetFlags { get; } - } - - /// - /// Can be applied to attributes, type parameters, and parameters of a type assignable from . - /// When applied to an attribute, the decorated attribute behaves the same as . - /// When applied to a type parameter or to a parameter of type , indicates that the corresponding type - /// is used implicitly. - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.GenericParameter | AttributeTargets.Parameter)] - public sealed class MeansImplicitUseAttribute : Attribute - { - public MeansImplicitUseAttribute() - : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { } - - public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags) - : this(useKindFlags, ImplicitUseTargetFlags.Default) { } - - public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags) - : this(ImplicitUseKindFlags.Default, targetFlags) { } - - public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) - { - UseKindFlags = useKindFlags; - TargetFlags = targetFlags; - } - - [UsedImplicitly] public ImplicitUseKindFlags UseKindFlags { get; } - - [UsedImplicitly] public ImplicitUseTargetFlags TargetFlags { get; } - } - - /// - /// Specify the details of implicitly used symbol when it is marked - /// with or . - /// - [Flags] - public enum ImplicitUseKindFlags - { - Default = Access | Assign | InstantiatedWithFixedConstructorSignature, - /// Only entity marked with attribute considered used. - Access = 1, - /// Indicates implicit assignment to a member. - Assign = 2, /// - /// Indicates implicit instantiation of a type with fixed constructor signature. - /// That means any unused constructor parameters won't be reported as such. + /// Indicates that the value of the marked element could be null sometimes, + /// so checking for null is required before its usage. /// - InstantiatedWithFixedConstructorSignature = 4, - /// Indicates implicit instantiation of a type. - InstantiatedNoFixedConstructorSignature = 8, - } - - /// - /// Specify what is considered to be used implicitly when marked - /// with or . - /// - [Flags] - public enum ImplicitUseTargetFlags - { - Default = Itself, - Itself = 1, - /// Members of entity marked with attribute are considered used. - Members = 2, - /// Entity marked with attribute and all its members considered used. - WithMembers = Itself | Members - } - - /// - /// This attribute is intended to mark publicly available API - /// which should not be removed and so is treated as used. - /// - [MeansImplicitUse(ImplicitUseTargetFlags.WithMembers)] - [AttributeUsage(AttributeTargets.All, Inherited = false)] - public sealed class PublicAPIAttribute : Attribute - { - public PublicAPIAttribute() { } - - public PublicAPIAttribute([NotNull] string comment) + /// + /// + /// [CanBeNull] object Test() => null; + /// + /// void UseTest() { + /// var p = Test(); + /// var s = p.ToString(); // Warning: Possible 'System.NullReferenceException' + /// } + /// + /// + [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | + AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event | + AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)] + public sealed class CanBeNullAttribute : Attribute { - Comment = comment; } - [CanBeNull] public string Comment { get; } - } - - /// - /// Tells code analysis engine if the parameter is completely handled when the invoked method is on stack. - /// If the parameter is a delegate, indicates that delegate is executed while the method is executed. - /// If the parameter is an enumerable, indicates that it is enumerated while the method is executed. - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class InstantHandleAttribute : Attribute { } - - /// - /// Indicates that a method does not make any observable state changes. - /// The same as System.Diagnostics.Contracts.PureAttribute. - /// - /// - /// [Pure] int Multiply(int x, int y) => x * y; - /// - /// void M() { - /// Multiply(123, 42); // Waring: Return value of pure method is not used - /// } - /// - [AttributeUsage(AttributeTargets.Method)] - public sealed class PureAttribute : Attribute { } - - /// - /// Indicates that the return value of the method invocation must be used. - /// - /// - /// Methods decorated with this attribute (in contrast to pure methods) might change state, - /// but make no sense without using their return value.
- /// Similarly to , this attribute - /// will help detecting usages of the method when the return value in not used. - /// Additionally, you can optionally specify a custom message, which will be used when showing warnings, e.g. - /// [MustUseReturnValue("Use the return value to...")]. - ///
- [AttributeUsage(AttributeTargets.Method)] - public sealed class MustUseReturnValueAttribute : Attribute - { - public MustUseReturnValueAttribute() { } - - public MustUseReturnValueAttribute([NotNull] string justification) - { - Justification = justification; - } - - [CanBeNull] public string Justification { get; } - } - - /// - /// Indicates the type member or parameter of some type, that should be used instead of all other ways - /// to get the value of that type. This annotation is useful when you have some "context" value evaluated - /// and stored somewhere, meaning that all other ways to get this value must be consolidated with existing one. - /// - /// - /// class Foo { - /// [ProvidesContext] IBarService _barService = ...; - /// - /// void ProcessNode(INode node) { - /// DoSomething(node, node.GetGlobalServices().Bar); - /// // ^ Warning: use value of '_barService' field - /// } - /// } - /// - [AttributeUsage( - AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.Method | - AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.GenericParameter)] - public sealed class ProvidesContextAttribute : Attribute { } - - /// - /// Indicates that a parameter is a path to a file or a folder within a web project. - /// Path can be relative or absolute, starting from web root (~). - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class PathReferenceAttribute : Attribute - { - public PathReferenceAttribute() { } - - public PathReferenceAttribute([NotNull, PathReference] string basePath) - { - BasePath = basePath; - } - - [CanBeNull] public string BasePath { get; } - } - - /// - /// An extension method marked with this attribute is processed by code completion - /// as a 'Source Template'. When the extension method is completed over some expression, its source code - /// is automatically expanded like a template at call site. - /// - /// - /// Template method body can contain valid source code and/or special comments starting with '$'. - /// Text inside these comments is added as source code when the template is applied. Template parameters - /// can be used either as additional method parameters or as identifiers wrapped in two '$' signs. - /// Use the attribute to specify macros for parameters. - /// - /// - /// In this example, the 'forEach' method is a source template available over all values - /// of enumerable types, producing ordinary C# 'foreach' statement and placing caret inside block: - /// - /// [SourceTemplate] - /// public static void forEach<T>(this IEnumerable<T> xs) { - /// foreach (var x in xs) { - /// //$ $END$ - /// } - /// } - /// - /// - [AttributeUsage(AttributeTargets.Method)] - public sealed class SourceTemplateAttribute : Attribute { } - - /// - /// Allows specifying a macro for a parameter of a source template. - /// - /// - /// You can apply the attribute on the whole method or on any of its additional parameters. The macro expression - /// is defined in the property. When applied on a method, the target - /// template parameter is defined in the property. To apply the macro silently - /// for the parameter, set the property value = -1. - /// - /// - /// Applying the attribute on a source template method: - /// - /// [SourceTemplate, Macro(Target = "item", Expression = "suggestVariableName()")] - /// public static void forEach<T>(this IEnumerable<T> collection) { - /// foreach (var item in collection) { - /// //$ $END$ - /// } - /// } - /// - /// Applying the attribute on a template method parameter: - /// - /// [SourceTemplate] - /// public static void something(this Entity x, [Macro(Expression = "guid()", Editable = -1)] string newguid) { - /// /*$ var $x$Id = "$newguid$" + x.ToString(); - /// x.DoSomething($x$Id); */ - /// } - /// - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method, AllowMultiple = true)] - public sealed class MacroAttribute : Attribute - { /// - /// Allows specifying a macro that will be executed for a source template - /// parameter when the template is expanded. + /// Indicates that the value of the marked element can never be null. /// - [CanBeNull] public string Expression { get; set; } + /// + /// + /// [NotNull] object Foo() { + /// return null; // Warning: Possible 'null' assignment + /// } + /// + /// + [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | + AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event | + AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)] + public sealed class NotNullAttribute : Attribute + { + } /// - /// Allows specifying which occurrence of the target parameter becomes editable when the template is deployed. + /// Can be applied to symbols of types derived from IEnumerable as well as to symbols of Task + /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property + /// or of the Lazy.Value property can never be null. + /// + /// + /// + /// public void Foo([ItemNotNull]List<string> books) + /// { + /// foreach (var book in books) { + /// if (book != null) // Warning: Expression is always true + /// Console.WriteLine(book.ToUpper()); + /// } + /// } + /// + /// + [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | + AttributeTargets.Delegate | AttributeTargets.Field)] + public sealed class ItemNotNullAttribute : Attribute + { + } + + /// + /// Can be applied to symbols of types derived from IEnumerable as well as to symbols of Task + /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property + /// or of the Lazy.Value property can be null. + /// + /// + /// + /// public void Foo([ItemCanBeNull]List<string> books) + /// { + /// foreach (var book in books) + /// { + /// // Warning: Possible 'System.NullReferenceException' + /// Console.WriteLine(book.ToUpper()); + /// } + /// } + /// + /// + [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | + AttributeTargets.Delegate | AttributeTargets.Field)] + public sealed class ItemCanBeNullAttribute : Attribute + { + } + + /// + /// Indicates that the marked method builds string by the format pattern and (optional) arguments. + /// The parameter, which contains the format string, should be given in constructor. The format string + /// should be in -like form. + /// + /// + /// + /// [StringFormatMethod("message")] + /// void ShowError(string message, params object[] args) { /* do something */ } + /// + /// void Foo() { + /// ShowError("Failed: {0}"); // Warning: Non-existing argument in format string + /// } + /// + /// + [AttributeUsage( + AttributeTargets.Constructor | AttributeTargets.Method | + AttributeTargets.Property | AttributeTargets.Delegate)] + public sealed class StringFormatMethodAttribute : Attribute + { + /// + /// Specifies which parameter of an annotated method should be treated as the format string + /// + public StringFormatMethodAttribute([NotNull] string formatParameterName) + { + FormatParameterName = formatParameterName; + } + + [NotNull] + public string FormatParameterName { get; } + } + + /// + /// Use this annotation to specify a type that contains static or const fields + /// with values for the annotated property/field/parameter. + /// The specified type will be used to improve completion suggestions. + /// + /// + /// + /// namespace TestNamespace + /// { + /// public class Constants + /// { + /// public static int INT_CONST = 1; + /// public const string STRING_CONST = "1"; + /// } + /// + /// public class Class1 + /// { + /// [ValueProvider("TestNamespace.Constants")] public int myField; + /// public void Foo([ValueProvider("TestNamespace.Constants")] string str) { } + /// + /// public void Test() + /// { + /// Foo(/*try completion here*/);// + /// myField = /*try completion here*/ + /// } + /// } + /// } + /// + /// + [AttributeUsage( + AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field, + AllowMultiple = true)] + public sealed class ValueProviderAttribute : Attribute + { + public ValueProviderAttribute([NotNull] string name) + { + Name = name; + } + + [NotNull] + public string Name { get; } + } + + /// + /// Indicates that the function argument should be a string literal and match one + /// of the parameters of the caller function. For example, ReSharper annotates + /// the parameter of . + /// + /// + /// + /// void Foo(string param) { + /// if (param == null) + /// throw new ArgumentNullException("par"); // Warning: Cannot resolve symbol + /// } + /// + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class InvokerParameterNameAttribute : Attribute + { + } + + /// + /// Indicates that the method is contained in a type that implements + /// System.ComponentModel.INotifyPropertyChanged interface and this method + /// is used to notify that some property value changed. /// /// - /// If the target parameter is used several times in the template, only one occurrence becomes editable; - /// other occurrences are changed synchronously. To specify the zero-based index of the editable occurrence, - /// use values >= 0. To make the parameter non-editable when the template is expanded, use -1. + /// The method should be non-static and conform to one of the supported signatures: + /// + /// + /// NotifyChanged(string) + /// + /// + /// NotifyChanged(params string[]) + /// + /// + /// NotifyChanged{T}(Expression{Func{T}}) + /// + /// + /// NotifyChanged{T,U}(Expression{Func{T,U}}) + /// + /// + /// SetProperty{T}(ref T, T, string) + /// + /// /// - public int Editable { get; set; } + /// + /// + /// public class Foo : INotifyPropertyChanged { + /// public event PropertyChangedEventHandler PropertyChanged; + /// + /// [NotifyPropertyChangedInvocator] + /// protected virtual void NotifyChanged(string propertyName) { ... } + /// + /// string _name; + /// + /// public string Name { + /// get { return _name; } + /// set { _name = value; NotifyChanged("LastName"); /* Warning */ } + /// } + /// } + /// + /// Examples of generated notifications: + /// + /// + /// NotifyChanged("Property") + /// + /// + /// NotifyChanged(() => Property) + /// + /// + /// NotifyChanged((VM x) => x.Property) + /// + /// + /// SetProperty(ref myField, value, "Property") + /// + /// + /// + [AttributeUsage(AttributeTargets.Method)] + public sealed class NotifyPropertyChangedInvocatorAttribute : Attribute + { + public NotifyPropertyChangedInvocatorAttribute() + { + } + + public NotifyPropertyChangedInvocatorAttribute([NotNull] string parameterName) + { + ParameterName = parameterName; + } + + [CanBeNull] + public string ParameterName { get; } + } /// - /// Identifies the target parameter of a source template if the - /// is applied on a template method. + /// Describes dependency between method input and output. /// - [CanBeNull] public string Target { get; set; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcAreaMasterLocationFormatAttribute : Attribute - { - public AspMvcAreaMasterLocationFormatAttribute([NotNull] string format) + /// + ///

Function Definition Table syntax:

+ /// + /// FDT ::= FDTRow [;FDTRow]* + /// FDTRow ::= Input => Output | Output <= Input + /// Input ::= ParameterName: Value [, Input]* + /// Output ::= [ParameterName: Value]* {halt|stop|void|nothing|Value} + /// Value ::= true | false | null | notnull | canbenull + /// + /// If the method has a single input parameter, its name could be omitted.
+ /// Using halt (or void/nothing, which is the same) for the method output + /// means that the method doesn't return normally (throws or terminates the process).
+ /// Value canbenull is only applicable for output parameters.
+ /// You can use multiple [ContractAnnotation] for each FDT row, or use single attribute + /// with rows separated by semicolon. There is no notion of order rows, all rows are checked + /// for applicability and applied per each program state tracked by the analysis engine.
+ ///
+ /// + /// + /// + /// + /// [ContractAnnotation("=> halt")] + /// public void TerminationMethod() + /// + /// + /// + /// + /// [ContractAnnotation("null <= param:null")] // reverse condition syntax + /// public string GetName(string surname) + /// + /// + /// + /// + /// [ContractAnnotation("s:null => true")] + /// public bool IsNullOrEmpty(string s) // string.IsNullOrEmpty() + /// + /// + /// + /// + /// // A method that returns null if the parameter is null, + /// // and not null if the parameter is not null + /// [ContractAnnotation("null => null; notnull => notnull")] + /// public object Transform(object data) + /// + /// + /// + /// + /// [ContractAnnotation("=> true, result: notnull; => false, result: null")] + /// public bool TryParse(string s, out Person result) + /// + /// + /// + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + public sealed class ContractAnnotationAttribute : Attribute { - Format = format; + public ContractAnnotationAttribute([NotNull] string contract) + : this(contract, false) + { + } + + public ContractAnnotationAttribute([NotNull] string contract, bool forceFullStates) + { + Contract = contract; + ForceFullStates = forceFullStates; + } + + [NotNull] + public string Contract { get; } + + public bool ForceFullStates { get; } } - [NotNull] public string Format { get; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcAreaPartialViewLocationFormatAttribute : Attribute - { - public AspMvcAreaPartialViewLocationFormatAttribute([NotNull] string format) + /// + /// Indicates whether the marked element should be localized. + /// + /// + /// + /// [LocalizationRequiredAttribute(true)] + /// class Foo { + /// string str = "my string"; // Warning: Localizable string + /// } + /// + /// + [AttributeUsage(AttributeTargets.All)] + public sealed class LocalizationRequiredAttribute : Attribute { - Format = format; + public LocalizationRequiredAttribute() : this(true) + { + } + + public LocalizationRequiredAttribute(bool required) + { + Required = required; + } + + public bool Required { get; } } - [NotNull] public string Format { get; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcAreaViewLocationFormatAttribute : Attribute - { - public AspMvcAreaViewLocationFormatAttribute([NotNull] string format) + /// + /// Indicates that the value of the marked type (or its derivatives) + /// cannot be compared using '==' or '!=' operators and Equals() + /// should be used instead. However, using '==' or '!=' for comparison + /// with null is always permitted. + /// + /// + /// + /// [CannotApplyEqualityOperator] + /// class NoEquality { } + /// + /// class UsesNoEquality { + /// void Test() { + /// var ca1 = new NoEquality(); + /// var ca2 = new NoEquality(); + /// if (ca1 != null) { // OK + /// bool condition = ca1 == ca2; // Warning + /// } + /// } + /// } + /// + /// + [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct)] + public sealed class CannotApplyEqualityOperatorAttribute : Attribute { - Format = format; } - [NotNull] public string Format { get; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcMasterLocationFormatAttribute : Attribute - { - public AspMvcMasterLocationFormatAttribute([NotNull] string format) + /// + /// When applied to a target attribute, specifies a requirement for any type marked + /// with the target attribute to implement or inherit specific type or types. + /// + /// + /// + /// [BaseTypeRequired(typeof(IComponent)] // Specify requirement + /// class ComponentAttribute : Attribute { } + /// + /// [Component] // ComponentAttribute requires implementing IComponent interface + /// class MyComponent : IComponent { } + /// + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + [BaseTypeRequired(typeof(Attribute))] + public sealed class BaseTypeRequiredAttribute : Attribute { - Format = format; + public BaseTypeRequiredAttribute([NotNull] Type baseType) + { + BaseType = baseType; + } + + [NotNull] + public Type BaseType { get; } } - [NotNull] public string Format { get; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcPartialViewLocationFormatAttribute : Attribute - { - public AspMvcPartialViewLocationFormatAttribute([NotNull] string format) + /// + /// Indicates that the marked symbol is used implicitly (e.g. via reflection, in external library), + /// so this symbol will not be reported as unused (as well as by other usage inspections). + /// + [AttributeUsage(AttributeTargets.All, Inherited = false)] + public sealed class UsedImplicitlyAttribute : Attribute { - Format = format; + public UsedImplicitlyAttribute() + : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) + { + } + + public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags) + : this(useKindFlags, ImplicitUseTargetFlags.Default) + { + } + + public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags) + : this(ImplicitUseKindFlags.Default, targetFlags) + { + } + + public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) + { + UseKindFlags = useKindFlags; + TargetFlags = targetFlags; + } + + public ImplicitUseKindFlags UseKindFlags { get; } + + public ImplicitUseTargetFlags TargetFlags { get; } } - [NotNull] public string Format { get; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - public sealed class AspMvcViewLocationFormatAttribute : Attribute - { - public AspMvcViewLocationFormatAttribute([NotNull] string format) + /// + /// Can be applied to attributes, type parameters, and parameters of a type assignable from + /// . + /// When applied to an attribute, the decorated attribute behaves the same as . + /// When applied to a type parameter or to a parameter of type , indicates that the + /// corresponding type + /// is used implicitly. + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.GenericParameter | AttributeTargets.Parameter)] + public sealed class MeansImplicitUseAttribute : Attribute { - Format = format; + public MeansImplicitUseAttribute() + : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) + { + } + + public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags) + : this(useKindFlags, ImplicitUseTargetFlags.Default) + { + } + + public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags) + : this(ImplicitUseKindFlags.Default, targetFlags) + { + } + + public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) + { + UseKindFlags = useKindFlags; + TargetFlags = targetFlags; + } + + [UsedImplicitly] + public ImplicitUseKindFlags UseKindFlags { get; } + + [UsedImplicitly] + public ImplicitUseTargetFlags TargetFlags { get; } } - [NotNull] public string Format { get; } - } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter - /// is an MVC action. If applied to a method, the MVC action name is calculated - /// implicitly from the context. Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcActionAttribute : Attribute - { - public AspMvcActionAttribute() { } - - public AspMvcActionAttribute([NotNull] string anonymousProperty) + /// + /// Specify the details of implicitly used symbol when it is marked + /// with or . + /// + [Flags] + public enum ImplicitUseKindFlags { - AnonymousProperty = anonymousProperty; + Default = Access | Assign | InstantiatedWithFixedConstructorSignature, + + /// Only entity marked with attribute considered used. + Access = 1, + + /// Indicates implicit assignment to a member. + Assign = 2, + + /// + /// Indicates implicit instantiation of a type with fixed constructor signature. + /// That means any unused constructor parameters won't be reported as such. + /// + InstantiatedWithFixedConstructorSignature = 4, + + /// Indicates implicit instantiation of a type. + InstantiatedNoFixedConstructorSignature = 8 } - [CanBeNull] public string AnonymousProperty { get; } - } - - /// - /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC area. - /// Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcAreaAttribute : Attribute - { - public AspMvcAreaAttribute() { } - - public AspMvcAreaAttribute([NotNull] string anonymousProperty) + /// + /// Specify what is considered to be used implicitly when marked + /// with or . + /// + [Flags] + public enum ImplicitUseTargetFlags { - AnonymousProperty = anonymousProperty; + Default = Itself, + Itself = 1, + + /// Members of entity marked with attribute are considered used. + Members = 2, + + /// Entity marked with attribute and all its members considered used. + WithMembers = Itself | Members } - [CanBeNull] public string AnonymousProperty { get; } - } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is - /// an MVC controller. If applied to a method, the MVC controller name is calculated - /// implicitly from the context. Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcControllerAttribute : Attribute - { - public AspMvcControllerAttribute() { } - - public AspMvcControllerAttribute([NotNull] string anonymousProperty) + /// + /// This attribute is intended to mark publicly available API + /// which should not be removed and so is treated as used. + /// + [MeansImplicitUse(ImplicitUseTargetFlags.WithMembers)] + [AttributeUsage(AttributeTargets.All, Inherited = false)] + public sealed class PublicAPIAttribute : Attribute { - AnonymousProperty = anonymousProperty; + public PublicAPIAttribute() + { + } + + public PublicAPIAttribute([NotNull] string comment) + { + Comment = comment; + } + + [CanBeNull] + public string Comment { get; } } - [CanBeNull] public string AnonymousProperty { get; } - } - - /// - /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC Master. Use this attribute - /// for custom wrappers similar to System.Web.Mvc.Controller.View(String, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcMasterAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC model type. Use this attribute - /// for custom wrappers similar to System.Web.Mvc.Controller.View(String, Object). - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class AspMvcModelTypeAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is an MVC - /// partial view. If applied to a method, the MVC partial view name is calculated implicitly - /// from the context. Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.RenderPartialExtensions.RenderPartial(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcPartialViewAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. Allows disabling inspections for MVC views within a class or a method. - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] - public sealed class AspMvcSuppressViewErrorAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. Indicates that a parameter is an MVC display template. - /// Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.DisplayExtensions.DisplayForModel(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcDisplayTemplateAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC editor template. - /// Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.EditorExtensions.EditorForModel(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcEditorTemplateAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC template. - /// Use this attribute for custom wrappers similar to - /// System.ComponentModel.DataAnnotations.UIHintAttribute(System.String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcTemplateAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter - /// is an MVC view component. If applied to a method, the MVC view name is calculated implicitly - /// from the context. Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Controller.View(Object). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcViewAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter - /// is an MVC view component name. - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcViewComponentAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter - /// is an MVC view component view. If applied to a method, the MVC view component view name is default. - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class AspMvcViewComponentViewAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. When applied to a parameter of an attribute, - /// indicates that this parameter is an MVC action name. - /// - /// - /// [ActionName("Foo")] - /// public ActionResult Login(string returnUrl) { - /// ViewBag.ReturnUrl = Url.Action("Foo"); // OK - /// return RedirectToAction("Bar"); // Error: Cannot resolve action - /// } - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property)] - public sealed class AspMvcActionSelectorAttribute : Attribute { } - - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field)] - public sealed class HtmlElementAttributesAttribute : Attribute - { - public HtmlElementAttributesAttribute() { } - - public HtmlElementAttributesAttribute([NotNull] string name) + /// + /// Tells code analysis engine if the parameter is completely handled when the invoked method is on stack. + /// If the parameter is a delegate, indicates that delegate is executed while the method is executed. + /// If the parameter is an enumerable, indicates that it is enumerated while the method is executed. + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class InstantHandleAttribute : Attribute { - Name = name; } - [CanBeNull] public string Name { get; } - } - - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - public sealed class HtmlAttributeValueAttribute : Attribute - { - public HtmlAttributeValueAttribute([NotNull] string name) + /// + /// Indicates that a method does not make any observable state changes. + /// The same as System.Diagnostics.Contracts.PureAttribute. + /// + /// + /// + /// [Pure] int Multiply(int x, int y) => x * y; + /// + /// void M() { + /// Multiply(123, 42); // Waring: Return value of pure method is not used + /// } + /// + /// + [AttributeUsage(AttributeTargets.Method)] + public sealed class PureAttribute : Attribute { - Name = name; } - [NotNull] public string Name { get; } - } - - /// - /// Razor attribute. Indicates that the marked parameter or method is a Razor section. - /// Use this attribute for custom wrappers similar to - /// System.Web.WebPages.WebPageBase.RenderSection(String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] - public sealed class RazorSectionAttribute : Attribute { } - - /// - /// Indicates how method, constructor invocation, or property access - /// over collection type affects the contents of the collection. - /// Use to specify the access type. - /// - /// - /// Using this attribute only makes sense if all collection methods are marked with this attribute. - /// - /// - /// public class MyStringCollection : List<string> - /// { - /// [CollectionAccess(CollectionAccessType.Read)] - /// public string GetFirstString() - /// { - /// return this.ElementAt(0); - /// } - /// } - /// class Test - /// { - /// public void Foo() - /// { - /// // Warning: Contents of the collection is never updated - /// var col = new MyStringCollection(); - /// string x = col.GetFirstString(); - /// } - /// } - /// - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property)] - public sealed class CollectionAccessAttribute : Attribute - { - public CollectionAccessAttribute(CollectionAccessType collectionAccessType) + /// + /// Indicates that the return value of the method invocation must be used. + /// + /// + /// Methods decorated with this attribute (in contrast to pure methods) might change state, + /// but make no sense without using their return value.
+ /// Similarly to , this attribute + /// will help detecting usages of the method when the return value in not used. + /// Additionally, you can optionally specify a custom message, which will be used when showing warnings, e.g. + /// [MustUseReturnValue("Use the return value to...")]. + ///
+ [AttributeUsage(AttributeTargets.Method)] + public sealed class MustUseReturnValueAttribute : Attribute { - CollectionAccessType = collectionAccessType; + public MustUseReturnValueAttribute() + { + } + + public MustUseReturnValueAttribute([NotNull] string justification) + { + Justification = justification; + } + + [CanBeNull] + public string Justification { get; } } - public CollectionAccessType CollectionAccessType { get; } - } - - /// - /// Provides a value for the to define - /// how the collection method invocation affects the contents of the collection. - /// - [Flags] - public enum CollectionAccessType - { - /// Method does not use or modify content of the collection. - None = 0, - /// Method only reads content of the collection but does not modify it. - Read = 1, - /// Method can change content of the collection but does not add new elements. - ModifyExistingContent = 2, - /// Method can add new elements to the collection. - UpdatedContent = ModifyExistingContent | 4 - } - - /// - /// Indicates that the marked method is assertion method, i.e. it halts the control flow if - /// one of the conditions is satisfied. To set the condition, mark one of the parameters with - /// attribute. - /// - [AttributeUsage(AttributeTargets.Method)] - public sealed class AssertionMethodAttribute : Attribute { } - - /// - /// Indicates the condition parameter of the assertion method. The method itself should be - /// marked by attribute. The mandatory argument of - /// the attribute is the assertion type. - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class AssertionConditionAttribute : Attribute - { - public AssertionConditionAttribute(AssertionConditionType conditionType) + /// + /// Indicates the type member or parameter of some type, that should be used instead of all other ways + /// to get the value of that type. This annotation is useful when you have some "context" value evaluated + /// and stored somewhere, meaning that all other ways to get this value must be consolidated with existing one. + /// + /// + /// + /// class Foo { + /// [ProvidesContext] IBarService _barService = ...; + /// + /// void ProcessNode(INode node) { + /// DoSomething(node, node.GetGlobalServices().Bar); + /// // ^ Warning: use value of '_barService' field + /// } + /// } + /// + /// + [AttributeUsage( + AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.Method | + AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.GenericParameter)] + public sealed class ProvidesContextAttribute : Attribute { - ConditionType = conditionType; } - public AssertionConditionType ConditionType { get; } - } - - /// - /// Specifies assertion type. If the assertion method argument satisfies the condition, - /// then the execution continues. Otherwise, execution is assumed to be halted. - /// - public enum AssertionConditionType - { - /// Marked parameter should be evaluated to true. - IS_TRUE = 0, - /// Marked parameter should be evaluated to false. - IS_FALSE = 1, - /// Marked parameter should be evaluated to null value. - IS_NULL = 2, - /// Marked parameter should be evaluated to not null value. - IS_NOT_NULL = 3, - } - - /// - /// Indicates that the marked method unconditionally terminates control flow execution. - /// For example, it could unconditionally throw exception. - /// - [Obsolete("Use [ContractAnnotation('=> halt')] instead")] - [AttributeUsage(AttributeTargets.Method)] - public sealed class TerminatesProgramAttribute : Attribute { } - - /// - /// Indicates that method is pure LINQ method, with postponed enumeration (like Enumerable.Select, - /// .Where). This annotation allows inference of [InstantHandle] annotation for parameters - /// of delegate type by analyzing LINQ method chains. - /// - [AttributeUsage(AttributeTargets.Method)] - public sealed class LinqTunnelAttribute : Attribute { } - - /// - /// Indicates that IEnumerable passed as a parameter is not enumerated. - /// Use this annotation to suppress the 'Possible multiple enumeration of IEnumerable' inspection. - /// - /// - /// static void ThrowIfNull<T>([NoEnumeration] T v, string n) where T : class - /// { - /// // custom check for null but no enumeration - /// } - /// - /// void Foo(IEnumerable<string> values) - /// { - /// ThrowIfNull(values, nameof(values)); - /// var x = values.ToList(); // No warnings about multiple enumeration - /// } - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class NoEnumerationAttribute : Attribute { } - - /// - /// Indicates that the marked parameter is a regular expression pattern. - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class RegexPatternAttribute : Attribute { } - - /// - /// Prevents the Member Reordering feature from tossing members of the marked class. - /// - /// - /// The attribute must be mentioned in your member reordering patterns. - /// - [AttributeUsage( - AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Enum)] - public sealed class NoReorderAttribute : Attribute { } - - /// - /// XAML attribute. Indicates the type that has ItemsSource property and should be treated - /// as ItemsControl-derived type, to enable inner items DataContext type resolve. - /// - [AttributeUsage(AttributeTargets.Class)] - public sealed class XamlItemsControlAttribute : Attribute { } - - /// - /// XAML attribute. Indicates the property of some BindingBase-derived type, that - /// is used to bind some item of ItemsControl-derived type. This annotation will - /// enable the DataContext type resolve for XAML bindings for such properties. - /// - /// - /// Property should have the tree ancestor of the ItemsControl type or - /// marked with the attribute. - /// - [AttributeUsage(AttributeTargets.Property)] - public sealed class XamlItemBindingOfItemsControlAttribute : Attribute { } - - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] - public sealed class AspChildControlTypeAttribute : Attribute - { - public AspChildControlTypeAttribute([NotNull] string tagName, [NotNull] Type controlType) + /// + /// Indicates that a parameter is a path to a file or a folder within a web project. + /// Path can be relative or absolute, starting from web root (~). + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class PathReferenceAttribute : Attribute { - TagName = tagName; - ControlType = controlType; + public PathReferenceAttribute() + { + } + + public PathReferenceAttribute([NotNull] [PathReference] string basePath) + { + BasePath = basePath; + } + + [CanBeNull] + public string BasePath { get; } } - [NotNull] public string TagName { get; } - - [NotNull] public Type ControlType { get; } - } - - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)] - public sealed class AspDataFieldAttribute : Attribute { } - - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)] - public sealed class AspDataFieldsAttribute : Attribute { } - - [AttributeUsage(AttributeTargets.Property)] - public sealed class AspMethodPropertyAttribute : Attribute { } - - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] - public sealed class AspRequiredAttributeAttribute : Attribute - { - public AspRequiredAttributeAttribute([NotNull] string attribute) + /// + /// An extension method marked with this attribute is processed by code completion + /// as a 'Source Template'. When the extension method is completed over some expression, its source code + /// is automatically expanded like a template at call site. + /// + /// + /// Template method body can contain valid source code and/or special comments starting with '$'. + /// Text inside these comments is added as source code when the template is applied. Template parameters + /// can be used either as additional method parameters or as identifiers wrapped in two '$' signs. + /// Use the attribute to specify macros for parameters. + /// + /// + /// In this example, the 'forEach' method is a source template available over all values + /// of enumerable types, producing ordinary C# 'foreach' statement and placing caret inside block: + /// + /// [SourceTemplate] + /// public static void forEach<T>(this IEnumerable<T> xs) { + /// foreach (var x in xs) { + /// //$ $END$ + /// } + /// } + /// + /// + [AttributeUsage(AttributeTargets.Method)] + public sealed class SourceTemplateAttribute : Attribute { - Attribute = attribute; } - [NotNull] public string Attribute { get; } - } - - [AttributeUsage(AttributeTargets.Property)] - public sealed class AspTypePropertyAttribute : Attribute - { - public bool CreateConstructorReferences { get; } - - public AspTypePropertyAttribute(bool createConstructorReferences) + /// + /// Allows specifying a macro for a parameter of a source template. + /// + /// + /// You can apply the attribute on the whole method or on any of its additional parameters. The macro expression + /// is defined in the property. When applied on a method, the target + /// template parameter is defined in the property. To apply the macro silently + /// for the parameter, set the property value = -1. + /// + /// + /// Applying the attribute on a source template method: + /// + /// [SourceTemplate, Macro(Target = "item", Expression = "suggestVariableName()")] + /// public static void forEach<T>(this IEnumerable<T> collection) { + /// foreach (var item in collection) { + /// //$ $END$ + /// } + /// } + /// + /// Applying the attribute on a template method parameter: + /// + /// [SourceTemplate] + /// public static void something(this Entity x, [Macro(Expression = "guid()", Editable = -1)] string newguid) { + /// /*$ var $x$Id = "$newguid$" + x.ToString(); + /// x.DoSomething($x$Id); */ + /// } + /// + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method, AllowMultiple = true)] + public sealed class MacroAttribute : Attribute { - CreateConstructorReferences = createConstructorReferences; - } - } + /// + /// Allows specifying a macro that will be executed for a source template + /// parameter when the template is expanded. + /// + [CanBeNull] + public string Expression { get; set; } - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class RazorImportNamespaceAttribute : Attribute - { - public RazorImportNamespaceAttribute([NotNull] string name) - { - Name = name; + /// + /// Allows specifying which occurrence of the target parameter becomes editable when the template is deployed. + /// + /// + /// If the target parameter is used several times in the template, only one occurrence becomes editable; + /// other occurrences are changed synchronously. To specify the zero-based index of the editable occurrence, + /// use values >= 0. To make the parameter non-editable when the template is expanded, use -1. + /// + public int Editable { get; set; } + + /// + /// Identifies the target parameter of a source template if the + /// is applied on a template method. + /// + [CanBeNull] + public string Target { get; set; } } - [NotNull] public string Name { get; } - } - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class RazorInjectionAttribute : Attribute - { - public RazorInjectionAttribute([NotNull] string type, [NotNull] string fieldName) + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcAreaMasterLocationFormatAttribute : Attribute { - Type = type; - FieldName = fieldName; + public AspMvcAreaMasterLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] + public string Format { get; } } - [NotNull] public string Type { get; } - - [NotNull] public string FieldName { get; } - } - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class RazorDirectiveAttribute : Attribute - { - public RazorDirectiveAttribute([NotNull] string directive) + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcAreaPartialViewLocationFormatAttribute : Attribute { - Directive = directive; + public AspMvcAreaPartialViewLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] + public string Format { get; } } - [NotNull] public string Directive { get; } - } + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcAreaViewLocationFormatAttribute : Attribute + { + public AspMvcAreaViewLocationFormatAttribute([NotNull] string format) + { + Format = format; + } - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class RazorPageBaseTypeAttribute : Attribute - { - public RazorPageBaseTypeAttribute([NotNull] string baseType) - { - BaseType = baseType; - } - public RazorPageBaseTypeAttribute([NotNull] string baseType, string pageName) - { - BaseType = baseType; - PageName = pageName; - } + [NotNull] + public string Format { get; } + } - [NotNull] public string BaseType { get; } - [CanBeNull] public string PageName { get; } - } + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcMasterLocationFormatAttribute : Attribute + { + public AspMvcMasterLocationFormatAttribute([NotNull] string format) + { + Format = format; + } - [AttributeUsage(AttributeTargets.Method)] - public sealed class RazorHelperCommonAttribute : Attribute { } + [NotNull] + public string Format { get; } + } - [AttributeUsage(AttributeTargets.Property)] - public sealed class RazorLayoutAttribute : Attribute { } + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcPartialViewLocationFormatAttribute : Attribute + { + public AspMvcPartialViewLocationFormatAttribute([NotNull] string format) + { + Format = format; + } - [AttributeUsage(AttributeTargets.Method)] - public sealed class RazorWriteLiteralMethodAttribute : Attribute { } + [NotNull] + public string Format { get; } + } - [AttributeUsage(AttributeTargets.Method)] - public sealed class RazorWriteMethodAttribute : Attribute { } + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcViewLocationFormatAttribute : Attribute + { + public AspMvcViewLocationFormatAttribute([NotNull] string format) + { + Format = format; + } - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class RazorWriteMethodParameterAttribute : Attribute { } + [NotNull] + public string Format { get; } + } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter + /// is an MVC action. If applied to a method, the MVC action name is calculated + /// implicitly from the context. Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcActionAttribute : Attribute + { + public AspMvcActionAttribute() + { + } + + public AspMvcActionAttribute([NotNull] string anonymousProperty) + { + AnonymousProperty = anonymousProperty; + } + + [CanBeNull] + public string AnonymousProperty { get; } + } + + /// + /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC area. + /// Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcAreaAttribute : Attribute + { + public AspMvcAreaAttribute() + { + } + + public AspMvcAreaAttribute([NotNull] string anonymousProperty) + { + AnonymousProperty = anonymousProperty; + } + + [CanBeNull] + public string AnonymousProperty { get; } + } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is + /// an MVC controller. If applied to a method, the MVC controller name is calculated + /// implicitly from the context. Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcControllerAttribute : Attribute + { + public AspMvcControllerAttribute() + { + } + + public AspMvcControllerAttribute([NotNull] string anonymousProperty) + { + AnonymousProperty = anonymousProperty; + } + + [CanBeNull] + public string AnonymousProperty { get; } + } + + /// + /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC Master. Use this attribute + /// for custom wrappers similar to System.Web.Mvc.Controller.View(String, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcMasterAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC model type. Use this attribute + /// for custom wrappers similar to System.Web.Mvc.Controller.View(String, Object). + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class AspMvcModelTypeAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is an MVC + /// partial view. If applied to a method, the MVC partial view name is calculated implicitly + /// from the context. Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.RenderPartialExtensions.RenderPartial(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcPartialViewAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. Allows disabling inspections for MVC views within a class or a method. + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] + public sealed class AspMvcSuppressViewErrorAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. Indicates that a parameter is an MVC display template. + /// Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.DisplayExtensions.DisplayForModel(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcDisplayTemplateAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC editor template. + /// Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.EditorExtensions.EditorForModel(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcEditorTemplateAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC template. + /// Use this attribute for custom wrappers similar to + /// System.ComponentModel.DataAnnotations.UIHintAttribute(System.String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcTemplateAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter + /// is an MVC view component. If applied to a method, the MVC view name is calculated implicitly + /// from the context. Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Controller.View(Object). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcViewAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter + /// is an MVC view component name. + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcViewComponentAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter + /// is an MVC view component view. If applied to a method, the MVC view component view name is default. + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcViewComponentViewAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. When applied to a parameter of an attribute, + /// indicates that this parameter is an MVC action name. + /// + /// + /// + /// [ActionName("Foo")] + /// public ActionResult Login(string returnUrl) { + /// ViewBag.ReturnUrl = Url.Action("Foo"); // OK + /// return RedirectToAction("Bar"); // Error: Cannot resolve action + /// } + /// + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property)] + public sealed class AspMvcActionSelectorAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field)] + public sealed class HtmlElementAttributesAttribute : Attribute + { + public HtmlElementAttributesAttribute() + { + } + + public HtmlElementAttributesAttribute([NotNull] string name) + { + Name = name; + } + + [CanBeNull] + public string Name { get; } + } + + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class HtmlAttributeValueAttribute : Attribute + { + public HtmlAttributeValueAttribute([NotNull] string name) + { + Name = name; + } + + [NotNull] + public string Name { get; } + } + + /// + /// Razor attribute. Indicates that the marked parameter or method is a Razor section. + /// Use this attribute for custom wrappers similar to + /// System.Web.WebPages.WebPageBase.RenderSection(String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] + public sealed class RazorSectionAttribute : Attribute + { + } + + /// + /// Indicates how method, constructor invocation, or property access + /// over collection type affects the contents of the collection. + /// Use to specify the access type. + /// + /// + /// Using this attribute only makes sense if all collection methods are marked with this attribute. + /// + /// + /// + /// public class MyStringCollection : List<string> + /// { + /// [CollectionAccess(CollectionAccessType.Read)] + /// public string GetFirstString() + /// { + /// return this.ElementAt(0); + /// } + /// } + /// class Test + /// { + /// public void Foo() + /// { + /// // Warning: Contents of the collection is never updated + /// var col = new MyStringCollection(); + /// string x = col.GetFirstString(); + /// } + /// } + /// + /// + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property)] + public sealed class CollectionAccessAttribute : Attribute + { + public CollectionAccessAttribute(CollectionAccessType collectionAccessType) + { + CollectionAccessType = collectionAccessType; + } + + public CollectionAccessType CollectionAccessType { get; } + } + + /// + /// Provides a value for the to define + /// how the collection method invocation affects the contents of the collection. + /// + [Flags] + public enum CollectionAccessType + { + /// Method does not use or modify content of the collection. + None = 0, + + /// Method only reads content of the collection but does not modify it. + Read = 1, + + /// Method can change content of the collection but does not add new elements. + ModifyExistingContent = 2, + + /// Method can add new elements to the collection. + UpdatedContent = ModifyExistingContent | 4 + } + + /// + /// Indicates that the marked method is assertion method, i.e. it halts the control flow if + /// one of the conditions is satisfied. To set the condition, mark one of the parameters with + /// attribute. + /// + [AttributeUsage(AttributeTargets.Method)] + public sealed class AssertionMethodAttribute : Attribute + { + } + + /// + /// Indicates the condition parameter of the assertion method. The method itself should be + /// marked by attribute. The mandatory argument of + /// the attribute is the assertion type. + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class AssertionConditionAttribute : Attribute + { + public AssertionConditionAttribute(AssertionConditionType conditionType) + { + ConditionType = conditionType; + } + + public AssertionConditionType ConditionType { get; } + } + + /// + /// Specifies assertion type. If the assertion method argument satisfies the condition, + /// then the execution continues. Otherwise, execution is assumed to be halted. + /// + public enum AssertionConditionType + { + /// Marked parameter should be evaluated to true. + IS_TRUE = 0, + + /// Marked parameter should be evaluated to false. + IS_FALSE = 1, + + /// Marked parameter should be evaluated to null value. + IS_NULL = 2, + + /// Marked parameter should be evaluated to not null value. + IS_NOT_NULL = 3 + } + + /// + /// Indicates that the marked method unconditionally terminates control flow execution. + /// For example, it could unconditionally throw exception. + /// + [Obsolete("Use [ContractAnnotation('=> halt')] instead")] + [AttributeUsage(AttributeTargets.Method)] + public sealed class TerminatesProgramAttribute : Attribute + { + } + + /// + /// Indicates that method is pure LINQ method, with postponed enumeration (like Enumerable.Select, + /// .Where). This annotation allows inference of [InstantHandle] annotation for parameters + /// of delegate type by analyzing LINQ method chains. + /// + [AttributeUsage(AttributeTargets.Method)] + public sealed class LinqTunnelAttribute : Attribute + { + } + + /// + /// Indicates that IEnumerable passed as a parameter is not enumerated. + /// Use this annotation to suppress the 'Possible multiple enumeration of IEnumerable' inspection. + /// + /// + /// + /// static void ThrowIfNull<T>([NoEnumeration] T v, string n) where T : class + /// { + /// // custom check for null but no enumeration + /// } + /// + /// void Foo(IEnumerable<string> values) + /// { + /// ThrowIfNull(values, nameof(values)); + /// var x = values.ToList(); // No warnings about multiple enumeration + /// } + /// + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class NoEnumerationAttribute : Attribute + { + } + + /// + /// Indicates that the marked parameter is a regular expression pattern. + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class RegexPatternAttribute : Attribute + { + } + + /// + /// Prevents the Member Reordering feature from tossing members of the marked class. + /// + /// + /// The attribute must be mentioned in your member reordering patterns. + /// + [AttributeUsage( + AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Enum)] + public sealed class NoReorderAttribute : Attribute + { + } + + /// + /// XAML attribute. Indicates the type that has ItemsSource property and should be treated + /// as ItemsControl-derived type, to enable inner items DataContext type resolve. + /// + [AttributeUsage(AttributeTargets.Class)] + public sealed class XamlItemsControlAttribute : Attribute + { + } + + /// + /// XAML attribute. Indicates the property of some BindingBase-derived type, that + /// is used to bind some item of ItemsControl-derived type. This annotation will + /// enable the DataContext type resolve for XAML bindings for such properties. + /// + /// + /// Property should have the tree ancestor of the ItemsControl type or + /// marked with the attribute. + /// + [AttributeUsage(AttributeTargets.Property)] + public sealed class XamlItemBindingOfItemsControlAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + public sealed class AspChildControlTypeAttribute : Attribute + { + public AspChildControlTypeAttribute([NotNull] string tagName, [NotNull] Type controlType) + { + TagName = tagName; + ControlType = controlType; + } + + [NotNull] + public string TagName { get; } + + [NotNull] + public Type ControlType { get; } + } + + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)] + public sealed class AspDataFieldAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)] + public sealed class AspDataFieldsAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Property)] + public sealed class AspMethodPropertyAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + public sealed class AspRequiredAttributeAttribute : Attribute + { + public AspRequiredAttributeAttribute([NotNull] string attribute) + { + Attribute = attribute; + } + + [NotNull] + public string Attribute { get; } + } + + [AttributeUsage(AttributeTargets.Property)] + public sealed class AspTypePropertyAttribute : Attribute + { + public AspTypePropertyAttribute(bool createConstructorReferences) + { + CreateConstructorReferences = createConstructorReferences; + } + + public bool CreateConstructorReferences { get; } + } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public sealed class RazorImportNamespaceAttribute : Attribute + { + public RazorImportNamespaceAttribute([NotNull] string name) + { + Name = name; + } + + [NotNull] + public string Name { get; } + } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public sealed class RazorInjectionAttribute : Attribute + { + public RazorInjectionAttribute([NotNull] string type, [NotNull] string fieldName) + { + Type = type; + FieldName = fieldName; + } + + [NotNull] + public string Type { get; } + + [NotNull] + public string FieldName { get; } + } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public sealed class RazorDirectiveAttribute : Attribute + { + public RazorDirectiveAttribute([NotNull] string directive) + { + Directive = directive; + } + + [NotNull] + public string Directive { get; } + } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public sealed class RazorPageBaseTypeAttribute : Attribute + { + public RazorPageBaseTypeAttribute([NotNull] string baseType) + { + BaseType = baseType; + } + + public RazorPageBaseTypeAttribute([NotNull] string baseType, string pageName) + { + BaseType = baseType; + PageName = pageName; + } + + [NotNull] + public string BaseType { get; } + + [CanBeNull] + public string PageName { get; } + } + + [AttributeUsage(AttributeTargets.Method)] + public sealed class RazorHelperCommonAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Property)] + public sealed class RazorLayoutAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Method)] + public sealed class RazorWriteLiteralMethodAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Method)] + public sealed class RazorWriteMethodAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class RazorWriteMethodParameterAttribute : Attribute + { + } } \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Properties/AssemblyInfo.cs b/src/Artemis.UI.Shared/Properties/AssemblyInfo.cs index 6d2819a7a..412a20daf 100644 --- a/src/Artemis.UI.Shared/Properties/AssemblyInfo.cs +++ b/src/Artemis.UI.Shared/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ -using System.Reflection; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; using System.Windows; // Setting ComVisible to false makes the types in this assembly not visible @@ -24,4 +23,4 @@ using System.Windows; ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located //(used if a resource is not found in the page, // app, or any theme specific resource dictionaries) -)] +)] \ No newline at end of file diff --git a/src/Artemis.UI.Shared/PropertyInput/PropertyInputRegistration.cs b/src/Artemis.UI.Shared/PropertyInput/PropertyInputRegistration.cs index 54fba5073..2d00f3074 100644 --- a/src/Artemis.UI.Shared/PropertyInput/PropertyInputRegistration.cs +++ b/src/Artemis.UI.Shared/PropertyInput/PropertyInputRegistration.cs @@ -23,7 +23,7 @@ namespace Artemis.UI.Shared.PropertyInput public PluginInfo PluginInfo { get; } public Type SupportedType { get; } public Type ViewModelType { get; } - + internal void Unsubscribe() { if (PluginInfo != Constants.CorePluginInfo) diff --git a/src/Artemis.UI.Shared/Screens/Dialogs/ExceptionDialogView.xaml b/src/Artemis.UI.Shared/Screens/Dialogs/ExceptionDialogView.xaml index 4a4ad281d..0ac419bdc 100644 --- a/src/Artemis.UI.Shared/Screens/Dialogs/ExceptionDialogView.xaml +++ b/src/Artemis.UI.Shared/Screens/Dialogs/ExceptionDialogView.xaml @@ -21,7 +21,7 @@ + TextWrapping="Wrap" FontWeight="Bold" /> + Margin="0 10 10 0" + Padding="10" /> diff --git a/src/Artemis.UI.Shared/Screens/Dialogs/ExceptionDialogViewModel.cs b/src/Artemis.UI.Shared/Screens/Dialogs/ExceptionDialogViewModel.cs index 7818f2aa3..01e14799f 100644 --- a/src/Artemis.UI.Shared/Screens/Dialogs/ExceptionDialogViewModel.cs +++ b/src/Artemis.UI.Shared/Screens/Dialogs/ExceptionDialogViewModel.cs @@ -32,13 +32,13 @@ namespace Artemis.UI.Shared.Screens.Dialogs public class DialogException { - public Exception Exception { get; } - public IDocument Document { get; set; } - public DialogException(Exception exception) { Exception = exception; Document = new TextDocument(new StringTextSource($"{exception.Message}\r\n\r\n{exception.StackTrace}")); } + + public Exception Exception { get; } + public IDocument Document { get; set; } } } \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Screens/GradientEditor/ColorStopViewModel.cs b/src/Artemis.UI.Shared/Screens/GradientEditor/ColorStopViewModel.cs index f43242776..80f750646 100644 --- a/src/Artemis.UI.Shared/Screens/GradientEditor/ColorStopViewModel.cs +++ b/src/Artemis.UI.Shared/Screens/GradientEditor/ColorStopViewModel.cs @@ -1,11 +1,9 @@ using System; using System.ComponentModel; -using System.Drawing; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Input; -using Artemis.Core.Models.Profile; using Artemis.Core.Models.Profile.Colors; using Artemis.UI.Shared.Utilities; using Stylet; @@ -25,11 +23,6 @@ namespace Artemis.UI.Shared.Screens.GradientEditor ColorStop.PropertyChanged += ColorStopOnPropertyChanged; } - private void ColorStopOnPropertyChanged(object sender, PropertyChangedEventArgs e) - { - _gradientEditorViewModel.ColorGradient.OnColorValuesUpdated(); - } - public ColorGradientStop ColorStop { get; } public double Offset @@ -66,8 +59,13 @@ namespace Artemis.UI.Shared.Screens.GradientEditor set => SetAndNotify(ref _willRemoveColorStop, value); } + private void ColorStopOnPropertyChanged(object sender, PropertyChangedEventArgs e) + { + _gradientEditorViewModel.ColorGradient.OnColorValuesUpdated(); + } + #region Movement - + public void StopMouseDown(object sender, MouseButtonEventArgs e) { e.Handled = true; diff --git a/src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditorViewModel.cs b/src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditorViewModel.cs index 9f25b57c9..6b71c8dbb 100644 --- a/src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditorViewModel.cs +++ b/src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditorViewModel.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Input; -using Artemis.Core.Models.Profile; using Artemis.Core.Models.Profile.Colors; using Artemis.UI.Shared.Services.Dialog; using Artemis.UI.Shared.Utilities; diff --git a/src/Artemis.UI.Shared/Services/Dialog/DialogService.cs b/src/Artemis.UI.Shared/Services/Dialog/DialogService.cs index c7c1174d9..18dfe74d8 100644 --- a/src/Artemis.UI.Shared/Services/Dialog/DialogService.cs +++ b/src/Artemis.UI.Shared/Services/Dialog/DialogService.cs @@ -123,7 +123,7 @@ namespace Artemis.UI.Shared.Services.Dialog else result = DialogHost.Show(view, identifier, viewModel.OnDialogOpened, viewModel.OnDialogClosed); }); - + return await result; } } diff --git a/src/Artemis.UI.Shared/Services/GradientPickerService.cs b/src/Artemis.UI.Shared/Services/GradientPickerService.cs index 608ea0401..e25489e41 100644 --- a/src/Artemis.UI.Shared/Services/GradientPickerService.cs +++ b/src/Artemis.UI.Shared/Services/GradientPickerService.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Artemis.Core.Models.Profile; using Artemis.Core.Models.Profile.Colors; using Artemis.UI.Shared.Screens.GradientEditor; using Artemis.UI.Shared.Services.Interfaces; diff --git a/src/Artemis.UI.Shared/Services/Interfaces/IGradientPickerService.cs b/src/Artemis.UI.Shared/Services/Interfaces/IGradientPickerService.cs index b28bf378d..1af54e639 100644 --- a/src/Artemis.UI.Shared/Services/Interfaces/IGradientPickerService.cs +++ b/src/Artemis.UI.Shared/Services/Interfaces/IGradientPickerService.cs @@ -1,5 +1,4 @@ using System.Threading.Tasks; -using Artemis.Core.Models.Profile; using Artemis.Core.Models.Profile.Colors; namespace Artemis.UI.Shared.Services.Interfaces diff --git a/src/Artemis.UI.Shared/Utilities/HitTestUtilities.cs b/src/Artemis.UI.Shared/Utilities/HitTestUtilities.cs index 172d1fa7a..cece0a0f9 100644 --- a/src/Artemis.UI.Shared/Utilities/HitTestUtilities.cs +++ b/src/Artemis.UI.Shared/Utilities/HitTestUtilities.cs @@ -7,7 +7,8 @@ namespace Artemis.UI.Shared.Utilities public static class HitTestUtilities { /// - /// Runs a hit test on children of the container within the rectangle matching all elements that have a data context of . + /// Runs a hit test on children of the container within the rectangle matching all elements that have a data context of + /// . /// /// /// diff --git a/src/Artemis.UI.Shared/Utilities/ShortcutUtilities.cs b/src/Artemis.UI.Shared/Utilities/ShortcutUtilities.cs index 237e51ffa..3d7e90a0b 100644 --- a/src/Artemis.UI.Shared/Utilities/ShortcutUtilities.cs +++ b/src/Artemis.UI.Shared/Utilities/ShortcutUtilities.cs @@ -1,44 +1,17 @@ using System; +using System.Reflection; using System.Runtime.InteropServices; namespace Artemis.UI.Shared.Utilities { public class ShortcutUtilities { - - private static Type m_type = Type.GetTypeFromProgID("WScript.Shell"); - private static object m_shell = Activator.CreateInstance(m_type); - - [ComImport, TypeLibType((short)0x1040), Guid("F935DC23-1CF0-11D0-ADB9-00C04FD58A0B")] - private interface IWshShortcut - { - [DispId(0)] - string FullName { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0)] get; } - [DispId(0x3e8)] - string Arguments { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3e8)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3e8)] set; } - [DispId(0x3e9)] - string Description { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3e9)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3e9)] set; } - [DispId(0x3ea)] - string Hotkey { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3ea)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3ea)] set; } - [DispId(0x3eb)] - string IconLocation { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3eb)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3eb)] set; } - [DispId(0x3ec)] - string RelativePath { [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3ec)] set; } - [DispId(0x3ed)] - string TargetPath { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3ed)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3ed)] set; } - [DispId(0x3ee)] - int WindowStyle { [DispId(0x3ee)] get; [param: In] [DispId(0x3ee)] set; } - [DispId(0x3ef)] - string WorkingDirectory { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3ef)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3ef)] set; } - [TypeLibFunc((short)0x40), DispId(0x7d0)] - void Load([In, MarshalAs(UnmanagedType.BStr)] string PathLink); - [DispId(0x7d1)] - void Save(); - } + private static readonly Type m_type = Type.GetTypeFromProgID("WScript.Shell"); + private static readonly object m_shell = Activator.CreateInstance(m_type); public static void Create(string fileName, string targetPath, string arguments, string workingDirectory, string description, string hotkey, string iconPath) { - IWshShortcut shortcut = (IWshShortcut)m_type.InvokeMember("CreateShortcut", System.Reflection.BindingFlags.InvokeMethod, null, m_shell, new object[] { fileName }); + var shortcut = (IWshShortcut) m_type.InvokeMember("CreateShortcut", BindingFlags.InvokeMethod, null, m_shell, new object[] {fileName}); shortcut.Description = description; shortcut.Hotkey = hotkey; shortcut.TargetPath = targetPath; @@ -48,5 +21,117 @@ namespace Artemis.UI.Shared.Utilities shortcut.IconLocation = iconPath; shortcut.Save(); } + + [ComImport] + [TypeLibType(0x1040)] + [Guid("F935DC23-1CF0-11D0-ADB9-00C04FD58A0B")] + private interface IWshShortcut + { + [DispId(0)] + string FullName + { + [return: MarshalAs(UnmanagedType.BStr)] + [DispId(0)] + get; + } + + [DispId(0x3e8)] + string Arguments + { + [return: MarshalAs(UnmanagedType.BStr)] + [DispId(0x3e8)] + get; + [param: In] + [param: MarshalAs(UnmanagedType.BStr)] + [DispId(0x3e8)] + set; + } + + [DispId(0x3e9)] + string Description + { + [return: MarshalAs(UnmanagedType.BStr)] + [DispId(0x3e9)] + get; + [param: In] + [param: MarshalAs(UnmanagedType.BStr)] + [DispId(0x3e9)] + set; + } + + [DispId(0x3ea)] + string Hotkey + { + [return: MarshalAs(UnmanagedType.BStr)] + [DispId(0x3ea)] + get; + [param: In] + [param: MarshalAs(UnmanagedType.BStr)] + [DispId(0x3ea)] + set; + } + + [DispId(0x3eb)] + string IconLocation + { + [return: MarshalAs(UnmanagedType.BStr)] + [DispId(0x3eb)] + get; + [param: In] + [param: MarshalAs(UnmanagedType.BStr)] + [DispId(0x3eb)] + set; + } + + [DispId(0x3ec)] + string RelativePath + { + [param: In] + [param: MarshalAs(UnmanagedType.BStr)] + [DispId(0x3ec)] + set; + } + + [DispId(0x3ed)] + string TargetPath + { + [return: MarshalAs(UnmanagedType.BStr)] + [DispId(0x3ed)] + get; + [param: In] + [param: MarshalAs(UnmanagedType.BStr)] + [DispId(0x3ed)] + set; + } + + [DispId(0x3ee)] + int WindowStyle + { + [DispId(0x3ee)] + get; + [param: In] + [DispId(0x3ee)] + set; + } + + [DispId(0x3ef)] + string WorkingDirectory + { + [return: MarshalAs(UnmanagedType.BStr)] + [DispId(0x3ef)] + get; + [param: In] + [param: MarshalAs(UnmanagedType.BStr)] + [DispId(0x3ef)] + set; + } + + [TypeLibFunc(0x40)] + [DispId(0x7d0)] + void Load([In] [MarshalAs(UnmanagedType.BStr)] string PathLink); + + [DispId(0x7d1)] + void Save(); + } } } \ No newline at end of file diff --git a/src/Artemis.UI/Events/RequestSelectSidebarItemEvent.cs b/src/Artemis.UI/Events/RequestSelectSidebarItemEvent.cs index 638eeec0a..f4c1e6bf4 100644 --- a/src/Artemis.UI/Events/RequestSelectSidebarItemEvent.cs +++ b/src/Artemis.UI/Events/RequestSelectSidebarItemEvent.cs @@ -2,11 +2,11 @@ { public class RequestSelectSidebarItemEvent { - public string Label { get; } - public RequestSelectSidebarItemEvent(string label) { Label = label; } + + public string Label { get; } } } \ No newline at end of file diff --git a/src/Artemis.UI/Ninject/UiModule.cs b/src/Artemis.UI/Ninject/UiModule.cs index 484fab1b9..01de5c687 100644 --- a/src/Artemis.UI/Ninject/UiModule.cs +++ b/src/Artemis.UI/Ninject/UiModule.cs @@ -3,7 +3,6 @@ using Artemis.UI.Ninject.Factories; using Artemis.UI.Screens; using Artemis.UI.Screens.Module.ProfileEditor; using Artemis.UI.Services.Interfaces; -using Artemis.UI.Shared.PropertyInput; using Artemis.UI.Shared.Services.Dialog; using Artemis.UI.Stylet; using FluentValidation; diff --git a/src/Artemis.UI/Properties/AssemblyInfo.cs b/src/Artemis.UI/Properties/AssemblyInfo.cs index d91c912d5..412a20daf 100644 --- a/src/Artemis.UI/Properties/AssemblyInfo.cs +++ b/src/Artemis.UI/Properties/AssemblyInfo.cs @@ -1,6 +1,4 @@ -using System.Reflection; -using System.Resources; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; using System.Windows; // Setting ComVisible to false makes the types in this assembly not visible @@ -25,4 +23,4 @@ using System.Windows; ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located //(used if a resource is not found in the page, // app, or any theme specific resource dictionaries) -)] +)] \ No newline at end of file diff --git a/src/Artemis.UI/PropertyInput/BrushPropertyInputView.xaml b/src/Artemis.UI/PropertyInput/BrushPropertyInputView.xaml index 62c395871..a4d285d1e 100644 --- a/src/Artemis.UI/PropertyInput/BrushPropertyInputView.xaml +++ b/src/Artemis.UI/PropertyInput/BrushPropertyInputView.xaml @@ -26,8 +26,8 @@ - - + + diff --git a/src/Artemis.UI/PropertyInput/ColorGradientPropertyInputViewModel.cs b/src/Artemis.UI/PropertyInput/ColorGradientPropertyInputViewModel.cs index 5b6c6df99..38457f8c3 100644 --- a/src/Artemis.UI/PropertyInput/ColorGradientPropertyInputViewModel.cs +++ b/src/Artemis.UI/PropertyInput/ColorGradientPropertyInputViewModel.cs @@ -8,7 +8,7 @@ namespace Artemis.UI.PropertyInput { public class ColorGradientPropertyInputViewModel : PropertyInputViewModel { - public ColorGradientPropertyInputViewModel(LayerProperty layerProperty, IProfileEditorService profileEditorService) + public ColorGradientPropertyInputViewModel(LayerProperty layerProperty, IProfileEditorService profileEditorService) : base(layerProperty, profileEditorService) { } diff --git a/src/Artemis.UI/PropertyInput/SKColorPropertyInputView.xaml b/src/Artemis.UI/PropertyInput/SKColorPropertyInputView.xaml index c1eb6cfaa..a27b8c8af 100644 --- a/src/Artemis.UI/PropertyInput/SKColorPropertyInputView.xaml +++ b/src/Artemis.UI/PropertyInput/SKColorPropertyInputView.xaml @@ -17,9 +17,9 @@ + Margin="0 -2 0 3" + Padding="0 -1" + Color="{Binding InputValue, Converter={StaticResource SKColorToColorConverter}}" /> \ No newline at end of file diff --git a/src/Artemis.UI/PropertyInput/SKPointPropertyInputView.xaml b/src/Artemis.UI/PropertyInput/SKPointPropertyInputView.xaml index 38f9ce08e..9d7a02ece 100644 --- a/src/Artemis.UI/PropertyInput/SKPointPropertyInputView.xaml +++ b/src/Artemis.UI/PropertyInput/SKPointPropertyInputView.xaml @@ -14,16 +14,16 @@ + Value="{Binding X}" + StepSize="{Binding LayerProperty.PropertyDescription.InputStepSize}" + DragStarted="{s:Action InputDragStarted}" + DragEnded="{s:Action InputDragEnded}" /> , + Value="{Binding Y}" + StepSize="{Binding LayerProperty.PropertyDescription.InputStepSize}" + DragStarted="{s:Action InputDragStarted}" + DragEnded="{s:Action InputDragEnded}" /> \ No newline at end of file diff --git a/src/Artemis.UI/PropertyInput/SKSizePropertyInputView.xaml b/src/Artemis.UI/PropertyInput/SKSizePropertyInputView.xaml index 237e29db1..bd41f054a 100644 --- a/src/Artemis.UI/PropertyInput/SKSizePropertyInputView.xaml +++ b/src/Artemis.UI/PropertyInput/SKSizePropertyInputView.xaml @@ -13,16 +13,16 @@ + Value="{Binding Height}" + StepSize="{Binding LayerProperty.PropertyDescription.InputStepSize}" + DragStarted="{s:Action InputDragStarted}" + DragEnded="{s:Action InputDragEnded}" /> , + Value="{Binding Width}" + StepSize="{Binding LayerProperty.PropertyDescription.InputStepSize}" + DragStarted="{s:Action InputDragStarted}" + DragEnded="{s:Action InputDragEnded}" /> \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ModuleRootViewModel.cs b/src/Artemis.UI/Screens/Module/ModuleRootViewModel.cs index 8d23a10d5..c0f230cf4 100644 --- a/src/Artemis.UI/Screens/Module/ModuleRootViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ModuleRootViewModel.cs @@ -1,5 +1,4 @@ -using System; -using System.Linq; +using System.Linq; using System.Threading.Tasks; using Artemis.Core.Plugins.Abstract; using Artemis.UI.Ninject.Factories; diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/RenameView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/RenameView.xaml index 8b8aeb136..a80c54313 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/RenameView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/RenameView.xaml @@ -9,8 +9,8 @@ d:DesignHeight="213.053" d:DesignWidth="254.425"> - - + + - Conditions will allow you to easily configure when a layer should be shown. + Conditions will allow you to easily configure when a layer should be shown. You'll also use this to set up how a layer reacts to its conditions being matched, like play the timeline once or keep repeating the timeline until the conditions are no longer matched. diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Abstract/LayerPropertyBaseViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Abstract/LayerPropertyBaseViewModel.cs index e3f0ac4d4..cbd0e5766 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Abstract/LayerPropertyBaseViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Abstract/LayerPropertyBaseViewModel.cs @@ -16,8 +16,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract public abstract bool IsVisible { get; } public List Children { get; set; } + public abstract void Dispose(); public abstract List GetKeyframes(bool expandedOnly); - public abstract void Dispose(); } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerEffects/EffectsView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerEffects/EffectsView.xaml index 0e006d289..03ceb7435 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerEffects/EffectsView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerEffects/EffectsView.xaml @@ -30,7 +30,7 @@ Visibility="{Binding HasLayerEffectDescriptors, Converter={x:Static s:BoolToVisibilityConverter.Instance}}"> - diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesView.xaml index 151366d0f..9d0cf4415 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesView.xaml @@ -136,7 +136,7 @@ - + diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs index faf79bd40..0b3f878bf 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs @@ -8,7 +8,6 @@ using Artemis.Core.Events; using Artemis.Core.Models.Profile; using Artemis.Core.Models.Profile.LayerProperties; using Artemis.Core.Models.Profile.LayerProperties.Attributes; -using Artemis.Core.Plugins.LayerBrush.Abstract; using Artemis.Core.Services; using Artemis.Core.Services.Interfaces; using Artemis.UI.Ninject.Factories; @@ -62,6 +61,21 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties public EffectsViewModel EffectsViewModel { get; set; } public TimelineViewModel TimelineViewModel { get; set; } + #region Effects + + public void ToggleAddEffect() + { + if (DateTime.Now - _lastToggle < TimeSpan.FromMilliseconds(500)) + return; + + _lastToggle = DateTime.Now; + PropertyTreeIndex = PropertyTreeIndex == 0 ? 1 : 0; + if (PropertyTreeIndex == 1) + EffectsViewModel.PopulateDescriptors(); + } + + #endregion + protected override void OnInitialActivate() { PopulateProperties(ProfileEditorService.SelectedProfileElement); @@ -115,10 +129,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties private void PopulateProperties(ProfileElement profileElement) { - if (SelectedFolder != null) - { - SelectedFolder = null; - } + if (SelectedFolder != null) SelectedFolder = null; if (SelectedLayer != null) { @@ -133,9 +144,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties _brushPropertyGroup = null; if (profileElement is Folder folder) - { SelectedFolder = folder; - } else if (profileElement is Layer layer) { SelectedLayer = layer; @@ -389,20 +398,5 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties } #endregion - - #region Effects - - public void ToggleAddEffect() - { - if (DateTime.Now - _lastToggle < TimeSpan.FromMilliseconds(500)) - return; - - _lastToggle = DateTime.Now; - PropertyTreeIndex = PropertyTreeIndex == 0 ? 1 : 0; - if (PropertyTreeIndex == 1) - EffectsViewModel.PopulateDescriptors(); - } - - #endregion } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyViewModel.cs index 22e7e31ff..f0a727569 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyViewModel.cs @@ -3,10 +3,10 @@ using System.Collections.Generic; using System.Linq; using Artemis.Core.Models.Profile.LayerProperties; using Artemis.UI.Exceptions; +using Artemis.UI.PropertyInput; using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract; using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline; using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree; -using Artemis.UI.PropertyInput; using Artemis.UI.Shared.PropertyInput; using Artemis.UI.Shared.Services.Interfaces; using Humanizer; diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/Controls/PropertyTimelineHeader.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/Controls/PropertyTimelineHeader.cs index df74157ac..84fa4c76c 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/Controls/PropertyTimelineHeader.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/Controls/PropertyTimelineHeader.cs @@ -16,7 +16,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline public static readonly DependencyProperty PixelsPerSecondProperty = DependencyProperty.Register(nameof(PixelsPerSecond), typeof(int), typeof(PropertyTimelineHeader), new FrameworkPropertyMetadata(default(int), FrameworkPropertyMetadataOptions.AffectsRender)); - + public static readonly DependencyProperty HorizontalOffsetProperty = DependencyProperty.Register(nameof(HorizontalOffset), typeof(double), typeof(PropertyTimelineHeader), new FrameworkPropertyMetadata(default(double), FrameworkPropertyMetadataOptions.AffectsRender)); diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineKeyframeViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineKeyframeViewModel.cs index d8aeb87c3..043427405 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineKeyframeViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineKeyframeViewModel.cs @@ -4,7 +4,6 @@ using System.Windows; using System.Windows.Input; using Artemis.Core.Models.Profile.LayerProperties; using Artemis.Core.Utilities; -using Artemis.UI.Services.Interfaces; using Artemis.UI.Shared.Services.Interfaces; using Stylet; diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelinePropertyGroupView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelinePropertyGroupView.xaml index b02d17c76..1fae0fbca 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelinePropertyGroupView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelinePropertyGroupView.xaml @@ -41,8 +41,7 @@ StrokeThickness="0" Width="10" Height="10" - Margin="-5,6,0,0"> - + Margin="-5,6,0,0" /> @@ -55,15 +54,15 @@ + VerticalContentAlignment="Stretch" + HorizontalContentAlignment="Stretch" + IsTabStop="False" /> + VerticalContentAlignment="Stretch" + HorizontalContentAlignment="Stretch" + IsTabStop="False" /> diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelinePropertyViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelinePropertyViewModel.cs index 688b621e0..a36a04d1c 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelinePropertyViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelinePropertyViewModel.cs @@ -2,7 +2,6 @@ using System.Linq; using Artemis.UI.Exceptions; using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract; -using Artemis.UI.Services.Interfaces; using Artemis.UI.Shared.Services.Interfaces; using Stylet; @@ -23,17 +22,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline _profileEditorService.PixelsPerSecondChanged += ProfileEditorServiceOnPixelsPerSecondChanged; } - private void LayerPropertyOnKeyframeModified(object sender, EventArgs e) - { - UpdateKeyframes(); - } - - private void ProfileEditorServiceOnPixelsPerSecondChanged(object sender, EventArgs e) - { - foreach (var timelineKeyframeViewModel in TimelineKeyframeViewModels) - timelineKeyframeViewModel.Update(_profileEditorService.PixelsPerSecond); - } - public LayerPropertyViewModel LayerPropertyViewModel { get; } public override void UpdateKeyframes() @@ -53,9 +41,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline ); } else - { TimelineKeyframeViewModels.Clear(); - } foreach (var timelineKeyframeViewModel in TimelineKeyframeViewModels) timelineKeyframeViewModel.Update(_profileEditorService.PixelsPerSecond); @@ -68,6 +54,17 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline LayerPropertyViewModel.LayerProperty.KeyframeRemoved -= LayerPropertyOnKeyframeModified; LayerPropertyViewModel.LayerProperty.KeyframesToggled -= LayerPropertyOnKeyframeModified; } + + private void LayerPropertyOnKeyframeModified(object sender, EventArgs e) + { + UpdateKeyframes(); + } + + private void ProfileEditorServiceOnPixelsPerSecondChanged(object sender, EventArgs e) + { + foreach (var timelineKeyframeViewModel in TimelineKeyframeViewModels) + timelineKeyframeViewModel.Update(_profileEditorService.PixelsPerSecond); + } } public abstract class TimelinePropertyViewModel : IDisposable @@ -82,8 +79,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline public TimelineViewModel TimelineViewModel { get; set; } public BindableCollection TimelineKeyframeViewModels { get; set; } - public abstract void UpdateKeyframes(); - public abstract void Dispose(); + + public abstract void UpdateKeyframes(); } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyGroupView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyGroupView.xaml index 21ced0a64..8604092ba 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyGroupView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyGroupView.xaml @@ -130,7 +130,7 @@ ToolTip="Rename" Width="24" Height="24" - VerticalAlignment="Center" + VerticalAlignment="Center" Command="{s:Action RenameEffect}"> @@ -140,11 +140,11 @@ ToolTip="Remove" Width="24" Height="24" - VerticalAlignment="Center" + VerticalAlignment="Center" Command="{s:Action DeleteEffect}"> - + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyGroupViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyGroupViewModel.cs index a1b90b712..5af7dbfb2 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyGroupViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyGroupViewModel.cs @@ -8,9 +8,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree { public class TreePropertyGroupViewModel { - private readonly IProfileEditorService _profileEditorService; - private readonly ILayerService _layerService; private readonly IDialogService _dialogService; + private readonly ILayerService _layerService; + private readonly IProfileEditorService _profileEditorService; public TreePropertyGroupViewModel(LayerPropertyBaseViewModel layerPropertyBaseViewModel, IProfileEditorService profileEditorService, ILayerService layerService, IDialogService dialogService) diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorViewModel.cs index dcb3cfdff..bc9b899f3 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorViewModel.cs @@ -11,10 +11,8 @@ using Artemis.Core.Services.Storage.Interfaces; using Artemis.UI.Screens.Module.ProfileEditor.Dialogs; using Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions; using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties; -using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract; using Artemis.UI.Screens.Module.ProfileEditor.ProfileTree; using Artemis.UI.Screens.Module.ProfileEditor.Visualization; -using Artemis.UI.Services.Interfaces; using Artemis.UI.Shared.Services.Interfaces; using Stylet; diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/ProfileTreeView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/ProfileTreeView.xaml index e6cb7c960..761447d45 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/ProfileTreeView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/ProfileTreeView.xaml @@ -25,7 +25,7 @@ - + - + diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/ProfileTreeViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/ProfileTreeViewModel.cs index 34a59503d..925e23b76 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/ProfileTreeViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/ProfileTreeViewModel.cs @@ -4,7 +4,6 @@ using System.Windows; using Artemis.Core.Models.Profile; using Artemis.UI.Ninject.Factories; using Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem; -using Artemis.UI.Services.Interfaces; using Artemis.UI.Shared.Services.Interfaces; using GongSolutions.Wpf.DragDrop; diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/FolderViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/FolderViewModel.cs index 36826950c..cf4722c41 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/FolderViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/FolderViewModel.cs @@ -1,7 +1,6 @@ using Artemis.Core.Models.Profile; using Artemis.Core.Services.Interfaces; using Artemis.UI.Ninject.Factories; -using Artemis.UI.Services.Interfaces; using Artemis.UI.Shared.Services.Interfaces; namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/LayerView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/LayerView.xaml index bfba28b80..e955fda0d 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/LayerView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/LayerView.xaml @@ -26,13 +26,13 @@ - + + Visibility="{Binding ShowIcons, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}" + Background="Transparent" /> diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/LayerViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/LayerViewModel.cs index 4aa6ad26b..99a4b506c 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/LayerViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/LayerViewModel.cs @@ -1,7 +1,6 @@ using Artemis.Core.Models.Profile; using Artemis.Core.Services.Interfaces; using Artemis.UI.Ninject.Factories; -using Artemis.UI.Services.Interfaces; using Artemis.UI.Shared.Services.Interfaces; namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem @@ -22,6 +21,5 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem public Layer Layer => ProfileElement as Layer; public bool ShowIcons => Layer?.LayerBrush != null; public override bool SupportsChildren => false; - } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs index fce6b0e02..e318e19b4 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs @@ -6,7 +6,6 @@ using Artemis.Core.Services.Interfaces; using Artemis.UI.Exceptions; using Artemis.UI.Ninject.Factories; using Artemis.UI.Screens.Module.ProfileEditor.Dialogs; -using Artemis.UI.Services.Interfaces; using Artemis.UI.Shared.Services.Interfaces; using Stylet; diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerView.xaml index f1a480253..0973f1062 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerView.xaml @@ -16,7 +16,7 @@ - + @@ -24,7 +24,7 @@ - + @@ -55,21 +55,20 @@ - - - + Style="{StaticResource SelectedLayerStyle}" /> \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerViewModel.cs index 97b681dae..652cf7a62 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerViewModel.cs @@ -7,7 +7,6 @@ using System.Windows.Media.Imaging; using Artemis.Core.Models.Profile; using Artemis.Core.Models.Profile.LayerShapes; using Artemis.Core.Models.Surface; -using Artemis.Core.Plugins.LayerBrush.Abstract; using Artemis.UI.Extensions; using Artemis.UI.Services.Interfaces; using Artemis.UI.Shared.Services.Interfaces; @@ -148,7 +147,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization break; } - if (Layer.LayerBrush == null || Layer.LayerBrush.SupportsTransformation) + if (Layer.LayerBrush == null || Layer.LayerBrush.SupportsTransformation) shapeGeometry.Transform = _layerEditorService.GetLayerTransformGroup(Layer); ShapeGeometry = shapeGeometry; diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileView.xaml index 0c40e351b..8775be1e3 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileView.xaml @@ -122,9 +122,9 @@ - + diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs index e7cf9a8a7..b3112afbc 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs @@ -6,8 +6,6 @@ using System.Windows.Input; using Artemis.Core.Events; using Artemis.Core.Models.Profile; using Artemis.Core.Models.Surface; -using Artemis.Core.Plugins.LayerBrush; -using Artemis.Core.Plugins.LayerBrush.Abstract; using Artemis.Core.Plugins.Models; using Artemis.Core.Services; using Artemis.Core.Services.Interfaces; diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionRemoveToolViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionRemoveToolViewModel.cs index 21d4a2ec7..4f67376ad 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionRemoveToolViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionRemoveToolViewModel.cs @@ -4,7 +4,6 @@ using System.Windows; using System.Windows.Input; using Artemis.Core.Models.Profile; using Artemis.UI.Properties; -using Artemis.UI.Services.Interfaces; using Artemis.UI.Shared.Services.Interfaces; namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionToolViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionToolViewModel.cs index 56e20911d..742cb2fd6 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionToolViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionToolViewModel.cs @@ -3,10 +3,8 @@ using System.Linq; using System.Windows; using System.Windows.Input; using Artemis.Core.Models.Profile; -using Artemis.Core.Services; using Artemis.Core.Services.Interfaces; using Artemis.UI.Properties; -using Artemis.UI.Services.Interfaces; using Artemis.UI.Shared.Services.Interfaces; namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/ViewpointMoveToolViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/ViewpointMoveToolViewModel.cs index 28246086f..ccd4f140b 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/ViewpointMoveToolViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/ViewpointMoveToolViewModel.cs @@ -1,5 +1,4 @@ using System.Windows.Input; -using Artemis.UI.Services.Interfaces; using Artemis.UI.Shared.Services.Interfaces; namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/VisualizationToolViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/VisualizationToolViewModel.cs index d0c7ad1b7..6632c8a1f 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/VisualizationToolViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/VisualizationToolViewModel.cs @@ -1,7 +1,6 @@ using System; using System.Windows; using System.Windows.Input; -using Artemis.UI.Services.Interfaces; using Artemis.UI.Shared.Services.Interfaces; namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools diff --git a/src/Artemis.UI/Screens/RootView.xaml b/src/Artemis.UI/Screens/RootView.xaml index a188a4773..a2c8d0ea3 100644 --- a/src/Artemis.UI/Screens/RootView.xaml +++ b/src/Artemis.UI/Screens/RootView.xaml @@ -51,18 +51,18 @@ - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/RootViewModel.cs b/src/Artemis.UI/Screens/RootViewModel.cs index 1e7c5e03b..a25ca502e 100644 --- a/src/Artemis.UI/Screens/RootViewModel.cs +++ b/src/Artemis.UI/Screens/RootViewModel.cs @@ -1,5 +1,4 @@ -using System; -using System.ComponentModel; +using System.ComponentModel; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; @@ -17,9 +16,9 @@ namespace Artemis.UI.Screens public class RootViewModel : Conductor { private readonly IEventAggregator _eventAggregator; + private readonly PluginSetting _colorScheme; private bool _lostFocus; - private PluginSetting _colorScheme; - private ThemeWatcher _themeWatcher; + private readonly ThemeWatcher _themeWatcher; public RootViewModel(IEventAggregator eventAggregator, SidebarViewModel sidebarViewModel, ISettingsService settingsService) { diff --git a/src/Artemis.UI/Screens/Settings/SettingsView.xaml b/src/Artemis.UI/Screens/Settings/SettingsView.xaml index 37ea52121..4db410ede 100644 --- a/src/Artemis.UI/Screens/Settings/SettingsView.xaml +++ b/src/Artemis.UI/Screens/Settings/SettingsView.xaml @@ -74,7 +74,7 @@ Color scheme - Pick between a light and dark color scheme, the automatic option copies your Windows settings. + Pick between a light and dark color scheme, the automatic option copies your Windows settings. diff --git a/src/Artemis.UI/Screens/Settings/SettingsViewModel.cs b/src/Artemis.UI/Screens/Settings/SettingsViewModel.cs index 332c94092..01ea815fb 100644 --- a/src/Artemis.UI/Screens/Settings/SettingsViewModel.cs +++ b/src/Artemis.UI/Screens/Settings/SettingsViewModel.cs @@ -3,10 +3,8 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; -using System.Net; using System.Threading.Tasks; using Artemis.Core; -using Artemis.Core.Plugins.Abstract; using Artemis.Core.Services; using Artemis.Core.Services.Interfaces; using Artemis.Core.Services.Storage.Interfaces; @@ -17,8 +15,6 @@ using Artemis.UI.Screens.Settings.Tabs.Devices; using Artemis.UI.Screens.Settings.Tabs.Plugins; using Artemis.UI.Shared.Services.Interfaces; using Artemis.UI.Shared.Utilities; -using Artemis.UI.Utilities; -using Microsoft.Win32; using Ninject; using Serilog.Events; using Stylet; @@ -120,8 +116,8 @@ namespace Artemis.UI.Screens.Settings _settingsService.GetSetting("Core.LoggingLevel", LogEventLevel.Information).Value = value; _settingsService.GetSetting("Core.LoggingLevel", LogEventLevel.Information).Save(); } - } - + } + public ApplicationColorScheme SelectedColorScheme { get => _settingsService.GetSetting("UI.ColorScheme", ApplicationColorScheme.Automatic).Value; @@ -197,10 +193,10 @@ namespace Artemis.UI.Screens.Settings DeviceSettingsViewModels.Clear(); DeviceSettingsViewModels.AddRange(_surfaceService.ActiveSurface.Devices.Select(d => _deviceSettingsVmFactory.Create(d))); - + Plugins.Clear(); Plugins.AddRange(_pluginService.GetAllPluginInfo().Select(p => new PluginSettingsViewModel(p.Instance, _windowManager, _dialogService, _pluginService))); - + base.OnInitialActivate(); } diff --git a/src/Artemis.UI/Screens/Settings/Tabs/Devices/DeviceSettingsViewModel.cs b/src/Artemis.UI/Screens/Settings/Tabs/Devices/DeviceSettingsViewModel.cs index 9f31e03ed..402eb0b2d 100644 --- a/src/Artemis.UI/Screens/Settings/Tabs/Devices/DeviceSettingsViewModel.cs +++ b/src/Artemis.UI/Screens/Settings/Tabs/Devices/DeviceSettingsViewModel.cs @@ -1,6 +1,5 @@ using System; using System.Diagnostics; -using System.IO; using Artemis.Core.Models.Surface; using Artemis.Core.Services; using Artemis.UI.Shared.Services.Interfaces; diff --git a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsView.xaml.cs b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsView.xaml.cs index 432ca670c..d845a142a 100644 --- a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsView.xaml.cs +++ b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsView.xaml.cs @@ -1,20 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; +using System.Windows.Controls; namespace Artemis.UI.Screens.Settings.Tabs.Plugins { /// - /// Interaction logic for PluginSettingsView.xaml + /// Interaction logic for PluginSettingsView.xaml /// public partial class PluginSettingsView : UserControl { @@ -23,4 +12,4 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins InitializeComponent(); } } -} +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsViewModel.cs b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsViewModel.cs index 4bdf74a6d..dd9a4fd8f 100644 --- a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsViewModel.cs +++ b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsViewModel.cs @@ -1,7 +1,6 @@ using System; using System.Threading.Tasks; using Artemis.Core.Plugins.Abstract; -using Artemis.Core.Plugins.LayerBrush; using Artemis.Core.Plugins.Models; using Artemis.Core.Services.Interfaces; using Artemis.UI.Shared.Services.Interfaces; @@ -33,34 +32,6 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins public PackIconKind Icon => GetIconKind(); - private PackIconKind GetIconKind() - { - if (PluginInfo.Icon != null) - { - var parsedIcon = Enum.TryParse(PluginInfo.Icon, true, out var iconEnum); - if (parsedIcon == false) - return PackIconKind.QuestionMarkCircle; - } - - switch (Plugin) - { - case DataModelExpansion _: - return PackIconKind.TableAdd; - case DeviceProvider _: - return PackIconKind.Devices; - case ProfileModule _: - return PackIconKind.VectorRectangle; - case Core.Plugins.Abstract.Module _: - return PackIconKind.GearBox; - case LayerBrushProvider _: - return PackIconKind.Brush; - case LayerEffectProvider _: - return PackIconKind.AutoAwesome; - } - - return PackIconKind.Plugin; - } - public bool IsEnabled { get => PluginInfo.Enabled; @@ -84,6 +55,34 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins } } + private PackIconKind GetIconKind() + { + if (PluginInfo.Icon != null) + { + var parsedIcon = Enum.TryParse(PluginInfo.Icon, true, out var iconEnum); + if (parsedIcon == false) + return PackIconKind.QuestionMarkCircle; + } + + switch (Plugin) + { + case DataModelExpansion _: + return PackIconKind.TableAdd; + case DeviceProvider _: + return PackIconKind.Devices; + case ProfileModule _: + return PackIconKind.VectorRectangle; + case Core.Plugins.Abstract.Module _: + return PackIconKind.GearBox; + case LayerBrushProvider _: + return PackIconKind.Brush; + case LayerEffectProvider _: + return PackIconKind.AutoAwesome; + } + + return PackIconKind.Plugin; + } + private async Task UpdateEnabled(bool enable) { if (PluginInfo.Enabled == enable) diff --git a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsWindowView.xaml b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsWindowView.xaml index b29094cb5..52706e2ec 100644 --- a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsWindowView.xaml +++ b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsWindowView.xaml @@ -1,23 +1,23 @@  + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:local="clr-namespace:Artemis.UI.Screens.Settings.Tabs.Plugins" + xmlns:controls="clr-namespace:MaterialDesignExtensions.Controls;assembly=MaterialDesignExtensions" + xmlns:s="https://github.com/canton7/Stylet" + mc:Ignorable="d" + Title="{Binding Title}" + Background="{DynamicResource MaterialDesignPaper}" + FontFamily="pack://application:,,,/MaterialDesignThemes.Wpf;component/Resources/Roboto/#Roboto" + UseLayoutRounding="True" + Width="800" + Height="800" + d:DesignHeight="800" + d:DesignWidth="800" + d:DataContext="{d:DesignInstance local:PluginSettingsWindowViewModel}" + Icon="/Resources/Images/Logo/logo-512.png"> - + - + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Splash/SplashViewModel.cs b/src/Artemis.UI/Screens/Splash/SplashViewModel.cs index 9e177b1d9..47955c793 100644 --- a/src/Artemis.UI/Screens/Splash/SplashViewModel.cs +++ b/src/Artemis.UI/Screens/Splash/SplashViewModel.cs @@ -46,7 +46,7 @@ namespace Artemis.UI.Screens.Splash _pluginService.PluginLoaded -= OnPluginServiceOnPluginLoaded; base.OnClose(); } - + private void OnPluginServiceOnPluginLoaded(object sender, PluginEventArgs args) { Status = "Initializing UI"; diff --git a/src/Artemis.UI/Screens/SurfaceEditor/SurfaceEditorViewModel.cs b/src/Artemis.UI/Screens/SurfaceEditor/SurfaceEditorViewModel.cs index 82525e9cc..75d63ad13 100644 --- a/src/Artemis.UI/Screens/SurfaceEditor/SurfaceEditorViewModel.cs +++ b/src/Artemis.UI/Screens/SurfaceEditor/SurfaceEditorViewModel.cs @@ -24,11 +24,11 @@ namespace Artemis.UI.Screens.SurfaceEditor { private readonly IDeviceService _deviceService; private readonly IDialogService _dialogService; - private readonly ISettingsService _settingsService; private readonly IRgbService _rgbService; + private readonly ISettingsService _settingsService; private readonly ISurfaceService _surfaceService; - public SurfaceEditorViewModel(IRgbService rgbService, ISurfaceService surfaceService, IDialogService dialogService, ISettingsService settingsService, + public SurfaceEditorViewModel(IRgbService rgbService, ISurfaceService surfaceService, IDialogService dialogService, ISettingsService settingsService, IDeviceService deviceService) { DisplayName = "Surface Editor"; diff --git a/src/Artemis.UI/Screens/SurfaceEditor/Visualization/SurfaceDeviceView.xaml b/src/Artemis.UI/Screens/SurfaceEditor/Visualization/SurfaceDeviceView.xaml index 3a2b7f9e2..2acf46f6f 100644 --- a/src/Artemis.UI/Screens/SurfaceEditor/Visualization/SurfaceDeviceView.xaml +++ b/src/Artemis.UI/Screens/SurfaceEditor/Visualization/SurfaceDeviceView.xaml @@ -26,7 +26,7 @@ - + Device.RgbDevice == null ? new Rect() : new Rect(Device.X, Device.Y, Device.RgbDevice.DeviceRectangle.Size.Width, Device.RgbDevice.DeviceRectangle.Size.Height); diff --git a/src/Artemis.UI/Screens/TrayView.xaml b/src/Artemis.UI/Screens/TrayView.xaml index bcf4665d2..0ff53f55d 100644 --- a/src/Artemis.UI/Screens/TrayView.xaml +++ b/src/Artemis.UI/Screens/TrayView.xaml @@ -1,17 +1,17 @@  + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:tb="http://www.hardcodet.net/taskbar" + xmlns:s="https://github.com/canton7/Stylet" + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:controls="clr-namespace:MaterialDesignExtensions.Controls;assembly=MaterialDesignExtensions" + mc:Ignorable="d" + Title="Artemis" + Height="1" + Width="1" + Visibility="Hidden"> - + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/TrayViewModel.cs b/src/Artemis.UI/Screens/TrayViewModel.cs index 9a0746c23..6000de372 100644 --- a/src/Artemis.UI/Screens/TrayViewModel.cs +++ b/src/Artemis.UI/Screens/TrayViewModel.cs @@ -3,11 +3,10 @@ using Artemis.Core.Services.Interfaces; using Artemis.Core.Utilities; using Artemis.UI.Events; using Artemis.UI.Screens.Splash; -using Artemis.UI.Shared; +using Artemis.UI.Shared.Controls; using Artemis.UI.Shared.Services.Interfaces; using Ninject; using Stylet; -using GradientPicker = Artemis.UI.Shared.Controls.GradientPicker; namespace Artemis.UI.Screens { diff --git a/src/Artemis.UI/Services/LayerEditorService.cs b/src/Artemis.UI/Services/LayerEditorService.cs index 3ad8008f2..c9dc4c7d3 100644 --- a/src/Artemis.UI/Services/LayerEditorService.cs +++ b/src/Artemis.UI/Services/LayerEditorService.cs @@ -3,10 +3,8 @@ using System.Windows; using System.Windows.Media; using Artemis.Core; using Artemis.Core.Models.Profile; -using Artemis.Core.Models.Profile.Colors; using Artemis.Core.Services; using Artemis.UI.PropertyInput; -using Artemis.UI.PropertyInput; using Artemis.UI.Services.Interfaces; using Artemis.UI.Shared.Services.Interfaces; using SkiaSharp; @@ -16,8 +14,8 @@ namespace Artemis.UI.Services { public class LayerEditorService : ILayerEditorService { - private readonly ISettingsService _settingsService; private readonly IProfileEditorService _profileEditorService; + private readonly ISettingsService _settingsService; public LayerEditorService(ISettingsService settingsService, IProfileEditorService profileEditorService) { @@ -26,17 +24,6 @@ namespace Artemis.UI.Services RegisterBuiltInPropertyEditors(); } - private void RegisterBuiltInPropertyEditors() - { - _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(BrushPropertyInputViewModel)); - _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(ColorGradientPropertyInputViewModel)); - _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(FloatPropertyInputViewModel)); - _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(IntPropertyInputViewModel)); - _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(SKColorPropertyInputViewModel)); - _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(SKPointPropertyInputViewModel)); - _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(SKSizePropertyInputViewModel)); - } - /// public Rect GetLayerBounds(Layer layer) { @@ -151,5 +138,16 @@ namespace Artemis.UI.Services // The difference between the two is the offset return topLeft - tempTopLeft; } + + private void RegisterBuiltInPropertyEditors() + { + _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(BrushPropertyInputViewModel)); + _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(ColorGradientPropertyInputViewModel)); + _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(FloatPropertyInputViewModel)); + _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(IntPropertyInputViewModel)); + _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(SKColorPropertyInputViewModel)); + _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(SKPointPropertyInputViewModel)); + _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(SKSizePropertyInputViewModel)); + } } } \ No newline at end of file diff --git a/src/Artemis.UI/Stylet/ArtemisViewManager.cs b/src/Artemis.UI/Stylet/ArtemisViewManager.cs index 40fbb62d6..9d9d1f511 100644 --- a/src/Artemis.UI/Stylet/ArtemisViewManager.cs +++ b/src/Artemis.UI/Stylet/ArtemisViewManager.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using Stylet; +using Stylet; namespace Artemis.UI.Stylet {