-
Notifications
You must be signed in to change notification settings - Fork 18
/
Annotations.cs
2096 lines (1886 loc) · 84.7 KB
/
Annotations.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* MIT License
Copyright (c) 2016 JetBrains http://www.jetbrains.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. */
#nullable disable
using System;
using System.Diagnostics;
#pragma warning disable 1591
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable UnusedAutoPropertyAccessor.Global
// ReSharper disable IntroduceOptionalParameters.Global
// ReSharper disable MemberCanBeProtected.Global
// ReSharper disable ConvertToPrimaryConstructor
// ReSharper disable RedundantTypeDeclarationBody
// ReSharper disable ArrangeNamespaceBody
// ReSharper disable InconsistentNaming
namespace JetBrains.Annotations
{
/// <summary>
/// Indicates that the value of the marked element could be <c>null</c> sometimes,
/// so checking for <c>null</c> is required before its usage.
/// </summary>
/// <example><code>
/// [CanBeNull] object Test() => null;
///
/// void UseTest() {
/// var p = Test();
/// var s = p.ToString(); // Warning: Possible 'System.NullReferenceException'
/// }
/// </code></example>
[AttributeUsage(
AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property |
AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event |
AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class CanBeNullAttribute : Attribute { }
/// <summary>
/// Indicates that the value of the marked element can never be <c>null</c>.
/// </summary>
/// <example><code>
/// [NotNull] object Foo() {
/// return null; // Warning: Possible 'null' assignment
/// }
/// </code></example>
[AttributeUsage(
AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property |
AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event |
AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class NotNullAttribute : Attribute { }
/// <summary>
/// Can be applied to symbols of types derived from <c>IEnumerable</c> as well as to symbols of <c>Task</c>
/// and <c>Lazy</c> classes to indicate that the value of a collection item, of the <c>Task.Result</c> property,
/// or of the <c>Lazy.Value</c> property can never be null.
/// </summary>
/// <example><code>
/// public void Foo([ItemNotNull]List<string> books)
/// {
/// foreach (var book in books) {
/// if (book != null) // Warning: Expression is always true
/// Console.WriteLine(book.ToUpper());
/// }
/// }
/// </code></example>
[AttributeUsage(
AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property |
AttributeTargets.Delegate | AttributeTargets.Field)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class ItemNotNullAttribute : Attribute { }
/// <summary>
/// Can be applied to symbols of types derived from <c>IEnumerable</c> as well as to symbols of <c>Task</c>
/// and <c>Lazy</c> classes to indicate that the value of a collection item, of the <c>Task.Result</c> property,
/// or of the <c>Lazy.Value</c> property can be null.
/// </summary>
/// <example><code>
/// public void Foo([ItemCanBeNull]List<string> books)
/// {
/// foreach (var book in books)
/// {
/// // Warning: Possible 'System.NullReferenceException'
/// Console.WriteLine(book.ToUpper());
/// }
/// }
/// </code></example>
[AttributeUsage(
AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property |
AttributeTargets.Delegate | AttributeTargets.Field)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class ItemCanBeNullAttribute : Attribute { }
/// <summary>
/// Indicates that the marked method builds a string by the format pattern and (optional) arguments.
/// The parameter that accepts the format string should be specified in the constructor. The format string
/// should be in the <see cref="string.Format(IFormatProvider,string,object[])"/>-like form.
/// </summary>
/// <example><code>
/// [StringFormatMethod("message")]
/// void ShowError(string message, params object[] args) { /* do something */ }
///
/// void Foo() {
/// ShowError("Failed: {0}"); // Warning: Non-existing argument in format string
/// }
/// </code></example>
/// <seealso cref="StructuredMessageTemplateAttribute"/>
[AttributeUsage(
AttributeTargets.Constructor | AttributeTargets.Method |
AttributeTargets.Property | AttributeTargets.Delegate)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class StringFormatMethodAttribute : Attribute
{
/// <param name="formatParameterName">
/// Specifies which parameter of an annotated method should be treated as the format string.
/// </param>
public StringFormatMethodAttribute([NotNull] string formatParameterName)
{
FormatParameterName = formatParameterName;
}
[NotNull] public string FormatParameterName { get; }
}
/// <summary>
/// Indicates that the marked parameter is a message template where placeholders are to be replaced by
/// the following arguments in the order in which they appear.
/// </summary>
/// <example><code>
/// void LogInfo([StructuredMessageTemplate]string message, params object[] args) { /* do something */ }
///
/// void Foo() {
/// LogInfo("User created: {username}"); // Warning: Non-existing argument in format string
/// }
/// </code></example>
/// <seealso cref="StringFormatMethodAttribute"/>
[AttributeUsage(AttributeTargets.Parameter)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class StructuredMessageTemplateAttribute : Attribute {}
/// <summary>
/// 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.
/// </summary>
/// <example><code>
/// 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*/
/// }
/// }
/// }
/// </code></example>
[AttributeUsage(
AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field,
AllowMultiple = true)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class ValueProviderAttribute : Attribute
{
public ValueProviderAttribute([NotNull] string name)
{
Name = name;
}
[NotNull] public string Name { get; }
}
/// <summary>
/// Indicates that the integral value falls into the specified interval.
/// It is allowed to specify multiple non-intersecting intervals.
/// Values of interval boundaries are included in the interval.
/// </summary>
/// <example><code>
/// void Foo([ValueRange(0, 100)] int value) {
/// if (value == -1) { // Warning: Expression is always 'false'
/// ...
/// }
/// }
/// </code></example>
[AttributeUsage(
AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property |
AttributeTargets.Method | AttributeTargets.Delegate,
AllowMultiple = true)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class ValueRangeAttribute : Attribute
{
public object From { get; }
public object To { get; }
public ValueRangeAttribute(long from, long to)
{
From = from;
To = to;
}
public ValueRangeAttribute(ulong from, ulong to)
{
From = from;
To = to;
}
public ValueRangeAttribute(long value)
{
From = To = value;
}
public ValueRangeAttribute(ulong value)
{
From = To = value;
}
}
/// <summary>
/// Indicates that the integral value never falls below zero.
/// </summary>
/// <example><code>
/// void Foo([NonNegativeValue] int value) {
/// if (value == -1) { // Warning: Expression is always 'false'
/// ...
/// }
/// }
/// </code></example>
[AttributeUsage(
AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property |
AttributeTargets.Method | AttributeTargets.Delegate)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class NonNegativeValueAttribute : Attribute { }
/// <summary>
/// Indicates that the function argument should be a string literal and match
/// one of the parameters of the caller function. This annotation is used for parameters
/// like <c>string paramName</c> parameter of the <see cref="System.ArgumentNullException"/> constructor.
/// </summary>
/// <example><code>
/// void Foo(string param) {
/// if (param == null)
/// throw new ArgumentNullException("par"); // Warning: Cannot resolve symbol
/// }
/// </code></example>
[AttributeUsage(AttributeTargets.Parameter)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class InvokerParameterNameAttribute : Attribute { }
/// <summary>
/// Indicates that the method is contained in a type that implements the
/// <c>System.ComponentModel.INotifyPropertyChanged</c> interface and this method
/// is used to notify that some property value changed.
/// </summary>
/// <remarks>
/// The method should be non-static and conform to one of the supported signatures:
/// <list>
/// <item><c>NotifyChanged(string)</c></item>
/// <item><c>NotifyChanged(params string[])</c></item>
/// <item><c>NotifyChanged{T}(Expression{Func{T}})</c></item>
/// <item><c>NotifyChanged{T,U}(Expression{Func{T,U}})</c></item>
/// <item><c>SetProperty{T}(ref T, T, string)</c></item>
/// </list>
/// </remarks>
/// <example><code>
/// 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 */ }
/// }
/// }
/// </code>
/// Examples of generated notifications:
/// <list>
/// <item><c>NotifyChanged("Property")</c></item>
/// <item><c>NotifyChanged(() => Property)</c></item>
/// <item><c>NotifyChanged((VM x) => x.Property)</c></item>
/// <item><c>SetProperty(ref myField, value, "Property")</c></item>
/// </list>
/// </example>
[AttributeUsage(AttributeTargets.Method)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class NotifyPropertyChangedInvocatorAttribute : Attribute
{
public NotifyPropertyChangedInvocatorAttribute() { }
public NotifyPropertyChangedInvocatorAttribute([NotNull] string parameterName)
{
ParameterName = parameterName;
}
[CanBeNull] public string ParameterName { get; }
}
/// <summary>
/// Describes dependence between the input and output of a method.
/// </summary>
/// <syntax>
/// <p>Function Definition Table syntax:</p>
/// <list>
/// <item>FDT ::= FDTRow [;FDTRow]*</item>
/// <item>FDTRow ::= Input => Output | Output <= Input</item>
/// <item>Input ::= ParameterName: Value [, Input]*</item>
/// <item>Output ::= [ParameterName: Value]* {halt|stop|void|nothing|Value}</item>
/// <item>Value ::= true | false | null | notnull | canbenull</item>
/// </list>
/// If the method has a single input parameter, its name could be omitted.<br/>
/// Using <c>halt</c> (or <c>void</c>/<c>nothing</c>, which is the same) for the method output
/// means that the method doesn't return normally (throws or terminates the process).<br/>
/// The <c>canbenull</c> value is only applicable to output parameters.<br/>
/// You can use multiple <c>[ContractAnnotation]</c> for each FDT row, or use a single attribute
/// with rows separated by the semicolon. The order of rows doesn't matter, all rows are checked
/// for applicability and applied per each program state tracked by the analysis engine.<br/>
/// </syntax>
/// <examples><list>
/// <item><code>
/// [ContractAnnotation("=> halt")]
/// public void TerminationMethod()
/// </code></item>
/// <item><code>
/// [ContractAnnotation("null <= param:null")] // reverse condition syntax
/// public string GetName(string surname)
/// </code></item>
/// <item><code>
/// [ContractAnnotation("s:null => true")]
/// public bool IsNullOrEmpty(string s) // string.IsNullOrEmpty()
/// </code></item>
/// <item><code>
/// // 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)
/// </code></item>
/// <item><code>
/// [ContractAnnotation("=> true, result: notnull; => false, result: null")]
/// public bool TryParse(string s, out Person result)
/// </code></item>
/// </list></examples>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
[Conditional("JETBRAINS_ANNOTATIONS")]
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; }
}
/// <summary>
/// Indicates whether the marked element should be localized.
/// </summary>
/// <example><code>
/// [LocalizationRequiredAttribute(true)]
/// class Foo {
/// string str = "my string"; // Warning: Localizable string
/// }
/// </code></example>
[AttributeUsage(AttributeTargets.All)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class LocalizationRequiredAttribute : Attribute
{
public LocalizationRequiredAttribute() : this(true) { }
public LocalizationRequiredAttribute(bool required)
{
Required = required;
}
public bool Required { get; }
}
/// <summary>
/// Indicates that the value of the marked type (or its derivatives)
/// cannot be compared using <c>==</c> or <c>!=</c> operators, and <c>Equals()</c>
/// should be used instead. However, using <c>==</c> or <c>!=</c> for comparison
/// with <c>null</c> is always permitted.
/// </summary>
/// <example><code>
/// [CannotApplyEqualityOperator]
/// class NoEquality { }
///
/// class UsesNoEquality {
/// void Test() {
/// var ca1 = new NoEquality();
/// var ca2 = new NoEquality();
/// if (ca1 != null) { // OK
/// bool condition = ca1 == ca2; // Warning
/// }
/// }
/// }
/// </code></example>
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class CannotApplyEqualityOperatorAttribute : Attribute { }
/// <summary>
/// Indicates that the method or type uses equality members of the annotated element.
/// </summary>
/// <remarks>
/// When applied to the method's generic parameter, indicates that the equality of the annotated type is used,
/// unless a custom equality comparer is passed when calling this method. The attribute can also be applied
/// directly to the method's parameter or return type to specify equality usage for it.
/// When applied to the type's generic parameter, indicates that type equality usage can happen anywhere
/// inside this type, so the instantiation of this type is treated as equality usage, unless a custom
/// equality comparer is passed to the constructor.
/// </remarks>
/// <example><code>
/// struct StructWithDefaultEquality { }
///
/// class MySet<[DefaultEqualityUsage] T> { }
///
/// static class Extensions {
/// public static MySet<T> ToMySet<[DefaultEqualityUsage] T>(this IEnumerable<T> items) => new();
/// }
///
/// class MyList<T> { public int IndexOf([DefaultEqualityUsage] T item) => 0; }
///
/// class UsesDefaultEquality {
/// void Test() {
/// var list = new MyList<StructWithDefaultEquality>();
/// list.IndexOf(new StructWithDefaultEquality()); // Warning: Default equality of struct 'StructWithDefaultEquality' is used
///
/// var set = new MySet<StructWithDefaultEquality>(); // Warning: Default equality of struct 'StructWithDefaultEquality' is used
/// var set2 = new StructWithDefaultEquality[1].ToMySet(); // Warning: Default equality of struct 'StructWithDefaultEquality' is used
/// }
/// }
/// </code></example>
[AttributeUsage(AttributeTargets.GenericParameter | AttributeTargets.Parameter | AttributeTargets.ReturnValue)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class DefaultEqualityUsageAttribute : Attribute { }
/// <summary>
/// When applied to a target attribute, specifies a requirement for any type marked
/// with the target attribute to implement or inherit the specific type or types.
/// </summary>
/// <example><code>
/// [BaseTypeRequired(typeof(IComponent)] // Specify requirement
/// class ComponentAttribute : Attribute { }
///
/// [Component] // ComponentAttribute requires implementing IComponent interface
/// class MyComponent : IComponent { }
/// </code></example>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
[BaseTypeRequired(typeof(Attribute))]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class BaseTypeRequiredAttribute : Attribute
{
public BaseTypeRequiredAttribute([NotNull] Type baseType)
{
BaseType = baseType;
}
[NotNull] public Type BaseType { get; }
}
/// <summary>
/// Indicates that the marked symbol is used implicitly (via reflection, in an external library, and so on),
/// so this symbol will be ignored by usage-checking inspections. <br/>
/// You can use <see cref="ImplicitUseKindFlags"/> and <see cref="ImplicitUseTargetFlags"/>
/// to configure how this attribute is applied.
/// </summary>
/// <example><code>
/// [UsedImplicitly]
/// public class TypeConverter {}
///
/// public class SummaryData
/// {
/// [UsedImplicitly(ImplicitUseKindFlags.InstantiatedWithFixedConstructorSignature)]
/// public SummaryData() {}
/// }
///
/// [UsedImplicitly(ImplicitUseTargetFlags.WithInheritors | ImplicitUseTargetFlags.Default)]
/// public interface IService {}
/// </code></example>
[AttributeUsage(AttributeTargets.All)]
[Conditional("JETBRAINS_ANNOTATIONS")]
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; }
public string Reason { get; set; }
}
/// <summary>
/// Can be applied to attributes, type parameters, and parameters of a type assignable from <see cref="System.Type"/>.
/// When applied to an attribute, the decorated attribute behaves the same as <see cref="UsedImplicitlyAttribute"/>.
/// When applied to a type parameter or to a parameter of type <see cref="System.Type"/>,
/// indicates that the corresponding type is used implicitly.
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.GenericParameter | AttributeTargets.Parameter)]
[Conditional("JETBRAINS_ANNOTATIONS")]
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; }
}
/// <summary>
/// Specifies the details of an implicitly used symbol when it is marked
/// with <see cref="MeansImplicitUseAttribute"/> or <see cref="UsedImplicitlyAttribute"/>.
/// </summary>
[Flags]
public enum ImplicitUseKindFlags
{
Default = Access | Assign | InstantiatedWithFixedConstructorSignature,
/// <summary>Only entity marked with attribute considered used.</summary>
Access = 1,
/// <summary>Indicates implicit assignment to a member.</summary>
Assign = 2,
/// <summary>
/// Indicates implicit instantiation of a type with fixed constructor signature.
/// That means any unused constructor parameters will not be reported as such.
/// </summary>
InstantiatedWithFixedConstructorSignature = 4,
/// <summary>Indicates implicit instantiation of a type.</summary>
InstantiatedNoFixedConstructorSignature = 8,
}
/// <summary>
/// Specifies what is considered to be used implicitly when marked
/// with <see cref="MeansImplicitUseAttribute"/> or <see cref="UsedImplicitlyAttribute"/>.
/// </summary>
[Flags]
public enum ImplicitUseTargetFlags
{
Default = Itself,
Itself = 1,
/// <summary>Members of the type marked with the attribute are considered used.</summary>
Members = 2,
/// <summary> Inherited entities are considered used. </summary>
WithInheritors = 4,
/// <summary>Entity marked with the attribute and all its members considered used.</summary>
WithMembers = Itself | Members
}
/// <summary>
/// This attribute is intended to mark publicly available APIs
/// that should not be removed and therefore should never be reported as unused.
/// </summary>
[MeansImplicitUse(ImplicitUseTargetFlags.WithMembers)]
[AttributeUsage(AttributeTargets.All, Inherited = false)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class PublicAPIAttribute : Attribute
{
public PublicAPIAttribute() { }
public PublicAPIAttribute([NotNull] string comment)
{
Comment = comment;
}
[CanBeNull] public string Comment { get; }
}
/// <summary>
/// Tells the code analysis engine if the parameter is completely handled when the invoked method is on stack.
/// If the parameter is a delegate, indicates that the delegate can only be invoked during method execution
/// (the delegate can be invoked zero or multiple times, but not stored to some field and invoked later,
/// when the containing method is no longer on the execution stack).
/// If the parameter is an enumerable, indicates that it is enumerated while the method is executed.
/// If <see cref="RequireAwait"/> is true, the attribute will only take effect
/// if the method invocation is located under the <c>await</c> expression.
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class InstantHandleAttribute : Attribute
{
/// <summary>
/// Requires the method invocation to be used under the <c>await</c> expression for this attribute to take effect.
/// Can be used for delegate/enumerable parameters of <c>async</c> methods.
/// </summary>
public bool RequireAwait { get; set; }
}
/// <summary>
/// Indicates that the method does not make any observable state changes.
/// The same as <see cref="T:System.Diagnostics.Contracts.PureAttribute"/>.
/// </summary>
/// <example><code>
/// [Pure] int Multiply(int x, int y) => x * y;
///
/// void M() {
/// Multiply(123, 42); // Warning: Return value of pure method is not used
/// }
/// </code></example>
[AttributeUsage(AttributeTargets.Method)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class PureAttribute : Attribute { }
/// <summary>
/// Indicates that the return value of the method invocation must be used.
/// </summary>
/// <remarks>
/// Methods decorated with this attribute (in contrast to pure methods) might change state,
/// but make no sense without using their return value. <br/>
/// Similarly to <see cref="PureAttribute"/>, this attribute
/// will help detect usages of the method when the return value is not used.
/// Optionally, you can specify a message to use when showing warnings, e.g.
/// <code>[MustUseReturnValue("Use the return value to...")]</code>.
/// </remarks>
[AttributeUsage(AttributeTargets.Method)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class MustUseReturnValueAttribute : Attribute
{
public MustUseReturnValueAttribute() { }
public MustUseReturnValueAttribute([NotNull] string justification)
{
Justification = justification;
}
[CanBeNull] public string Justification { get; }
/// <summary>
/// Enables the special handling of the "fluent" APIs that perform mutations and return 'this' object.
/// In this case the analysis checks the fluent invocations chain and only warns if the initial receiver value
/// is probably a temporary value - in this case the very last fluent method return assumed to be temporary as well,
/// therefore is a subject of warning if unused. If the initial receiver is a local variable or 'this' reference
/// the analysis assumes that fluent invocations were used to mutate the existing value and warning will not be shown.
/// </summary>
/// <remarks>
/// This property must only be used for methods with the return type matching the receiver type.
/// </remarks>
public bool IsFluentBuilderMethod { get; set; }
}
/// <summary>
/// Indicates that the resource disposal must be handled at the use site,
/// meaning that the resource ownership is transferred to the caller.
/// This annotation can be used to annotate disposable types or their constructors individually to enable
/// the IDE code analysis for resource disposal in every context where the new instance of this type is created.
/// Factory methods and <c>out</c> parameters can also be annotated to indicate that the return value
/// of the disposable type needs handling.
/// </summary>
/// <remarks>
/// Annotation of input parameters with this attribute is meaningless.<br/>
/// Constructors inherit this attribute from their type if it is annotated,
/// but not from the base constructors they delegate to (if any).<br/>
/// Resource disposal is expected via <c>using (resource)</c> statement,
/// <c>using var</c> declaration, explicit <c>Dispose()</c> call, or passing the resource as an argument
/// to a parameter annotated with the <see cref="HandlesResourceDisposalAttribute"/> attribute.
/// </remarks>
[AttributeUsage(
AttributeTargets.Class | AttributeTargets.Struct |
AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Parameter)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class MustDisposeResourceAttribute : Attribute
{
public MustDisposeResourceAttribute()
{
Value = true;
}
public MustDisposeResourceAttribute(bool value)
{
Value = value;
}
/// <summary>
/// When set to <c>false</c>, disposing of the resource is not obligatory.
/// The main use-case for explicit <c>[MustDisposeResource(false)]</c> annotation
/// is to loosen the annotation for inheritors.
/// </summary>
public bool Value { get; }
}
/// <summary>
/// Indicates that method or class instance acquires resource ownership and will dispose it after use.
/// </summary>
/// <remarks>
/// Annotation of <c>out</c> parameters with this attribute is meaningless.<br/>
/// When an instance method is annotated with this attribute,
/// it means that it is handling the resource disposal of the corresponding resource instance.<br/>
/// When a field or a property is annotated with this attribute, it means that this type owns the resource
/// and will handle the resource disposal properly (e.g. in own <c>IDisposable</c> implementation).
/// </remarks>
[AttributeUsage(
AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class HandlesResourceDisposalAttribute : Attribute { }
/// <summary>
/// This annotation allows enforcing allocation-less usage patterns of delegates for performance-critical APIs.
/// When this annotation is applied to the parameter of a delegate type,
/// the IDE checks the input argument of this parameter:
/// * When a lambda expression or anonymous method is passed as an argument, the IDE verifies that the passed closure
/// has no captures of the containing local variables and the compiler is able to cache the delegate instance
/// to avoid heap allocations. Otherwise, a warning is produced.
/// * The IDE warns when the method name or local function name is passed as an argument because this always results
/// in heap allocation of the delegate instance.
/// </summary>
/// <remarks>
/// In C# 9.0+ code, the IDE will also suggest annotating the anonymous functions with the <c>static</c> modifier
/// to make use of the similar analysis provided by the language/compiler.
/// </remarks>
[AttributeUsage(AttributeTargets.Parameter)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class RequireStaticDelegateAttribute : Attribute
{
public bool IsError { get; set; }
}
/// <summary>
/// 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 the existing one.
/// </summary>
/// <example><code>
/// class Foo {
/// [ProvidesContext] IBarService _barService = ...;
///
/// void ProcessNode(INode node) {
/// DoSomething(node, node.GetGlobalServices().Bar);
/// // ^ Warning: use value of '_barService' field
/// }
/// }
/// </code></example>
[AttributeUsage(
AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.Method |
AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.GenericParameter)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class ProvidesContextAttribute : Attribute { }
/// <summary>
/// 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 (~).
/// </summary>
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class PathReferenceAttribute : Attribute
{
public PathReferenceAttribute() { }
public PathReferenceAttribute([NotNull, PathReference] string basePath)
{
BasePath = basePath;
}
[CanBeNull] public string BasePath { get; }
}
/// <summary>
/// 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 the call site.
/// </summary>
/// <remarks>
/// Template method bodies 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 <see cref="MacroAttribute"/> attribute to specify macros for parameters.
/// The expression to be used in the expansion can be adjusted
/// by the <see cref="SourceTemplateAttribute.Target"/> parameter.
/// </remarks>
/// <example>
/// In this example, the <c>forEach</c> method is a source template available over all values
/// of enumerable types, producing an ordinary C# <c>foreach</c> statement and placing the caret inside the block:
/// <code>
/// [SourceTemplate]
/// public static void forEach<T>(this IEnumerable<T> xs) {
/// foreach (var x in xs) {
/// //$ $END$
/// }
/// }
/// </code>
/// </example>
[AttributeUsage(AttributeTargets.Method)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class SourceTemplateAttribute : Attribute
{
/// <summary>
/// Allows specifying the expression to capture for template execution if more than one expression
/// is available at the expansion point.
/// If not specified, <see cref="SourceTemplateTargetExpression.Inner"/> is assumed.
/// </summary>
public SourceTemplateTargetExpression Target { get; set; }
}
/// <summary>
/// Provides a value for the <see cref="SourceTemplateAttribute"/> to define how to capture
/// the expression at the point of expansion
/// </summary>
public enum SourceTemplateTargetExpression
{
/// <summary>Selects inner expression</summary>
/// <example><c>value > 42.{caret}</c> captures <c>42</c></example>
/// <example><c>_args = args.{caret}</c> captures <c>args</c></example>
Inner = 0,
/// <summary>Selects outer expression</summary>
/// <example><c>value > 42.{caret}</c> captures <c>value > 42</c></example>
/// <example><c>_args = args.{caret}</c> captures whole assignment</example>
Outer = 1
}
/// <summary>
/// Allows specifying a macro for a parameter of a <see cref="SourceTemplateAttribute">source template</see>.
/// </summary>
/// <remarks>
/// You can apply the attribute to the whole method or to any of its additional parameters. The macro expression
/// is defined in the <see cref="MacroAttribute.Expression"/> property. When applied to a method, the target
/// template parameter is defined in the <see cref="MacroAttribute.Target"/> property. To apply the macro silently
/// for the parameter, set the <see cref="MacroAttribute.Editable"/> property value to -1.
/// </remarks>
/// <example>
/// Applying the attribute to a source template method:
/// <code>
/// [SourceTemplate, Macro(Target = "item", Expression = "suggestVariableName()")]
/// public static void forEach<T>(this IEnumerable<T> collection) {
/// foreach (var item in collection) {
/// //$ $END$
/// }
/// }
/// </code>
/// Applying the attribute to a template method parameter:
/// <code>
/// [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); */
/// }
/// </code>
/// </example>
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method, AllowMultiple = true)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class MacroAttribute : Attribute
{
/// <summary>
/// Allows specifying a macro that will be executed for a <see cref="SourceTemplateAttribute">source template</see>
/// parameter when the template is expanded.
/// </summary>
[CanBeNull] public string Expression { get; set; }
/// <summary>
/// Allows specifying the occurrence of the target parameter that becomes editable when the template is deployed.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
public int Editable { get; set; }
/// <summary>
/// Identifies the target parameter of a <see cref="SourceTemplateAttribute">source template</see> if the
/// <see cref="MacroAttribute"/> is applied to a template method.
/// </summary>
[CanBeNull] public string Target { get; set; }
}
/// <summary>
/// Indicates how a method, constructor invocation, or property access
/// over a collection type affects the contents of the collection.
/// When applied to a return value of a method, indicates whether the returned collection
/// is created exclusively for the caller (<c>CollectionAccessType.UpdatedContent</c>) or
/// can be read/updated from outside (<c>CollectionAccessType.Read</c>/<c>CollectionAccessType.UpdatedContent</c>).
/// Use <see cref="CollectionAccessType"/> to specify the access type.
/// </summary>
/// <remarks>
/// Using this attribute only makes sense if all collection methods are marked with this attribute.
/// </remarks>
/// <example><code>
/// 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();
/// }
/// }
/// </code></example>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property | AttributeTargets.ReturnValue)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class CollectionAccessAttribute : Attribute
{
public CollectionAccessAttribute(CollectionAccessType collectionAccessType)
{
CollectionAccessType = collectionAccessType;
}
public CollectionAccessType CollectionAccessType { get; }
}
/// <summary>
/// Provides a value for the <see cref="CollectionAccessAttribute"/> to define
/// how the collection method invocation affects the contents of the collection.
/// </summary>
[Flags]
public enum CollectionAccessType
{
/// <summary>Method does not use or modify content of the collection.</summary>
None = 0,
/// <summary>Method only reads content of the collection but does not modify it.</summary>
Read = 1,
/// <summary>Method can change content of the collection but does not add new elements.</summary>
ModifyExistingContent = 2,
/// <summary>Method can add new elements to the collection.</summary>
UpdatedContent = ModifyExistingContent | 4
}
/// <summary>
/// Indicates that the marked method is an 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
/// <see cref="AssertionConditionAttribute"/> attribute.
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AssertionMethodAttribute : Attribute { }
/// <summary>
/// Indicates the condition parameter of the assertion method. The method itself should be
/// marked by the <see cref="AssertionMethodAttribute"/> attribute. The mandatory argument of
/// the attribute is the assertion type.
/// </summary>