0

The "ImplicitUsings" feature allows code to omit usings statements for standard namespaces. I need to analyze a random source file(s) for which I may not know an appropriate set of includes. In C# 10 a standard set of namespaces could be included implicitly, as described in the help topic. Is there a way to use the standard namespaces when creating a compilation?

using System.Diagnostics;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;

var sourceText = "class C{" +
    "public void M(){" +
    " Console.Write(123);" +
    "}}";
var syntaxTree = CSharpSyntaxTree.ParseText(sourceText);

var coreReferences =
    ((string)AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES"))
    .Split(Path.PathSeparator)
    .Select(p => MetadataReference.CreateFromFile(p));
var compilation = CSharpCompilation.Create("MyAnalysis")
    .WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
    .AddReferences(coreReferences)
    .AddSyntaxTrees(syntaxTree);

var diagnostics = compilation.GetDiagnostics();
Debug.Assert(diagnostics.Length == 0);
// diagnostics = "error CS0103: The name 'Console' does not exist in the current context"

To clarify the above example, I'm compiling the source in the sourceText variable. The diagnostics variable contains the error that Console does not exist. If I add "using System" in the sourceText above, the code compiles without the error. Is there a way to enable the Implicit Usings feature so that compilation resolves symbols from standard namespaces?

Mark Meyerovich
  • 193
  • 3
  • 9

2 Answers2

1

Not implicit usings, but you can add usings to your compilation externally by using the WithUsings method of the CSharpCompilationOptions class.

Blindy
  • 65,249
  • 10
  • 91
  • 131
  • Thanks, I do not know which usings are needed ahead of time, as I need to analyze a random piece of code or a class. – Mark Meyerovich Mar 31 '23 at 20:30
  • Then give up, if you don't know what you need ahead of time and won't write proper `using`s in code, then you can't compile. Was your hope that the standard "implicit usings" would somehow guess what you need? They don't, they're just a list of usings. You can see the full list [here](https://dotnetcoretutorials.com/2021/08/31/implicit-using-statements-in-net-6/), and you can feed it by hand using the API I listed above. – Blindy Apr 01 '23 at 21:00
  • Thanks for the link on implicit usings – Mark Meyerovich Apr 03 '23 at 15:58
0

Based on suggestions I'm pursuing a possible solution by creating a global usings file(s) corresponding to specific known SDK(s). Will probably look up SDK in the project file or use a default. For example, for Microsoft.NET.Sdk I created the following file (Microsoft.NET.Sdk.usings.cs):

global using System;
global using System.Collections.Generic;
global using System.IO;
global using System.Linq;
global using System.Net.Http;
global using System.Threading;
global using System.Threading.Tasks;

There is a document describing default namespaces for standard SDK(s). Then I can load it and parse as an additional syntax tree getting rid of the compilation error. There are warnings about unnecessary using directives. The complete code is this:

using System.Diagnostics;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;

var sourceText = "class C{" +
    "public void M(){" +
    " Console.Write(123);" +
    "}}";
var syntaxTree = CSharpSyntaxTree.ParseText(sourceText);

var globalUsings = File.ReadAllText("Microsoft.NET.Sdk.usings.cs");
var usingsTree = CSharpSyntaxTree.ParseText(globalUsings);

var coreReferences =
    ((string)AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES"))
    .Split(Path.PathSeparator)
    .Select(p => MetadataReference.CreateFromFile(p));
var compilation = CSharpCompilation.Create("MyAnalysis")
    .WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
    .AddReferences(coreReferences)
    .AddSyntaxTrees(usingsTree, syntaxTree);

var diagnostics = compilation.GetDiagnostics();
Debug.Assert(!diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error));
Mark Meyerovich
  • 193
  • 3
  • 9