VsixCommunity / Community.VisualStudio.Toolkit

Making it easier to write Visual Studio extensions
Other
253 stars 44 forks source link

No references at project.References for SDK style projects #183

Open AngryShaDoW opened 2 years ago

AngryShaDoW commented 2 years ago

At #180 have been added reference management functionality. But it work's only for project references and shared projects (with hack inside).

With SDK style projects IVsReferenceManagerUser.GetProviderContexts() have not return IVsAssemblyReferenceProviderContext, that's why no any assembly reference have returned at project.References.

With SDK style project and old style projects no any context to get nugget reference (PackageReference) - no any nugget reference have returned at project.References. Not sure that is such reference context type is exist.

reduckted commented 2 years ago

The Visual Studio API doesn't provide access to NuGet package references, but they can be accessed using NuGet libraries. The NuGet.VisualStudio.Contracts package provides an INuGetProjectService interface that allows you to get the packages installed in a project. I don't think there's much documentation on how to use those services, but you may be able to find some examples by searching for that interface on GitHub.

ErikEJ commented 2 years ago

I am using the NuGet.ProjectModel package to enumerate package references here: https://github.com/ErikEJ/EFCorePowerTools/blob/master/src/GUI/Shared/Extensions/ProjectExtensions.cs#L138

AngryShaDoW commented 2 years ago

The Visual Studio API doesn't provide access to NuGet package references, but they can be accessed using NuGet libraries. The NuGet.VisualStudio.Contracts package provides an INuGetProjectService interface that allows you to get the packages installed in a project. I don't think there's much documentation on how to use those services, but you may be able to find some examples by searching for that interface on GitHub.

Thanks for the tip. Small example of INuGetProjectService usage:

    public static async Task<IEnumerable<NuGetInstalledPackage>> GetInstalledPackagesAsync(this Community.VisualStudio.Toolkit.Project project)
    {
        var solution = await Community.VisualStudio.Toolkit.VS.GetServiceAsync<SVsSolution, IVsSolution>();
        project.GetItemInfo(out var hierarchy, out _, out _);

        if (hierarchy == null)
            return new NuGetInstalledPackage[0];

        int result = solution.GetGuidOfProject(hierarchy, out var projectGuid);
        if (result != VSConstants.S_OK)
            throw new Exception($"Error calling {nameof(IVsSolution)}.{nameof(IVsSolution.GetGuidOfProject)}: {result}");

        var serviceBrokerContainer = await Community.VisualStudio.Toolkit.VS.GetServiceAsync<SVsBrokeredServiceContainer, IBrokeredServiceContainer>();
        var serviceBroker = serviceBrokerContainer.GetFullAccessServiceBroker();

        var projectService = await serviceBroker.GetProxyAsync<INuGetProjectService>(NuGetServices.NuGetProjectServiceV1);
        using (projectService as IDisposable)
        {
            var packagesResult = await projectService.GetInstalledPackagesAsync(projectGuid, CancellationToken.None);
            if (packagesResult.Status != InstalledPackageResultStatus.Successful)
                throw new Exception($"Unexpected result from GetInstalledPackagesAsync: {packagesResult.Status}");

            var packs = packagesResult.Packages
                .Where(p => p.DirectDependency).ToArray();

            return packs;
        }
    }

Question about nuggets is resolved by code above. Do you think it is worth adding simplified methods for working with nuggets to the toolkit, by analogy with references?

AngryShaDoW commented 2 years ago

With SDK style projects IVsReferenceManagerUser.GetProviderContexts() have not return IVsAssemblyReferenceProviderContext, that's why no any assembly reference have returned at project.References.

Not all SDK style projects, if set <TargetFramework>net48</TargetFramework> then IVsAssemblyReferenceProviderContext is present, if <TargetFramework>netstandard2.0</TargetFramework> then it not exist.

AngryShaDoW commented 2 years ago

And one more related problem: If assembly reference does not resolved (for example wrong path to assembly) it does not exist at IVsAssemblyReferenceProviderContext.References.

madskristensen commented 2 years ago

The IBrokeredService stuff is VS 2022 only, right?

reduckted commented 2 years ago

2019 and 2022, I think.