private void AddTypeParameters(TypeSyntax typeSyntax, MultiDictionary<string, TypeParameterSymbol> map) { switch (typeSyntax.Kind()) { case SyntaxKind.AliasQualifiedName: AddTypeParameters(((AliasQualifiedNameSyntax)typeSyntax).Name, map); break; case SyntaxKind.QualifiedName: // NOTE: Dev11 does not warn about duplication, it just matches parameter types to the // *last* type parameter with the same name. That's why we're iterating backwards. QualifiedNameSyntax qualifiedNameSyntax = (QualifiedNameSyntax)typeSyntax; AddTypeParameters(qualifiedNameSyntax.Right, map); AddTypeParameters(qualifiedNameSyntax.Left, map); break; case SyntaxKind.GenericName: AddTypeParameters((GenericNameSyntax)typeSyntax, map); break; case SyntaxKind.IdentifierName: case SyntaxKind.PredefinedType: break; default: Debug.Assert(false, "Unexpected type syntax kind " + typeSyntax.Kind()); break; } }
private static void AppendTypeName(StringBuilder builder, TypeSyntax type) { if (type is NameSyntax) { AppendName(builder, (NameSyntax)type); } else { switch (type.Kind()) { case SyntaxKind.PredefinedType: builder.Append(((PredefinedTypeSyntax)type).Keyword.ValueText); break; case SyntaxKind.ArrayType: var arrayType = (ArrayTypeSyntax)type; AppendTypeName(builder, arrayType.ElementType); var specifiers = arrayType.RankSpecifiers; for (int i = 0; i < specifiers.Count; i++) { builder.Append('['); var specifier = specifiers[i]; if (specifier.Rank > 1) { builder.Append(',', specifier.Rank - 1); } builder.Append(']'); } break; case SyntaxKind.PointerType: AppendTypeName(builder, ((PointerTypeSyntax)type).ElementType); builder.Append('*'); break; case SyntaxKind.NullableType: AppendTypeName(builder, ((NullableTypeSyntax)type).ElementType); builder.Append('?'); break; } } }
private bool CompareTypes(TypeSyntax oldType, TypeSyntax newType) { // Type nodes can be NULL for ctor/dtor/operators ... if (oldType == null || newType == null) { return oldType == newType; } if (oldType.Kind() != newType.Kind()) { return false; } switch (oldType.Kind()) { case SyntaxKind.PredefinedType: var oldPredefinedType = (PredefinedTypeSyntax)oldType; var newPredefinedType = (PredefinedTypeSyntax)newType; return oldPredefinedType.Keyword.RawKind == newPredefinedType.Keyword.RawKind; case SyntaxKind.ArrayType: var oldArrayType = (ArrayTypeSyntax)oldType; var newArrayType = (ArrayTypeSyntax)newType; return (oldArrayType.RankSpecifiers.Count == newArrayType.RankSpecifiers.Count) && CompareTypes(oldArrayType.ElementType, newArrayType.ElementType); case SyntaxKind.PointerType: var oldPointerType = (PointerTypeSyntax)oldType; var newPointerType = (PointerTypeSyntax)newType; return CompareTypes(oldPointerType.ElementType, newPointerType.ElementType); case SyntaxKind.NullableType: var oldNullableType = (NullableTypeSyntax)oldType; var newNullableType = (NullableTypeSyntax)newType; return CompareTypes(oldNullableType.ElementType, newNullableType.ElementType); case SyntaxKind.IdentifierName: case SyntaxKind.QualifiedName: case SyntaxKind.AliasQualifiedName: case SyntaxKind.GenericName: var oldName = (NameSyntax)oldType; var newName = (NameSyntax)newType; return CompareNames(oldName, newName); } Debug.Fail("Unknown kind: " + oldType.Kind()); return false; }
private static bool IsNotNullableReplaceable(this NameSyntax name, TypeSyntax reducedName) { var isNotNullableReplaceable = false; var isLeftSideOfDot = name.IsLeftSideOfDot(); var isRightSideOfDot = name.IsRightSideOfDot(); if (reducedName.Kind() == SyntaxKind.NullableType) { if (((NullableTypeSyntax)reducedName).ElementType.Kind() == SyntaxKind.OmittedTypeArgument) { isNotNullableReplaceable = true; } else { isNotNullableReplaceable = name.IsLeftSideOfDot() || name.IsRightSideOfDot(); } } return isNotNullableReplaceable; }
/// <summary> /// Make a local variable symbol for an element of a deconstruction, /// which can be inferred (if necessary) by binding the enclosing statement. /// </summary> /// <param name="containingSymbol"></param> /// <param name="scopeBinder"> /// Binder that owns the scope for the local, the one that returns it in its <see cref="Binder.Locals"/> array. /// </param> /// <param name="nodeBinder"> /// Enclosing binder for the location where the local is declared. /// It should be used to bind something at that location. /// </param> /// <param name="closestTypeSyntax"></param> /// <param name="identifierToken"></param> /// <param name="kind"></param> /// <param name="deconstruction"></param> /// <returns></returns> public static SourceLocalSymbol MakeDeconstructionLocal( Symbol containingSymbol, Binder scopeBinder, Binder nodeBinder, TypeSyntax closestTypeSyntax, SyntaxToken identifierToken, LocalDeclarationKind kind, SyntaxNode deconstruction) { Debug.Assert(closestTypeSyntax != null); Debug.Assert(nodeBinder != null); Debug.Assert(closestTypeSyntax.Kind() != SyntaxKind.RefType); return closestTypeSyntax.IsVar ? new DeconstructionLocalSymbol(containingSymbol, scopeBinder, nodeBinder, closestTypeSyntax, identifierToken, kind, deconstruction) : new SourceLocalSymbol(containingSymbol, scopeBinder, false, closestTypeSyntax, identifierToken, kind); }
private static void ExpandTypeName(TypeSyntax type, StringBuilder builder) { switch (type.Kind()) { case SyntaxKind.AliasQualifiedName: var alias = (AliasQualifiedNameSyntax)type; builder.Append(alias.Alias.Identifier.ValueText); break; case SyntaxKind.ArrayType: var array = (ArrayTypeSyntax)type; ExpandTypeName(array.ElementType, builder); for (int i = 0; i < array.RankSpecifiers.Count; i++) { var rankSpecifier = array.RankSpecifiers[i]; builder.Append(rankSpecifier.OpenBracketToken.Text); for (int j = 1; j < rankSpecifier.Sizes.Count; j++) { builder.Append(','); } builder.Append(rankSpecifier.CloseBracketToken.Text); } break; case SyntaxKind.GenericName: var generic = (GenericNameSyntax)type; builder.Append(generic.Identifier.ValueText); if (generic.TypeArgumentList != null) { var arguments = generic.TypeArgumentList.Arguments; builder.Append(generic.TypeArgumentList.LessThanToken.Text); for (int i = 0; i < arguments.Count; i++) { if (i != 0) { builder.Append(','); } ExpandTypeName(arguments[i], builder); } builder.Append(generic.TypeArgumentList.GreaterThanToken.Text); } break; case SyntaxKind.IdentifierName: var identifierName = (IdentifierNameSyntax)type; builder.Append(identifierName.Identifier.ValueText); break; case SyntaxKind.NullableType: var nullable = (NullableTypeSyntax)type; ExpandTypeName(nullable.ElementType, builder); builder.Append(nullable.QuestionToken.Text); break; case SyntaxKind.OmittedTypeArgument: // do nothing since it was omitted, but don't reach the default block break; case SyntaxKind.PointerType: var pointer = (PointerTypeSyntax)type; ExpandTypeName(pointer.ElementType, builder); builder.Append(pointer.AsteriskToken.Text); break; case SyntaxKind.PredefinedType: var predefined = (PredefinedTypeSyntax)type; builder.Append(predefined.Keyword.Text); break; case SyntaxKind.QualifiedName: var qualified = (QualifiedNameSyntax)type; ExpandTypeName(qualified.Left, builder); builder.Append(qualified.DotToken.Text); ExpandTypeName(qualified.Right, builder); break; default: Debug.Assert(false, "Unexpected type syntax " + type.Kind()); break; } }
private static void TestGetSpeculativeSemanticModelForTypeSyntax_Common( SemanticModel model, int position, TypeSyntax speculatedTypeSyntax, SpeculativeBindingOption bindingOption, SymbolKind expectedSymbolKind, string expectedTypeDisplayString) { Assert.False(model.IsSpeculativeSemanticModel); Assert.Null(model.ParentModel); Assert.Equal(0, model.OriginalPositionForSpeculation); SemanticModel speculativeModel; var success = model.TryGetSpeculativeSemanticModel(position, speculatedTypeSyntax, out speculativeModel, bindingOption); Assert.True(success); Assert.NotNull(speculativeModel); Assert.True(speculativeModel.IsSpeculativeSemanticModel); Assert.Equal(model, speculativeModel.ParentModel); Assert.NotNull(speculativeModel); Assert.Equal(position, speculativeModel.OriginalPositionForSpeculation); var symbol = speculativeModel.GetSymbolInfo(speculatedTypeSyntax).Symbol; Assert.NotNull(symbol); Assert.Equal(expectedSymbolKind, symbol.Kind); Assert.Equal(expectedTypeDisplayString, symbol.ToDisplayString()); var typeSymbol = speculativeModel.GetTypeInfo(speculatedTypeSyntax).Type; Assert.NotNull(symbol); Assert.Equal(expectedSymbolKind, symbol.Kind); Assert.Equal(expectedTypeDisplayString, symbol.ToDisplayString()); if (speculatedTypeSyntax.Kind() == SyntaxKind.QualifiedName) { var right = ((QualifiedNameSyntax)speculatedTypeSyntax).Right; symbol = speculativeModel.GetSymbolInfo(right).Symbol; Assert.NotNull(symbol); Assert.Equal(expectedSymbolKind, symbol.Kind); Assert.Equal(expectedTypeDisplayString, symbol.ToDisplayString()); typeSymbol = speculativeModel.GetTypeInfo(right).Type; Assert.NotNull(symbol); Assert.Equal(expectedSymbolKind, symbol.Kind); Assert.Equal(expectedTypeDisplayString, symbol.ToDisplayString()); } }