Search code examples
compiler-errorsmissing-datax++optional-parametersdynamics-365-operations

Why does X++ compilation fail because of missing allegedly optional argument depending which class I save last?


I have two classes:

[DataContractAttribute, SysOperationContractProcessingAttribute(classStr(CustBalanceUIBuilder)), SysOperationGroupAttribute('Date',"@ApplicationPlatform:SingleSpace", '1')]
public class CustBalanceDataContract implements SysOperationValidatable
{
    NoYesId     allowModifyDate;
    TransDate   transDate;
    str packedQuery;
 
    [DataMemberAttribute('DateTransactionDate'), SysOperationLabelAttribute(literalStr("@SYS11284")), SysOperationGroupMemberAttribute('Date'), SysOperationDisplayOrderAttribute('1')]
    public TransDate parmTransDate(TransDate _transDate = transDate)
    {
        transDate = _transDate;
        return transDate;
    }

    [DataMemberAttribute('DateControl'), SysOperationLabelAttribute("Enable date control"), SysOperationGroupMemberAttribute('Date'), SysOperationDisplayOrderAttribute('0')]
    public NoYesId parmAllowModifyDate(NoYesId _allowModifyDate = allowModifyDate)
    {
        allowModifyDate = _allowModifyDate;
        return allowModifyDate;
    }

    public boolean validate()
    {
        boolean ret = true;
        if(!transDate && allowModifyDate)
        {
            ret = checkFailed('Transaction date cannot be empty');
        }
        return ret;
    }

    [DataMemberAttribute, AifQueryTypeAttribute('_packedQuery',   querystr(CustTableSRS))]
    public str parmQuery(str _packedQuery = packedQuery)
    {
        packedQuery = _packedQuery;
        return packedQuery;
    }

    public Query getQuery()
    {
        return new Query(SysOperationHelper::base64Decode(packedQuery));
    }

    public void setQuery(Query _query)
    {
        packedQuery =SysOperationHelper::base64Encode(_query.pack());
    }

}

and

public class CustBalanceService
{
    public void processData(CustBalanceDataContract _custBalanceDataContract)
    {
        QueryRun queryRun = new queryRun(_custBalanceDataContract.getQuery());
        while(queryRun.next())
        {
            CustTable custTable = queryRun.get(tableNum(custTable));
 
            TransDate transDate = _custBalanceDataContract.parmTransDate();
            Amount balance = (transDate)
                ? custTable.balanceMST(dateNull(), transDate)
                : custTable.balanceMST();

            info(strFmt('%1 - %2', custTable.AccountNum, balance));
        }
    }
}

When it compiles successfully, it behaves as expected.

However, if I save CustBalanceDataContract, the solution recompiles and then tells me there is an error in CustBalanceService because _custBalanceDataContract.parmTransDate(); is missing argument 1, which you can see from the signature public TransDate parmTransDate(TransDate _transDate = transDate) should be an optional argument.

But then if I change nothing and save CustBalanceService again, the compilation is as expected.

Is this a bug in the compiler? Is it a known issue? Is there a fix for this? Is there something actually wrong with the code which might cause failures even after it successfully compiles and executes?


Solution

  • I can reproduce the issue.

    It seems you have a knack for finding those little idiosynchracies in . To answer your questions, yes, this could be an issue in the compiler. As I said in a comment on one of your other questions, has some legacy baggage from the time when it wasn't part of the .NET language family. In general, I consider compilation during save of a single object or even the compilation of a whole project/solution more of a nice to have. The only compilation that in my experience works reliably and produces a useful result is the compilation of the complete package/model (in Visual Studio, it is the one called by the Dynamics 365 > Build models... menu).

    I don't think the issue you describe is a known issue. At least I wasn't aware of it and I don't know of a fix for it. And no, I don't think there is something wrong with the code. If it compiles successfully with the "Build models..." compilation, it should be good to go.