+ int i = 5;
+ i. // -- here
+ List ml = new List();
+
+ The problem is that "i.List" gets parsed as a type. In this case we need to try binding again as if "i" is
+ an expression and not a type. In order to do that, we need to speculate as to what 'i' meant if it wasn't
+ part of a local declaration's type.
+
+ stringList.
+ await Test2();
+
+ Here "stringList.await" is thought of as the return type of a local function.
+
+ int i = 5;
+ i. // -- here
+ List ml = new List();
+
+ The problem is that "i.List" gets parsed as a type. In this case we need to try binding again as if "i" is
+ an expression and not a type. In order to do that, we need to speculate as to what 'i' meant if it wasn't
+ part of a local declaration's type.
+
+ stringList.
+ await Test2();
+
+ Here "stringList.await" is thought of as the return type of a local function.
+ + Imports o = System.Object + Namespace NS + partial class C : Inherits o : End Class + partial class C : Inherits Object : End Class + partial class C : Inherits System.Object : End Class + End Namespace + ++ all three declarations for class C are equivalent and result in the same symbol table object for C. + However, these alias symbols do appear in the results of certain SemanticModel APIs. + Specifically, for the base clause of the first of C's class declarations, the + following APIs may produce a result that contains an AliasSymbol: +
+ SemanticInfo SemanticModel.GetSemanticInfo(ExpressionSyntax expression); + SemanticInfo SemanticModel.BindExpression(SyntaxNode location, ExpressionSyntax expression); + SemanticInfo SemanticModel.BindType(SyntaxNode location, ExpressionSyntax type); + SemanticInfo SemanticModel.BindNamespaceOrType(SyntaxNode location, ExpressionSyntax type); ++ Also, the following are affected if container=Nothing (and, for the latter, when container=Nothing or arity=0): +
+ Public Function LookupNames(position As Integer, Optional container As NamespaceOrTypeSymbol = Nothing, Optional options As LookupOptions = LookupOptions.Default, Optional results As List(Of String) = Nothing) As IList(Of String) + Public Function LookupSymbols(position As Integer, + Optional container As NamespaceOrTypeSymbol = Nothing, + Optional name As String = Nothing, + Optional arity As Integer? = Nothing, + Optional options As LookupOptions = LookupOptions.Default, + Optional results As List(Of Symbol) = Nothing) As IList(Of Symbol) ++
+ Function M() As (x As Integer, y As Integer)
+
+
+ will be encoded using an attribute on the return type as follows
+
+
+ < return: TupleElementNamesAttribute({ "x", "y" }) >
+ Function M() As System.ValueTuple(Of Integer, Integer)
+
+
+ Class C
+ Inherits BaseType(Of (e3 As (e1 As Integer, e2 As Integer), e4 As Integer))
+
+
+ becomes
+
+
+ < TupleElementNamesAttribute({ "e3", "e4", "e1", "e2" }) >
+ Class C
+ Inherits BaseType(of System.ValueTuple(of System.ValueTuple(Of Integer, Integer), Integer)
+
+
+ '''
+ Class Clazz
+ ...
+
+
+ Nothing if parent is not known.
+ + Imports o = System.Object + Namespace NS + partial class C : Inherits o : End Class + partial class C : Inherits Object : End Class + partial class C : Inherits System.Object : End Class + End Namespace + ++ all three declarations for class C are equivalent and result in the same symbol table object for C. + However, these alias symbols do appear in the results of certain SemanticModel APIs. + Specifically, for the base clause of the first of C's class declarations, the + following APIs may produce a result that contains an AliasSymbol: +
+ SemanticInfo SemanticModel.GetSemanticInfo(ExpressionSyntax expression); + SemanticInfo SemanticModel.BindExpression(SyntaxNode location, ExpressionSyntax expression); + SemanticInfo SemanticModel.BindType(SyntaxNode location, ExpressionSyntax type); + SemanticInfo SemanticModel.BindNamespaceOrType(SyntaxNode location, ExpressionSyntax type); ++ Also, the following are affected if container=Nothing (and, for the latter, when container=Nothing or arity=0): +
+ Public Function LookupNames(position As Integer, Optional container As NamespaceOrTypeSymbol = Nothing, Optional options As LookupOptions = LookupOptions.Default, Optional results As List(Of String) = Nothing) As IList(Of String) + Public Function LookupSymbols(position As Integer, + Optional container As NamespaceOrTypeSymbol = Nothing, + Optional name As String = Nothing, + Optional arity As Integer? = Nothing, + Optional options As LookupOptions = LookupOptions.Default, + Optional results As List(Of Symbol) = Nothing) As IList(Of Symbol) ++
+ Function M() As (x As Integer, y As Integer)
+
+
+ will be encoded using an attribute on the return type as follows
+
+
+ < return: TupleElementNamesAttribute({ "x", "y" }) >
+ Function M() As System.ValueTuple(Of Integer, Integer)
+
+
+ Class C
+ Inherits BaseType(Of (e3 As (e1 As Integer, e2 As Integer), e4 As Integer))
+
+
+ becomes
+
+
+ < TupleElementNamesAttribute({ "e3", "e4", "e1", "e2" }) >
+ Class C
+ Inherits BaseType(of System.ValueTuple(of System.ValueTuple(Of Integer, Integer), Integer)
+
+
+ '''
+ Class Clazz
+ ...
+
+
+ Nothing if parent is not known.
+
+ interface I { void Goo(); }
+ class C1 : I { public void Goo() { } }
+ class C2 : I { public void Goo() { } }
+
+
+ If
+ if (value is
+ { // This open brace token is part of a condition of the 'if' token.
+ Length: 2
+ })
+
+
+ dotnet_sort_system_directives_first = true
+
+
+ using var array = TemporaryArray<T>.Empty;
+
+ // Using the 'Unsafe.AsRef' method
+ Method(ref Unsafe.AsRef(in array));
+
+ // Using this helper method
+ Method(ref array.AsRef());
+
+
+ Typically a user analyzer has a reference to the compiler and some of the compiler's + dependencies such as System.Collections.Immutable. For the analyzer to correctly + interoperate with the compiler that created it, we need to ensure that we always use the + compiler's version of a given assembly over the analyzer's version.
+ +If we neglect to do this, then in the case where the user ships the compiler or its + dependencies in the analyzer's bin directory, we could end up loading a separate + instance of those assemblies in the process of loading the analyzer, which will surface + as a failure to load the analyzer.
+
+ int x = 3;
+ RunWithActionCallback(() => this.DoSomething(x));
+
+
+
+ int x = 3;
+ using var _ = GetPooledAction(arg => arg.self.DoSomething(arg.x), (self: this, x), out Action action);
+ RunWithActionCallback(action);
+
+
+ int x = 3;
+ RunWithActionCallback(a => this.DoSomething(a, x));
+
+
+
+ int x = 3;
+ using var _ = GetPooledAction((a, arg) => arg.self.DoSomething(a, arg.x), (self: this, x), out Action<int> action);
+ RunWithActionCallback(action);
+
+
+ int x = 3;
+ RunWithActionCallback((a, b) => this.DoSomething(a, b, x));
+
+
+
+ int x = 3;
+ using var _ = GetPooledAction((a, b, arg) => arg.self.DoSomething(a, b, arg.x), (self: this, x), out Action<int, int> action);
+ RunWithActionCallback(action);
+
+
+ int x = 3;
+ RunWithActionCallback((a, b, c) => this.DoSomething(a, b, c, x));
+
+
+
+ int x = 3;
+ using var _ = GetPooledAction((a, b, c, arg) => arg.self.DoSomething(a, b, c, arg.x), (self: this, x), out Action<int, int, int> action);
+ RunWithActionCallback(action);
+
+
+ int x = 3;
+ RunWithPredicate(() => this.IsSomething(x));
+
+
+
+ int x = 3;
+ using var _ = GetPooledFunction(arg => arg.self.IsSomething(arg.x), (self: this, x), out Func<bool> predicate);
+ RunWithPredicate(predicate);
+
+
+ int x = 3;
+ RunWithPredicate(a => this.IsSomething(a, x));
+
+
+
+ int x = 3;
+ using var _ = GetPooledFunction((a, arg) => arg.self.IsSomething(a, arg.x), (self: this, x), out Func<int, bool> predicate);
+ RunWithPredicate(predicate);
+
+
+ int x = 3;
+ RunWithPredicate((a, b) => this.IsSomething(a, b, x));
+
+
+
+ int x = 3;
+ using var _ = GetPooledFunction((a, b, arg) => arg.self.IsSomething(a, b, arg.x), (self: this, x), out Func<int, int, bool> predicate);
+ RunWithPredicate(predicate);
+
+
+ int x = 3;
+ RunWithPredicate((a, b, c) => this.IsSomething(a, b, c, x));
+
+
+
+ int x = 3;
+ using var _ = GetPooledFunction((a, b, c, arg) => arg.self.IsSomething(a, b, c, arg.x), (self: this, x), out Func<int, int, int, bool> predicate);
+ RunWithPredicate(predicate);
+
+
+ int x = 0;
+ x = 1;
+ Console.WriteLine(x);
+
+ This map will have two entries for 'x':
+ 1. Key = (symbol: x, write: 'int x = 0')
+ Value = 'false', because value assigned to 'x' here **is never** read.
+ 2. Key = (symbol: x, write: 'x = 1')
+ Value = 'true', because value assigned to 'x' here **may be** read on
+ some control flow path.
+ false.
+
+ int x = 0;
+ x = 1;
+ Console.WriteLine(x);
+
+ This map will have two entries for 'x':
+ 1. Key = (symbol: x, write: 'int x = 0')
+ Value = 'false', because value assigned to 'x' here **is never** read.
+ 2. Key = (symbol: x, write: 'x = 1')
+ Value = 'true', because value assigned to 'x' here **may be** read on
+ some control flow path.
+
+ class C
+ {
+ int M();
+ bool M();
+ }
+
+ The SymbolKey for both 'M' methods will be the same. The SymbolKey will then resolve to both methods.
+ a += b,
+ or a special null coalescing compoud assignment, i.e. a ??= b.
+ NS.Type x = new NS.Type(); or NS.Type.StaticMethod(); or
+ 'Type' in Type.NestedType x = new Type.NestedType(); or Type.StaticMethod();
+ Generic{Type} x = ...; or class Derived : Base{Type} { }
+ class Derived{T} where T : Type { }
+ class Derived : Base { }.
+ var x = new C();, where 'C' is a named type.
+ using NS; or using static NS.Extensions or using Alias = MyType.
+ namespaces N1.N2 { }.
+ true. If not, then the original document will be returned unchanged.
+ int _ = M(); is replaced with _ = M();
+ 2. int x = 1, _ = M(), y = 2; is replaced with following statements:
+
+ int x = 1;
+ _ = M();
+ int y = 2;
+
+ This is normally done in context of a code transformation that generates new discard assignment(s),
+ such as _ = M();, and wants to prevent compiler errors where the containing method already
+ has a discard variable declaration, say var _ = M2(); at some line after the one
+ where the code transformation wants to generate new discard assignment(s), which would be a compiler error.
+ This method replaces such discard variable declarations with discard assignments.
+ MethodAsync(TArg arg, CancellationToken cancellationToken)
+ {
+ var intermediate = await func(arg, cancellationToken).ConfigureAwait(false);
+ return transform(intermediate);
+ }
+ ]]>
+
+ interface I { void Goo(); }
+ class C1 : I { public void Goo() { } }
+ class C2 : I { public void Goo() { } }
+
+
+ If
+ if (value is
+ { // This open brace token is part of a condition of the 'if' token.
+ Length: 2
+ })
+
+
+ dotnet_sort_system_directives_first = true
+
+
+ using var array = TemporaryArray<T>.Empty;
+
+ // Using the 'Unsafe.AsRef' method
+ Method(ref Unsafe.AsRef(in array));
+
+ // Using this helper method
+ Method(ref array.AsRef());
+
+
+
+ int x = 3;
+ RunWithActionCallback(() => this.DoSomething(x));
+
+
+
+ int x = 3;
+ using var _ = GetPooledAction(arg => arg.self.DoSomething(arg.x), (self: this, x), out Action action);
+ RunWithActionCallback(action);
+
+
+ int x = 3;
+ RunWithActionCallback(a => this.DoSomething(a, x));
+
+
+
+ int x = 3;
+ using var _ = GetPooledAction((a, arg) => arg.self.DoSomething(a, arg.x), (self: this, x), out Action<int> action);
+ RunWithActionCallback(action);
+
+
+ int x = 3;
+ RunWithActionCallback((a, b) => this.DoSomething(a, b, x));
+
+
+
+ int x = 3;
+ using var _ = GetPooledAction((a, b, arg) => arg.self.DoSomething(a, b, arg.x), (self: this, x), out Action<int, int> action);
+ RunWithActionCallback(action);
+
+
+ int x = 3;
+ RunWithActionCallback((a, b, c) => this.DoSomething(a, b, c, x));
+
+
+
+ int x = 3;
+ using var _ = GetPooledAction((a, b, c, arg) => arg.self.DoSomething(a, b, c, arg.x), (self: this, x), out Action<int, int, int> action);
+ RunWithActionCallback(action);
+
+
+ int x = 3;
+ RunWithPredicate(() => this.IsSomething(x));
+
+
+
+ int x = 3;
+ using var _ = GetPooledFunction(arg => arg.self.IsSomething(arg.x), (self: this, x), out Func<bool> predicate);
+ RunWithPredicate(predicate);
+
+
+ int x = 3;
+ RunWithPredicate(a => this.IsSomething(a, x));
+
+
+
+ int x = 3;
+ using var _ = GetPooledFunction((a, arg) => arg.self.IsSomething(a, arg.x), (self: this, x), out Func<int, bool> predicate);
+ RunWithPredicate(predicate);
+
+
+ int x = 3;
+ RunWithPredicate((a, b) => this.IsSomething(a, b, x));
+
+
+
+ int x = 3;
+ using var _ = GetPooledFunction((a, b, arg) => arg.self.IsSomething(a, b, arg.x), (self: this, x), out Func<int, int, bool> predicate);
+ RunWithPredicate(predicate);
+
+
+ int x = 3;
+ RunWithPredicate((a, b, c) => this.IsSomething(a, b, c, x));
+
+
+
+ int x = 3;
+ using var _ = GetPooledFunction((a, b, c, arg) => arg.self.IsSomething(a, b, c, arg.x), (self: this, x), out Func<int, int, int, bool> predicate);
+ RunWithPredicate(predicate);
+
+
+ int x = 0;
+ x = 1;
+ Console.WriteLine(x);
+
+ This map will have two entries for 'x':
+ 1. Key = (symbol: x, write: 'int x = 0')
+ Value = 'false', because value assigned to 'x' here **is never** read.
+ 2. Key = (symbol: x, write: 'x = 1')
+ Value = 'true', because value assigned to 'x' here **may be** read on
+ some control flow path.
+ false.
+
+ int x = 0;
+ x = 1;
+ Console.WriteLine(x);
+
+ This map will have two entries for 'x':
+ 1. Key = (symbol: x, write: 'int x = 0')
+ Value = 'false', because value assigned to 'x' here **is never** read.
+ 2. Key = (symbol: x, write: 'x = 1')
+ Value = 'true', because value assigned to 'x' here **may be** read on
+ some control flow path.
+
+ class C
+ {
+ int M();
+ bool M();
+ }
+
+ The SymbolKey for both 'M' methods will be the same. The SymbolKey will then resolve to both methods.
+ a += b,
+ or a special null coalescing compoud assignment, i.e. a ??= b.
+ NS.Type x = new NS.Type(); or NS.Type.StaticMethod(); or
+ 'Type' in Type.NestedType x = new Type.NestedType(); or Type.StaticMethod();
+ Generic{Type} x = ...; or class Derived : Base{Type} { }
+ class Derived{T} where T : Type { }
+ class Derived : Base { }.
+ var x = new C();, where 'C' is a named type.
+ using NS; or using static NS.Extensions or using Alias = MyType.
+ namespaces N1.N2 { }.
+ true. If not, then the original document will be returned unchanged.
+ int _ = M(); is replaced with _ = M();
+ 2. int x = 1, _ = M(), y = 2; is replaced with following statements:
+
+ int x = 1;
+ _ = M();
+ int y = 2;
+
+ This is normally done in context of a code transformation that generates new discard assignment(s),
+ such as _ = M();, and wants to prevent compiler errors where the containing method already
+ has a discard variable declaration, say var _ = M2(); at some line after the one
+ where the code transformation wants to generate new discard assignment(s), which would be a compiler error.
+ This method replaces such discard variable declarations with discard assignments.
+ MethodAsync(TArg arg, CancellationToken cancellationToken)
+ {
+ var intermediate = await func(arg, cancellationToken).ConfigureAwait(false);
+ return transform(intermediate);
+ }
+ ]]>
+
+ int[] someArray = new int[5] { 1, 2, 3, 4, 5 } ;
+ int lastElement = someArray[^1]; // lastElement = 5
+
+
+ int[] someArray = new int[5] { 1, 2, 3, 4, 5 };
+ int[] subArray1 = someArray[0..2]; // { 1, 2 }
+ int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 }
+
+