-
Notifications
You must be signed in to change notification settings - Fork 231
Expand file tree
/
Copy pathVbExpressionValidator.cs
More file actions
109 lines (94 loc) · 4.46 KB
/
VbExpressionValidator.cs
File metadata and controls
109 lines (94 loc) · 4.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// This file is part of Core WF which is licensed under the MIT license.
// See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.VisualBasic;
using Microsoft.CodeAnalysis.VisualBasic.Scripting.Hosting;
using Microsoft.VisualBasic.Activities;
namespace System.Activities;
/// <summary>
/// Validates VB.NET expressions for use in fast design-time expression validation.
/// </summary>
public class VbExpressionValidator : RoslynExpressionValidator
{
private static readonly Lazy<VbExpressionValidator> s_default = new();
private static VbExpressionValidator s_instance;
private static readonly VisualBasicParseOptions s_vbScriptParseOptions =
new(kind: SourceCodeKind.Script, languageVersion: LanguageVersion.Latest);
private static readonly HashSet<Assembly> s_defaultReferencedAssemblies = new()
{
typeof(Collections.ICollection).Assembly,
typeof(Enum).Assembly,
typeof(ComponentModel.BrowsableAttribute).Assembly,
typeof(VisualBasicValue<>).Assembly,
};
private Compilation DefaultCompilationUnit;
/// <summary>
/// Singleton instance of the default validator.
/// </summary>
public static VbExpressionValidator Instance
{
get => s_instance ?? s_default.Value;
set => s_instance = value;
}
protected override int IdentifierKind => (int)SyntaxKind.IdentifierName;
/// <summary>
/// Initializes the MetadataReference collection.
/// </summary>
public VbExpressionValidator() : this(null) { }
/// <summary>
/// Initializes the MetadataReference collection.
/// </summary>
/// <param name="referencedAssemblies">
/// Assemblies to seed the collection.
/// </param>
public VbExpressionValidator(HashSet<Assembly> referencedAssemblies)
: base(referencedAssemblies != null
? new HashSet<Assembly>(s_defaultReferencedAssemblies.Union(referencedAssemblies))
: s_defaultReferencedAssemblies)
{ }
protected override void UpdateCompilationUnit(ExpressionContainer expressionContainer)
{
var globalImports = GlobalImport.Parse(expressionContainer.ExpressionToValidate.ImportedNamespaces);
var metadataReferences = GetMetadataReferencesForExpression(expressionContainer);
if (DefaultCompilationUnit == null)
{
var assemblyName = Guid.NewGuid().ToString();
VisualBasicCompilationOptions options = new(
OutputKind.DynamicallyLinkedLibrary,
mainTypeName: null,
globalImports: globalImports,
rootNamespace: "",
optionStrict: OptionStrict.On,
optionInfer: true,
optionExplicit: true,
optionCompareText: false,
embedVbCoreRuntime: false,
optimizationLevel: OptimizationLevel.Debug,
checkOverflow: true,
xmlReferenceResolver: null,
sourceReferenceResolver: SourceFileResolver.Default,
concurrentBuild: !RuntimeInformation.IsOSPlatform(OSPlatform.Create("BROWSER")));
expressionContainer.CompilationUnit = DefaultCompilationUnit =
VisualBasicCompilation.Create(assemblyName, null, metadataReferences, options);
}
else
{
var options = DefaultCompilationUnit.Options as VisualBasicCompilationOptions;
var compilation = DefaultCompilationUnit.WithOptions(options!.WithGlobalImports(globalImports));
expressionContainer.CompilationUnit = compilation.WithReferences(metadataReferences);
}
}
protected override string CreateValidationCode(string types, string names, ExpressionContainer expressionContainer)
{
var code = expressionContainer.ExpressionToValidate.Code;
return
$"Public Shared Function CreateExpression() As Expression(Of Func(Of {types}))\nReturn Function({names}) ({code})\nEnd Function";
}
protected override SyntaxTree GetSyntaxTreeForExpression(ExpressionContainer expressionContainer) =>
VisualBasicSyntaxTree.ParseText("? " + expressionContainer.ExpressionToValidate.Code, s_vbScriptParseOptions);
protected override string GetTypeName(Type type) => VisualBasicObjectFormatter.FormatTypeName(type);
}