public void BuiltInTypesShouldBeAssignableToThemselves() { foreach (TypeSymbol type in LanguageConstants.DeclarationTypes.Values) { TypeValidator.AreTypesAssignable(type, type).Should().BeTrue($"because type {type.Name} should be assignable to itself."); } }
protected override SyntaxBase ReplaceStringSyntax(StringSyntax syntax) { var declaredType = semanticModel.GetDeclaredType(syntax); if (semanticModel.GetTypeInfo(syntax) is not StringLiteralType actualType) { return(base.ReplaceStringSyntax(syntax)); } if (declaredType is null || TypeValidator.AreTypesAssignable(actualType, declaredType)) { return(base.ReplaceStringSyntax(syntax)); } var stringLiteralCandidates = Enumerable.Empty <StringLiteralType>(); if (declaredType is StringLiteralType stringLiteralType) { stringLiteralCandidates = stringLiteralType.AsEnumerable(); } else if (declaredType is UnionType unionType && unionType.Members.All(x => x.Type is StringLiteralType)) { stringLiteralCandidates = unionType.Members.Select(x => (StringLiteralType)x.Type); } var insensitiveMatch = stringLiteralCandidates.FirstOrDefault(x => StringComparer.OrdinalIgnoreCase.Equals(x.Name, actualType.Name)); if (insensitiveMatch == null) { return(base.ReplaceStringSyntax(syntax)); } return(SyntaxFactory.CreateStringLiteral(insensitiveMatch.RawStringValue)); }
public void BuiltInTypesShouldBeAssignableToAny() { foreach (TypeSymbol type in LanguageConstants.DeclarationTypes.Values) { TypeValidator.AreTypesAssignable(type, LanguageConstants.Any).Should().BeTrue($"because type {type.Name} should be assignable to the '{LanguageConstants.Any.Name}' type."); } }
public void Generic_strings_can_be_assigned_to_string_literals_with_loose_assignment() { var literalVal1 = new StringLiteralType("evie"); var literalVal2 = new StringLiteralType("casper"); var literalUnion = TypeHelper.CreateTypeUnion(literalVal1, literalVal2); var genericString = LanguageConstants.String; var looseString = LanguageConstants.LooseString; // both should be treated as equivalent TypeValidator.AreTypesAssignable(genericString, looseString).Should().BeTrue(); TypeValidator.AreTypesAssignable(looseString, genericString).Should().BeTrue(); // normal string cannot be assigned to string literal or union type of literals TypeValidator.AreTypesAssignable(genericString, literalVal1).Should().BeFalse(); TypeValidator.AreTypesAssignable(genericString, literalUnion).Should().BeFalse(); // loose string can be assigned to string literal and a union type of literals! TypeValidator.AreTypesAssignable(looseString, literalVal1).Should().BeTrue(); TypeValidator.AreTypesAssignable(looseString, literalUnion).Should().BeTrue(); // assignment from string literal works in both cases TypeValidator.AreTypesAssignable(literalVal1, genericString).Should().BeTrue(); TypeValidator.AreTypesAssignable(literalVal1, looseString).Should().BeTrue(); }
public void UnionSupersetShouldNotBeAssignableToUnion() { var union = UnionType.Create(LanguageConstants.Bool, LanguageConstants.String); TypeValidator.AreTypesAssignable(LanguageConstants.Int, union).Should().BeFalse(); TypeValidator.AreTypesAssignable(UnionType.Create(LanguageConstants.Bool, LanguageConstants.Int), union).Should().BeFalse(); TypeValidator.AreTypesAssignable(UnionType.Create(LanguageConstants.Bool, LanguageConstants.Int, LanguageConstants.String), union).Should().BeFalse(); }
static DecoratorValidator ValidateTargetType(TypeSymbol attachableType) => (decoratorName, decoratorSyntax, targetType, _, diagnosticWriter) => { if (!TypeValidator.AreTypesAssignable(targetType, attachableType)) { diagnosticWriter.Write(DiagnosticBuilder.ForPosition(decoratorSyntax).CannotAttacheDecoratorToTarget(decoratorName, attachableType, targetType)); } };
public void UnionSubsetShouldBeAssignableToUnion() { var union = TypeHelper.CreateTypeUnion(LanguageConstants.Int, LanguageConstants.Bool, LanguageConstants.String); TypeValidator.AreTypesAssignable(LanguageConstants.Bool, union).Should().BeTrue(); TypeValidator.AreTypesAssignable(TypeHelper.CreateTypeUnion(LanguageConstants.Bool, LanguageConstants.String), union).Should().BeTrue(); TypeValidator.AreTypesAssignable(TypeHelper.CreateTypeUnion(LanguageConstants.Bool, LanguageConstants.Int), union).Should().BeTrue(); TypeValidator.AreTypesAssignable(TypeHelper.CreateTypeUnion(LanguageConstants.Bool, LanguageConstants.String, LanguageConstants.Int), union).Should().BeTrue(); }
public void OnlyMemberOfUnionShouldBeAssignableToUnion() { var union = UnionType.Create(LanguageConstants.Bool, LanguageConstants.Int); TypeValidator.AreTypesAssignable(LanguageConstants.Int, union).Should().BeTrue(); TypeValidator.AreTypesAssignable(LanguageConstants.Bool, union).Should().BeTrue(); TypeValidator.AreTypesAssignable(LanguageConstants.String, union).Should().BeFalse(); TypeValidator.AreTypesAssignable(UnionType.Create(LanguageConstants.String, LanguageConstants.Null), union).Should().BeFalse(); }
public void PrimitiveTypesShouldNotBeAssignableToEachOther() { TypeValidator.AreTypesAssignable(LanguageConstants.Int, LanguageConstants.Bool).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.Int, LanguageConstants.String).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.Bool, LanguageConstants.Int).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.Bool, LanguageConstants.String).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.String, LanguageConstants.Bool).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.String, LanguageConstants.Int).Should().BeFalse(); }
public FunctionMatchResult Match(IList <TypeSymbol> argumentTypes, out ArgumentCountMismatch?argumentCountMismatch, out ArgumentTypeMismatch?argumentTypeMismatch) { argumentCountMismatch = null; argumentTypeMismatch = null; if (argumentTypes.Count < this.MinimumArgumentCount || (this.MaximumArgumentCount.HasValue && argumentTypes.Count > this.MaximumArgumentCount.Value)) { // Too few or too many arguments. argumentCountMismatch = new ArgumentCountMismatch(argumentTypes.Count, this.MinimumArgumentCount, this.MaximumArgumentCount); return(FunctionMatchResult.Mismatch); } if (argumentTypes.All(a => a.TypeKind == TypeKind.Any)) { // all argument types are "any" // it's a potential match at best return(FunctionMatchResult.PotentialMatch); } for (int i = 0; i < argumentTypes.Count; i++) { var argumentType = argumentTypes[i]; TypeSymbol expectedType; if (i < this.FixedParameters.Length) { expectedType = this.FixedParameters[i].Type; } else { if (this.VariableParameter == null) { // Theoretically this shouldn't happen, becase it already passed argument count checking, either: // - The function takes 0 argument - argumentTypes must be empty, so it won't enter the loop // - The function take at least one argument - when i >= FixedParameterTypes.Length, VariableParameterType // must not be null, otherwise, the function overload has invalid parameter count definition. throw new ArgumentException($"Got unexpected null value for {nameof(this.VariableParameter)}. Ensure the function overload definition is correct: '{this.TypeSignature}'."); } expectedType = this.VariableParameter.Type; } if (TypeValidator.AreTypesAssignable(argumentType, expectedType) != true) { argumentTypeMismatch = new ArgumentTypeMismatch(this, i, argumentType, expectedType); return(FunctionMatchResult.Mismatch); } } return(FunctionMatchResult.Match); }
public void AllTypesShouldBeAssignableToAnyType() { TypeValidator.AreTypesAssignable(LanguageConstants.Any, LanguageConstants.Bool).Should().BeTrue(); TypeValidator.AreTypesAssignable(LanguageConstants.Any, LanguageConstants.Int).Should().BeTrue(); TypeValidator.AreTypesAssignable(LanguageConstants.Any, LanguageConstants.String).Should().BeTrue(); TypeValidator.AreTypesAssignable(LanguageConstants.Any, LanguageConstants.Array).Should().BeTrue(); TypeValidator.AreTypesAssignable(LanguageConstants.Any, LanguageConstants.Object).Should().BeTrue(); TypeValidator.AreTypesAssignable(LanguageConstants.Any, LanguageConstants.Null).Should().BeTrue(); TypeValidator.AreTypesAssignable(LanguageConstants.Any, LanguageConstants.Tags).Should().BeTrue(); TypeValidator.AreTypesAssignable(LanguageConstants.Any, LanguageConstants.ParameterModifierMetadata).Should().BeTrue(); }
public void ObjectAndNonObjectTypesAreNotAssignable() { TypeValidator.AreTypesAssignable(LanguageConstants.Object, LanguageConstants.String).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.Object, LanguageConstants.Int).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.Object, LanguageConstants.Array).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.Object, LanguageConstants.Bool).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.String, LanguageConstants.Object).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.Int, LanguageConstants.Object).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.Array, LanguageConstants.Object).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.Bool, LanguageConstants.Object).Should().BeFalse(); }
public void NothingShouldBeAssignableToNeverType() { var never = UnionType.Create(); TypeValidator.AreTypesAssignable(LanguageConstants.Bool, never).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.Int, never).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.String, never).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.Array, never).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.Object, never).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.Null, never).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.Tags, never).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.ParameterModifierMetadata, never).Should().BeFalse(); }
public void NothingShouldBeAssignableToNeverType() { var never = TypeHelper.CreateTypeUnion(Enumerable.Empty <ITypeReference>()); TypeValidator.AreTypesAssignable(LanguageConstants.Bool, never).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.Int, never).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.String, never).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.Array, never).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.Object, never).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.Null, never).Should().BeFalse(); TypeValidator.AreTypesAssignable(AzResourceTypeProvider.Tags, never).Should().BeFalse(); TypeValidator.AreTypesAssignable(LanguageConstants.ParameterModifierMetadata, never).Should().BeFalse(); }
public void StringLiteralTypesShouldBeAssignableToAndFromStrings() { var literalVal1 = new StringLiteralType("evie"); var literalVal2 = new StringLiteralType("casper"); // different string literals should not be assignable to each other TypeValidator.AreTypesAssignable(literalVal1, literalVal2).Should().BeFalse(); // same-name string literals should be assignable to each other TypeValidator.AreTypesAssignable(literalVal1, new StringLiteralType("evie")).Should().BeTrue(); // string literals should be assignable to and from regular strings TypeValidator.AreTypesAssignable(literalVal1, LanguageConstants.String).Should().BeTrue(); TypeValidator.AreTypesAssignable(LanguageConstants.String, literalVal1).Should().BeTrue(); }
public override IEnumerable <ErrorDiagnostic> GetDiagnostics() { TypeSymbol valueType = this.Context.TypeManager.GetTypeInfo(this.Value, new TypeManagerContext()); // this type is not a property in a symbol so the semantic error visitor won't collect the errors automatically if (valueType is ErrorTypeSymbol) { return(valueType.GetDiagnostics()); } if (TypeValidator.AreTypesAssignable(valueType, this.Type) == false) { return(this.CreateError(this.Value, b => b.OutputTypeMismatch(this.Type.Name, valueType.Name)).AsEnumerable()); } return(Enumerable.Empty <ErrorDiagnostic>()); }
private IEnumerable <ErrorDiagnostic> ValidateDefaultValue(ParameterDefaultValueSyntax defaultValueSyntax) { // figure out type of the default value TypeSymbol?defaultValueType = this.Context.TypeManager.GetTypeInfo(defaultValueSyntax.DefaultValue, new TypeManagerContext()); // this type is not a property in a symbol so the semantic error visitor won't collect the errors automatically if (defaultValueType is ErrorTypeSymbol) { return(defaultValueType.GetDiagnostics()); } if (TypeValidator.AreTypesAssignable(defaultValueType, this.Type) == false) { return(this.CreateError(defaultValueSyntax.DefaultValue, b => b.ParameterTypeMismatch(this.Type.Name, defaultValueType.Name)).AsEnumerable()); } return(Enumerable.Empty <ErrorDiagnostic>()); }
public void UnionShouldBeAssignableToTypeIfAllMembersAre() { var boolIntUnion = UnionType.Create(LanguageConstants.Bool, LanguageConstants.Int); var stringUnion = UnionType.Create(LanguageConstants.String); TypeValidator.AreTypesAssignable(stringUnion, LanguageConstants.String).Should().BeTrue(); TypeValidator.AreTypesAssignable(stringUnion, LanguageConstants.Bool).Should().BeFalse(); TypeValidator.AreTypesAssignable(stringUnion, boolIntUnion).Should().BeFalse(); var logLevelsUnion = UnionType.Create(new StringLiteralType("Error"), new StringLiteralType("Warning"), new StringLiteralType("Info")); var failureLogLevelsUnion = UnionType.Create(new StringLiteralType("Error"), new StringLiteralType("Warning")); TypeValidator.AreTypesAssignable(logLevelsUnion, LanguageConstants.String).Should().BeTrue(); TypeValidator.AreTypesAssignable(logLevelsUnion, stringUnion).Should().BeTrue(); TypeValidator.AreTypesAssignable(logLevelsUnion, boolIntUnion).Should().BeFalse(); // Source union is a subset of target union - this should be allowed TypeValidator.AreTypesAssignable(failureLogLevelsUnion, logLevelsUnion).Should().BeTrue(); // Source union is a strict superset of target union - this should not be allowed TypeValidator.AreTypesAssignable(logLevelsUnion, failureLogLevelsUnion).Should().BeFalse(); }
public override void VisitFunctionCallSyntax(FunctionCallSyntax syntax) { // must have more than 1 argument to use interpolation if (syntax.NameEquals(concatFunction) && syntax.Arguments.Length > 1 && !syntax.GetParseDiagnostics().Any()) { // We should only suggest rewriting concat() calls that result in a string (concat can also operate on and // return arrays) var resultType = this.model.GetTypeInfo(syntax); if (resultType is not AnyType && TypeValidator.AreTypesAssignable(resultType, LanguageConstants.String)) { if (CreateFix(syntax) is CodeFix fix) { this.diagnostics.Add(parent.CreateFixableDiagnosticForSpan(syntax.Span, fix)); // Only report on the top-most string-valued concat call return; } } } base.VisitFunctionCallSyntax(syntax); }
public void AnyTypeShouldBeAssignableToAnyType() { TypeValidator.AreTypesAssignable(LanguageConstants.Any, LanguageConstants.Any).Should().BeTrue(); }
public bool CanAttachTo(TypeSymbol targetType) => TypeValidator.AreTypesAssignable(targetType, attachableType);
private bool IsStrictlyAssignableToString(TypeSymbol typeSymbol) { return(!(typeSymbol is AnyType) && TypeValidator.AreTypesAssignable(typeSymbol, LanguageConstants.String)); }