Пример #1
0
        private static void Check(Node node, [NotNull] FunctionCall call,
                                  [NotNull] FunctionDeclaration definition)
        {
            var table         = node.SymbolTable;
            var parameters    = definition.Profile.Parameters;
            var callerProfile = call.AsProfile(node);
            var callArgsCount = call.Arguments != null ? call.Arguments.Length : 0;

            if (callArgsCount > parameters.Count)
            {
                var m = string.Format("Function '{0}' only takes {1} parameter(s)", call.FunctionName,
                                      parameters.Count);
                DiagnosticUtils.AddError(node, m);
            }

            if (callerProfile.InputParameters.Count != definition.Profile.InputParameters.Count ||
                callerProfile.InoutParameters.Count != definition.Profile.InoutParameters.Count ||
                callerProfile.OutputParameters.Count != definition.Profile.OutputParameters.Count)
            {
                var m = string.Format("No suitable function signature found for '{0}' {1}", call.FunctionName,
                                      callerProfile.GetSignature());
                DiagnosticUtils.AddError(node, m);
            }

            for (int c = 0; c < parameters.Count; c++)
            {
                var expected = parameters[c];
                if (c < callArgsCount)
                {
                    //Omitted
                    if (call.Arguments[c].IsOmitted)
                    {
                        if (expected.IsOmittable)
                        {
                            continue;
                        }
                        else
                        {
                            DiagnosticUtils.AddError(node, "Omitted not allowed for this parameter");
                            return;
                        }
                    }


                    var actual = call.Arguments[c].StorageAreaOrValue;
                    if (actual.IsLiteral)
                    {
                        continue;                   //TODO
                    }
                    var callArgName = actual.StorageArea.ToString();
                    var found       = node.GetDataDefinitionFromStorageAreaDictionary(actual.StorageArea);
                    if (found == null)
                    {
                        continue;
                    }

                    var actualDataDefinition = found;

                    var actualSpecialRegister = actual.StorageArea as StorageAreaPropertySpecialRegister;
                    if (actualSpecialRegister != null)
                    {
                        var tokenType = actualSpecialRegister.SpecialRegisterName.TokenType;
                        if (tokenType == TokenType.LENGTH)
                        {
                            if (call is ProcedureCall)
                            {
                                ProcedureCall procedureCall = call as ProcedureCall;
                                if (procedureCall.OutputParameters.Contains(call.Arguments[c]))
                                {
                                    DiagnosticUtils.AddError(node, "LENGTH cannot be used as an output",
                                                             actualSpecialRegister.SpecialRegisterName);
                                    continue;
                                }
                            }

                            // accepted format is "PIC [S]9(5..9) comp-5"
                            if (expected.PrimitiveDataType.Name != "Numeric" || expected.Length < 5 ||
                                expected.Length > 9 || expected.Usage != DataUsage.NativeBinary)
                            {
                                DiagnosticUtils.AddError(node, "LENGTH can only be used as PIC S9(5..9) comp-5",
                                                         actualSpecialRegister.SpecialRegisterName);
                                continue;
                            }
                        }
                        else if (tokenType == TokenType.ADDRESS && expected.Usage == DataUsage.Pointer)
                        {
                            if (!actualDataDefinition.IsFlagSet(Node.Flag.LinkageSectionNode) &&
                                call.Arguments[c].SharingMode.Value == ParameterSharingMode.ByReference)
                            {
                                DiagnosticUtils.AddError(node,
                                                         "ADDRESS OF can only be used with a LINKAGE variable, or with a sharing mode BY CONTENT/BY VALUE",
                                                         actualSpecialRegister.SpecialRegisterName);
                            }

                            continue;
                        }
                        else if (tokenType == TokenType.LINAGE_COUNTER)
                        {
                            //Do not know what to do : RFC
                            DiagnosticUtils.AddError(node, "LINAGE_COUNTER not allowed yet with procedure");
                            return;
                        }

                        continue; //If it's a special register we don't want to check more rules.
                    }



                    //TODO use SubscriptExpression and ReferenceModifier of the StorageArea to correct the type
                    //Ex: MyVar1(1:10) has a length of 10 and is of type Alphanumeric
                    //Ex: MyArray(1) only target one element of the array, so we need to get the type of this element.



                    //If the actual dataDefinition is a table occurence try to match it with subscripts
                    //If the actual dataDefinition is under a table occurence, then don't care about subscripts
                    long            actualMinOccurencesCount             = actualDataDefinition.MinOccurencesCount;
                    long            actualMaxOccurencesCount             = actualDataDefinition.MaxOccurencesCount;
                    bool            actualHasUnboundedNumberOfOccurences = actualDataDefinition.HasUnboundedNumberOfOccurences;
                    NumericVariable actualOccursDependingOn = actualDataDefinition.OccursDependingOn;
                    bool            actualIsTableOccurence  = actualDataDefinition.IsTableOccurence;

                    if (actualDataDefinition.IsTableOccurence)
                    {
                        var subscriptedStorageArea = actual.StorageArea as DataOrConditionStorageArea;
                        if (subscriptedStorageArea != null && subscriptedStorageArea.Subscripts.Count > 0)
                        {
                            //if there are subscripts


                            //Do not allow ALL
                            if (subscriptedStorageArea.Subscripts.Any(s => s.ALL != null))
                            {
                                DiagnosticUtils.AddError(node, "You cannot use ALL for procedure argument");
                                return;
                            }

                            actualMinOccurencesCount             = 0;
                            actualMaxOccurencesCount             = 0;
                            actualHasUnboundedNumberOfOccurences = false;
                            actualOccursDependingOn = null;
                            actualIsTableOccurence  = false;
                        }
                    }


                    //Cobol 85 Type will be checked with their picture
                    if (actualDataDefinition.DataType.CobolLanguageLevel > CobolLanguageLevel.Cobol85 ||
                        expected.DataType.CobolLanguageLevel > CobolLanguageLevel.Cobol85)
                    {
                        if (actualDataDefinition.DataType.CobolLanguageLevel == CobolLanguageLevel.Cobol85 ||
                            expected.DataType.CobolLanguageLevel == CobolLanguageLevel.Cobol85)
                        {
                            var m = string.Format(
                                "Function '{0}' expected parameter '{1}' of type {2} and received '{3}' of type {4} ",
                                call.FunctionName, expected.Name, expected.DataType,
                                callArgName ?? string.Format("position {0}", c + 1), actualDataDefinition.DataType);
                            DiagnosticUtils.AddError(node, m);
                        }
                        else if (actualDataDefinition.DataType != expected.DataType)
                        {
                            TypeDefinition callerType = actualDataDefinition.TypeDefinition;
                            TypeDefinition calleeType = expected.TypeDefinition;
                            if (callerType == null || calleeType == null)
                            {
                                //Ignore, it's an unknown DataType. It's already checked
                            }
                            else if (!Equals(callerType.QualifiedName, calleeType.QualifiedName))
                            {
                                var m = string.Format(
                                    "Function '{0}' expected parameter '{1}' of type {2} and received '{3}' of type {4} ",
                                    call.FunctionName, calleeType.Name, calleeType.DataType,
                                    callArgName ?? string.Format("position {0}", c + 1), callerType.DataType);
                                DiagnosticUtils.AddError(node, m);
                            }
                        }
                    }

                    if (actualDataDefinition.Picture != null && expected.Picture != null &&
                        actualDataDefinition.Picture.NormalizedValue != expected.Picture.NormalizedValue)
                    {
                        var m =
                            string.Format(
                                "Function '{0}' expected parameter '{1}' with picture {2} and received '{3}' with picture {4}",
                                call.FunctionName, expected.Name, expected.Picture.Value,
                                callArgName ?? string.Format("position {0}", c + 1),
                                actualDataDefinition.Picture.Value);
                        DiagnosticUtils.AddError(node, m);
                    }


//                    if (dataDefinitionOfActual.Length != expectedParameter.Length)
//                    {
//                        var m =
//                            string.Format(
//                                "Function '{0}' expected parameter '{1}' of length {2} and received '{3}' of length {4}",
//                                call.FunctionName, expectedParameter.Name, expectedParameter.Length,
//                                callArgName ?? string.Format("position {0}", c + 1), dataDefinitionOfActual.Length);
//                        DiagnosticUtils.AddError(e, m);
//                    }

                    if (actualDataDefinition.Usage != expected.Usage)
                    {
                        var m =
                            string.Format(
                                "Function '{0}' expected parameter '{1}' of usage {2} and received '{3}' of usage {4}",
                                call.FunctionName, expected.Name, expected.Usage,
                                callArgName ?? string.Format("position {0}", c + 1), actualDataDefinition.Usage);
                        DiagnosticUtils.AddError(node, m);
                    }

                    if (actualDataDefinition.IsJustified != expected.IsJustified)
                    {
                        var m =
                            string.Format(
                                "Function '{0}' expected parameter '{1}' {2} and received '{3}' {4}",
                                call.FunctionName, expected.Name, expected.IsJustified ? "justified" : "non-justified",
                                callArgName ?? string.Format("position {0}", c + 1),
                                actualDataDefinition.IsJustified ? "justified" : "non-justified");
                        DiagnosticUtils.AddError(node, m);
                    }

                    if (actualDataDefinition.IsGroupUsageNational != expected.IsGroupUsageNational)
                    {
                        var m =
                            string.Format(
                                "Function '{0}' expected parameter '{1}' {2} and received '{3}' {4}",
                                call.FunctionName, expected.Name,
                                expected.IsGroupUsageNational ? "national group-usage" : "non national group-usage",
                                callArgName ?? string.Format("position {0}", c + 1),
                                actualDataDefinition.IsGroupUsageNational
                                    ? "national group-usage"
                                    : "non national group-usage");
                        DiagnosticUtils.AddError(node, m);
                    }



                    //Array
                    if (actualIsTableOccurence != expected.IsTableOccurence)
                    {
                        var m =
                            string.Format(
                                "Function '{0}' expected parameter '{1}' to {2} an array and received '{3}' which {4} an array",
                                call.FunctionName, expected.Name, expected.IsTableOccurence ? "be" : "be NOT",
                                actualDataDefinition.Name,
                                actualIsTableOccurence ? "is" : "is NOT ");
                        DiagnosticUtils.AddError(node, m);
                    }
                    else if (actualIsTableOccurence && expected.IsTableOccurence)
                    {
                        if (actualMinOccurencesCount != expected.MinOccurencesCount)
                        {
                            var m =
                                string.Format(
                                    "Function '{0}' expected parameter '{1}' to have at least {2} occurences and received '{3}' with a minimum of {4} occurences",
                                    call.FunctionName, expected.Name, expected.MinOccurencesCount,
                                    callArgName ?? string.Format("position {0}", c + 1), actualMinOccurencesCount);
                            DiagnosticUtils.AddError(node, m);
                        }

                        if (actualMaxOccurencesCount != expected.MaxOccurencesCount)
                        {
                            var m =
                                string.Format(
                                    "Function '{0}' expected parameter '{1}' to have at most {2} occurences and received '{3}' with a maximum of {4} occurences",
                                    call.FunctionName, expected.Name, expected.MaxOccurencesCount,
                                    callArgName ?? string.Format("position {0}", c + 1), actualMaxOccurencesCount);
                            DiagnosticUtils.AddError(node, m);
                        }
                    }

                    if (actualOccursDependingOn != expected.OccursDependingOn)
                    {
                        var m =
                            string.Format(
                                "Function '{0}' expected parameter '{1}' occurs depending on ({2}) occurences and received '{3}' occurs depending on ({4})",
                                call.FunctionName, expected.Name, expected.OccursDependingOn,
                                callArgName ?? string.Format("position {0}", c + 1), actualOccursDependingOn);
                        DiagnosticUtils.AddError(node, m);
                    }

                    if (actualHasUnboundedNumberOfOccurences != expected.HasUnboundedNumberOfOccurences)
                    {
                        var m =
                            string.Format(
                                "Function '{0}' expected parameter '{1}' {2} and received '{3}' {4}",
                                call.FunctionName, expected.Name,
                                expected.HasUnboundedNumberOfOccurences
                                    ? "has unbounded number of occurences"
                                    : "hasn't unbounded number of occurences",
                                callArgName ?? string.Format("position {0}", c + 1),
                                actualHasUnboundedNumberOfOccurences
                                    ? "has unbounded number of occurences"
                                    : "hasn't unbounded number of occurences");
                        DiagnosticUtils.AddError(node, m);
                    }


                    if (actualDataDefinition.SignIsSeparate != expected.SignIsSeparate)
                    {
                        var m =
                            string.Format(
                                "Function '{0}' expected parameter '{1}' {2} and received '{3}' {4}",
                                call.FunctionName, expected.Name,
                                expected.HasUnboundedNumberOfOccurences
                                    ? "has unbounded number of occurences"
                                    : "hasn't unbounded number of occurences",
                                callArgName ?? string.Format("position {0}", c + 1),
                                actualDataDefinition.HasUnboundedNumberOfOccurences
                                    ? "has unbounded number of occurences"
                                    : "hasn't unbounded number of occurences");
                        DiagnosticUtils.AddError(node, m);
                    }

                    if (actualDataDefinition.SignPosition != expected.SignPosition)
                    {
                        var m =
                            string.Format(
                                "Function '{0}' expected parameter '{1}' with sign position {2} and received '{3}' with sign position {4}",
                                call.FunctionName, expected.Name,
                                expected.SignPosition == null ? "empty" : expected.SignPosition.ToString(),
                                callArgName ?? string.Format("position {0}", c + 1),
                                actualDataDefinition.SignPosition == null
                                    ? "empty"
                                    : actualDataDefinition.SignPosition.ToString());
                        DiagnosticUtils.AddError(node, m);
                    }

                    if (actualDataDefinition.IsSynchronized != expected.IsSynchronized)
                    {
                        var m =
                            string.Format(
                                "Function '{0}' expected parameter '{1}' {2} and received '{3}' {4}",
                                call.FunctionName, expected.Name,
                                expected.IsSynchronized ? "synchonized" : "not synchronized",
                                callArgName ?? string.Format("position {0}", c + 1),
                                actualDataDefinition.IsSynchronized ? "synchonized" : "not synchronized");
                        DiagnosticUtils.AddError(node, m);
                    }

                    if (actualDataDefinition.ObjectReferenceClass != expected.ObjectReferenceClass)
                    {
                        var m =
                            string.Format(
                                "Function '{0}' expected parameter '{1}' and received '{2}' with wrong object reference.",
                                call.FunctionName, expected.Name, callArgName ?? string.Format("position {0}", c + 1));
                        DiagnosticUtils.AddError(node, m);
                    }
                }
                else
                {
                    var m = string.Format("Function '{0}' is missing parameter '{1}' of type {2} and length {3}",
                                          call.FunctionName, expected.Name, expected.DataType, expected.Length);
                    DiagnosticUtils.AddError(node, m);
                }
            }
        }