コード例 #1
0
        public override void VisitParameterDeclarationSyntax(ParameterDeclarationSyntax syntax)
        => AssignTypeWithDiagnostics(syntax, diagnostics => {
            diagnostics.AddRange(this.ValidateIdentifierAccess(syntax));

            // assume "any" type when the parameter has parse errors (either missing or was skipped)
            var declaredType = syntax.ParameterType == null
                    ? LanguageConstants.Any
                    : LanguageConstants.TryGetDeclarationType(syntax.ParameterType.TypeName);

            if (declaredType == null)
            {
                return(new ErrorTypeSymbol(DiagnosticBuilder.ForPosition(syntax.Type).InvalidParameterType()));
            }

            var assignedType = declaredType;
            if (object.ReferenceEquals(assignedType, LanguageConstants.String))
            {
                var allowedItemTypes = SyntaxHelper.TryGetAllowedItems(syntax)?
                                       .Select(item => typeManager.GetTypeInfo(item));

                if (allowedItemTypes != null && allowedItemTypes.All(itemType => itemType is StringLiteralType))
                {
                    assignedType = UnionType.Create(allowedItemTypes);
                }
            }

            switch (syntax.Modifier)
            {
            case ParameterDefaultValueSyntax defaultValueSyntax:
                diagnostics.AddRange(ValidateDefaultValue(defaultValueSyntax, assignedType));
                break;

            case ObjectSyntax modifierSyntax:
                var modifierType = LanguageConstants.CreateParameterModifierType(declaredType, assignedType);
                // we don't need to actually use the narrowed type; just need to use this to collect assignment diagnostics
                TypeValidator.NarrowTypeAndCollectDiagnostics(typeManager, modifierSyntax, modifierType, diagnostics);
                break;
            }

            return(assignedType);
        });
コード例 #2
0
        public override void VisitParameterDeclarationSyntax(ParameterDeclarationSyntax syntax)
        {
            diagnostics.AddRange(this.ValidateIdentifierAccess(syntax));

            var assignedType = typeManager.GetTypeInfo(syntax);

            switch (syntax.Modifier)
            {
            case ParameterDefaultValueSyntax defaultValueSyntax:
                diagnostics.AddRange(ValidateDefaultValue(defaultValueSyntax, assignedType));
                break;

            case ObjectSyntax modifierSyntax:
                if (assignedType.TypeKind != TypeKind.Error && SyntaxHelper.TryGetPrimitiveType(syntax) is PrimitiveType primitiveType)
                {
                    var modifierType = LanguageConstants.CreateParameterModifierType(primitiveType, assignedType);
                    diagnostics.AddRange(TypeValidator.GetExpressionAssignmentDiagnostics(typeManager, modifierSyntax, modifierType));
                }
                break;
            }
        }
コード例 #3
0
        private DeclaredTypeAssignment?GetArrayAccessType(ArrayAccessSyntax syntax)
        {
            var baseExpressionAssignment = GetDeclaredTypeAssignment(syntax.BaseExpression);
            var indexAssignedType        = this.typeManager.GetTypeInfo(syntax.IndexExpression);

            // TODO: Currently array access is broken with discriminated object types - revisit when that is fixed
            switch (baseExpressionAssignment?.Reference.Type)
            {
            case ArrayType arrayType when TypeValidator.AreTypesAssignable(indexAssignedType, LanguageConstants.Int):
                // we are accessing an array by an expression of a numeric type
                // return the item type of the array

                // for regular array we can't evaluate the array index at this point, but for loops the index is irrelevant
                // and we need to set declaring syntax, so property access can provide completions correctly for resource and module loops
                var declaringSyntax = baseExpressionAssignment.DeclaringSyntax is ForSyntax
                {
                    Body : ObjectSyntax loopBody
                }

                                                                                                                              ? loopBody : null;

                return(new DeclaredTypeAssignment(arrayType.Item.Type, declaringSyntax));
コード例 #4
0
ファイル: TypeManager.cs プロジェクト: ryanazuretest/bicep
        private TypeSymbol GetArrayAccessType(TypeManagerContext context, ArrayAccessSyntax syntax)
        {
            var errors = new List <ErrorDiagnostic>();

            var baseType = this.GetTypeInfoInternal(context, syntax.BaseExpression);

            CollectErrors(errors, baseType);

            var indexType = this.GetTypeInfoInternal(context, syntax.IndexExpression);

            CollectErrors(errors, indexType);

            if (errors.Any() || indexType.TypeKind == TypeKind.Error)
            {
                return(new ErrorTypeSymbol(errors));
            }

            if (baseType.TypeKind == TypeKind.Any)
            {
                // base expression is of type any
                if (indexType.TypeKind == TypeKind.Any)
                {
                    // index is also of type any
                    return(LanguageConstants.Any);
                }

                if (TypeValidator.AreTypesAssignable(indexType, LanguageConstants.Int) == true ||
                    TypeValidator.AreTypesAssignable(indexType, LanguageConstants.String) == true)
                {
                    // index expression is string | int but base is any
                    return(LanguageConstants.Any);
                }

                // index was of the wrong type
                return(new ErrorTypeSymbol(DiagnosticBuilder.ForPosition(syntax.IndexExpression).StringOrIntegerIndexerRequired(indexType)));
            }

            if (baseType is ArrayType baseArray)
            {
                // we are indexing over an array
                if (TypeValidator.AreTypesAssignable(indexType, LanguageConstants.Int) == true)
                {
                    // the index is of "any" type or integer type
                    // return the item type
                    return(baseArray.ItemType);
                }

                return(new ErrorTypeSymbol(DiagnosticBuilder.ForPosition(syntax.IndexExpression).ArraysRequireIntegerIndex(indexType)));
            }

            if (baseType is ObjectType baseObject)
            {
                // we are indexing over an object
                if (indexType.TypeKind == TypeKind.Any)
                {
                    // index is of type "any"
                    return(GetExpressionedPropertyType(baseObject, syntax.IndexExpression));
                }

                if (TypeValidator.AreTypesAssignable(indexType, LanguageConstants.String) == true)
                {
                    switch (syntax.IndexExpression)
                    {
                    case StringSyntax @string when @string.IsInterpolated() == false:
                        var propertyName = @string.GetLiteralValue();

                        return(this.GetNamedPropertyType(baseObject, syntax.IndexExpression, propertyName));

                    default:
                        // the property name is itself an expression
                        return(this.GetExpressionedPropertyType(baseObject, syntax.IndexExpression));
                    }
                }

                return(new ErrorTypeSymbol(DiagnosticBuilder.ForPosition(syntax.IndexExpression).ObjectsRequireStringIndex(indexType)));
            }

            // index was of the wrong type
            return(new ErrorTypeSymbol(DiagnosticBuilder.ForPosition(syntax.BaseExpression).IndexerRequiresObjectOrArray(baseType)));
        }
コード例 #5
0
 public static BinaryOperatorInfo?TryMatchExact(BinaryOperator @operator, TypeSymbol operandType1, TypeSymbol operandType2)
 {
     return(OperatorLookup[@operator]
            .SingleOrDefault(info => TypeValidator.AreTypesAssignable(operandType1, info.OperandType) == true &&
                             TypeValidator.AreTypesAssignable(operandType2, info.OperandType) == true));
 }