| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,371 @@ | ||
| // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
|
||
| using System; | ||
| using System.Collections; | ||
| using System.Collections.Generic; | ||
| using System.Globalization; | ||
| using System.Text; | ||
| using Microsoft.CodeAnalysis; | ||
| using Microsoft.CodeAnalysis.CSharp; | ||
| using Microsoft.CodeAnalysis.CSharp.Symbols; | ||
| using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
| using Roslyn.Utilities; | ||
|
|
||
| namespace Roslyn.Scripting.CSharp | ||
| { | ||
| public sealed class CSharpObjectFormatter : ObjectFormatter | ||
| { | ||
| public static readonly CSharpObjectFormatter Instance = new CSharpObjectFormatter(); | ||
|
|
||
| private CSharpObjectFormatter() | ||
| { | ||
| } | ||
|
|
||
| public override object VoidDisplayString | ||
| { | ||
| get { return "<void>"; } | ||
| } | ||
|
|
||
| public override string NullLiteral | ||
| { | ||
| get { return ObjectDisplay.NullLiteral; } | ||
| } | ||
|
|
||
| public override string FormatLiteral(bool value) | ||
| { | ||
| return ObjectDisplay.FormatLiteral(value); | ||
| } | ||
|
|
||
| public override string FormatLiteral(string value, bool quote, bool useHexadecimalNumbers = false) | ||
| { | ||
| var options = ObjectDisplayOptions.None; | ||
| if (quote) | ||
| { | ||
| options |= ObjectDisplayOptions.UseQuotes; | ||
| } | ||
| if (useHexadecimalNumbers) | ||
| { | ||
| options |= ObjectDisplayOptions.UseHexadecimalNumbers; | ||
| } | ||
| return ObjectDisplay.FormatLiteral(value, options); | ||
| } | ||
|
|
||
| public override string FormatLiteral(char c, bool quote, bool includeCodePoints = false, bool useHexadecimalNumbers = false) | ||
| { | ||
| var options = ObjectDisplayOptions.None; | ||
| if (quote) | ||
| { | ||
| options |= ObjectDisplayOptions.UseQuotes; | ||
| } | ||
| if (includeCodePoints) | ||
| { | ||
| options |= ObjectDisplayOptions.IncludeCodePoints; | ||
| } | ||
| if (useHexadecimalNumbers) | ||
| { | ||
| options |= ObjectDisplayOptions.UseHexadecimalNumbers; | ||
| } | ||
| return ObjectDisplay.FormatLiteral(c, options); | ||
| } | ||
|
|
||
| public override string FormatLiteral(sbyte value, bool useHexadecimalNumbers = false) | ||
| { | ||
| return ObjectDisplay.FormatLiteral(value, GetObjectDisplayOptions(useHexadecimalNumbers)); | ||
| } | ||
|
|
||
| public override string FormatLiteral(byte value, bool useHexadecimalNumbers = false) | ||
| { | ||
| return ObjectDisplay.FormatLiteral(value, GetObjectDisplayOptions(useHexadecimalNumbers)); | ||
| } | ||
|
|
||
| public override string FormatLiteral(short value, bool useHexadecimalNumbers = false) | ||
| { | ||
| return ObjectDisplay.FormatLiteral(value, GetObjectDisplayOptions(useHexadecimalNumbers)); | ||
| } | ||
|
|
||
| public override string FormatLiteral(ushort value, bool useHexadecimalNumbers = false) | ||
| { | ||
| return ObjectDisplay.FormatLiteral(value, GetObjectDisplayOptions(useHexadecimalNumbers)); | ||
| } | ||
|
|
||
| public override string FormatLiteral(int value, bool useHexadecimalNumbers = false) | ||
| { | ||
| return ObjectDisplay.FormatLiteral(value, GetObjectDisplayOptions(useHexadecimalNumbers)); | ||
| } | ||
|
|
||
| public override string FormatLiteral(uint value, bool useHexadecimalNumbers = false) | ||
| { | ||
| return ObjectDisplay.FormatLiteral(value, GetObjectDisplayOptions(useHexadecimalNumbers)); | ||
| } | ||
|
|
||
| public override string FormatLiteral(long value, bool useHexadecimalNumbers = false) | ||
| { | ||
| return ObjectDisplay.FormatLiteral(value, GetObjectDisplayOptions(useHexadecimalNumbers)); | ||
| } | ||
|
|
||
| public override string FormatLiteral(ulong value, bool useHexadecimalNumbers = false) | ||
| { | ||
| return ObjectDisplay.FormatLiteral(value, GetObjectDisplayOptions(useHexadecimalNumbers)); | ||
| } | ||
|
|
||
| public override string FormatLiteral(double value) | ||
| { | ||
| return ObjectDisplay.FormatLiteral(value, ObjectDisplayOptions.None); | ||
| } | ||
|
|
||
| public override string FormatLiteral(float value) | ||
| { | ||
| return ObjectDisplay.FormatLiteral(value, ObjectDisplayOptions.None); | ||
| } | ||
|
|
||
| public override string FormatLiteral(decimal value) | ||
| { | ||
| return ObjectDisplay.FormatLiteral(value, ObjectDisplayOptions.None); | ||
| } | ||
|
|
||
| public override string FormatTypeName(Type type, ObjectFormattingOptions options) | ||
| { | ||
| return GetPrimitiveTypeName(type) ?? AppendComplexTypeName(new StringBuilder(), type, options).ToString(); | ||
| } | ||
|
|
||
| private static string GetPrimitiveTypeName(Type type) | ||
| { | ||
| switch (Type.GetTypeCode(type)) | ||
| { | ||
| case TypeCode.Boolean: return "bool"; | ||
| case TypeCode.Byte: return "byte"; | ||
| case TypeCode.Char: return "char"; | ||
| case TypeCode.Decimal: return "decimal"; | ||
| case TypeCode.Double: return "double"; | ||
| case TypeCode.Int16: return "short"; | ||
| case TypeCode.Int32: return "int"; | ||
| case TypeCode.Int64: return "long"; | ||
| case TypeCode.SByte: return "sbyte"; | ||
| case TypeCode.Single: return "float"; | ||
| case TypeCode.String: return "string"; | ||
| case TypeCode.UInt16: return "ushort"; | ||
| case TypeCode.UInt32: return "uint"; | ||
| case TypeCode.UInt64: return "ulong"; | ||
|
|
||
| case TypeCode.Object: | ||
| case TypeCode.Empty: | ||
| case TypeCode.DBNull: | ||
| case TypeCode.DateTime: | ||
| default: | ||
| if (type == typeof(object)) | ||
| { | ||
| return "object"; | ||
| } | ||
| return null; | ||
| } | ||
| } | ||
|
|
||
| private StringBuilder AppendComplexTypeName(StringBuilder builder, Type type, ObjectFormattingOptions options) | ||
| { | ||
| if (type.IsArray) | ||
| { | ||
| builder.Append(FormatArrayTypeName(type, arrayOpt: null, options: options)); | ||
| return builder; | ||
| } | ||
|
|
||
| // compiler generated (e.g. iterator/async) | ||
| string stateMachineName; | ||
| if (GeneratedNames.TryParseSourceMethodNameFromGeneratedName(type.Name, GeneratedNameKind.StateMachineType, out stateMachineName)) | ||
| { | ||
| builder.Append(stateMachineName); | ||
| return builder; | ||
| } | ||
|
|
||
| if (type.IsGenericType) | ||
| { | ||
| // consolidated generic arguments (includes arguments of all declaring types): | ||
| Type[] genericArguments = type.GetGenericArguments(); | ||
|
|
||
| if (type.DeclaringType != null) | ||
| { | ||
| List<Type> nestedTypes = new List<Type>(); | ||
| do | ||
| { | ||
| nestedTypes.Add(type); | ||
| type = type.DeclaringType; | ||
| } | ||
| while (type != null); | ||
|
|
||
| int typeArgumentIndex = 0; | ||
| for (int i = nestedTypes.Count - 1; i >= 0; i--) | ||
| { | ||
| AppendTypeInstantiation(builder, nestedTypes[i], genericArguments, ref typeArgumentIndex, options); | ||
| if (i > 0) | ||
| { | ||
| builder.Append('.'); | ||
| } | ||
| } | ||
| } | ||
| else | ||
| { | ||
| int typeArgumentIndex = 0; | ||
| return AppendTypeInstantiation(builder, type, genericArguments, ref typeArgumentIndex, options); | ||
| } | ||
| } | ||
| else if (type.DeclaringType != null) | ||
| { | ||
| builder.Append(type.Name.Replace('+', '.')); | ||
| } | ||
| else | ||
| { | ||
| builder.Append(type.Name); | ||
| } | ||
|
|
||
| return builder; | ||
| } | ||
|
|
||
| private StringBuilder AppendTypeInstantiation(StringBuilder builder, Type type, Type[] genericArguments, ref int genericArgIndex, | ||
| ObjectFormattingOptions options) | ||
| { | ||
| // generic arguments of all the outer types and the current type; | ||
| Type[] currentGenericArgs = type.GetGenericArguments(); | ||
| int currentArgCount = currentGenericArgs.Length - genericArgIndex; | ||
|
|
||
| if (currentArgCount > 0) | ||
| { | ||
| int backtick = type.Name.IndexOf('`'); | ||
| if (backtick > 0) | ||
| { | ||
| builder.Append(type.Name.Substring(0, backtick)); | ||
| } | ||
| else | ||
| { | ||
| builder.Append(type.Name); | ||
| } | ||
|
|
||
| builder.Append('<'); | ||
|
|
||
| for (int i = 0; i < currentArgCount; i++) | ||
| { | ||
| if (i > 0) | ||
| { | ||
| builder.Append(", "); | ||
| } | ||
| builder.Append(FormatTypeName(genericArguments[genericArgIndex++], options)); | ||
| } | ||
|
|
||
| builder.Append('>'); | ||
| } | ||
| else | ||
| { | ||
| builder.Append(type.Name); | ||
| } | ||
|
|
||
| return builder; | ||
| } | ||
|
|
||
| public override string FormatArrayTypeName(Array array, ObjectFormattingOptions options) | ||
| { | ||
| return FormatArrayTypeName(array.GetType(), array, options); | ||
| } | ||
|
|
||
| private string FormatArrayTypeName(Type arrayType, Array arrayOpt, ObjectFormattingOptions options) | ||
| { | ||
| StringBuilder sb = new StringBuilder(); | ||
|
|
||
| // print the inner-most element type first: | ||
| Type elementType = arrayType.GetElementType(); | ||
| while (elementType.IsArray) | ||
| { | ||
| elementType = elementType.GetElementType(); | ||
| } | ||
|
|
||
| sb.Append(FormatTypeName(elementType, options)); | ||
|
|
||
| // print all components of a jagged array: | ||
| Type type = arrayType; | ||
| do | ||
| { | ||
| if (arrayOpt != null) | ||
| { | ||
| sb.Append('['); | ||
|
|
||
| int rank = type.GetArrayRank(); | ||
|
|
||
| bool anyNonzeroLowerBound = false; | ||
| for (int i = 0; i < rank; i++) | ||
| { | ||
| if (arrayOpt.GetLowerBound(i) > 0) | ||
| { | ||
| anyNonzeroLowerBound = true; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| for (int i = 0; i < rank; i++) | ||
| { | ||
| int lowerBound = arrayOpt.GetLowerBound(i); | ||
| long length = arrayOpt.GetLongLength(i); | ||
|
|
||
| if (i > 0) | ||
| { | ||
| sb.Append(", "); | ||
| } | ||
|
|
||
| if (anyNonzeroLowerBound) | ||
| { | ||
| AppendArrayBound(sb, lowerBound, options.UseHexadecimalNumbers); | ||
| sb.Append(".."); | ||
| AppendArrayBound(sb, length + lowerBound, options.UseHexadecimalNumbers); | ||
| } | ||
| else | ||
| { | ||
| AppendArrayBound(sb, length, options.UseHexadecimalNumbers); | ||
| } | ||
| } | ||
|
|
||
| sb.Append(']'); | ||
| arrayOpt = null; | ||
| } | ||
| else | ||
| { | ||
| AppendArrayRank(sb, type); | ||
| } | ||
|
|
||
| type = type.GetElementType(); | ||
| } | ||
| while (type.IsArray); | ||
|
|
||
| return sb.ToString(); | ||
| } | ||
|
|
||
| private void AppendArrayBound(StringBuilder sb, long bound, bool useHexadecimalNumbers) | ||
| { | ||
| if (bound <= Int32.MaxValue) | ||
| { | ||
| sb.Append(FormatLiteral((int)bound, useHexadecimalNumbers)); | ||
| } | ||
| else | ||
| { | ||
| sb.Append(FormatLiteral(bound, useHexadecimalNumbers)); | ||
| } | ||
| } | ||
|
|
||
| private static void AppendArrayRank(StringBuilder sb, Type arrayType) | ||
| { | ||
| sb.Append('['); | ||
| int rank = arrayType.GetArrayRank(); | ||
| if (rank > 1) | ||
| { | ||
| sb.Append(',', rank - 1); | ||
| } | ||
| sb.Append(']'); | ||
| } | ||
|
|
||
| public override string FormatMemberName(System.Reflection.MemberInfo member) | ||
| { | ||
| return member.Name; | ||
| } | ||
|
|
||
| public override bool IsHiddenMember(System.Reflection.MemberInfo member) | ||
| { | ||
| // Generated fields, e.g. "<property_name>k__BackingField" | ||
| return GeneratedNames.IsGeneratedMemberName(member.Name); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,189 @@ | ||
| // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
|
||
| using System; | ||
| using System.Diagnostics; | ||
| using System.Globalization; | ||
| using System.Text; | ||
| using Microsoft.CodeAnalysis; | ||
| using Microsoft.CodeAnalysis.CSharp; | ||
| using Microsoft.CodeAnalysis.Text; | ||
|
|
||
| namespace Roslyn.Scripting.CSharp | ||
| { | ||
| /// <summary> | ||
| /// A factory for creating and running csharp scripts. | ||
| /// </summary> | ||
| public sealed class CSharpScript : Script | ||
| { | ||
| private CSharpScript(string code, string path, ScriptOptions options, Type globalsType, Type returnType, ScriptBuilder builder, Script previous) | ||
| : base(code, path, options, globalsType, returnType, builder, previous) | ||
| { | ||
| } | ||
|
|
||
| internal override Script Make(string code, string path, ScriptOptions options, Type globalsType, Type returnType, ScriptBuilder builder, Script previous) | ||
| { | ||
| return new CSharpScript(code, path, options, globalsType, returnType, builder, previous); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Create a new C# script. | ||
| /// <param name="code">The source code of the script.</param> | ||
| /// <param name="options">The script options.</param> | ||
| /// </summary> | ||
| public static Script Create(string code, ScriptOptions options) | ||
| { | ||
| return new CSharpScript(code, null, options, null, typeof(object), null, null); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Create a new C# script. | ||
| /// <param name="code">The source code of the script.</param> | ||
| /// </summary> | ||
| public static Script Create(string code) | ||
| { | ||
| return Create(code, null); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Run a C# script. | ||
| /// </summary> | ||
| /// <param name="code">The source code of the script.</param> | ||
| /// <param name="options">The script options.</param> | ||
| /// <param name="globals">An object instance whose members can be accessed by the script as global variables, | ||
| /// or a <see cref="ScriptState"/> instance that was the output from a previously run script.</param> | ||
| public static ScriptState Run(string code, ScriptOptions options, object globals) | ||
| { | ||
| return Create(code, options).Run(globals); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Run a C# script. | ||
| /// </summary> | ||
| /// <param name="code">The source code of the script.</param> | ||
| /// <param name="options">The script options.</param> | ||
| public static ScriptState Run(string code, ScriptOptions options) | ||
| { | ||
| return Run(code, options, globals: null); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Run a C# script. | ||
| /// </summary> | ||
| /// <param name="code">The source code of the script.</param> | ||
| /// <param name="globals">An object instance whose members can be accessed by the script as global variables, | ||
| /// or a <see cref="ScriptState"/> instance that was the output from a previously run script.</param> | ||
| public static ScriptState Run(string code, object globals) | ||
| { | ||
| return Run(code, options: null, globals: globals); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Run a C# script. | ||
| /// </summary> | ||
| /// <param name="code">The source code of the script.</param> | ||
| public static ScriptState Run(string code) | ||
| { | ||
| return Run(code, null, null); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Run a C# script and return its resulting value. | ||
| /// </summary> | ||
| /// <param name="code">The source code of the script.</param> | ||
| /// <param name="options">The script options.</param> | ||
| /// <param name="globals">An object instance whose members can be accessed by the script as global variables, | ||
| /// or a <see cref="ScriptState"/> instance that was the output from a previously run script.</param> | ||
| /// <return>Returns the value returned by running the script.</return> | ||
| public static object Eval(string code, ScriptOptions options, object globals) | ||
| { | ||
| return Run(code, options, globals).ReturnValue; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Run a C# script and return its resulting value. | ||
| /// </summary> | ||
| /// <param name="code">The source code of the script.</param> | ||
| /// <param name="options">The script options.</param> | ||
| /// <return>Returns the value returned by running the script.</return> | ||
| public static object Eval(string code, ScriptOptions options) | ||
| { | ||
| return Run(code, options).ReturnValue; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Run a C# script and return its resulting value. | ||
| /// </summary> | ||
| /// <param name="code">The source code of the script.</param> | ||
| /// <param name="globals">An object instance whose members can be accessed by the script as global variables, | ||
| /// or a <see cref="ScriptState"/> instance that was the output from a previously run script.</param> | ||
| /// <return>Returns the value returned by running the script.</return> | ||
| public static object Eval(string code, object globals) | ||
| { | ||
| return Run(code, globals).ReturnValue; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Run a C# script and return its resulting value. | ||
| /// </summary> | ||
| /// <param name="code">The source code of the script.</param> | ||
| /// <return>Returns the value returned by running the script.</return> | ||
| public static object Eval(string code) | ||
| { | ||
| return Run(code).ReturnValue; | ||
| } | ||
|
|
||
| #region Compilation | ||
| private static readonly CSharpParseOptions s_defaultInteractive = new CSharpParseOptions(languageVersion: LanguageVersion.CSharp6, kind: SourceCodeKind.Interactive); | ||
| private static readonly CSharpParseOptions s_defaultScript = new CSharpParseOptions(languageVersion: LanguageVersion.CSharp6, kind: SourceCodeKind.Script); | ||
|
|
||
| protected override Compilation CreateCompilation() | ||
| { | ||
| Compilation previousSubmission = null; | ||
| if (this.Previous != null) | ||
| { | ||
| previousSubmission = this.Previous.GetCompilation(); | ||
| } | ||
|
|
||
| var references = this.GetReferencesForCompilation(); | ||
|
|
||
| var parseOptions = this.Options.IsInteractive ? s_defaultInteractive : s_defaultScript; | ||
| var tree = SyntaxFactory.ParseSyntaxTree(this.Code, parseOptions, path: this.Path); | ||
|
|
||
| string assemblyName, submissionTypeName; | ||
| this.Builder.GenerateSubmissionId(out assemblyName, out submissionTypeName); | ||
|
|
||
| var compilation = CSharpCompilation.CreateSubmission( | ||
| assemblyName, | ||
| tree, | ||
| references, | ||
| new CSharpCompilationOptions( | ||
| outputKind: OutputKind.DynamicallyLinkedLibrary, | ||
| mainTypeName: null, | ||
| scriptClassName: submissionTypeName, | ||
| usings: this.Options.Namespaces, | ||
| optimizationLevel: OptimizationLevel.Debug, // TODO | ||
| checkOverflow: false, // TODO | ||
| allowUnsafe: true, // TODO | ||
| platform: Platform.AnyCpu, | ||
| warningLevel: 4, | ||
| xmlReferenceResolver: null, // don't support XML file references in interactive (permissions & doc comment includes) | ||
| sourceReferenceResolver: SourceFileResolver.Default, // TODO | ||
| metadataReferenceResolver: this.Options.ReferenceResolver, | ||
| assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default | ||
| ), | ||
| previousSubmission, | ||
| this.ReturnType, | ||
| this.GlobalsType | ||
| ); | ||
|
|
||
| return compilation; | ||
| } | ||
|
|
||
| protected override string FormatDiagnostic(Diagnostic diagnostic, CultureInfo culture) | ||
| { | ||
| return CSharpDiagnosticFormatter.Instance.Format(diagnostic, culture); | ||
| } | ||
| #endregion | ||
| } | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
| <ImportGroup Label="Settings"> | ||
| <Import Project="..\..\Tools\Microsoft.CodeAnalysis.Toolset.Open\Targets\VSL.Settings.targets" /> | ||
| <Import Project="..\..\..\build\VSL.Settings.Closed.targets" /> | ||
| </ImportGroup> | ||
| <PropertyGroup> | ||
| <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | ||
| <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | ||
| <ProjectGuid>{066F0DBD-C46C-4C20-AFEC-99829A172625}</ProjectGuid> | ||
| <OutputType>Library</OutputType> | ||
| <RootNamespace>Roslyn.Scripting.CSharp</RootNamespace> | ||
| <AssemblyName>Roslyn.Scripting.CSharp</AssemblyName> | ||
| <SolutionDir Condition="'$(SolutionDir)' == '' OR '$(SolutionDir)' == '*Undefined*'">..\..\..\</SolutionDir> | ||
| <RestorePackages>true</RestorePackages> | ||
| </PropertyGroup> | ||
| <ItemGroup Label="Project References"> | ||
| <ProjectReference Include="..\..\Compilers\Core\Desktop\CodeAnalysis.Desktop.csproj"> | ||
| <Project>{dfa21ca1-7f96-47ee-940c-069858e81727}</Project> | ||
| <Name>CodeAnalysis.Desktop</Name> | ||
| </ProjectReference> | ||
| <ProjectReference Include="..\..\Compilers\Core\Portable\CodeAnalysis.csproj"> | ||
| <Project>{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}</Project> | ||
| <Name>CodeAnalysis</Name> | ||
| </ProjectReference> | ||
| <ProjectReference Include="..\..\Compilers\CSharp\Portable\CSharpCodeAnalysis.csproj"> | ||
| <Project>{B501A547-C911-4A05-AC6E-274A50DFF30E}</Project> | ||
| <Name>CSharpCodeAnalysis</Name> | ||
| </ProjectReference> | ||
| <ProjectReference Include="..\Core\CommonScripting.csproj"> | ||
| <Project>{12A68549-4E8C-42D6-8703-A09335F97997}</Project> | ||
| <Name>CommonScripting</Name> | ||
| </ProjectReference> | ||
| </ItemGroup> | ||
| <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|Any CPU' "> | ||
| </PropertyGroup> | ||
| <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|Any CPU' "> | ||
| </PropertyGroup> | ||
| <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|ARM' "> | ||
| <PlatformTarget>ARM</PlatformTarget> | ||
| </PropertyGroup> | ||
| <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|ARM' "> | ||
| <PlatformTarget>ARM</PlatformTarget> | ||
| </PropertyGroup> | ||
| <ItemGroup> | ||
| <Reference Include="System" /> | ||
| <Reference Include="System.Collections.Immutable, Version=1.1.33.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | ||
| <SpecificVersion>False</SpecificVersion> | ||
| <HintPath>..\..\..\packages\System.Collections.Immutable.1.1.33-beta\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath> | ||
| </Reference> | ||
| <Reference Include="System.Core" /> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <Compile Include="CSharpObjectFormatter.cs" /> | ||
| <Compile Include="CSharpScript.cs" /> | ||
| <Compile Include="CSharpScriptingResources.Designer.cs"> | ||
| <AutoGen>True</AutoGen> | ||
| <DesignTime>True</DesignTime> | ||
| <DependentUpon>CSharpScriptingResources.resx</DependentUpon> | ||
| </Compile> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <InternalsVisibleToTest Include="Roslyn.Compilers.CSharp.Emit.UnitTests" /> | ||
| <InternalsVisibleToTest Include="Roslyn.Compilers.UnitTests" /> | ||
| <InternalsVisibleToTest Include="Roslyn.Compilers.VisualBasic.Emit.UnitTests" /> | ||
| <InternalsVisibleToTest Include="Roslyn.Scripting.Common.UnitTests" /> | ||
| <InternalsVisibleToTest Include="Roslyn.Scripting.CSharp.UnitTests" /> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <EmbeddedResource Include="CSharpScriptingResources.resx"> | ||
| <Generator>ResXFileCodeGenerator</Generator> | ||
| <LastGenOutput>CSharpScriptingResources.Designer.cs</LastGenOutput> | ||
| </EmbeddedResource> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <None Include="packages.config" /> | ||
| </ItemGroup> | ||
| <ImportGroup Label="Targets"> | ||
| <Import Project="..\..\Tools\Microsoft.CodeAnalysis.Toolset.Open\Targets\VSL.Imports.targets" /> | ||
| <Import Project="..\..\..\build\VSL.Imports.Closed.targets" /> | ||
| <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" /> | ||
| </ImportGroup> | ||
| </Project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <root> | ||
| <!-- | ||
| Microsoft ResX Schema | ||
| Version 1.3 | ||
| The primary goals of this format is to allow a simple XML format | ||
| that is mostly human readable. The generation and parsing of the | ||
| various data types are done through the TypeConverter classes | ||
| associated with the data types. | ||
| Example: | ||
| ... ado.net/XML headers & schema ... | ||
| <resheader name="resmimetype">text/microsoft-resx</resheader> | ||
| <resheader name="version">1.3</resheader> | ||
| <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> | ||
| <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> | ||
| <data name="Name1">this is my long string</data> | ||
| <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> | ||
| <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> | ||
| [base64 mime encoded serialized .NET Framework object] | ||
| </data> | ||
| <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> | ||
| [base64 mime encoded string representing a byte array form of the .NET Framework object] | ||
| </data> | ||
| There are any number of "resheader" rows that contain simple | ||
| name/value pairs. | ||
| Each data row contains a name, and value. The row also contains a | ||
| type or mimetype. Type corresponds to a .NET class that support | ||
| text/value conversion through the TypeConverter architecture. | ||
| Classes that don't support this are serialized and stored with the | ||
| mimetype set. | ||
| The mimetype is used for serialized objects, and tells the | ||
| ResXResourceReader how to depersist the object. This is currently not | ||
| extensible. For a given mimetype the value must be set accordingly: | ||
| Note - application/x-microsoft.net.object.binary.base64 is the format | ||
| that the ResXResourceWriter will generate, however the reader can | ||
| read any of the formats listed below. | ||
| mimetype: application/x-microsoft.net.object.binary.base64 | ||
| value : The object must be serialized with | ||
| : System.Serialization.Formatters.Binary.BinaryFormatter | ||
| : and then encoded with base64 encoding. | ||
| mimetype: application/x-microsoft.net.object.soap.base64 | ||
| value : The object must be serialized with | ||
| : System.Runtime.Serialization.Formatters.Soap.SoapFormatter | ||
| : and then encoded with base64 encoding. | ||
| mimetype: application/x-microsoft.net.object.bytearray.base64 | ||
| value : The object must be serialized into a byte array | ||
| : using a System.ComponentModel.TypeConverter | ||
| : and then encoded with base64 encoding. | ||
| --> | ||
|
|
||
| <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> | ||
| <xsd:element name="root" msdata:IsDataSet="true"> | ||
| <xsd:complexType> | ||
| <xsd:choice maxOccurs="unbounded"> | ||
| <xsd:element name="data"> | ||
| <xsd:complexType> | ||
| <xsd:sequence> | ||
| <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | ||
| <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> | ||
| </xsd:sequence> | ||
| <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> | ||
| <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> | ||
| <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> | ||
| </xsd:complexType> | ||
| </xsd:element> | ||
| <xsd:element name="resheader"> | ||
| <xsd:complexType> | ||
| <xsd:sequence> | ||
| <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | ||
| </xsd:sequence> | ||
| <xsd:attribute name="name" type="xsd:string" use="required" /> | ||
| </xsd:complexType> | ||
| </xsd:element> | ||
| </xsd:choice> | ||
| </xsd:complexType> | ||
| </xsd:element> | ||
| </xsd:schema> | ||
| <resheader name="resmimetype"> | ||
| <value>text/microsoft-resx</value> | ||
| </resheader> | ||
| <resheader name="version"> | ||
| <value>1.3</value> | ||
| </resheader> | ||
| <resheader name="reader"> | ||
| <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | ||
| </resheader> | ||
| <resheader name="writer"> | ||
| <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | ||
| </resheader> | ||
| </root> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <packages> | ||
| <package id="System.Collections.Immutable" version="1.1.33-beta" targetFramework="net45" /> | ||
| </packages> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
|
||
| using System; | ||
| using Microsoft.CodeAnalysis; | ||
| using Microsoft.CodeAnalysis.CSharp; | ||
|
|
||
| namespace Roslyn.Scripting.CSharp | ||
| { | ||
| /// <summary> | ||
| /// Represents a runtime execution context for C# scripts. | ||
| /// </summary> | ||
| internal sealed class CSharpScriptEngine : ScriptEngine | ||
| { | ||
| public CSharpScriptEngine(MetadataFileReferenceProvider metadataReferenceProvider = null, AssemblyLoader assemblyLoader = null) | ||
| : base(metadataReferenceProvider, assemblyLoader) | ||
| { | ||
| } | ||
|
|
||
| internal override Script Create(string code, ScriptOptions options, Type globalsType, Type returnType) | ||
| { | ||
| return CSharpScript.Create(code, options).WithGlobalsType(globalsType).WithReturnType(returnType).WithBuilder(this.Builder); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
| <ImportGroup Label="Settings"> | ||
| <Import Project="..\..\Tools\Microsoft.CodeAnalysis.Toolset.Open\Targets\VSL.Settings.targets" /> | ||
| <Import Project="..\..\..\build\VSL.Settings.Closed.targets" /> | ||
| </ImportGroup> | ||
| <PropertyGroup> | ||
| <Nonshipping>true</Nonshipping> | ||
| <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | ||
| <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | ||
| <ProjectGuid>{2DAE4406-7A89-4B5F-95C3-BC5422CE47CE}</ProjectGuid> | ||
| <OutputType>Library</OutputType> | ||
| <AppDesignerFolder>Properties</AppDesignerFolder> | ||
| <RootNamespace>Roslyn.Scripting.CSharpTest</RootNamespace> | ||
| <AssemblyName>Roslyn.Scripting.CSharp.UnitTests</AssemblyName> | ||
| <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
| <SolutionDir Condition="'$(SolutionDir)' == '' OR '$(SolutionDir)' == '*Undefined*'">..\..\..\</SolutionDir> | ||
| <RestorePackages>true</RestorePackages> | ||
| </PropertyGroup> | ||
| <ItemGroup Label="Project References"> | ||
| <ProjectReference Include="..\..\Compilers\Core\Desktop\CodeAnalysis.Desktop.csproj"> | ||
| <Project>{dfa21ca1-7f96-47ee-940c-069858e81727}</Project> | ||
| <Name>CodeAnalysis.Desktop</Name> | ||
| </ProjectReference> | ||
| <ProjectReference Include="..\..\Compilers\Core\Portable\CodeAnalysis.csproj"> | ||
| <Project>{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}</Project> | ||
| <Name>CodeAnalysis</Name> | ||
| </ProjectReference> | ||
| <ProjectReference Include="..\..\Compilers\CSharp\Desktop\CSharpCodeAnalysis.Desktop.csproj"> | ||
| <Project>{079af8ef-1058-48b6-943f-ab02d39e0641}</Project> | ||
| <Name>CSharpCodeAnalysis.Desktop</Name> | ||
| </ProjectReference> | ||
| <ProjectReference Include="..\..\Compilers\CSharp\Portable\CSharpCodeAnalysis.csproj"> | ||
| <Project>{B501A547-C911-4A05-AC6E-274A50DFF30E}</Project> | ||
| <Name>CSharpCodeAnalysis</Name> | ||
| </ProjectReference> | ||
| <ProjectReference Include="..\..\Compilers\VisualBasic\Desktop\BasicCodeAnalysis.Desktop.vbproj"> | ||
| <Project>{73f3e2c5-d742-452e-b9e1-20732ddbc75d}</Project> | ||
| <Name>BasicCodeAnalysis.Desktop</Name> | ||
| </ProjectReference> | ||
| <ProjectReference Include="..\..\Compilers\VisualBasic\Portable\BasicCodeAnalysis.vbproj"> | ||
| <Project>{2523D0E6-DF32-4A3E-8AE0-A19BFFAE2EF6}</Project> | ||
| <Name>BasicCodeAnalysis</Name> | ||
| </ProjectReference> | ||
| <ProjectReference Include="..\..\Compilers\Test\Resources\Core\CompilerTestResources.vbproj"> | ||
| <Project>{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}</Project> | ||
| <Name>CompilerTestResources</Name> | ||
| </ProjectReference> | ||
| <ProjectReference Include="..\..\Compilers\Test\Utilities\CSharp\CSharpCompilerTestUtilities.csproj"> | ||
| <Project>{4371944A-D3BA-4B5B-8285-82E5FFC6D1F9}</Project> | ||
| <Name>CSharpCompilerTestUtilities</Name> | ||
| </ProjectReference> | ||
| <ProjectReference Include="..\Core\CommonScripting.csproj"> | ||
| <Project>{12A68549-4E8C-42D6-8703-A09335F97997}</Project> | ||
| <Name>CommonScripting</Name> | ||
| </ProjectReference> | ||
| <ProjectReference Include="..\Test\CommonScriptingTest.csproj"> | ||
| <Project>{2DAE4406-7A89-4B5F-95C3-BC5472CE47CE}</Project> | ||
| <Name>CommonScriptingTest</Name> | ||
| </ProjectReference> | ||
| <ProjectReference Include="..\CSharp\CSharpScripting.csproj"> | ||
| <Project>{066F0DBD-C46C-4C20-AFEC-99829A172625}</Project> | ||
| <Name>CSharpScripting</Name> | ||
| </ProjectReference> | ||
| <ProjectReference Include="..\..\Test\Utilities\TestUtilities.csproj"> | ||
| <Project>{76C6F005-C89D-4348-BB4A-391898DBEB52}</Project> | ||
| <Name>TestUtilities</Name> | ||
| </ProjectReference> | ||
| <ProjectReference Include="..\..\Compilers\CSharp\Test\Symbol\CSharpCompilerSymbolTest.csproj"> | ||
| <Project>{28026D16-EB0C-40B0-BDA7-11CAA2B97CCC}</Project> | ||
| <Name>CSharpCompilerSymbolTest</Name> | ||
| </ProjectReference> | ||
| <ProjectReference Include="..\..\Compilers\Test\Utilities\Core2\CompilerTestUtilities2.csproj"> | ||
| <Project>{F7712928-1175-47B3-8819-EE086753DEE2}</Project> | ||
| <Name>CompilerTestUtilities2</Name> | ||
| </ProjectReference> | ||
| </ItemGroup> | ||
| <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | ||
| </PropertyGroup> | ||
| <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | ||
| </PropertyGroup> | ||
| <ItemGroup> | ||
| <Reference Include="Microsoft.CSharp" /> | ||
| <Reference Include="System" /> | ||
| <Reference Include="System.Collections.Immutable, Version=1.1.33.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | ||
| <SpecificVersion>False</SpecificVersion> | ||
| <HintPath>..\..\..\packages\System.Collections.Immutable.1.1.33-beta\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath> | ||
| </Reference> | ||
| <Reference Include="xunit"> | ||
| <HintPath>..\..\..\packages\xunit.1.9.2\lib\net20\xunit.dll</HintPath> | ||
| </Reference> | ||
| <Reference Include="System.Core" /> | ||
| <Reference Include="System.Data" /> | ||
| <Reference Include="System.Windows.Forms" /> | ||
| <Reference Include="System.Xml" /> | ||
| <Reference Include="System.Xml.Linq" /> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <Compile Include="CSharpScriptEngine.cs" /> | ||
| <Compile Include="InteractiveSessionTests.cs" /> | ||
| <Compile Include="ObjectFormatterTests.cs" /> | ||
| <Compile Include="ScriptTests.cs" /> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <None Include="packages.config" /> | ||
| </ItemGroup> | ||
| <ImportGroup Label="Targets"> | ||
| <Import Project="..\..\Tools\Microsoft.CodeAnalysis.Toolset.Open\Targets\VSL.Imports.targets" /> | ||
| <Import Project="..\..\..\build\VSL.Imports.Closed.targets" /> | ||
| <Import Project="..\..\..\build\Roslyn.Toolsets.Xunit.targets" /> | ||
| <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" /> | ||
| </ImportGroup> | ||
| </Project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,177 @@ | ||
| // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
|
||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using Microsoft.CodeAnalysis.CSharp.Test.Utilities; | ||
| using Roslyn.Utilities; | ||
| using Xunit; | ||
|
|
||
| namespace Roslyn.Scripting.CSharp.Test | ||
| { | ||
| public class ScriptTests : CSharpTestBase | ||
| { | ||
| [Fact] | ||
| public void TestCreateScript() | ||
| { | ||
| var script = CSharpScript.Create("1 + 2"); | ||
| Assert.Equal("1 + 2", script.Code); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void TestGetCompilation() | ||
| { | ||
| var script = CSharpScript.Create("1 + 2"); | ||
| var compilation = script.GetCompilation(); | ||
| Assert.Equal(script.Code, compilation.SyntaxTrees.First().GetText().ToString()); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void TestCreateScriptDelegate() | ||
| { | ||
| // create a delegate for the entire script | ||
| var script = CSharpScript.Create("1 + 2"); | ||
| var fn = script.CreateDelegate(); | ||
| var value = fn(); | ||
| Assert.Equal(3, value); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void TestRunScript() | ||
| { | ||
| var result = CSharpScript.Run("1 + 2"); | ||
| Assert.Equal(3, result.ReturnValue); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void TestCreateAndRunScript() | ||
| { | ||
| var script = CSharpScript.Create("1 + 2"); | ||
| var result = script.Run(); | ||
| Assert.Same(script, result.Script); | ||
| Assert.Equal(3, result.ReturnValue); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void TestEvalScript() | ||
| { | ||
| var value = CSharpScript.Eval("1 + 2"); | ||
| Assert.Equal(3, value); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void TestRunScriptWithSpecifiedReturnType() | ||
| { | ||
| var result = CSharpScript.Create("1 + 2").WithReturnType(typeof(int)).Run(); | ||
| Assert.Equal(3, result.ReturnValue); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void TestRunVoidScript() | ||
| { | ||
| var result = CSharpScript.Run("Console.WriteLine(0);"); | ||
| } | ||
|
|
||
| public class Globals | ||
| { | ||
| public int X; | ||
| public int Y; | ||
| } | ||
|
|
||
| [Fact] | ||
| public void TestRunScriptWithGlobals() | ||
| { | ||
| var result = CSharpScript.Run("X + Y", new Globals { X = 1, Y = 2 }); | ||
| Assert.Equal(3, result.ReturnValue); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void TestRunCreatedScriptWithExpectedGlobals() | ||
| { | ||
| var script = CSharpScript.Create("X + Y").WithGlobalsType(typeof(Globals)); | ||
| var result = script.Run(new Globals { X = 1, Y = 2 }); | ||
| Assert.Equal(3, result.ReturnValue); | ||
| Assert.Same(script, result.Script); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void TestRunCreatedScriptWithUnexpectedGlobals() | ||
| { | ||
| var script = CSharpScript.Create("X + Y"); | ||
| var result = script.Run(new Globals { X = 1, Y = 2 }); | ||
| Assert.Equal(3, result.ReturnValue); | ||
|
|
||
| // the end state of running the script should be based on a different script instance because of the globals | ||
| // not matching the original script definition. | ||
| Assert.NotSame(script, result.Script); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void TestRunScriptWithScriptState() | ||
| { | ||
| // run a script using another scripts end state as the starting state (globals) | ||
| var result = CSharpScript.Run("int X = 100;"); | ||
| var result2 = CSharpScript.Run("X + X", result); | ||
| Assert.Equal(200, result2.ReturnValue); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void TestRepl() | ||
| { | ||
| string[] submissions = new[] | ||
| { | ||
| "int x = 100;", | ||
| "int y = x * x;", | ||
| "x + y" | ||
| }; | ||
|
|
||
| object input = null; | ||
| ScriptState result = null; | ||
| foreach (var submission in submissions) | ||
| { | ||
| result = CSharpScript.Run(submission, input); | ||
| input = result; | ||
| } | ||
|
|
||
| Assert.Equal(10100, result.ReturnValue); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void TestCreateMethodDelegate() | ||
| { | ||
| // create a delegate to a method declared in the script | ||
| var state = CSharpScript.Run("int Times(int x) { return x * x; }"); | ||
| var fn = state.CreateDelegate<Func<int, int>>("Times"); | ||
| var result = fn(5); | ||
| Assert.Equal(25, result); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void TestGetScriptVariableAfterRunningScript() | ||
| { | ||
| var result = CSharpScript.Run("int x = 100;"); | ||
| var globals = result.Variables.Names.ToList(); | ||
| Assert.Equal(1, globals.Count); | ||
| Assert.Equal(true, globals.Contains("x")); | ||
| Assert.Equal(true, result.Variables.ContainsVariable("x")); | ||
| Assert.Equal(100, (int)result.Variables["x"].Value); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void TestBranchingSubscripts() | ||
| { | ||
| // run script to create declaration of M | ||
| var result1 = CSharpScript.Run("int M(int x) { return x + x; }"); | ||
|
|
||
| // run second script starting from first script's end state | ||
| // this script's new declaration should hide the old declaration | ||
| var result2 = CSharpScript.Run("int M(int x) { return x * x; } M(5)", result1); | ||
| Assert.Equal(25, result2.ReturnValue); | ||
|
|
||
| // run third script also starting from first script's end state | ||
| // it should not see any declarations made by the second script. | ||
| var result3 = CSharpScript.Run("M(5)", result1); | ||
| Assert.Equal(10, result3.ReturnValue); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <packages> | ||
| <package id="StyleCop.MSBuild" version="4.7.48.2" targetFramework="net45" developmentDependency="true" /> | ||
| <package id="System.Collections.Immutable" version="1.1.33-beta" targetFramework="net45" /> | ||
| <package id="xunit" version="1.9.2" targetFramework="net45" /> | ||
| </packages> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
|
||
| using System; | ||
|
|
||
| namespace Roslyn.Scripting | ||
| { | ||
| /// <summary> | ||
| /// The result of loading an assembly reference to the interactive session. | ||
| /// </summary> | ||
| [Serializable] | ||
| public struct AssemblyLoadResult | ||
| { | ||
| private readonly string _path; | ||
| private readonly string _originalPath; | ||
| private readonly bool _successful; | ||
|
|
||
| internal static AssemblyLoadResult CreateSuccessful(string path, string originalPath) | ||
| { | ||
| return new AssemblyLoadResult(path, originalPath, successful: true); | ||
| } | ||
|
|
||
| internal static AssemblyLoadResult CreateAlreadyLoaded(string path, string originalPath) | ||
| { | ||
| return new AssemblyLoadResult(path, originalPath, successful: false); | ||
| } | ||
|
|
||
| private AssemblyLoadResult(string path, string originalPath, bool successful) | ||
| { | ||
| _path = path; | ||
| _originalPath = originalPath; | ||
| _successful = successful; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// True if the assembly was loaded by the assembly loader, false if has been loaded before. | ||
| /// </summary> | ||
| public bool IsSuccessful | ||
| { | ||
| get { return _successful; } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Full path to the physical assembly file (might be a shadow-copy of the original assembly file). | ||
| /// </summary> | ||
| public string Path | ||
| { | ||
| get { return _path; } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Original assembly file path. | ||
| /// </summary> | ||
| public string OriginalPath | ||
| { | ||
| get { return _originalPath; } | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
|
||
| using Microsoft.CodeAnalysis; | ||
| using System.Reflection; | ||
|
|
||
| namespace Roslyn.Scripting | ||
| { | ||
| /// <summary> | ||
| /// Loads assemblies for Reflection based APIs. | ||
| /// </summary> | ||
| public abstract class AssemblyLoader | ||
| { | ||
| private sealed class _Default : AssemblyLoader | ||
| { | ||
| public override Assembly Load(AssemblyIdentity identity, string location = null) | ||
| { | ||
| return Assembly.Load(identity.ToAssemblyName()); | ||
| } | ||
| } | ||
|
|
||
| internal static readonly AssemblyLoader Default = new _Default(); | ||
|
|
||
| /// <summary> | ||
| /// Loads an assembly given its full name. | ||
| /// </summary> | ||
| /// <param name="identity">The identity of the assembly to load.</param> | ||
| /// <param name="location">Location of the assembly.</param> | ||
| /// <returns>The loaded assembly.</returns> | ||
| public abstract Assembly Load(AssemblyIdentity identity, string location = null); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,142 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
| <ImportGroup Label="Settings"> | ||
| <Import Project="..\..\Tools\Microsoft.CodeAnalysis.Toolset.Open\Targets\VSL.Settings.targets" /> | ||
| <Import Project="..\..\..\build\VSL.Settings.Closed.targets" /> | ||
| </ImportGroup> | ||
| <PropertyGroup> | ||
| <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | ||
| <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | ||
| <ProjectGuid>{12A68549-4E8C-42D6-8703-A09335F97997}</ProjectGuid> | ||
| <OutputType>Library</OutputType> | ||
| <RootNamespace>Roslyn.Scripting</RootNamespace> | ||
| <AssemblyName>Roslyn.Scripting.Common</AssemblyName> | ||
| <SolutionDir Condition="'$(SolutionDir)' == '' OR '$(SolutionDir)' == '*Undefined*'">..\..\..\</SolutionDir> | ||
| <RestorePackages>true</RestorePackages> | ||
| </PropertyGroup> | ||
| <ItemGroup Label="Linked Files"> | ||
| <Compile Include="..\..\Compilers\Helpers\GlobalAssemblyCacheHelpers\FusionAssemblyIdentity.cs"> | ||
| <Link>FusionAssemblyIdentity.cs</Link> | ||
| </Compile> | ||
| <Compile Include="..\..\Compilers\Helpers\GlobalAssemblyCacheHelpers\GlobalAssemblyCache.cs"> | ||
| <Link>GlobalAssemblyCache.cs</Link> | ||
| </Compile> | ||
| <Compile Include="..\..\Compilers\Helpers\GlobalAssemblyCacheHelpers\GacFileResolver.cs"> | ||
| <Link>GacFileResolver.cs</Link> | ||
| </Compile> | ||
| </ItemGroup> | ||
| <ItemGroup Label="Project References"> | ||
| <ProjectReference Include="..\..\Compilers\Core\Desktop\CodeAnalysis.Desktop.csproj"> | ||
| <Project>{dfa21ca1-7f96-47ee-940c-069858e81727}</Project> | ||
| <Name>CodeAnalysis.Desktop</Name> | ||
| </ProjectReference> | ||
| <ProjectReference Include="..\..\Compilers\Core\Portable\CodeAnalysis.csproj"> | ||
| <Project>{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}</Project> | ||
| <Name>CodeAnalysis</Name> | ||
| </ProjectReference> | ||
| </ItemGroup> | ||
| <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|Any CPU' "> | ||
| </PropertyGroup> | ||
| <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|Any CPU' "> | ||
| </PropertyGroup> | ||
| <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|ARM' "> | ||
| <PlatformTarget>ARM</PlatformTarget> | ||
| <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
| </PropertyGroup> | ||
| <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|ARM' "> | ||
| <PlatformTarget>ARM</PlatformTarget> | ||
| <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
| </PropertyGroup> | ||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DogfoodDebug|AnyCPU'"> | ||
| <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
| </PropertyGroup> | ||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DogfoodDebug|ARM'"> | ||
| <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
| </PropertyGroup> | ||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DogfoodRelease|AnyCPU'"> | ||
| <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
| </PropertyGroup> | ||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DogfoodRelease|ARM'"> | ||
| <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
| </PropertyGroup> | ||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'"> | ||
| <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
| <DefineConstants>TRACE;DEBUG;SCRIPTING</DefineConstants> | ||
| </PropertyGroup> | ||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'"> | ||
| <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
| <DefineConstants>TRACE;SCRIPTING</DefineConstants> | ||
| </PropertyGroup> | ||
| <ItemGroup> | ||
| <Reference Include="System" /> | ||
| <Reference Include="System.Collections.Immutable, Version=1.1.33.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | ||
| <SpecificVersion>False</SpecificVersion> | ||
| <HintPath>..\..\..\packages\System.Collections.Immutable.1.1.33-beta\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath> | ||
| </Reference> | ||
| <Reference Include="System.Core" /> | ||
| <Reference Include="System.Reflection.Metadata, Version=1.0.18.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | ||
| <SpecificVersion>False</SpecificVersion> | ||
| <HintPath>..\..\..\packages\System.Reflection.Metadata.1.0.18-beta\lib\portable-net45+win8\System.Reflection.Metadata.dll</HintPath> | ||
| </Reference> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <Compile Include="AssemblyLoader.cs" /> | ||
| <Compile Include="AssemblyLoadResult.cs" /> | ||
| <Compile Include="ObjectFormatter.cs" /> | ||
| <Compile Include="ObjectFormatter.Formatter.cs" /> | ||
| <Compile Include="Script.cs" /> | ||
| <Compile Include="ScriptBuilder.cs" /> | ||
| <Compile Include="CommonScriptingResources.Designer.cs"> | ||
| <AutoGen>True</AutoGen> | ||
| <DesignTime>True</DesignTime> | ||
| <DependentUpon>CommonScriptingResources.resx</DependentUpon> | ||
| </Compile> | ||
| <Compile Include="CompilationErrorException.cs" /> | ||
| <Compile Include="Emit\CommonCompilationExtensions.cs" /> | ||
| <Compile Include="Emit\ReflectionEmitResult.cs" /> | ||
| <Compile Include="Emit\ReflectionEmitter.cs" /> | ||
| <Compile Include="Emit\ReflectionEmitter.Refs.cs" /> | ||
| <Compile Include="InteractiveAssemblyLoader.cs" /> | ||
| <Compile Include="MemberDisplayFormat.cs" /> | ||
| <Compile Include="MetadataShadowCopy.cs" /> | ||
| <Compile Include="MetadataShadowCopyProvider.cs" /> | ||
| <Compile Include="ObjectFormattingOptions.cs" /> | ||
| <Compile Include="ScriptExecutionState.cs" /> | ||
| <Compile Include="ScriptVariables.cs" /> | ||
| <Compile Include="ScriptOptions.cs" /> | ||
| <Compile Include="ScriptState.cs" /> | ||
| <Compile Include="ScriptVariable.cs" /> | ||
| <Compile Include="ShadowCopy.cs" /> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <InternalsVisibleTo Include="Roslyn.Scripting.CSharp" /> | ||
| <InternalsVisibleTo Include="Roslyn.Scripting.VisualBasic" /> | ||
| <InternalsVisibleTo Include="Roslyn.InteractiveFeatures" /> | ||
| <InternalsVisibleTo Include="Roslyn.InteractiveEditorFeatures" /> | ||
| <InternalsVisibleTo Include="Roslyn.VisualStudio.InteractiveServices" /> | ||
| <InternalsVisibleTo Include="csi" /> | ||
| <InternalsVisibleTo Include="vbi" /> | ||
| <!-- GAC helpers --> | ||
| <InternalsVisibleToTest Include="Roslyn.Compilers.UnitTests" /> | ||
| <InternalsVisibleToTest Include="Roslyn.Scripting.Common.UnitTests" /> | ||
| <InternalsVisibleToTest Include="Roslyn.Scripting.CSharp.UnitTests" /> | ||
| <InternalsVisibleToTest Include="Roslyn.Scripting.VisualBasic.UnitTests" /> | ||
| <InternalsVisibleToTest Include="Roslyn.Test.Utilities" /> | ||
| <InternalsVisibleToTest Include="RoslynTaoActions" /> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <EmbeddedResource Include="CommonScriptingResources.resx"> | ||
| <Generator>ResXFileCodeGenerator</Generator> | ||
| <LastGenOutput>CommonScriptingResources.Designer.cs</LastGenOutput> | ||
| <SubType>Designer</SubType> | ||
| </EmbeddedResource> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <None Include="packages.config" /> | ||
| </ItemGroup> | ||
| <ImportGroup Label="Targets"> | ||
| <Import Project="..\..\Tools\Microsoft.CodeAnalysis.Toolset.Open\Targets\VSL.Imports.targets" /> | ||
| <Import Project="..\..\..\build\VSL.Imports.Closed.targets" /> | ||
| <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" /> | ||
| </ImportGroup> | ||
| </Project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,153 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <root> | ||
| <!-- | ||
| Microsoft ResX Schema | ||
| Version 2.0 | ||
| The primary goals of this format is to allow a simple XML format | ||
| that is mostly human readable. The generation and parsing of the | ||
| various data types are done through the TypeConverter classes | ||
| associated with the data types. | ||
| Example: | ||
| ... ado.net/XML headers & schema ... | ||
| <resheader name="resmimetype">text/microsoft-resx</resheader> | ||
| <resheader name="version">2.0</resheader> | ||
| <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> | ||
| <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> | ||
| <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> | ||
| <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> | ||
| <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> | ||
| <value>[base64 mime encoded serialized .NET Framework object]</value> | ||
| </data> | ||
| <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> | ||
| <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> | ||
| <comment>This is a comment</comment> | ||
| </data> | ||
| There are any number of "resheader" rows that contain simple | ||
| name/value pairs. | ||
| Each data row contains a name, and value. The row also contains a | ||
| type or mimetype. Type corresponds to a .NET class that support | ||
| text/value conversion through the TypeConverter architecture. | ||
| Classes that don't support this are serialized and stored with the | ||
| mimetype set. | ||
| The mimetype is used for serialized objects, and tells the | ||
| ResXResourceReader how to depersist the object. This is currently not | ||
| extensible. For a given mimetype the value must be set accordingly: | ||
| Note - application/x-microsoft.net.object.binary.base64 is the format | ||
| that the ResXResourceWriter will generate, however the reader can | ||
| read any of the formats listed below. | ||
| mimetype: application/x-microsoft.net.object.binary.base64 | ||
| value : The object must be serialized with | ||
| : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter | ||
| : and then encoded with base64 encoding. | ||
| mimetype: application/x-microsoft.net.object.soap.base64 | ||
| value : The object must be serialized with | ||
| : System.Runtime.Serialization.Formatters.Soap.SoapFormatter | ||
| : and then encoded with base64 encoding. | ||
| mimetype: application/x-microsoft.net.object.bytearray.base64 | ||
| value : The object must be serialized into a byte array | ||
| : using a System.ComponentModel.TypeConverter | ||
| : and then encoded with base64 encoding. | ||
| --> | ||
| <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> | ||
| <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> | ||
| <xsd:element name="root" msdata:IsDataSet="true"> | ||
| <xsd:complexType> | ||
| <xsd:choice maxOccurs="unbounded"> | ||
| <xsd:element name="metadata"> | ||
| <xsd:complexType> | ||
| <xsd:sequence> | ||
| <xsd:element name="value" type="xsd:string" minOccurs="0" /> | ||
| </xsd:sequence> | ||
| <xsd:attribute name="name" use="required" type="xsd:string" /> | ||
| <xsd:attribute name="type" type="xsd:string" /> | ||
| <xsd:attribute name="mimetype" type="xsd:string" /> | ||
| <xsd:attribute ref="xml:space" /> | ||
| </xsd:complexType> | ||
| </xsd:element> | ||
| <xsd:element name="assembly"> | ||
| <xsd:complexType> | ||
| <xsd:attribute name="alias" type="xsd:string" /> | ||
| <xsd:attribute name="name" type="xsd:string" /> | ||
| </xsd:complexType> | ||
| </xsd:element> | ||
| <xsd:element name="data"> | ||
| <xsd:complexType> | ||
| <xsd:sequence> | ||
| <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | ||
| <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> | ||
| </xsd:sequence> | ||
| <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> | ||
| <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> | ||
| <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> | ||
| <xsd:attribute ref="xml:space" /> | ||
| </xsd:complexType> | ||
| </xsd:element> | ||
| <xsd:element name="resheader"> | ||
| <xsd:complexType> | ||
| <xsd:sequence> | ||
| <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | ||
| </xsd:sequence> | ||
| <xsd:attribute name="name" type="xsd:string" use="required" /> | ||
| </xsd:complexType> | ||
| </xsd:element> | ||
| </xsd:choice> | ||
| </xsd:complexType> | ||
| </xsd:element> | ||
| </xsd:schema> | ||
| <resheader name="resmimetype"> | ||
| <value>text/microsoft-resx</value> | ||
| </resheader> | ||
| <resheader name="version"> | ||
| <value>2.0</value> | ||
| </resheader> | ||
| <resheader name="reader"> | ||
| <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | ||
| </resheader> | ||
| <resheader name="writer"> | ||
| <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | ||
| </resheader> | ||
| <data name="StackOverflowWhileEvaluat" xml:space="preserve"> | ||
| <value>!<Stack overflow while evaluating object></value> | ||
| </data> | ||
| <data name="CantAssignTo" xml:space="preserve"> | ||
| <value>Can't assign '{0}' to '{1}'.</value> | ||
| </data> | ||
| <data name="ExpectedAnAssemblyReference" xml:space="preserve"> | ||
| <value>Expected an assembly reference.</value> | ||
| </data> | ||
| <data name="DisplayNameOrPathCannotBe" xml:space="preserve"> | ||
| <value>Display name or path cannot be empty.</value> | ||
| </data> | ||
| <data name="AssemblyNotFound" xml:space="preserve"> | ||
| <value>Assembly not found.</value> | ||
| </data> | ||
| <data name="AbsolutePathExpected" xml:space="preserve"> | ||
| <value>Absolute path expected</value> | ||
| </data> | ||
| <data name="ExecutionStateFrozen" xml:space="preserve"> | ||
| <value>Execution state is frozen and cannot be modified.</value> | ||
| </data> | ||
| <data name="GlobalsNotAssignable" xml:space="preserve"> | ||
| <value>The globals of type '{0}' is not assignable to '{1}'</value> | ||
| </data> | ||
| <data name="StartingStateIncompatible" xml:space="preserve"> | ||
| <value>Starting state was incompatible with script.</value> | ||
| </data> | ||
| <data name="InvalidAssemblyName" xml:space="preserve"> | ||
| <value>Invalid assembly name</value> | ||
| </data> | ||
| <data name="InvalidCharactersInAssemblyName" xml:space="preserve"> | ||
| <value>Invalid characters in assemblyName</value> | ||
| </data> | ||
| </root> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
|
||
| using System; | ||
| using System.Collections.Immutable; | ||
| using Microsoft.CodeAnalysis; | ||
|
|
||
| namespace Roslyn.Scripting | ||
| { | ||
| /// <summary> | ||
| /// An exception thrown when the compilation stage of interactive execution produces compilation errors. | ||
| /// </summary> | ||
| public class CompilationErrorException : Exception | ||
| { | ||
| private readonly ImmutableArray<Diagnostic> _diagnostics; | ||
|
|
||
| internal CompilationErrorException(string message, ImmutableArray<Diagnostic> diagnostics) | ||
| : base(message) | ||
| { | ||
| _diagnostics = diagnostics; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// The list of diagnostics produced by compilation. | ||
| /// </summary> | ||
| public ImmutableArray<Diagnostic> Diagnostics | ||
| { | ||
| get { return _diagnostics; } | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,174 @@ | ||
| // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
|
||
| using Microsoft.CodeAnalysis; | ||
| using System; | ||
| using System.Linq; | ||
| using System.Reflection; | ||
| using System.Reflection.Emit; | ||
| using System.Threading; | ||
| using Roslyn.Utilities; | ||
| using Cci = Microsoft.Cci; | ||
| using Microsoft.CodeAnalysis.Emit; | ||
|
|
||
| namespace Roslyn.Scripting.Emit | ||
| { | ||
| internal static class CommonCompilationExtensions | ||
| { | ||
| /// <summary> | ||
| /// Emits the compilation into given <see cref="ModuleBuilder"/> using Reflection.Emit APIs. | ||
| /// </summary> | ||
| /// <param name="compilation">Compilation.</param> | ||
| /// <param name="moduleBuilder"> | ||
| /// The module builder to add the types into. Can be reused for multiple compilation units. | ||
| /// </param> | ||
| /// <param name="assemblyLoader"> | ||
| /// Loads an assembly given an <see cref="AssemblyIdentity"/>. | ||
| /// This callback is used for loading assemblies referenced by the compilation. | ||
| /// <see cref="System.Reflection.Assembly.Load(AssemblyName)"/> is used if not specified. | ||
| /// </param> | ||
| /// <param name="assemblySymbolMapper"> | ||
| /// Applied when converting assembly symbols to assembly references. | ||
| /// <see cref="IAssemblySymbol"/> is mapped to its <see cref="IAssemblySymbol.Identity"/> by default. | ||
| /// </param> | ||
| /// <param name="cancellationToken">Can be used to cancel the emit process.</param> | ||
| /// <param name="recoverOnError">If false the method returns an unsuccessful result instead of falling back to CCI writer.</param> | ||
| /// <param name="compiledAssemblyImage">Assembly image, returned only if we fallback to CCI writer.</param> | ||
| /// <param name="entryPoint">An entry point or null if not applicable or on failure.</param> | ||
| /// <param name="diagnostics">Diagnostics.</param> | ||
| /// <returns>True on success, false if a compilation error occurred or the compilation doesn't contain any code or declarations.</returns> | ||
| /// <remarks> | ||
| /// Reflection.Emit doesn't support all metadata constructs. If an unsupported construct is | ||
| /// encountered a metadata writer that procudes uncollectible code is used instead. This is | ||
| /// indicated by | ||
| /// <see cref="ReflectionEmitResult.IsUncollectible"/> flag on the result. | ||
| /// | ||
| /// Reusing <see cref="System.Reflection.Emit.ModuleBuilder"/> may be beneficial in certain | ||
| /// scenarios. For example, when emitting a sequence of code snippets one at a time (like in | ||
| /// REPL). All the snippets can be compiled into a single module as long as the types being | ||
| /// emitted have unique names. Reusing a single module/assembly reduces memory overhead. On | ||
| /// the other hand, collectible assemblies are units of collection. Defining too many | ||
| /// unrelated types in a single assemly might prevent the unused types to be collected. | ||
| /// | ||
| /// No need to provide a name override when using Reflection.Emit, since the assembly already | ||
| /// exists. | ||
| /// </remarks> | ||
| /// <exception cref="InvalidOperationException">Referenced assembly can't be resolved.</exception> | ||
| internal static bool Emit( | ||
| this Compilation compilation, | ||
| ModuleBuilder moduleBuilder, | ||
| AssemblyLoader assemblyLoader, | ||
| Func<IAssemblySymbol, AssemblyIdentity> assemblySymbolMapper, | ||
| bool recoverOnError, | ||
| DiagnosticBag diagnostics, | ||
| CancellationToken cancellationToken, | ||
| out MethodInfo entryPoint, | ||
| out byte[] compiledAssemblyImage) | ||
| { | ||
| compiledAssemblyImage = default(byte[]); | ||
|
|
||
| var moduleBeingBuilt = compilation.CreateModuleBuilder( | ||
| emitOptions: EmitOptions.Default, | ||
| manifestResources: null, | ||
| assemblySymbolMapper: assemblySymbolMapper, | ||
| testData: null, | ||
| diagnostics: diagnostics, | ||
| cancellationToken: cancellationToken); | ||
|
|
||
| if (moduleBeingBuilt == null) | ||
| { | ||
| entryPoint = null; | ||
| return false; | ||
| } | ||
|
|
||
| if (!compilation.Compile( | ||
| moduleBeingBuilt, | ||
| win32Resources: null, | ||
| xmlDocStream: null, | ||
| generateDebugInfo: false, | ||
| diagnostics: diagnostics, | ||
| filterOpt: null, | ||
| cancellationToken: cancellationToken)) | ||
| { | ||
| entryPoint = null; | ||
| return false; | ||
| } | ||
|
|
||
| Cci.IMethodReference cciEntryPoint = moduleBeingBuilt.EntryPoint; | ||
|
|
||
| cancellationToken.ThrowIfCancellationRequested(); | ||
|
|
||
| DiagnosticBag metadataDiagnostics = DiagnosticBag.GetInstance(); | ||
|
|
||
| var context = new EmitContext((Cci.IModule)moduleBeingBuilt, null, metadataDiagnostics); | ||
|
|
||
| // try emit via Reflection.Emit | ||
| try | ||
| { | ||
| var referencedAssemblies = from referencedAssembly in compilation.GetBoundReferenceManager().GetReferencedAssemblies() | ||
| let peReference = referencedAssembly.Key as PortableExecutableReference | ||
| select KeyValuePair.Create( | ||
| moduleBeingBuilt.Translate(referencedAssembly.Value, metadataDiagnostics), | ||
| (peReference != null) ? peReference.FilePath : null); | ||
|
|
||
| entryPoint = ReflectionEmitter.Emit( | ||
| context, | ||
| referencedAssemblies, | ||
| moduleBuilder, | ||
| assemblyLoader ?? AssemblyLoader.Default, | ||
| cciEntryPoint, | ||
| cancellationToken); | ||
|
|
||
| // translate metadata errors. | ||
| return compilation.FilterAndAppendAndFreeDiagnostics(diagnostics, ref metadataDiagnostics); | ||
| } | ||
| catch (TypeLoadException) | ||
| { | ||
| // attempted to emit reference to a type that can't be loaded (has invalid metadata) | ||
| } | ||
| catch (NotSupportedException) | ||
| { | ||
| // nop | ||
| } | ||
|
|
||
| // TODO (tomat): | ||
| // | ||
| // Another possible approach would be to just return an error, that we can't emit via | ||
| // Ref.Emit and let the user choose another method of emitting. For that we would want | ||
| // to preserve the state of the Emit.Assembly object with all the compiled methods so | ||
| // that the subsequent emit doesn't need to compile method bodies again. | ||
|
|
||
| // TODO (tomat): | ||
| // | ||
| // If Ref.Emit fails to emit the code the type builders already created will stay | ||
| // defined on the module builder. Ideally we would clean them up but Ref.Emit doesn't | ||
| // provide any API to do so. In fact it also keeps baked TypeBuilders alive as well. | ||
|
|
||
| if (!recoverOnError) | ||
| { | ||
| metadataDiagnostics.Free(); | ||
| entryPoint = null; | ||
| return false; | ||
| } | ||
|
|
||
| using (var stream = new System.IO.MemoryStream()) | ||
| { | ||
| Cci.PeWriter.WritePeToStream( | ||
| context, | ||
| compilation.MessageProvider, | ||
| stream, | ||
| pdbWriterOpt: null, | ||
| allowMissingMethodBodies: false, | ||
| deterministic: false, | ||
| cancellationToken: cancellationToken); | ||
|
|
||
| compiledAssemblyImage = stream.ToArray(); | ||
| } | ||
|
|
||
| var compiledAssembly = Assembly.Load(compiledAssemblyImage); | ||
| entryPoint = (cciEntryPoint != null) ? ReflectionEmitter.ResolveEntryPoint(compiledAssembly, cciEntryPoint, context) : null; | ||
|
|
||
| // translate metadata errors. | ||
| return compilation.FilterAndAppendAndFreeDiagnostics(diagnostics, ref metadataDiagnostics); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
|
||
| using System.Collections.Immutable; | ||
| using System.Reflection; | ||
|
|
||
| namespace Microsoft.CodeAnalysis.Emit | ||
| { | ||
| public class ReflectionEmitResult : EmitResult | ||
| { | ||
| private readonly MethodInfo _entryPoint; | ||
| private readonly bool _isUncollectible; | ||
|
|
||
| internal ReflectionEmitResult(MethodInfo entryPoint, bool success, bool isUncollectible, ImmutableArray<Diagnostic> diagnostics) | ||
| : base(success, diagnostics) | ||
| { | ||
| _entryPoint = entryPoint; | ||
| _isUncollectible = isUncollectible; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets method information about the entrypoint of the emitted assembly. | ||
| /// </summary> | ||
| public MethodInfo EntryPoint | ||
| { | ||
| get { return _entryPoint; } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Indicates whether the emitted assembly can be garbage collected. | ||
| /// </summary> | ||
| public bool IsUncollectible | ||
| { | ||
| get { return _isUncollectible; } | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
|
||
| namespace Roslyn.Scripting | ||
| { | ||
| public enum MemberDisplayFormat | ||
| { | ||
| /// <summary> | ||
| /// Display just a simple description of the object, like type name or ToString(). Don't | ||
| /// display any members or items of the object. | ||
| /// </summary> | ||
| NoMembers, | ||
|
|
||
| /// <summary> | ||
| /// Display structure of the object on a single line. | ||
| /// </summary> | ||
| Inline, | ||
|
|
||
| /// <summary> | ||
| /// Display structure of the object on a single line, where the object is displayed as a value of its container's member. | ||
| /// E.g. { a = ... } | ||
| /// </summary> | ||
| InlineValue, | ||
|
|
||
| /// <summary> | ||
| /// Displays a siple description of the object followed by list of members. Each member is | ||
| /// displayed on a separate line. | ||
| /// </summary> | ||
| List, | ||
| } | ||
|
|
||
| internal static partial class EnumBounds | ||
| { | ||
| internal static bool IsValid(this MemberDisplayFormat value) | ||
| { | ||
| return value >= MemberDisplayFormat.NoMembers && value <= MemberDisplayFormat.List; | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
|
||
| using System.Diagnostics; | ||
| using Microsoft.CodeAnalysis.Text; | ||
| using Microsoft.Win32.SafeHandles; | ||
|
|
||
| namespace Microsoft.CodeAnalysis | ||
| { | ||
| /// <summary> | ||
| /// Represents a shadow copy of an assembly or a standalone module. | ||
| /// </summary> | ||
| public sealed class MetadataShadowCopy | ||
| { | ||
| private readonly ShadowCopy _primaryModule; | ||
| private readonly ShadowCopy _documentationFile; | ||
|
|
||
| // this instance doesn't own the image | ||
| private readonly Metadata _metadataCopy; | ||
|
|
||
| internal MetadataShadowCopy(ShadowCopy primaryModule, ShadowCopy documentationFile, Metadata metadataCopy) | ||
| { | ||
| Debug.Assert(primaryModule != null); | ||
| Debug.Assert(metadataCopy != null); | ||
| ////Debug.Assert(!metadataCopy.IsImageOwner); property is now internal | ||
|
|
||
| _primaryModule = primaryModule; | ||
| _documentationFile = documentationFile; | ||
| _metadataCopy = metadataCopy; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Assembly manifest module copy or a standalone module copy. | ||
| /// </summary> | ||
| public ShadowCopy PrimaryModule | ||
| { | ||
| get { return _primaryModule; } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Documentation file copy or null if there is none. | ||
| /// </summary> | ||
| public ShadowCopy DocumentationFile | ||
| { | ||
| get { return _documentationFile; } | ||
| } | ||
|
|
||
| public Metadata Metadata | ||
| { | ||
| get { return _metadataCopy; } | ||
| } | ||
|
|
||
| // keep this internal so that users can't delete files that the provider manages | ||
| internal void DisposeFileHandles() | ||
| { | ||
| _primaryModule.DisposeFileStream(); | ||
|
|
||
| if (_documentationFile != null) | ||
| { | ||
| _documentationFile.DisposeFileStream(); | ||
| } | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
|
||
| using System; | ||
|
|
||
| namespace Roslyn.Scripting | ||
| { | ||
| [Serializable] | ||
| public sealed class ObjectFormattingOptions | ||
| { | ||
| public static readonly ObjectFormattingOptions Default = new ObjectFormattingOptions(); | ||
|
|
||
| public bool QuoteStrings { get; private set; } | ||
| public MemberDisplayFormat MemberFormat { get; private set; } | ||
| public int MaxLineLength { get; private set; } | ||
| public int MaxOutputLength { get; private set; } | ||
| public bool UseHexadecimalNumbers { get; private set; } | ||
| public string MemberIndentation { get; private set; } | ||
| public string Ellipsis { get; private set; } | ||
| public string NewLine { get; private set; } | ||
| public bool IncludeCodePoints { get; private set; } | ||
|
|
||
| public ObjectFormattingOptions( | ||
| MemberDisplayFormat memberFormat = MemberDisplayFormat.NoMembers, | ||
| bool quoteStrings = true, | ||
| bool useHexadecimalNumbers = false, | ||
| bool includeCodePoints = false, | ||
| int maxLineLength = Int32.MaxValue, | ||
| int maxOutputLength = Int32.MaxValue, | ||
| string memberIndentation = null, | ||
| string ellipsis = null, | ||
| string lineBreak = null) | ||
| { | ||
| if (!memberFormat.IsValid()) | ||
| { | ||
| throw new ArgumentOutOfRangeException("memberFormat"); | ||
| } | ||
|
|
||
| this.MemberFormat = memberFormat; | ||
| this.QuoteStrings = quoteStrings; | ||
| this.IncludeCodePoints = includeCodePoints; | ||
| this.MaxOutputLength = (maxOutputLength >= 0) ? maxOutputLength : int.MaxValue; | ||
| this.MaxLineLength = (maxLineLength >= 0) ? maxLineLength : int.MaxValue; | ||
| this.UseHexadecimalNumbers = useHexadecimalNumbers; | ||
| this.MemberIndentation = memberIndentation ?? " "; | ||
| this.Ellipsis = ellipsis ?? "..."; | ||
| this.NewLine = lineBreak ?? Environment.NewLine; | ||
| } | ||
|
|
||
| public ObjectFormattingOptions Copy( | ||
| MemberDisplayFormat? memberFormat = null, | ||
| bool? quoteStrings = null, | ||
| bool? useHexadecimalNumbers = null, | ||
| bool? includeCodePoints = null, | ||
| int? maxLineLength = null, | ||
| int? maxOutputLength = null, | ||
| string memberIndentation = null, | ||
| string ellipsis = null, | ||
| string newLine = null) | ||
| { | ||
| return new ObjectFormattingOptions( | ||
| memberFormat ?? this.MemberFormat, | ||
| quoteStrings ?? this.QuoteStrings, | ||
| useHexadecimalNumbers ?? this.UseHexadecimalNumbers, | ||
| includeCodePoints ?? this.IncludeCodePoints, | ||
| maxLineLength ?? this.MaxLineLength, | ||
| maxOutputLength ?? this.MaxOutputLength, | ||
| memberIndentation ?? this.MemberIndentation, | ||
| ellipsis ?? this.Ellipsis, | ||
| newLine ?? this.NewLine); | ||
| } | ||
| } | ||
| } |