예제 #1
0
 public NamespaceType(string name, IEnumerable <TypeProperty> properties, FunctionResolver methodResolver, DecoratorResolver decoratorResolver)
     : base(name)
 {
     this.Properties        = properties.ToImmutableDictionary(property => property.Name, LanguageConstants.IdentifierComparer);
     this.MethodResolver    = methodResolver;
     this.DecoratorResolver = decoratorResolver;
 }
예제 #2
0
 public NamedObjectType(string name, TypeSymbolValidationFlags validationFlags, IEnumerable <TypeProperty> properties, ITypeReference?additionalPropertiesType, TypePropertyFlags additionalPropertiesFlags = TypePropertyFlags.None, IEnumerable <FunctionOverload>?functions = null)
     : base(name)
 {
     this.ValidationFlags           = validationFlags;
     this.Properties                = properties.ToImmutableDictionary(property => property.Name, LanguageConstants.IdentifierComparer);
     this.MethodResolver            = FunctionResolver.Create(functions);
     this.AdditionalPropertiesType  = additionalPropertiesType;
     this.AdditionalPropertiesFlags = additionalPropertiesFlags;
 }
예제 #3
0
        public IEnumerable <Decorator> GetMatches(FunctionSymbol symbol, IList <TypeSymbol> argumentTypes)
        {
            foreach (var overload in FunctionResolver.GetMatches(symbol, argumentTypes, out var _, out var _))
            {
                var decorator = this.TryGetDecorator(overload);

                if (decorator != null)
                {
                    yield return(decorator);
                }
            }
        }
예제 #4
0
        public IEnumerable <Decorator> GetMatches(FunctionSymbol symbol, IList <TypeSymbol> argumentTypes)
        {
            if (!functionSymbols.Contains(symbol))
            {
                yield break;
            }

            foreach (var overload in FunctionResolver.GetMatches(symbol, argumentTypes, out var _, out var _))
            {
                this.decoratorsByOverloads.TryGetValue(overload, out Decorator? decorator);

                if (decorator != null)
                {
                    yield return(decorator);
                }
            }
        }
예제 #5
0
 public DecoratorResolver(IEnumerable <Decorator> decorators)
 {
     this.decoratorsByOverloads = decorators.ToImmutableDictionary(decorator => decorator.Overload, decorator => decorator);
     this.functionResolver      = new FunctionResolver(decoratorsByOverloads.Keys);
 }
예제 #6
0
 public DecoratorResolver(IEnumerable <Decorator> decorators)
 {
     this.decoratorsByOverloads = decorators.ToImmutableDictionary(decorator => decorator.Overload, decorator => decorator);
     this.functionResolver      = FunctionResolver.Create(decoratorsByOverloads.Keys);
     this.functionSymbols       = functionResolver.GetKnownFunctions().Values.ToImmutableHashSet();
 }
예제 #7
0
        private TypeSymbol GetFunctionSymbolType(
            FunctionCallSyntax syntax,
            FunctionSymbol function,
            ImmutableArray <FunctionArgumentSyntax> argumentSyntaxes,
            IList <TypeSymbol> argumentTypes,
            IList <ErrorDiagnostic> errors)
        {
            // Recover argument type errors so we can continue type checking for the parent function call.
            var recoveredArgumentTypes = argumentTypes
                                         .Select(t => t.TypeKind == TypeKind.Error ? LanguageConstants.Any : t)
                                         .ToList();

            var matches = FunctionResolver.GetMatches(
                function,
                recoveredArgumentTypes,
                out IList <ArgumentCountMismatch> countMismatches,
                out IList <ArgumentTypeMismatch> typeMismatches).ToList();

            if (matches.Count == 0)
            {
                if (typeMismatches.Any())
                {
                    if (typeMismatches.Count > 1 && typeMismatches.Skip(1).All(tm => tm.ArgumentIndex == typeMismatches[0].ArgumentIndex))
                    {
                        // All type mismatches are equally good (or bad).
                        var parameterTypes = typeMismatches.Select(tm => tm.ParameterType).ToList();
                        var argumentType   = typeMismatches[0].ArgumentType;
                        var signatures     = typeMismatches.Select(tm => tm.Source.TypeSignature).ToList();
                        var argumentSyntax = argumentSyntaxes[typeMismatches[0].ArgumentIndex];

                        errors.Add(DiagnosticBuilder.ForPosition(argumentSyntax).CannotResolveFunctionOverload(signatures, argumentType, parameterTypes));
                    }
                    else
                    {
                        // Choose the type mismatch that has the largest index as the best one.
                        var(_, argumentIndex, argumentType, parameterType) = typeMismatches.OrderBy(tm => tm.ArgumentIndex).Last();

                        errors.Add(DiagnosticBuilder.ForPosition(argumentSyntaxes[argumentIndex]).ArgumentTypeMismatch(argumentType, parameterType));
                    }
                }
                else
                {
                    // Argument type mismatch wins over count mismatch. Handle count mismatch only when there's no type mismatch.
                    var(actualCount, mininumArgumentCount, maximumArgumentCount) = countMismatches.Aggregate(ArgumentCountMismatch.Reduce);
                    var argumentsSpan = TextSpan.Between(syntax.OpenParen, syntax.CloseParen);

                    errors.Add(DiagnosticBuilder.ForPosition(argumentsSpan).ArgumentCountMismatch(actualCount, mininumArgumentCount, maximumArgumentCount));
                }
            }

            if (errors.Any())
            {
                return(new ErrorTypeSymbol(errors));
            }

            if (matches.Count == 1)
            {
                // we have an exact match or a single ambiguous match
                // return its type
                return(matches.Single().ReturnType);
            }

            // function arguments are ambiguous (due to "any" type)
            // technically, the correct behavior would be to return a union of all possible types
            // unfortunately our language lacks a good type checking construct
            // and we also don't want users to have to use the converter functions to work around it
            // instead, we will return the "any" type to short circuit the type checking for those cases
            return(LanguageConstants.Any);
        }
예제 #8
0
 public ObjectType(string name, TypeSymbolValidationFlags validationFlags, IEnumerable <TypeProperty> properties, ITypeReference?additionalPropertiesType, TypePropertyFlags additionalPropertiesFlags, FunctionResolver methodResolver)
     : base(name)
 {
     this.ValidationFlags           = validationFlags;
     this.Properties                = properties.ToImmutableDictionary(property => property.Name, LanguageConstants.IdentifierComparer);
     this.MethodResolver            = methodResolver;
     this.AdditionalPropertiesType  = additionalPropertiesType;
     this.AdditionalPropertiesFlags = additionalPropertiesFlags;
 }
예제 #9
0
 public ObjectType(string name) : base(name)
 {
     AdditionalPropertiesType = LanguageConstants.Any;
     MethodResolver           = new FunctionResolver(this, null);
 }