Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error AS0064: Implementation of interface '__MissingInterface__' has been deleted on Codeunit 'abcd'. #7662

Closed
RadoArvay opened this issue Feb 6, 2024 · 9 comments
Labels
AppSourceCop This is a specific static-code-analysis group (AS) input-needed requires-triage

Comments

@RadoArvay
Copy link

(Maybe it is somehow related to #7496 you solved for us a couple of months ago.)

There is the interface (version 1 - V1) in obsoleting state = Pending in our workspace. The interface was implemented in the enum (extensible) and codeunits (used in enum values) in a base app and an extending app. All objects are public.
The interface was replaced by other one of version 2 (V2) with the same set of methods plus something in addition.

Now we have decided to remove the obsoleted interface and clean the objects. When we remove all relations to V1 interface from the enum and codeunits in both apps, everything is OK and we are able to compile/build the apps. But when we also delete V1 interface object, then:

  • base app is OK,
  • for extending app we are getting the error Implementation of interface 'MissingInterface' has been deleted on Codeunit 'abcd'. AS0064.

Note: there is one more extending app with V1 interface implementations, but all objects there are internal and there is no error after deleting V1 interface.

AL: 12.5.914975 (I have not tried an insider)
platform: "22.0.0.0",
application: "22.3.0.0",
runtime: "11.0",
apps versions in app.json and AppSourceCop.json are set correctly

@qutreson qutreson added the AppSourceCop This is a specific static-code-analysis group (AS) label Feb 19, 2024
@qutreson
Copy link
Contributor

@RadoArvay - Can you share a simple project/workspace (including the baseline versions) that reproduces the issue?

@RadoArvay
Copy link
Author

@qutreson
Yes, I can. But in what form? Just a simple code example? Whole workspace (it is not small)? Before/after? Or...?
Note: I have just done a simple test and I have found out (as I expected) that deleting version property from AppSourceCop.json removes the error.

@qutreson
Copy link
Contributor

@RadoArvay - Sorry for the delayed answer. Removing the version property in the AppSourceCop.json will disable the breaking change validation including AS0064. That can be a temporary workaround, but prevents you from running breaking changes though.

It would be great if you could share the definition of the interface, of the enum implementing and of the codeunits implementing it for both your base app and for the apps extending it. You can remove the content of the procedures in the codeunit and just return some dummy values instead.

From your issue description, I guess the code from BaseApp V1 would look like:

interface MyInterface
{
    ObsoleteState = Pending;
    procedure MyProcedure();
}
enum 50100 MyEnum implements MyInterface
{
    Extensible = true;
    value(1; MyValue)
    {
        Implementation = MyInterface = MyCodeunit;
    }
}
codeunit 50100 MyCodeunit implements MyInterface
{
    procedure MyProcedure()
    begin
    end;
}

Base App V2 would look like this:

interface MyNewInterface
{
    procedure MyProcedure();
    procedure MyNewProcedure();
}
enum 50100 MyEnum implements MyNewInterface
{
    Extensible = true;
    DefaultImplementation = MyNewInterface = MyCodeunit; // Required by AS0067
    value(1; MyValue)
    {
        Implementation = MyNewInterface = MyCodeunit;
    }
}
codeunit 50100 MyCodeunit implements MyNewInterface
{
    procedure MyProcedure()
    begin
    end;
    procedure MyNewProcedure()
    begin
    end;
}

Is that matching a simplified version of your apps? How does the app depending on it look like what kind of objects does it have?

@qutreson
Copy link
Contributor

qutreson commented Mar 14, 2024

Ok, I actually can get a repro by having this code in the dependent app, but only if I don't set tup my baseline packages correctly.

My code for the dependent app is as follows:

V1:

 codeunit 50101 MyOtherCodeunit implements MyInterface
{
    procedure MyProcedure()
    begin
    end;
}
enum 50101 MyOtherEnum implements MyInterface
{
    Extensible = true;
    value(0; MyValue)
    {
        Implementation = MyInterface = MyCodeunit;
    }
    value(1; MyOtherValue)
    {
        Implementation = MyInterface = MyOtherCodeunit;
    }
}
enumextension 50100 MyEnumExtension extends MyEnum
{
    value(50100; MyExtValue)
    {
        Implementation = MyInterface = MyOtherCodeunit;
    }
}

V2:

codeunit 50101 MyOtherCodeunit implements MyNewInterface
{
    procedure MyProcedure()
    begin
    end;
    procedure MyNewProcedure()
    begin
    end;
}
enum 50101 MyOtherEnum implements MyNewInterface
{
    Extensible = true;
    DefaultImplementation = MyNewInterface = MyCodeunit; // Required by AS0067
    value(0; MyValue)
    {
        Implementation = MyNewInterface = MyCodeunit;
    }
    value(1; MyOtherValue)
    {
        Implementation = MyNewInterface = MyOtherCodeunit;
    }
}
enumextension 50100 MyEnumExtension extends MyEnum
{
    value(50100; MyExtValue)
    {
        Implementation = MyNewInterface = MyOtherCodeunit;
    }
}

And my AppSourceCop.json looks like:

{
    "baselinePackageCachePath": "./.appSourceCopPackages",
    "version": "1.0.0.0"
}

If my appSourceCopPackages folder only contains the V1 of the dependent app (named GithubInterfacesExt), or the V1 of the dependent app (named GithubInterfacesExt), and the V2 of the base app (named GithubInterfaces), then I get this error.

image

image

If my appSourceCopPackages folder contains the V1 of the dependent app and the V1 of the base app, then I don't get this error and I can build the package.

image

Can you let me know how you are setting up your baseline package cache path?

@RadoArvay
Copy link
Author

Hmm, interesting.

We do not use AppSourceCop.baselinePackageCachePath property in our workspace. We just use al.packageCachePath property in the workspace configuration file. And we always copy the "AppSource" packages to that common folder.
I have found 2 informations in the documentation article:

The baselinePackageCachePath allows you to specify the folder that will act as a cache for the baseline package and its dependencies for the AppSourceCop analyzer.
If the baselinePackageCachePath is not specified, the baseline and its dependencies are expected to be found in the dependency package cache path. The al.packageCachePath setting allows you to specify the path to a folder that will act as the cache for the symbol files used by your project.

but also:

Note
If you are using a workspace with multiple projects in Visual Studio Code, you must set the baselinePackageCachePath property in the AppSourceCop.json file.

So, are you saying that if there are two independent package cache folders and baselinePackageCachePath contains previous versions of apps only, everthing should be OK? And it would be just a issue of a compiler on a local computer?
I did not try to ignore the error and send changes to a validation pipeline (with BcContainerHelper Run-AlPipeline). Will be there an isssue or not? I have found an old issue (but for Run-AlValidation): BCH#2339.
And, will be there or not a problem when we will try to validate an app on AppSource?

@qutreson
Copy link
Contributor

The problem with using the al.packageCachePath for both the dependencies of your current version and the baseline package is that the baseline package's dependencies will be resolved to the latest version available in the the al.packageCachePath.

If your package cache contains Base V1, Base V2 and the extending app V1, then the baseline version V1 will be loaded using Base V2 as dependency. Since the extending app V1 uses an interface that doesn't exist in V2 that's why it surfaces as a missing interface.

This is why we introduced the ability to have a dedicated folder for the baseline and its dependencies, so that you can control the versions being used. I am not sure how Run-AlValidation handles this - based on the Github issue you linked, it might not use the baselinePackageCachePath from the AppSourceCop.json. However, during the technical validation of AppSource submissions, this is used. So if you submit together the V2 versions of your apps, the validation will be done against both Base V1 and the extending app V1.

@RadoArvay
Copy link
Author

Ok, thank you for the clarification. I will reconfigure our workspace; along with al.compilerOptions.outFolder if it finally works (#7536) (can this property have any impact on packageCache resolving/using?)

@qutreson
Copy link
Contributor

qutreson commented Mar 15, 2024

Using 'al.compilerOptions.outFolder' will allow you to push the package built for your project toward a specific folder. It doesn't influence the resolution approach as such, but since the resolution relies on what is in the package cache path, then adding some app files there will have some influence on the resolution.

@RadoArvay
Copy link
Author

Ok, thanks.
As I wrote, I will try to change the configuration...so maybe we can close this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
AppSourceCop This is a specific static-code-analysis group (AS) input-needed requires-triage
Projects
None yet
Development

No branches or pull requests

3 participants