Registering namespaces for C# scripts

I’m trying to add namespaces to the CsParser Repository so that the user doesn’t have to explicitly write them:

_csSource = new TextSource(this._components);

var solution = new CsSolution(Microsoft.CodeAnalysis.SourceCodeKind.Script, globalType: _associatedType);

_parser = new CsParser(solution);
_csSource.Lexer = _parser;
_parser.Repository.RegisterDefaultAssemblies();
_parser.Repository.RegisterAssembly("System.Core");
_parser.Repository.RegisterDefaultNamespaces(Alternet.Common.TechnologyEnvironment.System);
_parser.Repository.RegisterNamespaces(new string[] { "System.Linq" });
_parser.Repository.RegisterAssembly(_associatedType.Assembly.Location);
_parser.TextReparsed += _parser_TextReparsed;

foreach (var line in StringItem.Split(ScriptExpression))
{
  _csSource.Lines.Add(line);
}

_syntaxEdit = new SyntaxEdit(this._components);
_syntaxEdit.Source = _csSource;
_syntaxEdit.NeedCodeCompletion += _syntaxEdit_NeedCodeCompletion;

but it fails to parse the script with the exception below. How do we provide default usings?

System.ArgumentException
HResult=0x80070057
Message=Submission can have at most one syntax tree. (Parameter ‘trees’)
Source=Microsoft.CodeAnalysis.CSharp
StackTrace:
at Microsoft.CodeAnalysis.CSharp.CSharpCompilation.AddSyntaxTrees(IEnumerable`1 trees) in /_/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs:line 874

Submission can have at most one syntax tree. (Parameter ‘trees’)
at Microsoft.CodeAnalysis.CSharp.CSharpCompilation.AddSyntaxTrees(IEnumerable`1 trees)
at Microsoft.CodeAnalysis.SolutionState.CompilationTracker.BuildDeclarationCompilationFromScratchAsync(SolutionServices solutionServices, CompilationTrackerGeneratorInfo generatorInfo, CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.SolutionState.CompilationTracker.BuildCompilationInfoFromScratchAsync(SolutionState solution, CompilationTrackerGeneratorInfo generatorInfo, CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.SolutionState.CompilationTracker.BuildCompilationInfoAsync(SolutionState solution, CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.SolutionState.CompilationTracker.GetOrBuildCompilationInfoAsync(SolutionState solution, Boolean lockGate, CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.SolutionState.CompilationTracker.GetCompilationSlowAsync(SolutionState solution, CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.Document.GetSemanticModelAsync(CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.Shared.Extensions.DocumentExtensions.GetRequiredSemanticModelAsync(Document document, CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.Classification.Classifier.GetClassifiedSpansAsync(Document document, TextSpan textSpan, CancellationToken cancellationToken)
at Alternet.Syntax.Parsers.Roslyn.RoslynParser.Tokenizer.ParsedAsync(Document document, Int32 first, Int32 last, CancellationToken cancellationToken)
at Alternet.Syntax.Parsers.Roslyn.RoslynParser.ParseSyntaxAsync(Document document, Int32 first, Int32 last, CancellationToken cancellationToken)
at Alternet.Syntax.Parsers.Roslyn.RoslynParser.ReparseTextAsync(Document document, Int32 first, Int32 last)
at System.Threading.Tasks.Task.<>c.b__128_0(Object state)

Hi Daniel,

We must’ve solved this issue already internally, and the fix will be included in the coming update.

Meanwhile, could you try to use the following workaround to see if it works for you?

var solution = new MyCsSolution(Microsoft.CodeAnalysis.SourceCodeKind.Script, _associatedType);
....
public class MyCsSolution : CsSolution
{
    public MyCsSolution(SourceCodeKind sourceKind = SourceCodeKind.Regular, Type scriptGlobalsType = null)
        :base(sourceKind, scriptGlobalsType)
    {
    }

    public override bool RegisterNamespaces(string[] nameSpaces, ProjectId projectId = null)
    {
        if (SourceKind == SourceCodeKind.Regular)
            return base.RegisterNamespaces(nameSpaces, projectId);

        Project project = GetProjectOrDefault(projectId);
        if (project == null)
            return false;

        var options = GetCompilationOptions() as CSharpCompilationOptions;
        ApplySolutionChanges(s => s.WithProjectCompilationOptions(project.Id, options.WithUsings(nameSpaces)));

        Update();
        return true;
    }
}

Kind regards,
Dmitry

Dmitry,

That worked, thank you.

Regards,

Daniel Perry

1 Like