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

HostObjectType/GlobalsType for .csx files is unknown for custom script runners #1171

Open
bramerdaniel opened this issue Apr 24, 2018 · 3 comments

Comments

@bramerdaniel
Copy link

Hi together,

I'm using omnisharp + vscode to execute c# scripts that automate my application.
to execute my script I had to write my own script runner because it is required to have my own host/globals object that provides access to the 'application scripting api' form iside a script.

That works quite good but there is one feature missing that would make writing scripts much simpler.

You do not get language server support for the globals object in the root of a script, because omnisharp does not the type ?

From my first view of the source code of omnisharp-roslyn I thought that it could be possible, but there is this no way to set this GlobalsType in the ScriptContextModel class, as it is comming from the ProjectInfo.

public class ScriptContextModel
    {
        public ScriptContextModel(string csxPath, ProjectInfo project, HashSet<string> implicitAssemblyReferences)
        {
            Path = csxPath;
            ImplicitAssemblyReferences = implicitAssemblyReferences;
            CommonUsings = ScriptHelper.DefaultNamespaces;
            GlobalsType = project.HostObjectType;
        }

        public string Path { get; }

        public HashSet<string> ImplicitAssemblyReferences { get; }

        public Type GlobalsType { get; }

        public IEnumerable<string> CommonUsings { get; }
    }

I followed the way up the call tree to find out the if it could be possible to set this type in any way, but came the result that it is not :-( because the projectInfo is always created with the CommandLineScriptGlobals type.

        public ProjectInfo CreateProject(string csxFileName, IEnumerable<MetadataReference> references, string csxFilePath, IEnumerable<string> namespaces = null)
        {
            var project = ProjectInfo.Create(
                filePath: csxFilePath,
                id: ProjectId.CreateNewId(),
                version: VersionStamp.Create(),
                name: csxFileName,
                assemblyName: $"{csxFileName}.dll",
                language: LanguageNames.CSharp,
                compilationOptions: namespaces == null ? _compilationOptions.Value : _compilationOptions.Value.WithUsings(namespaces),
                metadataReferences: references,
                parseOptions: ParseOptions,
                isSubmission: true,
                hostObjectType: typeof(CommandLineScriptGlobals));

            return project;
        }

Can anybody tell me if I am wrong ?
If not does anybody else think that this should be possible or am I the only one with this problem.

In my oppinion there could be two possible ways to implement that.

  1. Configure this type in workspace
  2. Define this type in the script.

I would choose the second one.

Please let me know if I am completely wrong, and if not, is the team interested in solution.

Thanks in advance

Daniel

@filipw filipw added the csx label Apr 24, 2018
@filipw
Copy link
Member

filipw commented Apr 24, 2018

This is a very reasonable request, and is something that is definitely on the radar. Unfortunately, the support for this is somewhat complicated, due to current limitations in Roslyn.
At the moment we decided to simply always use CommandLineScriptGlobals as the globals type because that covers the base for "standard" scripting such as CSI or other syntactically compatible runners like dotnet-script

The main problem is that at the moment Roslyn APIs require the globals type to be passed in as Type, meaning that it must be loaded into the current application process. This already restricts us a lot, because OmniSharp is a net46 application, and if your host type is inside an incompatible/unloadable assembly, say in a netstandard2.0 or netcoreapp2.0 assembly, there is no way to make it work. There are two open issues in the Roslyn repo (here and here) that specifically try to address this situation. Ultimately, the proper solution to your problem would be for Roslyn to allow us different ways of passing in the globals type information (i.e. via ITypeSymbol).

As a short term fix we could allow passing in the assembly+type of the globals via script configuration, that you would configure in an omnisharp.json. The restriction here would be that it would have to be a net46 or netstandard1.6 (or lower) as it would have to be loaded into the OmniSharp process. Would that work for you?

@bramerdaniel
Copy link
Author

That would perfectly fit my needs !

My script runner is also a net46 application and I took my inspiration from your dotnet-scripts project, and setup my workspace for vs code in kind of the same way.

I have also a class that

  • creates the folder structure
  • creates the tasks.json for my runner
  • some scripts to include . . .

It would be no problem to create the omnisharp.json as well.
Am I right that this can also be located in the worspace folder of vs code ?

Additionaly I didn't think about the problem that netstandard.2.0 assemblies are not loadable from the Omnisharp.exe, so thank you for your detailed answer.

So would you like to implement the discussed solution, or should I give it a try and create a pull request ?
For me both would be fine, and you could work on more common issues ?

@germanftorres
Copy link

germanftorres commented Nov 4, 2020

Hi Filip!

Any update on allowing to specify a custom globals type?

In my use case, I allow to configure my application via C# scripts (using monaco editor + monaco-languageclient + omnisharp). These scripts get executed at runtime via CSharpScript.Create(...) passing a specific "globals" types so that the user can directly access the implicit members of this type. This works great at runtime, but I'm struggling to give proper intellisense experience in the monaco editor due to the fact that it's not possible to customize the globals type through omnisharp.json.

Is this still blocked by a poor support in the Roslyn apis? Any workaround?

Also, is there a way to specify LangVersion and Nullable (NRT) in omnisharp.json for a script environment? I have managed to configure that for a regular c# project via .csproj file, but not for a script project.

Thanks for all the good work in this repo.

Germán

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants