Example #1
0
 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.");
     }
 }
Example #2
0
        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));
        }
Example #3
0
 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.");
     }
 }
Example #4
0
        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();
        }
Example #5
0
        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();
        }
Example #6
0
 static DecoratorValidator ValidateTargetType(TypeSymbol attachableType) =>
 (decoratorName, decoratorSyntax, targetType, _, diagnosticWriter) =>
 {
     if (!TypeValidator.AreTypesAssignable(targetType, attachableType))
     {
         diagnosticWriter.Write(DiagnosticBuilder.ForPosition(decoratorSyntax).CannotAttacheDecoratorToTarget(decoratorName, attachableType, targetType));
     }
 };
Example #7
0
        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();
        }
Example #8
0
        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();
        }
Example #9
0
        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();
        }
Example #10
0
        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);
        }
Example #11
0
 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();
 }
Example #12
0
        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();
        }
Example #13
0
        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();
        }
Example #14
0
        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();
        }
Example #15
0
        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();
        }
Example #16
0
        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>());
        }
Example #17
0
        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>());
        }
Example #18
0
        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();
        }
Example #19
0
            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);
            }
Example #20
0
 public void AnyTypeShouldBeAssignableToAnyType()
 {
     TypeValidator.AreTypesAssignable(LanguageConstants.Any, LanguageConstants.Any).Should().BeTrue();
 }
Example #21
0
 public bool CanAttachTo(TypeSymbol targetType) => TypeValidator.AreTypesAssignable(targetType, attachableType);
 private bool IsStrictlyAssignableToString(TypeSymbol typeSymbol)
 {
     return(!(typeSymbol is AnyType) &&
            TypeValidator.AreTypesAssignable(typeSymbol, LanguageConstants.String));
 }