<LangVersion>preview</LangVersion>
<LangVersion Condition="'$(MSBuildProjectExtension)' == '.vbproj'">latest</LangVersion>
<Deterministic>true</Deterministic>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup>
<PropertyGroup>
<CodeAnalysisRuleset>$(MSBuildThisFileDirectory)CodeAnalysis.ruleset</CodeAnalysisRuleset>
<!-- Disable analyzers in sourcebuild -->
- <EnableAnalyzers Condition="'$(DotNetBuildFromSource)' == 'true'">false</EnableAnalyzers>
+ <RunAnalyzers Condition="'$(DotNetBuildFromSource)' == 'true'">false</RunAnalyzers>
</PropertyGroup>
- <ItemGroup Condition="'$(EnableAnalyzers)' == 'true'">
+ <ItemGroup Condition="'$(RunAnalyzers)' != 'false'">
<PackageReference Include="Microsoft.DotNet.CodeAnalysis" Version="$(MicrosoftDotNetCodeAnalysisVersion)" PrivateAssets="all" IsImplicitlyDefined="true" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="5.0.0-rc2.20458.2" PrivateAssets="all" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164" PrivateAssets="all" />
<AdditionalBuildTargetFrameworks Condition="!$(BuildTargetFramework.StartsWith('netcoreapp2.0'))">$(AdditionalBuildTargetFrameworks);netstandard2.1</AdditionalBuildTargetFrameworks>
<!-- Reference assemblies are special and don't initialize fields or have empty finalizers, etc. -->
- <EnableAnalyzers>false</EnableAnalyzers>
+ <RunAnalyzers>false</RunAnalyzers>
</PropertyGroup>
<PropertyGroup>
<SkipCommonResourcesIncludes>true</SkipCommonResourcesIncludes>
<DocumentationFile>$(OutputPath)$(MSBuildProjectName).xml</DocumentationFile>
- <EnableAnalyzers>true</EnableAnalyzers>
</PropertyGroup>
<!-- Platform specific properties -->
<PropertyGroup>
<IsShipping>false</IsShipping>
<SignAssembly>false</SignAssembly>
+ <RunAnalyzers>false</RunAnalyzers>
</PropertyGroup>
</Project>
<CLRTestBuildAllTargets></CLRTestBuildAllTargets>
</PropertyGroup>
+ <!-- Language settings -->
+ <PropertyGroup>
+ <RunAnalyzers>false</RunAnalyzers>
+ </PropertyGroup>
+
</Project>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<EnableDefaultItems>false</EnableDefaultItems>
<Platform>AnyCPU</Platform>
+ <NoWarn>$(NoWarn),618,SYSLIB0012</NoWarn>
<!-- [ARCADE REMOVE] This line should be removed we use the Arcade Sdk. -->
<DeterministicSourcePaths>false</DeterministicSourcePaths>
</PropertyGroup>
- <!-- Set up handling of build warnings -->
- <PropertyGroup>
- <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
- </PropertyGroup>
-
<PropertyGroup>
<TargetsWindows>false</TargetsWindows>
<TargetsOSX>false</TargetsOSX>
namespace Microsoft.NET.HostModel.AppHost
{
/// <summary>
- /// The application host executable cannot be customized because adding resources requires
+ /// The application host executable cannot be customized because adding resources requires
/// that the build be performed on Windows (excluding Nano Server).
/// </summary>
public class AppHostCustomizationUnsupportedOSException : AppHostUpdateException
{
}
}
-
SignBlobNotLast, // Signature blob must be at the very end of the file
SignDoesntFollowSymtab, // Signature blob must immediately follow the Symtab
MemoryMapAccessFault, // Error reading the memory-mapped apphost
- InvalidUTF8 // UTF8 decoding failed
+ InvalidUTF8 // UTF8 decoding failed
}
/// <summary>
- /// The MachO application host executable cannot be customized because
+ /// The MachO application host executable cannot be customized because
/// it was not in the expected format
/// </summary>
public class AppHostMachOFormatException : AppHostUpdateException
}
}
}
-
namespace Microsoft.NET.HostModel.AppHost
{
/// <summary>
- /// Unable to use the input file as application host executable because it's not a
+ /// Unable to use the input file as application host executable because it's not a
/// Windows executable for the CUI (Console) subsystem.
/// </summary>
public class AppHostNotCUIException : AppHostUpdateException
{
}
}
-
namespace Microsoft.NET.HostModel.AppHost
{
/// <summary>
- /// Unable to use the input file as an application host executable
+ /// Unable to use the input file as an application host executable
/// because it's not a Windows PE file
/// </summary>
public class AppHostNotPEFileException : AppHostUpdateException
{
}
}
-
namespace Microsoft.NET.HostModel.AppHost
{
/// <summary>
- /// An instance of this exception is thrown when an AppHost binary update
+ /// An instance of this exception is thrown when an AppHost binary update
/// fails due to known user errors.
/// </summary>
public class AppHostUpdateException : Exception
{
}
}
-
}
public static unsafe void SearchAndReplace(
- string filePath,
- byte[] searchPattern,
+ string filePath,
+ byte[] searchPattern,
byte[] patternToReplace,
bool pad0s = true)
{
// The Linux Headers are copied from elf.h
#pragma warning disable 0649
- struct ElfHeader
+ private struct ElfHeader
{
- byte EI_MAG0;
- byte EI_MAG1;
- byte EI_MAG2;
- byte EI_MAG3;
+ private byte EI_MAG0;
+ private byte EI_MAG1;
+ private byte EI_MAG2;
+ private byte EI_MAG3;
public bool IsValid()
{
}
}
}
-
long bundleHeaderOffset)
{
byte[] bundleHeaderPlaceholder = {
- // 8 bytes represent the bundle header-offset
+ // 8 bytes represent the bundle header-offset
// Zero for non-bundle apphosts (default).
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 32 bytes represent the bundle signature: SHA-256 for ".net core bundle"
throw new PlaceHolderNotFoundInAppHostException(bundleSignature);
}
- headerOffset = accessor.ReadInt64(position - sizeof(Int64));
+ headerOffset = accessor.ReadInt64(position - sizeof(long));
}
}
}
{
internal static class MachOUtils
{
- // The MachO Headers are copied from
+ // The MachO Headers are copied from
// https://opensource.apple.com/source/cctools/cctools-870/include/mach-o/loader.h
//
// The data fields and enumerations match the structure definitions in the above file,
// and hence do not conform to C# CoreFx naming style.
- enum Magic : uint
+ private enum Magic : uint
{
MH_MAGIC = 0xfeedface,
MH_CIGAM = 0xcefaedfe,
MH_CIGAM_64 = 0xcffaedfe
}
- enum FileType : uint
+ private enum FileType : uint
{
MH_EXECUTE = 0x2
}
#pragma warning disable 0649
- struct MachHeader
+ private struct MachHeader
{
public Magic magic;
public int cputype;
}
}
- enum Command : uint
+ private enum Command : uint
{
LC_SYMTAB = 0x2,
LC_SEGMENT_64 = 0x19,
LC_CODE_SIGNATURE = 0x1d,
}
- struct LoadCommand
+ private struct LoadCommand
{
public Command cmd;
public uint cmdsize;
}
// The linkedit_data_command contains the offsets and sizes of a blob
- // of data in the __LINKEDIT segment (including LC_CODE_SIGNATURE).
- struct LinkEditDataCommand
+ // of data in the __LINKEDIT segment (including LC_CODE_SIGNATURE).
+ private struct LinkEditDataCommand
{
public Command cmd;
public uint cmdsize;
public uint datasize;
}
- struct SymtabCommand
+ private struct SymtabCommand
{
public uint cmd;
public uint cmdsize;
public uint strsize;
};
- unsafe struct SegmentCommand64
+ private unsafe struct SegmentCommand64
{
public Command cmd;
public uint cmdsize;
/// <summary>
/// This Method is a utility to remove the code-signature (if any)
/// from a MachO AppHost binary.
- ///
+ ///
/// The tool assumes the following layout of the executable:
- ///
+ ///
/// * MachoHeader (64-bit, executable, not swapped integers)
/// * LoadCommands
/// LC_SEGMENT_64 (__PAGEZERO)
/// LC_SEGMENT_64 (__DATA)
/// LC_SEGMENT_64 (__LINKEDIT)
/// ...
- /// LC_SYMTAB
+ /// LC_SYMTAB
/// ...
/// LC_CODE_SIGNATURE (last)
- ///
+ ///
/// * ... Different Segments ...
- ///
+ ///
/// * The __LINKEDIT Segment (last)
- /// * ... Different sections ...
- /// * SYMTAB
+ /// * ... Different sections ...
+ /// * SYMTAB
/// * (Some alignment bytes)
/// * The Code-signature
- ///
+ ///
/// In order to remove the signature, the method:
/// - Removes (zeros out) the LC_CODE_SIGNATURE command
/// - Adjusts the size and count of the load commands in the header
/// - Truncates the size of the __LINKEDIT segment to the end of SYMTAB
/// - Truncates the apphost file to the end of the __LINKEDIT segment
- ///
+ ///
/// </summary>
/// <param name="filePath">Path to the AppHost</param>
/// <returns>
- /// True if
- /// - The input is a MachO binary, and
- /// - It is a signed binary, and
+ /// True if
+ /// - The input is a MachO binary, and
+ /// - It is a signed binary, and
/// - The signature was successfully removed
- /// False otherwise
+ /// False otherwise
/// </returns>
/// <exception cref="AppHostMachOFormatException">
/// The input is a MachO file, but doesn't match the expect format of the AppHost.
/// </exception>
- unsafe public static bool RemoveSignature(string filePath)
+ public static unsafe bool RemoveSignature(string filePath)
{
using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite))
{
Verify(symtab->symoff > linkEdit->fileoff, MachOFormatError.SymtabNotInLinkEdit);
Verify(signature->dataoff > linkEdit->fileoff, MachOFormatError.SignNotInLinkEdit);
- // The signature blob immediately follows the symtab blob,
+ // The signature blob immediately follows the symtab blob,
// except for a few bytes of padding.
Verify(signature->dataoff >= symtabEnd && signature->dataoff - symtabEnd < 32, MachOFormatError.SignBlobNotLast);
linkEdit->filesize -= signatureSize;
// codesign --remove-signature doesn't reset the vmsize.
- // Setting the vmsize here makes the output bin-equal with the original
+ // Setting the vmsize here makes the output bin-equal with the original
// unsigned apphost (and not bin-equal with a signed-unsigned-apphost).
linkEdit->vmsize = linkEdit->filesize;
}
}
}
}
-
/// <summary>
/// The first two bytes of a PE file are a constant signature.
/// </summary>
- private const UInt16 PEFileSignature = 0x5A4D;
+ private const ushort PEFileSignature = 0x5A4D;
/// <summary>
/// The offset of the PE header pointer in the DOS header.
/// <summary>
/// The value of the sybsystem field which indicates Windows GUI (Graphical UI)
/// </summary>
- private const UInt16 WindowsGUISubsystem = 0x2;
+ private const ushort WindowsGUISubsystem = 0x2;
/// <summary>
/// The value of the subsystem field which indicates Windows CUI (Console)
/// </summary>
- private const UInt16 WindowsCUISubsystem = 0x3;
+ private const ushort WindowsCUISubsystem = 0x3;
/// <summary>
/// Check whether the apphost file is a windows PE image by looking at the first few bytes.
// https://en.wikipedia.org/wiki/Portable_Executable
// Validate that we're looking at Windows PE file
- if (((UInt16*)bytes)[0] != PEFileSignature || accessor.Capacity < PEHeaderPointerOffset + sizeof(UInt32))
+ if (((ushort*)bytes)[0] != PEFileSignature || accessor.Capacity < PEHeaderPointerOffset + sizeof(uint))
{
return false;
}
{
using (BinaryReader reader = new BinaryReader(File.OpenRead(filePath)))
{
- if (reader.BaseStream.Length < PEHeaderPointerOffset + sizeof(UInt32))
+ if (reader.BaseStream.Length < PEHeaderPointerOffset + sizeof(uint))
{
return false;
}
byte* bytes = pointer + accessor.PointerOffset;
// https://en.wikipedia.org/wiki/Portable_Executable
- UInt32 peHeaderOffset = ((UInt32*)(bytes + PEHeaderPointerOffset))[0];
+ uint peHeaderOffset = ((uint*)(bytes + PEHeaderPointerOffset))[0];
- if (accessor.Capacity < peHeaderOffset + SubsystemOffset + sizeof(UInt16))
+ if (accessor.Capacity < peHeaderOffset + SubsystemOffset + sizeof(ushort))
{
throw new AppHostNotPEFileException();
}
- UInt16* subsystem = ((UInt16*)(bytes + peHeaderOffset + SubsystemOffset));
+ ushort* subsystem = ((ushort*)(bytes + peHeaderOffset + SubsystemOffset));
// https://docs.microsoft.com/en-us/windows/desktop/Debug/pe-format#windows-subsystem
// The subsystem of the prebuilt apphost should be set to CUI
/// This method will return the subsystem CUI/GUI value. The apphost file should be a windows PE file.
/// </summary>
/// <param name="accessor">The memory accessor which has the apphost file opened.</param>
- internal static unsafe UInt16 GetWindowsGraphicalUserInterfaceBit(MemoryMappedViewAccessor accessor)
+ internal static unsafe ushort GetWindowsGraphicalUserInterfaceBit(MemoryMappedViewAccessor accessor)
{
byte* pointer = null;
byte* bytes = pointer + accessor.PointerOffset;
// https://en.wikipedia.org/wiki/Portable_Executable
- UInt32 peHeaderOffset = ((UInt32*)(bytes + PEHeaderPointerOffset))[0];
+ uint peHeaderOffset = ((uint*)(bytes + PEHeaderPointerOffset))[0];
- if (accessor.Capacity < peHeaderOffset + SubsystemOffset + sizeof(UInt16))
+ if (accessor.Capacity < peHeaderOffset + SubsystemOffset + sizeof(ushort))
{
throw new AppHostNotPEFileException();
}
- UInt16* subsystem = ((UInt16*)(bytes + peHeaderOffset + SubsystemOffset));
+ ushort* subsystem = ((ushort*)(bytes + peHeaderOffset + SubsystemOffset));
return subsystem[0];
}
}
}
- public static unsafe UInt16 GetWindowsGraphicalUserInterfaceBit(string filePath)
+ public static unsafe ushort GetWindowsGraphicalUserInterfaceBit(string filePath)
{
using (var mappedFile = MemoryMappedFile.CreateFromFile(filePath))
{
namespace Microsoft.NET.HostModel.AppHost
{
/// <summary>
- /// Unable to use input file as a valid application host executable, as it does not contain
+ /// Unable to use input file as a valid application host executable, as it does not contain
/// the expected placeholder byte sequence.
/// </summary>
public class PlaceHolderNotFoundInAppHostException : AppHostUpdateException
}
}
}
-
/// <summary>
/// HostModel library implements several services for updating the AppHost DLL.
/// These updates involve multiple file open/close operations.
- /// An Antivirus scanner may intercept in-between and lock the file,
+ /// An Antivirus scanner may intercept in-between and lock the file,
/// causing the operations to fail with IO-Error.
/// So, the operations are retried a few times on failures such as
- /// - IOException
+ /// - IOException
/// - Failure with Win32 errors indicating file-lock
/// </summary>
public static class RetryUtil
BundleAllContent = BundleNativeBinaries | BundleOtherFiles,
};
}
-
/// </summary>
public class Bundler
{
- readonly string HostName;
- readonly string OutputDir;
- readonly string DepsJson;
- readonly string RuntimeConfigJson;
- readonly string RuntimeConfigDevJson;
+ private readonly string HostName;
+ private readonly string OutputDir;
+ private readonly string DepsJson;
+ private readonly string RuntimeConfigJson;
+ private readonly string RuntimeConfigDevJson;
- readonly Trace Tracer;
+ private readonly Trace Tracer;
public readonly Manifest BundleManifest;
- readonly TargetInfo Target;
- readonly BundleOptions Options;
+ private readonly TargetInfo Target;
+ private readonly BundleOptions Options;
public Bundler(string hostName,
string outputDir,
/// </summary>
/// <returns>Returns the offset of the start 'file' within 'bundle'</returns>
- long AddToBundle(Stream bundle, Stream file, FileType type)
+ private long AddToBundle(Stream bundle, Stream file, FileType type)
{
if (type == FileType.Assembly)
{
return startOffset;
}
- bool IsHost(string fileRelativePath)
+ private bool IsHost(string fileRelativePath)
{
return fileRelativePath.Equals(HostName);
}
- bool ShouldIgnore(string fileRelativePath)
+ private bool ShouldIgnore(string fileRelativePath)
{
return fileRelativePath.Equals(RuntimeConfigDevJson);
}
- bool ShouldExclude(FileType type, string relativePath)
+ private bool ShouldExclude(FileType type, string relativePath)
{
switch (type)
{
}
}
- bool IsAssembly(string path, out bool isPE)
+ private bool IsAssembly(string path, out bool isPE)
{
isPE = false;
return false;
}
- FileType InferType(FileSpec fileSpec)
+ private FileType InferType(FileSpec fileSpec)
{
if (fileSpec.BundleRelativePath.Equals(DepsJson))
{
/// </summary>
/// <param name="fileSpecs">
/// An enumeration FileSpecs for the files to be embedded.
- ///
+ ///
/// Files in fileSpecs that are not bundled within the single file bundle,
/// and should be published as separate files are marked as "IsExcluded" by this method.
/// This doesn't include unbundled files that should be dropped, and not publised as output.
}
}
}
-
{
/// <summary>
/// FileEntry: Records information about embedded files.
- ///
- /// The bundle manifest records the following meta-data for each
+ ///
+ /// The bundle manifest records the following meta-data for each
/// file embedded in the bundle:
/// * Type (1 byte)
/// * NameLength (7-bit extension encoding, typically 1 byte)
public override string ToString() => $"{RelativePath} [{Type}] @{Offset} Sz={Size}";
}
}
-
{
/// <summary>
/// Information about files to embed into the Bundle (input to the Bundler).
- ///
+ ///
/// SourcePath: path to the file to be bundled at compile time
- /// BundleRelativePath: path where the file is expected at run time,
+ /// BundleRelativePath: path where the file is expected at run time,
/// relative to the app DLL.
/// </summary>
public class FileSpec
public bool IsValid()
{
- return !string.IsNullOrWhiteSpace(SourcePath) &&
+ return !string.IsNullOrWhiteSpace(SourcePath) &&
!string.IsNullOrWhiteSpace(BundleRelativePath);
}
public override string ToString() => $"SourcePath: {SourcePath}, RelativePath: {BundleRelativePath} {(Excluded ? "[Excluded]" : "")}";
}
}
-
{
/// <summary>
/// FileType: Identifies the type of file embedded into the bundle.
- ///
+ ///
/// The bundler differentiates a few kinds of files via the manifest,
/// with respect to the way in which they'll be used by the runtime.
/// </summary>
Symbols // PDB Files
};
}
-
/// <summary>
/// BundleManifest is a description of the contents of a bundle file.
/// This class handles creation and consumption of bundle-manifests.
- ///
+ ///
/// Here is the description of the Bundle Layout:
/// _______________________________________________
- /// AppHost
+ /// AppHost
///
///
/// ------------Embedded Files ---------------------
/// The embedded files including the app, its
- /// configuration files, dependencies, and
+ /// configuration files, dependencies, and
/// possibly the runtime.
- ///
- ///
- ///
- ///
- ///
- ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
///
/// ------------ Bundle Header -------------
/// MajorVersion
/// - - - - - - Manifest Entries - - - - - - - - - - -
/// Series of FileEntries (for each embedded file)
/// [File Type, Name, Offset, Size information]
- ///
- ///
- ///
+ ///
+ ///
+ ///
/// _________________________________________________
/// </summary>
public class Manifest
// by constructing the bundler with BundleAllConent option.
// This mode is expected to be deprecated in future versions of .NET.
[Flags]
- enum HeaderFlags : ulong
+ private enum HeaderFlags : ulong
{
None = 0,
NetcoreApp3CompatMode = 1
}
- // Bundle ID is a string that is used to uniquely
+ // Bundle ID is a string that is used to uniquely
// identify this bundle. It is choosen to be compatible
// with path-names so that the AppHost can use it in
// extraction path.
public static string CurrentVersion => $"{CurrentMajorVersion}.{MinorVersion}";
public string DesiredVersion => $"{DesiredMajorVersion}.{MinorVersion}";
- FileEntry DepsJsonEntry = null;
- FileEntry RuntimeConfigJsonEntry = null;
- HeaderFlags Flags;
+ private FileEntry DepsJsonEntry;
+ private FileEntry RuntimeConfigJsonEntry;
+ private HeaderFlags Flags;
public List<FileEntry> Files;
FileEntry entry = new FileEntry(type, relativePath, offset, size);
Files.Add(entry);
- switch(entry.Type)
+ switch (entry.Type)
{
case FileType.DepsJson:
DepsJsonEntry = entry;
long startOffset = writer.BaseStream.Position;
// Write the bundle header
- writer.Write(DesiredMajorVersion);
+ writer.Write(DesiredMajorVersion);
writer.Write(MinorVersion);
- writer.Write(Files.Count());
+ writer.Write(Files.Count);
writer.Write(BundleID);
if (DesiredMajorVersion == 2)
{
/// <summary>
/// TargetInfo: Information about the target for which the single-file bundle is built.
- ///
+ ///
/// Currently the TargetInfo only tracks:
/// - the target operating system
/// - the target architecture
Debug.Assert(IsLinux || IsOSX || IsWindows);
- if(FrameworkVersion.CompareTo(net50) >= 0)
+ if (FrameworkVersion.CompareTo(net50) >= 0)
{
BundleVersion = 2u;
DefaultOptions = BundleOptions.None;
}
- else if(FrameworkVersion.Major == 3 && (FrameworkVersion.Minor == 0 || FrameworkVersion.Minor == 1))
+ else if (FrameworkVersion.Major == 3 && (FrameworkVersion.Minor == 0 || FrameworkVersion.Minor == 1))
{
BundleVersion = 1u;
DefaultOptions = BundleOptions.BundleAllContent;
return $"OS: {os} Arch: {arch} FrameworkVersion: {FrameworkVersion}";
}
- static OSPlatform HostOS => RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? OSPlatform.Linux :
+ private static OSPlatform HostOS => RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? OSPlatform.Linux :
RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? OSPlatform.OSX : OSPlatform.Windows;
public bool IsLinux => OS.Equals(OSPlatform.Linux);
public bool ShouldExclude(string relativePath) =>
(FrameworkVersion.Major != 3) && (relativePath.Equals(HostFxr) || relativePath.Equals(HostPolicy));
- readonly Version net50 = new Version(5, 0);
- string HostFxr => IsWindows ? "hostfxr.dll" : IsLinux ? "libhostfxr.so" : "libhostfxr.dylib";
- string HostPolicy => IsWindows ? "hostpolicy.dll" : IsLinux ? "libhostpolicy.so" : "libhostpolicy.dylib";
+ private readonly Version net50 = new Version(5, 0);
+ private string HostFxr => IsWindows ? "hostfxr.dll" : IsLinux ? "libhostfxr.so" : "libhostfxr.dylib";
+ private string HostPolicy => IsWindows ? "hostpolicy.dll" : IsLinux ? "libhostpolicy.so" : "libhostpolicy.dylib";
}
}
-
/// </summary>
public class Trace
{
- readonly bool Verbose = false;
+ private readonly bool Verbose;
public Trace(bool verbose)
{
}
}
}
-
return attr;
}
}
- return new CustomAttributeHandle();
+ return default;
}
private static Guid GetTypeGuid(MetadataReader reader, TypeDefinition type)
namespace Microsoft.NET.HostModel.ComHost
{
/// <summary>
- /// The application host executable cannot be customized because adding resources requires
+ /// The application host executable cannot be customized because adding resources requires
/// that the build be performed on Windows (excluding Nano Server).
/// </summary>
public class ComHostCustomizationUnsupportedOSException : Exception
{
}
}
-
ushort wLang,
IntPtr lParam);
- [DllImport(nameof(Kernel32),SetLastError=true)]
+ [DllImport(nameof(Kernel32), SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumResourceTypes(IntPtr hModule,
EnumResTypeProc lpEnumFunc,
<TestArchitectures>$(TargetArchitecture)</TestArchitectures>
<TestInfraTargetFramework>$(NetCoreAppCurrent)</TestInfraTargetFramework>
<TestRunnerAdditionalArguments>-notrait category=failing</TestRunnerAdditionalArguments>
+ <RunAnalyzers>false</RunAnalyzers>
</PropertyGroup>
</Project>
/// <summary>
/// Undo the processing which took place to create string[] args in Main,
/// so that the next process will receive the same string[] args
- ///
+ ///
/// See here for more info:
/// https://docs.microsoft.com/en-us/archive/blogs/twistylittlepassagesallalike/everyone-quotes-command-line-arguments-the-wrong-way
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
public static string EscapeAndConcatenateArgArrayForProcessStart(IEnumerable<string> args)
- {
+ {
return string.Join(" ", EscapeArgArray(args));
}
/// <summary>
/// Undo the processing which took place to create string[] args in Main,
/// so that the next process will receive the same string[] args
- ///
+ ///
/// See here for more info:
/// https://docs.microsoft.com/en-us/archive/blogs/twistylittlepassagesallalike/everyone-quotes-command-line-arguments-the-wrong-way
/// </summary>
/// <summary>
/// Undo the processing which took place to create string[] args in Main,
/// so that the next process will receive the same string[] args
- ///
+ ///
/// See here for more info:
/// https://docs.microsoft.com/en-us/archive/blogs/twistylittlepassagesallalike/everyone-quotes-command-line-arguments-the-wrong-way
/// </summary>
/// <summary>
/// This prefixes every character with the '^' character to force cmd to
- /// interpret the argument string literally. An alternative option would
+ /// interpret the argument string literally. An alternative option would
/// be to do this only for cmd metacharacters.
- ///
+ ///
/// See here for more info:
/// https://docs.microsoft.com/en-us/archive/blogs/twistylittlepassagesallalike/everyone-quotes-command-line-arguments-the-wrong-way
/// </summary>
var sb = new StringBuilder();
var quoted = ShouldSurroundWithQuotes(arg);
- if (quoted) sb.Append("\"");
+ if (quoted) sb.Append('"');
for (int i = 0; i < arg.Length; ++i)
{
sb.Append(arg[i]);
}
}
-
- if (quoted) sb.Append("\"");
+
+ if (quoted) sb.Append('"');
return sb.ToString();
}
/// <summary>
- /// Prepare as single argument to
+ /// Prepare as single argument to
/// roundtrip properly through cmd.
- ///
+ ///
/// This prefixes every character with the '^' character to force cmd to
- /// interpret the argument string literally. An alternative option would
+ /// interpret the argument string literally. An alternative option would
/// be to do this only for cmd metacharacters.
- ///
+ ///
/// See here for more info:
/// https://docs.microsoft.com/en-us/archive/blogs/twistylittlepassagesallalike/everyone-quotes-command-line-arguments-the-wrong-way
/// </summary>
if (character == '"')
{
-
sb.Append('^');
sb.Append('"');
sb.Append('^');
}
else
{
- sb.Append("^");
+ sb.Append('^');
sb.Append(character);
}
}
}
/// <summary>
- /// Prepare as single argument to
+ /// Prepare as single argument to
/// roundtrip properly through cmd.
- ///
+ ///
/// This prefixes every character with the '^' character to force cmd to
- /// interpret the argument string literally. An alternative option would
+ /// interpret the argument string literally. An alternative option would
/// be to do this only for cmd metacharacters.
- ///
+ ///
/// See here for more info:
/// https://docs.microsoft.com/en-us/archive/blogs/twistylittlepassagesallalike/everyone-quotes-command-line-arguments-the-wrong-way
/// </summary>
'
Imports System.Resources
-Imports System.Text
Namespace System
<!-- Language configuration -->
<PropertyGroup>
<Features>strict;nullablePublicOnly</Features>
- <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<!-- We decided to keep this disabled by default: https://github.com/dotnet/runtime/issues/15152 -->
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
<GenFacadesIgnoreBuildAndRevisionMismatch>true</GenFacadesIgnoreBuildAndRevisionMismatch>
- <EnableAnalyzers Condition="'$(EnableAnalyzers)' == '' and '$(IsSourceProject)' == 'true' and '$(MSBuildProjectExtension)' != '.ilproj'">true</EnableAnalyzers>
+ <!-- Disable analyzers for tests and unsupported projects -->
+ <RunAnalyzers Condition="'$(IsSourceProject)' != 'true' or '$(MSBuildProjectExtension)' == '.ilproj'">false</RunAnalyzers>
</PropertyGroup>
<!-- Set up common paths -->
<WarningsNotAsErrors>42025</WarningsNotAsErrors>
<DefineConstants>$(DefineConstants),LATEBINDING=True</DefineConstants>
<DefineConstants Condition="'$(TargetsWindows)' == 'true'">$(DefineConstants),TARGET_WINDOWS=True</DefineConstants>
- <NoWarn Condition="'$(TargetsWindows)' != 'true'">$(NoWarn);CA1823</NoWarn> <!-- Avoid unused fields warnings in Unix build -->
+ <NoWarn>$(NoWarn),CA1810,CA2200</NoWarn>
+ <NoWarn Condition="'$(TargetsWindows)' != 'true'">$(NoWarn);CA1823</NoWarn>
+ <!-- Avoid unused fields warnings in Unix build -->
<AssemblyName>Microsoft.VisualBasic.Core</AssemblyName>
<RemoveIntegerChecks>false</RemoveIntegerChecks>
<RootNamespace />
- <!-- No plans to fix the analyzer issues. -->
- <EnableAnalyzers>false</EnableAnalyzers>
<TargetFrameworks>$(NetCoreAppCurrent);$(NetCoreAppCurrent)-Windows_NT</TargetFrameworks>
</PropertyGroup>
<ItemGroup Condition="'$(TargetsWindows)' == 'true'">
' The .NET Foundation licenses this file to you under the MIT license.
Imports System
-Imports System.Globalization
Imports Microsoft.VisualBasic.CompilerServices.Utils
Imports System.Collections.Generic
Imports Microsoft.VisualBasic.CompilerServices.Symbols
-Imports Microsoft.VisualBasic.CompilerServices.ConversionResolution
Imports Microsoft.VisualBasic.CompilerServices.ConversionResolution.OperatorCaches
Namespace Microsoft.VisualBasic.CompilerServices
End Class
- Friend Shared ReadOnly ConversionCache As FixedList
- Friend Shared ReadOnly UnconvertibleTypeCache As FixedExistanceList
-
- Shared Sub New()
- ConversionCache = New FixedList
- UnconvertibleTypeCache = New FixedExistanceList
- End Sub
+ Friend Shared ReadOnly ConversionCache As FixedList = New FixedList
+ Friend Shared ReadOnly UnconvertibleTypeCache As FixedExistanceList = New FixedExistanceList
End Class
End Class
Imports System
Imports System.Collections.Generic
-Imports System.Collections.ObjectModel
-Imports System.Diagnostics
Imports System.Dynamic
Imports System.Linq.Expressions
Imports System.Reflection
'There is some inconsistency in the handling of argNames, sometimes it
'has been normalized to non-null by this point, sometimes not.
If argNames Is Nothing Then
- argNames = New String(-1) {}
+ argNames = Array.Empty(Of String)()
End If
callInfo = New CallInfo(args.Length - valueArgs, argNames)
Imports System.IO
Imports Microsoft.VisualBasic.CompilerServices.ExceptionUtils
-Imports Microsoft.VisualBasic.CompilerServices.Utils
Namespace Microsoft.VisualBasic.CompilerServices
' The .NET Foundation licenses this file to you under the MIT license.
Imports System
-Imports System.Globalization
Imports Microsoft.VisualBasic.CompilerServices.Utils
Imports System
Imports System.Diagnostics
-Imports System.Globalization
Imports System.Reflection
Imports System.Runtime.InteropServices
-Imports System.Runtime.Remoting
Imports Microsoft.VisualBasic.CompilerServices.ExceptionUtils
Imports Microsoft.VisualBasic.CompilerServices.Utils
Imports System.Collections.Generic
Imports System.Diagnostics
-Imports Microsoft.VisualBasic.Strings
Imports Microsoft.VisualBasic.CompilerServices.Symbols
Imports Microsoft.VisualBasic.CompilerServices.Operators
Imports Microsoft.VisualBasic.CompilerServices.Utils
' The .NET Foundation licenses this file to you under the MIT license.
Imports System
-Imports System.Globalization
Imports Microsoft.VisualBasic.CompilerServices.Utils
' The .NET Foundation licenses this file to you under the MIT license.
Imports System
-Imports System.Collections
Imports System.Collections.Generic
Imports System.Diagnostics
Imports System.Dynamic
-Imports System.Globalization
Imports System.Reflection
-Imports System.Runtime.InteropServices
Imports Microsoft.VisualBasic.CompilerServices.Symbols
Imports Microsoft.VisualBasic.CompilerServices.OverloadResolution
-Imports Microsoft.VisualBasic.CompilerServices.ExceptionUtils
-Imports Microsoft.VisualBasic.CompilerServices.Utils
-Imports Microsoft.VisualBasic.CompilerServices.ReflectionExtensions
-Imports System.Runtime.Versioning
#Const NEW_BINDER = True
#Const BINDING_LOG = False
ByVal RValueBase As Boolean)
ObjectLateSetComplex(
- Instance, Nothing, MemberName, Arguments, New String() {},
+ Instance, Nothing, MemberName, Arguments, Array.Empty(Of String)(),
NoTypeArguments, OptimisticSet, RValueBase)
End Sub 'FallbackSetComplex
Imports System
Imports System.ComponentModel
-Imports System.Diagnostics
Imports System.Reflection
Imports Microsoft.VisualBasic.CompilerServices.ConversionResolution
' The .NET Foundation licenses this file to you under the MIT license.
Imports System
-Imports System.Diagnostics
-Imports System.Globalization
Imports Microsoft.VisualBasic.CompilerServices.StringType
Imports Microsoft.VisualBasic.CompilerServices.Utils
Imports System
Imports System.Collections.Generic
Imports System.Diagnostics
-Imports System.Dynamic
-Imports System.Linq.Expressions
Imports System.Reflection
Imports Microsoft.VisualBasic.CompilerServices.Symbols
Imports Microsoft.VisualBasic.CompilerServices.OverloadResolution
-Imports Microsoft.VisualBasic.CompilerServices.Utils
Namespace Microsoft.VisualBasic.CompilerServices
Option Strict On
Imports System
-Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Diagnostics
-Imports System.Globalization
-Imports System.Reflection
Imports System.Runtime.CompilerServices
-
-Imports Microsoft.VisualBasic.CompilerServices.ExceptionUtils
Imports Microsoft.VisualBasic.CompilerServices.Symbols
Imports Microsoft.VisualBasic.CompilerServices.Utils
' The .NET Foundation licenses this file to you under the MIT license.
Imports System
-Imports Microsoft.VisualBasic.CompilerServices.Utils
-Imports Microsoft.VisualBasic.FileIO
Namespace Global.Microsoft.VisualBasic.CompilerServices
' The .NET Foundation licenses this file to you under the MIT license.
Imports System
-Imports System.Globalization
Imports Microsoft.VisualBasic.CompilerServices.Utils
' The .NET Foundation licenses this file to you under the MIT license.
Imports System
-Imports System.Globalization
Imports System.Diagnostics
Imports System.Reflection
Imports Microsoft.VisualBasic.CompilerServices.ExceptionUtils
-Imports Microsoft.VisualBasic.CompilerServices.Utils
Namespace Microsoft.VisualBasic.CompilerServices
Imports System
Imports System.Reflection
Imports System.Diagnostics
-Imports System.Collections
Imports System.Collections.Generic
Imports System.Linq
MAX
End Enum
- Friend Shared ReadOnly NoArguments As Object() = {}
- Friend Shared ReadOnly NoArgumentNames As String() = {}
- Friend Shared ReadOnly NoTypeArguments As Type() = {}
- Friend Shared ReadOnly NoTypeParameters As Type() = {}
+ Friend Shared ReadOnly NoArguments As Object() = Array.Empty(Of Object)()
+ Friend Shared ReadOnly NoArgumentNames As String() = Array.Empty(Of String)()
+ Friend Shared ReadOnly NoTypeArguments As Type() = Array.Empty(Of Type)()
+ Friend Shared ReadOnly NoTypeParameters As Type() = Array.Empty(Of Type)()
Friend Shared ReadOnly OperatorCLSNames As String()
Friend Shared ReadOnly OperatorNames As String()
BindingFlags.Static Or
BindingFlags.Instance
- Private Shared ReadOnly s_noMembers As MemberInfo() = {}
+ Private Shared ReadOnly s_noMembers As MemberInfo() = Array.Empty(Of MemberInfo)()
Private Shared Function FilterInvalidMembers(ByVal members As MemberInfo()) As MemberInfo()
If CheckEOF(lChar) Then
m_eof = True
Else
- Do While (sTermChars.IndexOf(ChrW(lChar)) = -1)
+ Do While (Not sTermChars.Contains(ChrW(lChar)))
lChar = m_sr.Read()
m_position += 1
For i As Integer = 0 To namedParameters.GetUpperBound(0)
If (namedParameters(i) Is Nothing) Then
Diagnostics.Debug.Assert(False, "Should never be reached")
+#Disable Warning CA2208 ' Instantiate argument exceptions correctly
Throw New ArgumentException
+#Enable Warning CA2208 ' Instantiate argument exceptions correctly
End If
Next i
End If
p = GetMethodsByName(objType, objIReflect, name, invokeAttr)
If (args Is Nothing) Then
- args = New Object() {}
+ args = Array.Empty(Of Object)()
End If
Dim binderState As Object = Nothing
Imports Microsoft.VisualBasic.CompilerServices
Imports Microsoft.VisualBasic.CompilerServices.Utils
-Imports Microsoft.VisualBasic.CompilerServices.ExceptionUtils
Imports System
Imports System.Runtime.InteropServices
Namespace Microsoft.VisualBasic
-
+
Public NotInheritable Class ErrObject
' Error object private values
Friend Function MapErrorNumber(ByVal Number As Integer) As Integer
If Number > 65535 Then
' Number cannot be greater than 65535.
- Throw New ArgumentException(SR.Format(SR.Argument_InvalidValue1), "Number")
+ Throw New ArgumentException(SR.Format(SR.Argument_InvalidValue1), NameOf(Number))
End If
If Number >= 0 Then
' Cannot call through IO.File.WriteAllBytes (since they don't support append)
' so only check for trailing separator
- CheckFilePathTrailingSeparator(file, "file")
+ CheckFilePathTrailingSeparator(file, NameOf(file))
Dim FileStream As IO.FileStream = Nothing
Try
'Cannot call through IO.File.WriteAllText (since they don't support: append, prefer current encoding than specified one)
' so only check for trailing separator.
- CheckFilePathTrailingSeparator(file, "file")
+ CheckFilePathTrailingSeparator(file, NameOf(file))
Dim StreamWriter As IO.StreamWriter = Nothing
Try
Private m_SearchText As String ' The text to search.
Private m_IgnoreCase As Boolean ' Should we ignore case?
Private m_Decoder As Text.Decoder ' The Decoder to use.
- Private m_PreviousCharBuffer() As Char = {} ' The cached character array from previous call to IsTextExist.
+ Private m_PreviousCharBuffer() As Char = Array.Empty(Of Char)() ' The cached character array from previous call to IsTextExist.
Private m_CheckPreamble As Boolean = True ' True to check for preamble. False otherwise.
Private m_Preamble() As Byte ' The byte order mark we need to consider.
End Class 'Private Class TextSearchHelper
Imports System.ComponentModel
Imports System.Globalization
-Imports Microsoft.VisualBasic.CompilerServices.Utils
-
Namespace Microsoft.VisualBasic.FileIO
''' <summary>
Imports System
Imports System.Environment
Imports System.Reflection
-Imports Microsoft.VisualBasic.CompilerServices.Utils
Imports ExUtils = Microsoft.VisualBasic.CompilerServices.ExceptionUtils
Namespace Microsoft.VisualBasic.FileIO
Imports System.Text.RegularExpressions
Imports Microsoft.VisualBasic.CompilerServices.ExceptionUtils
-Imports Microsoft.VisualBasic.CompilerServices.Utils
Namespace Microsoft.VisualBasic.FileIO
Return m_TextFieldType
End Get
Set(ByVal value As FieldType)
- ValidateFieldTypeEnumValue(value, "value")
+ ValidateFieldTypeEnumValue(value, NameOf(value))
m_TextFieldType = value
m_NeedPropertyCheck = True
End Set
End If
Cursor = i + 1
+#Disable Warning CA1834 ' Consider using 'StringBuilder.Append(char)' when applicable
' See if vbLf should be added as well
If Character = vbCr Then
If Cursor < m_CharsRead Then
End If
End If
End If
+#Enable Warning CA1834 ' Consider using 'StringBuilder.Append(char)' when applicable
Return Builder.ToString()
End If
Private m_Reader As TextReader
' An array holding the strings that indicate a line is a comment
- Private m_CommentTokens() As String = New String() {}
+ Private m_CommentTokens() As String = Array.Empty(Of String)()
' The line last read by either ReadLine or ReadFields
Private m_LineNumber As Long = 1
' Flags whether or not there is data left to read. Assume there is at creation
- Private m_EndOfData As Boolean = False
+ Private m_EndOfData As Boolean
' Holds the last malformed line
Private m_ErrorLine As String = ""
Private m_TrimWhiteSpace As Boolean = True
' The position of the cursor in the buffer
- Private m_Position As Integer = 0
+ Private m_Position As Integer
' The position of the peek cursor
- Private m_PeekPosition As Integer = 0
+ Private m_PeekPosition As Integer
' The number of chars in the buffer
- Private m_CharsRead As Integer = 0
+ Private m_CharsRead As Integer
' Indicates that the user has changed properties so that we need to validate before a read
Private m_NeedPropertyCheck As Boolean = True
Private Const ENDING_QUOTE As String = """[{0}]*"
' Indicates passed in stream should be not be closed
- Private m_LeaveOpen As Boolean = False
+ Private m_LeaveOpen As Boolean
End Class
''' <summary>
' This exception should never be hit.
' We will throw Arguments are not valid.
- Throw New ArgumentException(SR.Argument_InvalidValue, "om")
+ Throw New ArgumentException(SR.Argument_InvalidValue, NameOf(om))
End Function
Friend Sub CloseAllFiles(ByVal assem As System.Reflection.Assembly)
Imports System
Imports System.Math
-Imports Microsoft.VisualBasic.CompilerServices
-Imports Microsoft.VisualBasic.CompilerServices.Utils
Namespace Microsoft.VisualBasic
Imports System
Imports System.Collections
Imports System.Diagnostics
-Imports Microsoft.VisualBasic.CompilerServices
Namespace Microsoft.VisualBasic
' because of threading and synchronization issues involved which would then cause
' perf degrade.
- Private mDisposed As Boolean = False
+ Private mDisposed As Boolean
'The collection this enumerator is enumerating over
Private mCollectionObject As Microsoft.VisualBasic.Collection
CloseHandle _
Lib "kernel32" (ByVal hObject As IntPtr) As Integer
+#Disable Warning CA1838 ' Avoid 'StringBuilder' parameters for P/Invokes
<DllImport(
"kernel32",
CharSet:=CharSet.Auto,
ByVal lpFileSystemNameBuffer As IntPtr,
ByVal nFileSystemNameSize As Integer) As Integer
End Function
+#Enable Warning CA1838
''' <summary>
''' Given a 32-bit SHFILEOPSTRUCT, call the appropriate SHFileOperation function
' The .NET Foundation licenses this file to you under the MIT license.
Imports System
-Imports System.Globalization
-Imports System.Security
Imports Microsoft.VisualBasic.CompilerServices
Imports Microsoft.VisualBasic.CompilerServices.ExceptionUtils
Imports Microsoft.VisualBasic.CompilerServices.Utils
Imports System
Imports System.Reflection
-Imports System.Text
Imports System.Runtime.InteropServices
Imports System.Runtime.Versioning
Imports Microsoft.Win32
Imports Microsoft.VisualBasic.CompilerServices
Imports Microsoft.VisualBasic.CompilerServices.ExceptionUtils
-Imports Microsoft.VisualBasic.CompilerServices.Utils
Namespace Microsoft.VisualBasic
<SkipCommonResourcesIncludes>true</SkipCommonResourcesIncludes>
<DocumentationFile>$(OutputPath)$(MSBuildProjectName).xml</DocumentationFile>
- <EnableAnalyzers>true</EnableAnalyzers>
</PropertyGroup>
<!-- Platform specific properties -->
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
- <EnableDefaultItems>false</EnableDefaultItems>
+ <EnableDefaultItems>false</EnableDefaultItems>
+ <RunAnalyzers>false</RunAnalyzers>
</PropertyGroup>
<ItemGroup>
<PublishTrimmed>true</PublishTrimmed>
<_TrimmerDefaultAction>link</_TrimmerDefaultAction>
<InvariantGlobalization>true</InvariantGlobalization> <!-- workaround for https://github.com/dotnet/runtime/issues/41866 -->
+ <NoWarn>$(NoWarn),CA1050</NoWarn>
</PropertyGroup>
<!-- Redirect 'dotnet publish' to in-tree runtime pack -->
namespace HelloWorld
{
- class Program
+ internal class Program
{
- static void Main(string[] args)
+ private static void Main(string[] args)
{
bool isMono = typeof(object).Assembly.GetType("Mono.RuntimeStructs") != null;
Console.WriteLine("Hello World " + (isMono ? "from Mono!" : "from CoreCLR!"));
<_TrimmerDefaultAction>link</_TrimmerDefaultAction>
<Optimized Condition="'$(Configuration)' == 'Release'">True</Optimized>
<InvariantGlobalization>true</InvariantGlobalization> <!-- workaround for https://github.com/dotnet/runtime/issues/41866 -->
+ <RunAnalyzers>false</RunAnalyzers>
</PropertyGroup>
<!-- Redirect 'dotnet publish' to in-tree runtime pack -->
{
public class Test
{
- public static void Main(String[] args)
+ public static void Main(string[] args)
{
Console.WriteLine ("Hello, World!");
}
public class Test
{
- public static void Main (String[] args) {
+ public static void Main (string[] args) {
Console.WriteLine ("Hello, World!");
}
}
<TargetFramework>netcoreapp3.0</TargetFramework>
<EnableSourceControlManagerQueries>false</EnableSourceControlManagerQueries>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <RunAnalyzers>false</RunAnalyzers>
</PropertyGroup>
</Project>
namespace JitDiffTools
{
- class Program
- {
- static void Main (string [] args)
- {
- if (args?.Length != 2)
- {
- Console.WriteLine ("usage:\n\tjitdiff folder1 folder2");
- return;
- }
-
- string [] filesBefore = Directory.GetFiles (args [0], "*.dasm");
- string [] filesAfter = Directory.GetFiles (args [1], "*.dasm");
- var pairs = new List<Tuple<string, string>> ();
-
- foreach (string fileBefore in filesBefore)
- {
- string fileName = Path.GetFileName (fileBefore);
- string fileAfter = filesAfter.FirstOrDefault (f =>
- Path.GetFileName (f).Equals (fileName, StringComparison.InvariantCultureIgnoreCase));
-
- if (fileAfter != null)
- pairs.Add (new Tuple<string, string> (fileBefore, fileAfter));
- }
-
- long totalFileDiff = 0;
- Console.WriteLine ();
- foreach (var pair in pairs)
- {
- long sizeBefore = new FileInfo (pair.Item1).Length;
- long sizeAfter = new FileInfo (pair.Item2).Length;
- long diff = sizeAfter - sizeBefore;
- totalFileDiff += diff;
- if (diff != 0)
- Console.WriteLine ($"Total diff for {Path.GetFileName (pair.Item1)}: {diff} bytes");
- }
- if (totalFileDiff != 0)
- Console.WriteLine ($"Total diff for all files: {totalFileDiff} bytes");
-
- Console.WriteLine ("\n=====================\n= Per-method diffs (may take a while):\n=====================\n");
- foreach (var pair in pairs)
- {
- PrintDiffs (pair.Item1, pair.Item2);
- }
- Console.WriteLine ("Done.");
- }
-
- static void PrintDiffs (string fileBefore, string fileAfter)
- {
- List<DiffItem> diff = GetDiffs (fileBefore, fileAfter);
-
- int totalRegression = 0, totalImprovement = 0;
- int methodRegressed = 0, methodImproved = 0;
- foreach (var diffItem in diff.OrderByDescending (d => d.DiffPercentage))
- {
- if (diffItem.HasChanges)
- {
- Console.WriteLine (diffItem);
- if (diffItem.Diff > 0)
- {
- totalRegression += diffItem.Diff;
- methodRegressed++;
- }
- else
- {
- totalImprovement += diffItem.Diff;
- methodImproved++;
- }
- }
- }
-
- if (methodRegressed == 0 && methodImproved == 0)
- return;
-
- Console.WriteLine ("\n");
- Console.WriteLine (Path.GetFileNameWithoutExtension (fileBefore));
- Console.WriteLine ($"Methods \"regressed\": {methodRegressed}");
- Console.WriteLine ($"Methods \"improved\": {methodImproved}");
- Console.WriteLine ($"Total regression: {totalRegression} lines, Total improvement: {totalImprovement} lines.");
- Console.WriteLine ("\n");
- }
-
- static List<DiffItem> GetDiffs (string file1, string file2)
- {
- List<FunctionInfo> file1Functions = ParseFunctions (file1);
- List<FunctionInfo> file2Functions = ParseFunctions (file2);
-
- var diffItems = new List<DiffItem> (); // diffs
-
- foreach (FunctionInfo file1Function in file1Functions)
- {
- // SingleOrDefault to make sure functions are unique
- FunctionInfo file2Function = file2Functions.FirstOrDefault (f => f.Name == file1Function.Name);
- diffItems.Add (new DiffItem (file1Function, file2Function)); // file2Function can be null here - means function was removed in file2
- }
-
- foreach (FunctionInfo file2Function in file2Functions)
- {
- // SingleOrDefault to make sure functions are unique
- FunctionInfo file1Function = file1Functions.FirstOrDefault (f => f.Name == file2Function.Name);
- if (file1Function == null)
- diffItems.Add (new DiffItem (null, file2Function)); // function was added in file2
- }
-
- return diffItems;
- }
-
- static bool TryParseFunctionName (string str, out string name)
- {
- // depends on objdump, let's use the whole line as a name if it ends with `:`
- if (str.EndsWith (':'))
- {
- // Possible formats:
- // 1) func_name:
- // 2) p_%var%_func_name:
- // 3) %var% <func_name>:
- // 4) %var% <p_%var%_func_name>:
- name = Regex.Replace (str, @"\b([a-f0-9]+)\b", m => "");
- name = Regex.Replace (name, @"(p_\d+_)?", m => "");
- return true;
- }
- name = null;
- return false;
- }
-
- static List<FunctionInfo> ParseFunctions (string file)
- {
- string [] lines = File.ReadAllLines (file)
- .Select (l => l.Trim (' ', '\t', '\r', '\n'))
- .Where (l => !string.IsNullOrEmpty (l))
- .ToArray ();
-
- var result = new List<FunctionInfo> ();
- FunctionInfo current = null;
- foreach (string line in lines)
- {
- if (TryParseFunctionName (line, out string name))
- {
- current = new FunctionInfo (name);
- result.Add (current);
- }
- current?.Body.Add (line);
- }
- return result;
- }
- }
-
- public class FunctionInfo
- {
- public FunctionInfo (string name)
- {
- if (string.IsNullOrWhiteSpace (name))
- throw new ArgumentException ("Function name should not be empty", nameof (name));
- Name = name;
- }
-
- public string Name { get; }
-
- public List<string> Body { get; set; } = new List<string>();
-
- public override string ToString () => $"{Name} (lines:{Body?.Count})";
- }
-
- public class DiffItem
- {
- public DiffItem (FunctionInfo before, FunctionInfo after)
- {
- if (before == null && after == null)
- throw new ArgumentException ("Both Before and After can not be null at the same time");
- if (before != null && after != null && before.Name != after.Name)
- throw new ArgumentException ("After.Name != Before.Name");
- Before = before;
- After = after;
- Name = before != null ? before.Name : after.Name;
- }
-
- public string Name { get; }
-
- public FunctionInfo Before { get; }
-
- public FunctionInfo After { get; }
-
- public int Diff => CalculateBytes (After) - CalculateBytes (Before);
-
- static int CalculateBytes (FunctionInfo info)
- {
- // TODO: calculate bytes
- return info?.Body?.Count ?? 0;
- }
-
- public bool HasChanges => Diff != 0;
-
- public double DiffPercentage
- {
- get
- {
- int b = Before?.Body?.Count ?? 0;
- int a = (After?.Body?.Count ?? 0) * 100;
- if (a == 0 && b == 0)
- return 0;
- if (a > 0 && b == 0)
- return -100;
- return -(100 - a / b);
- }
- }
-
- public override string ToString () => $"Diff for {Name}: {Diff} lines ({DiffPercentage:F1}%)";
- }
-}
\ No newline at end of file
+ internal class Program
+ {
+ private static void Main (string [] args)
+ {
+ if (args?.Length != 2)
+ {
+ Console.WriteLine ("usage:\n\tjitdiff folder1 folder2");
+ return;
+ }
+
+ string [] filesBefore = Directory.GetFiles (args [0], "*.dasm");
+ string [] filesAfter = Directory.GetFiles (args [1], "*.dasm");
+ var pairs = new List<Tuple<string, string>> ();
+
+ foreach (string fileBefore in filesBefore)
+ {
+ string fileName = Path.GetFileName (fileBefore);
+ string fileAfter = filesAfter.FirstOrDefault (f =>
+ Path.GetFileName (f).Equals (fileName, StringComparison.InvariantCultureIgnoreCase));
+
+ if (fileAfter != null)
+ pairs.Add (new Tuple<string, string> (fileBefore, fileAfter));
+ }
+
+ long totalFileDiff = 0;
+ Console.WriteLine ();
+ foreach (var pair in pairs)
+ {
+ long sizeBefore = new FileInfo (pair.Item1).Length;
+ long sizeAfter = new FileInfo (pair.Item2).Length;
+ long diff = sizeAfter - sizeBefore;
+ totalFileDiff += diff;
+ if (diff != 0)
+ Console.WriteLine ($"Total diff for {Path.GetFileName (pair.Item1)}: {diff} bytes");
+ }
+ if (totalFileDiff != 0)
+ Console.WriteLine ($"Total diff for all files: {totalFileDiff} bytes");
+
+ Console.WriteLine ("\n=====================\n= Per-method diffs (may take a while):\n=====================\n");
+ foreach (var pair in pairs)
+ {
+ PrintDiffs (pair.Item1, pair.Item2);
+ }
+ Console.WriteLine ("Done.");
+ }
+
+ private static void PrintDiffs (string fileBefore, string fileAfter)
+ {
+ List<DiffItem> diff = GetDiffs (fileBefore, fileAfter);
+
+ int totalRegression = 0, totalImprovement = 0;
+ int methodRegressed = 0, methodImproved = 0;
+ foreach (var diffItem in diff.OrderByDescending (d => d.DiffPercentage))
+ {
+ if (diffItem.HasChanges)
+ {
+ Console.WriteLine (diffItem);
+ if (diffItem.Diff > 0)
+ {
+ totalRegression += diffItem.Diff;
+ methodRegressed++;
+ }
+ else
+ {
+ totalImprovement += diffItem.Diff;
+ methodImproved++;
+ }
+ }
+ }
+
+ if (methodRegressed == 0 && methodImproved == 0)
+ return;
+
+ Console.WriteLine ("\n");
+ Console.WriteLine (Path.GetFileNameWithoutExtension (fileBefore));
+ Console.WriteLine ($"Methods \"regressed\": {methodRegressed}");
+ Console.WriteLine ($"Methods \"improved\": {methodImproved}");
+ Console.WriteLine ($"Total regression: {totalRegression} lines, Total improvement: {totalImprovement} lines.");
+ Console.WriteLine ("\n");
+ }
+
+ private static List<DiffItem> GetDiffs (string file1, string file2)
+ {
+ List<FunctionInfo> file1Functions = ParseFunctions (file1);
+ List<FunctionInfo> file2Functions = ParseFunctions (file2);
+
+ var diffItems = new List<DiffItem> (); // diffs
+
+ foreach (FunctionInfo file1Function in file1Functions)
+ {
+ // SingleOrDefault to make sure functions are unique
+ FunctionInfo file2Function = file2Functions.FirstOrDefault (f => f.Name == file1Function.Name);
+ diffItems.Add (new DiffItem (file1Function, file2Function)); // file2Function can be null here - means function was removed in file2
+ }
+
+ foreach (FunctionInfo file2Function in file2Functions)
+ {
+ // SingleOrDefault to make sure functions are unique
+ FunctionInfo file1Function = file1Functions.FirstOrDefault (f => f.Name == file2Function.Name);
+ if (file1Function == null)
+ diffItems.Add (new DiffItem (null, file2Function)); // function was added in file2
+ }
+
+ return diffItems;
+ }
+
+ private static bool TryParseFunctionName (string str, out string name)
+ {
+ // depends on objdump, let's use the whole line as a name if it ends with `:`
+ if (str.EndsWith (':'))
+ {
+ // Possible formats:
+ // 1) func_name:
+ // 2) p_%var%_func_name:
+ // 3) %var% <func_name>:
+ // 4) %var% <p_%var%_func_name>:
+ name = Regex.Replace (str, @"\b([a-f0-9]+)\b", m => "");
+ name = Regex.Replace (name, @"(p_\d+_)?", m => "");
+ return true;
+ }
+ name = null;
+ return false;
+ }
+
+ private static List<FunctionInfo> ParseFunctions (string file)
+ {
+ string [] lines = File.ReadAllLines (file)
+ .Select (l => l.Trim (' ', '\t', '\r', '\n'))
+ .Where (l => !string.IsNullOrEmpty (l))
+ .ToArray ();
+
+ var result = new List<FunctionInfo> ();
+ FunctionInfo current = null;
+ foreach (string line in lines)
+ {
+ if (TryParseFunctionName (line, out string name))
+ {
+ current = new FunctionInfo (name);
+ result.Add (current);
+ }
+ current?.Body.Add (line);
+ }
+ return result;
+ }
+ }
+
+ public class FunctionInfo
+ {
+ public FunctionInfo (string name)
+ {
+ if (string.IsNullOrWhiteSpace (name))
+ throw new ArgumentException ("Function name should not be empty", nameof(name));
+ Name = name;
+ }
+
+ public string Name { get; }
+
+ public List<string> Body { get; set; } = new List<string>();
+
+ public override string ToString () => $"{Name} (lines:{Body?.Count})";
+ }
+
+ public class DiffItem
+ {
+ public DiffItem (FunctionInfo before, FunctionInfo after)
+ {
+ if (before == null && after == null)
+ throw new ArgumentException ("Both Before and After can not be null at the same time");
+ if (before != null && after != null && before.Name != after.Name)
+ throw new ArgumentException ("After.Name != Before.Name");
+ Before = before;
+ After = after;
+ Name = before != null ? before.Name : after.Name;
+ }
+
+ public string Name { get; }
+
+ public FunctionInfo Before { get; }
+
+ public FunctionInfo After { get; }
+
+ public int Diff => CalculateBytes (After) - CalculateBytes (Before);
+
+ private static int CalculateBytes (FunctionInfo info)
+ {
+ // TODO: calculate bytes
+ return info?.Body?.Count ?? 0;
+ }
+
+ public bool HasChanges => Diff != 0;
+
+ public double DiffPercentage
+ {
+ get
+ {
+ int b = Before?.Body?.Count ?? 0;
+ int a = (After?.Body?.Count ?? 0) * 100;
+ if (a == 0 && b == 0)
+ return 0;
+ if (a > 0 && b == 0)
+ return -100;
+ return -(100 - a / b);
+ }
+ }
+
+ public override string ToString () => $"Diff for {Name}: {Diff} lines ({DiffPercentage:F1}%)";
+ }
+}
<PropertyGroup>
<TargetFramework>$(NetCoreAppCurrent)</TargetFramework>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
+ <NoWarn>$(NoWarn),CA2007</NoWarn>
</PropertyGroup>
<ItemGroup>
{
public static void Main(string[] args)
{
- var host = new WebHostBuilder()
+ IWebHost host = new WebHostBuilder()
.UseSetting("UseIISIntegration", false.ToString())
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IOptionsMonitor<ProxyOptions> optionsAccessor, IWebHostEnvironment env)
{
- var options = optionsAccessor.CurrentValue;
+ ProxyOptions options = optionsAccessor.CurrentValue;
app.UseDeveloperExceptionPage()
.UseWebSockets()
.UseDebugProxy(options);
}
}
- static class DebugExtensions
+ internal static class DebugExtensions
{
public static Dictionary<string, string> MapValues(Dictionary<string, string> response, HttpContext context, Uri debuggerHost)
{
var filtered = new Dictionary<string, string>();
- var request = context.Request;
+ HttpRequest request = context.Request;
- foreach (var key in response.Keys)
+ foreach (string key in response.Keys)
{
switch (key)
{
case "devtoolsFrontendUrl":
- var front = response[key];
+ string front = response[key];
filtered[key] = $"{debuggerHost.Scheme}://{debuggerHost.Authority}{front.Replace($"ws={debuggerHost.Authority}", $"ws={request.Host}")}";
break;
case "webSocketDebuggerUrl":
ProxyOptions options,
Func<Dictionary<string, string>, HttpContext, Uri, Dictionary<string, string>> mapFunc)
{
- var devToolsHost = options.DevToolsUrl;
+ Uri devToolsHost = options.DevToolsUrl;
app.UseRouter(router =>
{
router.MapGet("/", Copy);
string GetEndpoint(HttpContext context)
{
- var request = context.Request;
- var requestPath = request.Path;
+ HttpRequest request = context.Request;
+ PathString requestPath = request.Path;
return $"{devToolsHost.Scheme}://{devToolsHost.Authority}{request.Path}{request.QueryString}";
}
{
using (var httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(5) })
{
- var response = await httpClient.GetAsync(GetEndpoint(context));
+ HttpResponseMessage response = await httpClient.GetAsync(GetEndpoint(context));
context.Response.ContentType = response.Content.Headers.ContentType.ToString();
if ((response.Content.Headers.ContentLength ?? 0) > 0)
context.Response.ContentLength = response.Content.Headers.ContentLength;
- var bytes = await response.Content.ReadAsByteArrayAsync();
+ byte[] bytes = await response.Content.ReadAsByteArrayAsync();
await context.Response.Body.WriteAsync(bytes);
}
async Task RewriteSingle(HttpContext context)
{
- var version = await ProxyGetJsonAsync<Dictionary<string, string>>(GetEndpoint(context));
+ Dictionary<string, string> version = await ProxyGetJsonAsync<Dictionary<string, string>>(GetEndpoint(context));
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(
JsonSerializer.Serialize(mapFunc(version, context, devToolsHost)));
async Task RewriteArray(HttpContext context)
{
- var tabs = await ProxyGetJsonAsync<Dictionary<string, string>[]>(GetEndpoint(context));
- var alteredTabs = tabs.Select(t => mapFunc(t, context, devToolsHost)).ToArray();
+ Dictionary<string, string>[] tabs = await ProxyGetJsonAsync<Dictionary<string, string>[]>(GetEndpoint(context));
+ Dictionary<string, string>[] alteredTabs = tabs.Select(t => mapFunc(t, context, devToolsHost)).ToArray();
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(JsonSerializer.Serialize(alteredTabs));
}
var endpoint = new Uri($"ws://{devToolsHost.Authority}{context.Request.Path.ToString()}");
try
{
- using var loggerFactory = LoggerFactory.Create(
+ using ILoggerFactory loggerFactory = LoggerFactory.Create(
builder => builder.AddConsole().AddFilter(null, LogLevel.Information));
context.Request.Query.TryGetValue("urlSymbolServer", out StringValues urlSymbolServerList);
var proxy = new DebuggerProxy(loggerFactory, urlSymbolServerList.ToList());
-
- var ideSocket = await context.WebSockets.AcceptWebSocketAsync();
+
+ System.Net.WebSockets.WebSocket ideSocket = await context.WebSockets.AcceptWebSocketAsync();
await proxy.Run(endpoint, ideSocket);
}
return app;
}
- static async Task<T> ProxyGetJsonAsync<T>(string url)
+ private static async Task<T> ProxyGetJsonAsync<T>(string url)
{
using (var httpClient = new HttpClient())
{
- var response = await httpClient.GetAsync(url);
+ HttpResponseMessage response = await httpClient.GetAsync(url);
return await JsonSerializer.DeserializeAsync<T>(await response.Content.ReadAsStreamAsync());
}
}
<PropertyGroup>
<TargetFramework>$(NetCoreAppCurrent)</TargetFramework>
+ <NoWarn>$(NoWarn),CA2007</NoWarn>
</PropertyGroup>
<ItemGroup>
public int Column { get; private set; }
public MethodInfo Method { get; private set; }
- JObject request;
+ private JObject request;
public bool IsResolved => Assembly != null;
public List<Breakpoint> Locations { get; } = new List<Breakpoint>();
public bool IsMatch(SourceFile sourceFile)
{
- var url = request?["url"]?.Value<string>();
+ string url = request?["url"]?.Value<string>();
if (url == null)
{
- var urlRegex = request?["urlRegex"].Value<string>();
+ string urlRegex = request?["urlRegex"].Value<string>();
var regex = new Regex(urlRegex);
return regex.IsMatch(sourceFile.Url.ToString()) || regex.IsMatch(sourceFile.DocUrl);
}
if (!IsMatch(sourceFile))
return false;
- var line = request?["lineNumber"]?.Value<int>();
- var column = request?["columnNumber"]?.Value<int>();
+ int? line = request?["lineNumber"]?.Value<int>();
+ int? column = request?["columnNumber"]?.Value<int>();
if (line == null || column == null)
return false;
internal class SourceLocation
{
- SourceId id;
- int line;
- int column;
- CliLocation cliLoc;
+ private SourceId id;
+ private int line;
+ private int column;
+ private CliLocation cliLoc;
public SourceLocation(SourceId id, int line, int column)
{
if (obj == null)
return null;
- if (!SourceId.TryParse(obj["scriptId"]?.Value<string>(), out var id))
+ if (!SourceId.TryParse(obj["scriptId"]?.Value<string>(), out SourceId id))
return null;
- var line = obj["lineNumber"]?.Value<int>();
- var column = obj["columnNumber"]?.Value<int>();
+ int? line = obj["lineNumber"]?.Value<int>();
+ int? column = obj["columnNumber"]?.Value<int>();
if (id == null || line == null || column == null)
return null;
internal class SourceId
{
- const string Scheme = "dotnet://";
+ private const string Scheme = "dotnet://";
- readonly int assembly, document;
+ private readonly int assembly, document;
public int Assembly => assembly;
public int Document => document;
public static bool TryParse(string id, out SourceId source)
{
source = null;
- if (!TryParse(id, out var assembly, out var document))
+ if (!TryParse(id, out int assembly, out int document))
return false;
source = new SourceId(assembly, document);
return true;
}
- static bool TryParse(string id, out int assembly, out int document)
+ private static bool TryParse(string id, out int assembly, out int document)
{
assembly = document = 0;
if (id == null || !id.StartsWith(Scheme, StringComparison.Ordinal))
return false;
- var sp = id.Substring(Scheme.Length).Split('_');
+ string[] sp = id.Substring(Scheme.Length).Split('_');
if (sp.Length != 2)
return false;
internal class MethodInfo
{
- MethodDefinition methodDef;
- SourceFile source;
+ private MethodDefinition methodDef;
+ private SourceFile source;
public SourceId SourceId => source.SourceId;
this.methodDef = methodDef;
this.source = source;
- var sps = DebugInformation.SequencePoints;
- if (sps == null || sps.Count() < 1)
+ Mono.Collections.Generic.Collection<SequencePoint> sps = DebugInformation.SequencePoints;
+ if (sps == null || sps.Count < 1)
return;
SequencePoint start = sps[0];
SequencePoint end = sps[0];
- foreach (var sp in sps)
+ foreach (SequencePoint sp in sps)
{
if (sp.StartLine < start.StartLine)
start = sp;
public SourceLocation GetLocationByIl(int pos)
{
SequencePoint prev = null;
- foreach (var sp in DebugInformation.SequencePoints)
+ foreach (SequencePoint sp in DebugInformation.SequencePoints)
{
if (sp.Offset > pos)
break;
internal class TypeInfo
{
- AssemblyInfo assembly;
- TypeDefinition type;
- List<MethodInfo> methods;
+ private AssemblyInfo assembly;
+ private TypeDefinition type;
+ private List<MethodInfo> methods;
public TypeInfo(AssemblyInfo assembly, TypeDefinition type)
{
public override string ToString() => "TypeInfo('" + FullName + "')";
}
- class AssemblyInfo
+ internal class AssemblyInfo
{
- static int next_id;
- ModuleDefinition image;
- readonly int id;
- readonly ILogger logger;
- Dictionary<uint, MethodInfo> methods = new Dictionary<uint, MethodInfo>();
- Dictionary<string, string> sourceLinkMappings = new Dictionary<string, string>();
- Dictionary<string, TypeInfo> typesByName = new Dictionary<string, TypeInfo>();
- readonly List<SourceFile> sources = new List<SourceFile>();
+ private static int next_id;
+ private ModuleDefinition image;
+ private readonly int id;
+ private readonly ILogger logger;
+ private Dictionary<uint, MethodInfo> methods = new Dictionary<uint, MethodInfo>();
+ private Dictionary<string, string> sourceLinkMappings = new Dictionary<string, string>();
+ private Dictionary<string, TypeInfo> typesByName = new Dictionary<string, TypeInfo>();
+ private readonly List<SourceFile> sources = new List<SourceFile>();
internal string Url { get; }
public bool TriedToLoadSymbolsOnDemand { get; set; }
{
this.logger = logger;
}
-
+
public ModuleDefinition Image => image;
public void ClearDebugInfo()
{
- foreach (var type in image.GetTypes())
+ foreach (TypeDefinition type in image.GetTypes())
{
var typeInfo = new TypeInfo(this, type);
typesByName[type.FullName] = typeInfo;
- foreach (var method in type.Methods)
+ foreach (MethodDefinition method in type.Methods)
{
method.DebugInformation = null;
}
}
}
-
+
public void Populate()
{
ProcessSourceLink();
if (doc == null)
return null;
- if (d2s.TryGetValue(doc, out var source))
+ if (d2s.TryGetValue(doc, out SourceFile source))
return source;
var src = new SourceFile(this, sources.Count, doc, GetSourceLinkUrl(doc.Url));
return src;
};
- foreach (var type in image.GetTypes())
+ foreach (TypeDefinition type in image.GetTypes())
{
var typeInfo = new TypeInfo(this, type);
typesByName[type.FullName] = typeInfo;
- foreach (var method in type.Methods)
+ foreach (MethodDefinition method in type.Methods)
{
- foreach (var sp in method.DebugInformation.SequencePoints)
+ foreach (SequencePoint sp in method.DebugInformation.SequencePoints)
{
- var source = FindSource(sp.Document);
+ SourceFile source = FindSource(sp.Document);
var methodInfo = new MethodInfo(this, method, source);
methods[method.MetadataToken.RID] = methodInfo;
if (source != null)
private void ProcessSourceLink()
{
- var sourceLinkDebugInfo = image.CustomDebugInformations.FirstOrDefault(i => i.Kind == CustomDebugInformationKind.SourceLink);
+ CustomDebugInformation sourceLinkDebugInfo = image.CustomDebugInformations.FirstOrDefault(i => i.Kind == CustomDebugInformationKind.SourceLink);
if (sourceLinkDebugInfo != null)
{
- var sourceLinkContent = ((SourceLinkDebugInformation)sourceLinkDebugInfo).Content;
+ string sourceLinkContent = ((SourceLinkDebugInformation)sourceLinkDebugInfo).Content;
if (sourceLinkContent != null)
{
- var jObject = JObject.Parse(sourceLinkContent)["documents"];
+ JToken jObject = JObject.Parse(sourceLinkContent)["documents"];
sourceLinkMappings = JsonConvert.DeserializeObject<Dictionary<string, string>>(jObject.ToString());
}
}
if (sourceLinkMappings.TryGetValue(document, out string url))
return new Uri(url);
- foreach (var sourceLinkDocument in sourceLinkMappings)
+ foreach (KeyValuePair<string, string> sourceLinkDocument in sourceLinkMappings)
{
string key = sourceLinkDocument.Key;
continue;
}
- var keyTrim = key.TrimEnd('*');
+ string keyTrim = key.TrimEnd('*');
if (document.StartsWith(keyTrim, StringComparison.OrdinalIgnoreCase))
{
- var docUrlPart = document.Replace(keyTrim, "");
+ string docUrlPart = document.Replace(keyTrim, "");
return new Uri(sourceLinkDocument.Value.TrimEnd('*') + docUrlPart);
}
}
public MethodInfo GetMethodByToken(uint token)
{
- methods.TryGetValue(token, out var value);
+ methods.TryGetValue(token, out MethodInfo value);
return value;
}
public TypeInfo GetTypeByName(string name)
{
- typesByName.TryGetValue(name, out var res);
+ typesByName.TryGetValue(name, out TypeInfo res);
return res;
}
}
internal class SourceFile
{
- Dictionary<uint, MethodInfo> methods;
- AssemblyInfo assembly;
- int id;
- Document doc;
+ private Dictionary<uint, MethodInfo> methods;
+ private AssemblyInfo assembly;
+ private int id;
+ private Document doc;
internal SourceFile(AssemblyInfo assembly, int id, Document doc, Uri sourceLinkUri)
{
public (int startLine, int startColumn, int endLine, int endColumn) GetExtents()
{
- var start = Methods.OrderBy(m => m.StartLocation.Line).ThenBy(m => m.StartLocation.Column).First();
- var end = Methods.OrderByDescending(m => m.EndLocation.Line).ThenByDescending(m => m.EndLocation.Column).First();
+ MethodInfo start = Methods.OrderBy(m => m.StartLocation.Line).ThenBy(m => m.StartLocation.Column).First();
+ MethodInfo end = Methods.OrderByDescending(m => m.EndLocation.Line).ThenByDescending(m => m.EndLocation.Column).First();
return (start.StartLocation.Line, start.StartLocation.Column, end.EndLocation.Line, end.EndLocation.Column);
}
- async Task<MemoryStream> GetDataAsync(Uri uri, CancellationToken token)
+ private async Task<MemoryStream> GetDataAsync(Uri uri, CancellationToken token)
{
var mem = new MemoryStream();
try
{
if (uri.IsFile && File.Exists(uri.LocalPath))
{
- using (var file = File.Open(SourceUri.LocalPath, FileMode.Open))
+ using (FileStream file = File.Open(SourceUri.LocalPath, FileMode.Open))
{
await file.CopyToAsync(mem, token).ConfigureAwait(false);
mem.Position = 0;
}
else if (uri.Scheme == "http" || uri.Scheme == "https")
{
- var client = new HttpClient();
- using (var stream = await client.GetStreamAsync(uri))
+ using (var client = new HttpClient())
+ using (Stream stream = await client.GetStreamAsync(uri, token))
{
await stream.CopyToAsync(mem, token).ConfigureAwait(false);
mem.Position = 0;
return mem;
}
- static HashAlgorithm GetHashAlgorithm(DocumentHashAlgorithm algorithm)
+ private static HashAlgorithm GetHashAlgorithm(DocumentHashAlgorithm algorithm)
{
switch (algorithm)
{
case DocumentHashAlgorithm.SHA1:
+#pragma warning disable CA5350 // Do Not Use Weak Cryptographic Algorithms
return SHA1.Create();
+#pragma warning restore CA5350 // Do Not Use Weak Cryptographic Algorithms
case DocumentHashAlgorithm.SHA256:
return SHA256.Create();
case DocumentHashAlgorithm.MD5:
+#pragma warning disable CA5351 // Do Not Use Broken Cryptographic Algorithms
return MD5.Create();
+#pragma warning restore CA5351 // Do Not Use Broken Cryptographic Algorithms
}
return null;
}
- bool CheckPdbHash(byte[] computedHash)
+ private bool CheckPdbHash(byte[] computedHash)
{
if (computedHash.Length != doc.Hash.Length)
return false;
- for (var i = 0; i < computedHash.Length; i++)
+ for (int i = 0; i < computedHash.Length; i++)
if (computedHash[i] != doc.Hash[i])
return false;
return true;
}
- byte[] ComputePdbHash(Stream sourceStream)
+ private byte[] ComputePdbHash(Stream sourceStream)
{
- var algorithm = GetHashAlgorithm(doc.HashAlgorithm);
+ HashAlgorithm algorithm = GetHashAlgorithm(doc.HashAlgorithm);
if (algorithm != null)
using (algorithm)
return algorithm.ComputeHash(sourceStream);
if (doc.EmbeddedSource.Length > 0)
return new MemoryStream(doc.EmbeddedSource, false);
- foreach (var url in new[] { SourceUri, SourceLinkUri })
+ foreach (Uri url in new[] { SourceUri, SourceLinkUri })
{
- var mem = await GetDataAsync(url, token).ConfigureAwait(false);
+ MemoryStream mem = await GetDataAsync(url, token).ConfigureAwait(false);
if (mem != null && (!checkHash || CheckPdbHash(ComputePdbHash(mem))))
{
mem.Position = 0;
internal class DebugStore
{
- List<AssemblyInfo> assemblies = new List<AssemblyInfo>();
- readonly HttpClient client;
- readonly ILogger logger;
+ private List<AssemblyInfo> assemblies = new List<AssemblyInfo>();
+ private readonly HttpClient client;
+ private readonly ILogger logger;
public DebugStore(ILogger logger, HttpClient client)
{
public DebugStore(ILogger logger) : this(logger, new HttpClient())
{ }
- class DebugItem
+ private class DebugItem
{
public string Url { get; set; }
public Task<byte[][]> Data { get; set; }
{
var asm_files = new List<string>();
var pdb_files = new List<string>();
- foreach (var file_name in loaded_files)
+ foreach (string file_name in loaded_files)
{
if (file_name.EndsWith(".pdb", StringComparison.OrdinalIgnoreCase))
pdb_files.Add(file_name);
}
List<DebugItem> steps = new List<DebugItem>();
- foreach (var url in asm_files)
+ foreach (string url in asm_files)
{
try
{
new DebugItem
{
Url = url,
- Data = Task.WhenAll(client.GetByteArrayAsync(url), pdb != null ? client.GetByteArrayAsync(pdb) : Task.FromResult<byte[]>(null))
+ Data = Task.WhenAll(client.GetByteArrayAsync(url, token), pdb != null ? client.GetByteArrayAsync(pdb, token) : Task.FromResult<byte[]>(null))
});
}
catch (Exception e)
}
var resolver = new DefaultAssemblyResolver();
- foreach (var step in steps)
+ foreach (DebugItem step in steps)
{
AssemblyInfo assembly = null;
try
{
- var bytes = await step.Data.ConfigureAwait(false);
+ byte[][] bytes = await step.Data.ConfigureAwait(false);
assembly = new AssemblyInfo(resolver, step.Url, bytes[0], bytes[1]);
}
catch (Exception e)
continue;
assemblies.Add(assembly);
- foreach (var source in assembly.Sources)
+ foreach (SourceFile source in assembly.Sources)
yield return source;
}
}
V8 uses zero based indexing for both line and column.
PPDBs uses one based indexing for both line and column.
*/
- static bool Match(SequencePoint sp, SourceLocation start, SourceLocation end)
+ private static bool Match(SequencePoint sp, SourceLocation start, SourceLocation end)
{
- var spStart = (Line: sp.StartLine - 1, Column: sp.StartColumn - 1);
- var spEnd = (Line: sp.EndLine - 1, Column: sp.EndColumn - 1);
+ (int Line, int Column) spStart = (Line: sp.StartLine - 1, Column: sp.StartColumn - 1);
+ (int Line, int Column) spEnd = (Line: sp.EndLine - 1, Column: sp.EndColumn - 1);
if (start.Line > spEnd.Line)
return false;
return null;
}
- var sourceId = start.Id;
+ SourceId sourceId = start.Id;
- var doc = GetFileById(sourceId);
+ SourceFile doc = GetFileById(sourceId);
var res = new List<SourceLocation>();
if (doc == null)
return res;
}
- foreach (var method in doc.Methods)
+ foreach (MethodInfo method in doc.Methods)
{
- foreach (var sequencePoint in method.DebugInformation.SequencePoints)
+ foreach (SequencePoint sequencePoint in method.DebugInformation.SequencePoints)
{
if (!sequencePoint.IsHidden && Match(sequencePoint, start, end))
res.Add(new SourceLocation(method, sequencePoint));
V8 uses zero based indexing for both line and column.
PPDBs uses one based indexing for both line and column.
*/
- static bool Match(SequencePoint sp, int line, int column)
+ private static bool Match(SequencePoint sp, int line, int column)
{
- var bp = (line: line + 1, column: column + 1);
+ (int line, int column) bp = (line: line + 1, column: column + 1);
if (sp.StartLine > bp.line || sp.EndLine < bp.line)
return false;
{
request.TryResolve(this);
- var asm = assemblies.FirstOrDefault(a => a.Name.Equals(request.Assembly, StringComparison.OrdinalIgnoreCase));
- var sourceFile = asm?.Sources?.SingleOrDefault(s => s.DebuggerFileName.Equals(request.File, StringComparison.OrdinalIgnoreCase));
+ AssemblyInfo asm = assemblies.FirstOrDefault(a => a.Name.Equals(request.Assembly, StringComparison.OrdinalIgnoreCase));
+ SourceFile sourceFile = asm?.Sources?.SingleOrDefault(s => s.DebuggerFileName.Equals(request.File, StringComparison.OrdinalIgnoreCase));
if (sourceFile == null)
yield break;
- foreach (var method in sourceFile.Methods)
+ foreach (MethodInfo method in sourceFile.Methods)
{
- foreach (var sequencePoint in method.DebugInformation.SequencePoints)
+ foreach (SequencePoint sequencePoint in method.DebugInformation.SequencePoints)
{
if (!sequencePoint.IsHidden && Match(sequencePoint, request.Line, request.Column))
yield return new SourceLocation(method, sequencePoint);
public static bool operator !=(SessionId a, SessionId b) => a.sessionId != b.sessionId;
- public static SessionId Null { get; } = new SessionId();
+ public static SessionId Null { get; }
public override string ToString() => $"session-{sessionId}";
}
if (!id.StartsWith("dotnet:"))
return false;
- var parts = id.Split(":", 3);
+ string[] parts = id.Split(":", 3);
if (parts.Length < 3)
return false;
public bool IsOk => Value != null;
public bool IsErr => Error != null;
- Result(JObject result, JObject error)
+ private Result(JObject result, JObject error)
{
if (result != null && error != null)
throw new ArgumentException($"Both {nameof(result)} and {nameof(error)} arguments cannot be non-null.");
- bool resultHasError = String.Compare((result?["result"] as JObject)?["subtype"]?.Value<string>(), "error") == 0;
+ bool resultHasError = string.Compare((result?["result"] as JObject)?["subtype"]?.Value<string>(), "error") == 0;
if (result != null && resultHasError)
{
this.Value = null;
{
public string expression { get; set; }
public string objectGroup { get; set; } = "mono-debugger";
- public bool includeCommandLineAPI { get; set; } = false;
- public bool silent { get; set; } = false;
+ public bool includeCommandLineAPI { get; set; }
+ public bool silent { get; set; }
public bool returnByValue { get; set; } = true;
public MonoCommands(string expression) => this.expression = expression;
public const string EVENT_RAISED = "mono_wasm_debug_event_raised:aef14bca-5519-4dfe-b35a-f867abc123ae";
}
- class Frame
+ internal class Frame
{
public Frame(MethodInfo method, SourceLocation location, int id)
{
public int Id { get; private set; }
}
- class Breakpoint
+ internal class Breakpoint
{
public SourceLocation Location { get; private set; }
public int RemoteId { get; set; }
}
}
- enum BreakpointState
+ internal enum BreakpointState
{
Active,
Disabled,
Pending
}
- enum StepKind
+ internal enum StepKind
{
Into,
Out,
public string DebuggerId { get; set; }
public Dictionary<string, BreakpointRequest> BreakpointRequests { get; } = new Dictionary<string, BreakpointRequest>();
- public TaskCompletionSource<DebugStore> ready = null;
+ public TaskCompletionSource<DebugStore> ready;
public bool IsRuntimeReady => ready != null && ready.Task.IsCompleted;
public int Id { get; set; }
internal DebugStore store;
public TaskCompletionSource<DebugStore> Source { get; } = new TaskCompletionSource<DebugStore>();
- Dictionary<int, PerScopeCache> perScopeCaches { get; } = new Dictionary<int, PerScopeCache>();
+ private Dictionary<int, PerScopeCache> perScopeCaches { get; } = new Dictionary<int, PerScopeCache>();
public DebugStore Store
{
public PerScopeCache GetCacheForScope(int scope_id)
{
- if (perScopeCaches.TryGetValue(scope_id, out var cache))
+ if (perScopeCaches.TryGetValue(scope_id, out PerScopeCache cache))
return cache;
cache = new PerScopeCache();
namespace Microsoft.WebAssembly.Diagnostics
{
- class DevToolsQueue
+ internal class DevToolsQueue
{
- Task current_send;
- List<byte[]> pending;
+ private Task current_send;
+ private List<byte[]> pending;
public WebSocket Ws { get; private set; }
public Task CurrentSend { get { return current_send; } }
internal class DevToolsProxy
{
- TaskCompletionSource<bool> side_exception = new TaskCompletionSource<bool>();
- TaskCompletionSource<bool> client_initiated_close = new TaskCompletionSource<bool>();
- Dictionary<MessageId, TaskCompletionSource<Result>> pending_cmds = new Dictionary<MessageId, TaskCompletionSource<Result>>();
- ClientWebSocket browser;
- WebSocket ide;
- int next_cmd_id;
- List<Task> pending_ops = new List<Task>();
- List<DevToolsQueue> queues = new List<DevToolsQueue>();
+ private TaskCompletionSource<bool> side_exception = new TaskCompletionSource<bool>();
+ private TaskCompletionSource<bool> client_initiated_close = new TaskCompletionSource<bool>();
+ private Dictionary<MessageId, TaskCompletionSource<Result>> pending_cmds = new Dictionary<MessageId, TaskCompletionSource<Result>>();
+ private ClientWebSocket browser;
+ private WebSocket ide;
+ private int next_cmd_id;
+ private List<Task> pending_ops = new List<Task>();
+ private List<DevToolsQueue> queues = new List<DevToolsQueue>();
protected readonly ILogger logger;
return Task.FromResult(false);
}
- async Task<string> ReadOne(WebSocket socket, CancellationToken token)
+ private async Task<string> ReadOne(WebSocket socket, CancellationToken token)
{
byte[] buff = new byte[4000];
var mem = new MemoryStream();
return null;
}
- var result = await socket.ReceiveAsync(new ArraySegment<byte>(buff), token);
+ WebSocketReceiveResult result = await socket.ReceiveAsync(new ArraySegment<byte>(buff), token);
if (result.MessageType == WebSocketMessageType.Close)
{
client_initiated_close.TrySetResult(true);
}
}
- DevToolsQueue GetQueueForSocket(WebSocket ws)
+ private DevToolsQueue GetQueueForSocket(WebSocket ws)
{
return queues.FirstOrDefault(q => q.Ws == ws);
}
- DevToolsQueue GetQueueForTask(Task task)
+ private DevToolsQueue GetQueueForTask(Task task)
{
return queues.FirstOrDefault(q => q.CurrentSend == task);
}
- void Send(WebSocket to, JObject o, CancellationToken token)
+ private void Send(WebSocket to, JObject o, CancellationToken token)
{
- var sender = browser == to ? "Send-browser" : "Send-ide";
+ string sender = browser == to ? "Send-browser" : "Send-ide";
- var method = o["method"]?.ToString();
+ string method = o["method"]?.ToString();
//if (method != "Debugger.scriptParsed" && method != "Runtime.consoleAPICalled")
Log("protocol", $"{sender}: " + JsonConvert.SerializeObject(o));
- var bytes = Encoding.UTF8.GetBytes(o.ToString());
+ byte[] bytes = Encoding.UTF8.GetBytes(o.ToString());
- var queue = GetQueueForSocket(to);
+ DevToolsQueue queue = GetQueueForSocket(to);
- var task = queue.Send(bytes, token);
+ Task task = queue.Send(bytes, token);
if (task != null)
pending_ops.Add(task);
}
- async Task OnEvent(SessionId sessionId, string method, JObject args, CancellationToken token)
+ private async Task OnEvent(SessionId sessionId, string method, JObject args, CancellationToken token)
{
try
{
}
}
- async Task OnCommand(MessageId id, string method, JObject args, CancellationToken token)
+ private async Task OnCommand(MessageId id, string method, JObject args, CancellationToken token)
{
try
{
if (!await AcceptCommand(id, method, args, token))
{
- var res = await SendCommandInternal(id, method, args, token);
+ Result res = await SendCommandInternal(id, method, args, token);
SendResponseInternal(id, res, token);
}
}
}
}
- void OnResponse(MessageId id, Result result)
+ private void OnResponse(MessageId id, Result result)
{
//logger.LogTrace ("got id {0} res {1}", id, result);
// Fixme
- if (pending_cmds.Remove(id, out var task))
+ if (pending_cmds.Remove(id, out TaskCompletionSource<Result> task))
{
task.SetResult(result);
return;
logger.LogError("Cannot respond to command: {id} with result: {result} - command is not pending", id, result);
}
- void ProcessBrowserMessage(string msg, CancellationToken token)
+ private void ProcessBrowserMessage(string msg, CancellationToken token)
{
var res = JObject.Parse(msg);
- var method = res["method"]?.ToString();
+ string method = res["method"]?.ToString();
//if (method != "Debugger.scriptParsed" && method != "Runtime.consoleAPICalled")
Log("protocol", $"browser: {msg}");
OnResponse(new MessageId(res["sessionId"]?.Value<string>(), res["id"].Value<int>()), Result.FromJson(res));
}
- void ProcessIdeMessage(string msg, CancellationToken token)
+ private void ProcessIdeMessage(string msg, CancellationToken token)
{
Log("protocol", $"ide: {msg}");
if (!string.IsNullOrEmpty(msg))
return await SendCommandInternal(id, method, args, token);
}
- Task<Result> SendCommandInternal(SessionId sessionId, string method, JObject args, CancellationToken token)
+ private Task<Result> SendCommandInternal(SessionId sessionId, string method, JObject args, CancellationToken token)
{
int id = Interlocked.Increment(ref next_cmd_id);
SendEventInternal(sessionId, method, args, token);
}
- void SendEventInternal(SessionId sessionId, string method, JObject args, CancellationToken token)
+ private void SendEventInternal(SessionId sessionId, string method, JObject args, CancellationToken token)
{
var o = JObject.FromObject(new
{
SendResponseInternal(id, result, token);
}
- void SendResponseInternal(MessageId id, Result result, CancellationToken token)
+ private void SendResponseInternal(MessageId id, Result result, CancellationToken token)
{
JObject o = result.ToJObject(id);
if (result.IsErr)
{
while (!x.IsCancellationRequested)
{
- var task = await Task.WhenAny(pending_ops.ToArray());
+ Task task = await Task.WhenAny(pending_ops.ToArray());
//logger.LogTrace ("pump {0} {1}", task, pending_ops.IndexOf (task));
if (task == pending_ops[0])
{
- var msg = ((Task<string>)task).Result;
+ string msg = ((Task<string>)task).Result;
if (msg != null)
{
pending_ops[0] = ReadOne(browser, x.Token); //queue next read
}
else if (task == pending_ops[1])
{
- var msg = ((Task<string>)task).Result;
+ string msg = ((Task<string>)task).Result;
if (msg != null)
{
pending_ops[1] = ReadOne(ide, x.Token); //queue next read
}
else if (task == pending_ops[2])
{
- var res = ((Task<bool>)task).Result;
+ bool res = ((Task<bool>)task).Result;
throw new Exception("side task must always complete with an exception, what's going on???");
}
else if (task == pending_ops[3])
{
- var res = ((Task<bool>)task).Result;
+ bool res = ((Task<bool>)task).Result;
Log("verbose", $"DevToolsProxy: Client initiated close from {browserUri}");
x.Cancel();
}
{
//must be a background task
pending_ops.Remove(task);
- var queue = GetQueueForTask(task);
+ DevToolsQueue queue = GetQueueForTask(task);
if (queue != null)
{
- var tsk = queue.Pump(x.Token);
+ Task tsk = queue.Pump(x.Token);
if (tsk != null)
pending_ops.Add(tsk);
}
internal class EvaluateExpression
{
- class FindVariableNMethodCall : CSharpSyntaxWalker
+ private class FindVariableNMethodCall : CSharpSyntaxWalker
{
public List<IdentifierNameSyntax> identifiers = new List<IdentifierNameSyntax>();
public List<InvocationExpressionSyntax> methodCall = new List<InvocationExpressionSyntax>();
public List<MemberAccessExpressionSyntax> memberAccesses = new List<MemberAccessExpressionSyntax>();
- public List<object> argValues = new List<Object>();
+ public List<object> argValues = new List<object>();
public override void Visit(SyntaxNode node)
{
// 1. Replace all this.a occurrences with this_a_ABDE
root = root.ReplaceNodes(memberAccesses, (maes, _) =>
{
- var ma_str = maes.ToString();
- if (!memberAccessToParamName.TryGetValue(ma_str, out var id_name))
+ string ma_str = maes.ToString();
+ if (!memberAccessToParamName.TryGetValue(ma_str, out string id_name))
{
// Generate a random suffix
string suffix = Guid.NewGuid().ToString().Substring(0, 5);
var paramsSet = new HashSet<string>();
// 2. For every unique member ref, add a corresponding method param
- foreach (var (maes, value) in memberAccesses.Zip(ma_values))
+ foreach ((MemberAccessExpressionSyntax maes, JObject value) in memberAccesses.Zip(ma_values))
{
- var node_str = maes.ToString();
- if (!memberAccessToParamName.TryGetValue(node_str, out var id_name))
+ string node_str = maes.ToString();
+ if (!memberAccessToParamName.TryGetValue(node_str, out string id_name))
{
throw new Exception($"BUG: Expected to find an id name for the member access string: {node_str}");
}
root = UpdateWithNewMethodParam(root, id_name, value);
}
- foreach (var (idns, value) in identifiers.Zip(id_values))
+ foreach ((IdentifierNameSyntax idns, JObject value) in identifiers.Zip(id_values))
{
root = UpdateWithNewMethodParam(root, idns.Identifier.Text, value);
}
argValues.Add(ConvertJSToCSharpType(value));
- var updatedMethod = method.AddParameterListParameters(
+ MethodDeclarationSyntax updatedMethod = method.AddParameterListParameters(
SyntaxFactory.Parameter(
SyntaxFactory.Identifier(id_name))
.WithType(SyntaxFactory.ParseTypeName(GetTypeFullName(value))));
private object ConvertJSToCSharpType(JToken variable)
{
- var value = variable["value"];
- var type = variable["type"].Value<string>();
- var subType = variable["subtype"]?.Value<string>();
+ JToken value = variable["value"];
+ string type = variable["type"].Value<string>();
+ string subType = variable["subtype"]?.Value<string>();
switch (type)
{
private string GetTypeFullName(JToken variable)
{
- var type = variable["type"].ToString();
- var subType = variable["subtype"]?.Value<string>();
+ string type = variable["type"].ToString();
+ string subType = variable["subtype"]?.Value<string>();
object value = ConvertJSToCSharpType(variable);
switch (type)
}
}
- static SyntaxNode GetExpressionFromSyntaxTree(SyntaxTree syntaxTree)
+ private static SyntaxNode GetExpressionFromSyntaxTree(SyntaxTree syntaxTree)
{
CompilationUnitSyntax root = syntaxTree.GetCompilationUnitRoot();
ClassDeclarationSyntax classDeclaration = root.Members.ElementAt(0) as ClassDeclarationSyntax;
MemberReferenceResolver resolver, CancellationToken token)
{
var memberAccessValues = new List<JObject>();
- foreach (var maes in member_accesses)
+ foreach (MemberAccessExpressionSyntax maes in member_accesses)
{
- var memberAccessString = maes.ToString();
- var value = await resolver.Resolve(memberAccessString, token);
+ string memberAccessString = maes.ToString();
+ JObject value = await resolver.Resolve(memberAccessString, token);
if (value == null)
throw new ReturnAsErrorException($"Failed to resolve member access for {memberAccessString}", "ReferenceError");
private static async Task<IList<JObject>> ResolveIdentifiers(IEnumerable<IdentifierNameSyntax> identifiers, MemberReferenceResolver resolver, CancellationToken token)
{
var values = new List<JObject>();
- foreach (var var in identifiers)
+ foreach (IdentifierNameSyntax var in identifiers)
{
JObject value = await resolver.Resolve(var.Identifier.Text, token);
if (value == null)
{
return (" + expression + @");
}
- }");
+ }", cancellationToken: token);
- var expressionTree = GetExpressionFromSyntaxTree(syntaxTree);
+ SyntaxNode expressionTree = GetExpressionFromSyntaxTree(syntaxTree);
if (expressionTree == null)
throw new Exception($"BUG: Unable to evaluate {expression}, could not get expression from the syntax tree");
// and the returned expression from GetExpressionFromSyntaxTree is `a`!
if (expressionTree.Kind() == SyntaxKind.IdentifierName || expressionTree.Kind() == SyntaxKind.ThisExpression)
{
- var var_name = expressionTree.ToString();
- var value = await resolver.Resolve(var_name, token);
+ string var_name = expressionTree.ToString();
+ JObject value = await resolver.Resolve(var_name, token);
if (value == null)
throw new ReturnAsErrorException($"Cannot find member named '{var_name}'.", "ReferenceError");
return value;
}
- var memberAccessValues = await ResolveMemberAccessExpressions(findVarNMethodCall.memberAccesses, resolver, token);
+ IList<JObject> memberAccessValues = await ResolveMemberAccessExpressions(findVarNMethodCall.memberAccesses, resolver, token);
// eg. "this.dateTime", " dateTime.TimeOfDay"
if (expressionTree.Kind() == SyntaxKind.SimpleMemberAccessExpression && findVarNMethodCall.memberAccesses.Count == 1)
return memberAccessValues[0];
}
- var identifierValues = await ResolveIdentifiers(findVarNMethodCall.identifiers, resolver, token);
+ IList<JObject> identifierValues = await ResolveIdentifiers(findVarNMethodCall.identifiers, resolver, token);
syntaxTree = findVarNMethodCall.ReplaceVars(syntaxTree, memberAccessValues, identifierValues);
expressionTree = GetExpressionFromSyntaxTree(syntaxTree);
references: references,
options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
- var semanticModel = compilation.GetSemanticModel(syntaxTree);
- var typeInfo = semanticModel.GetTypeInfo(expressionTree);
+ SemanticModel semanticModel = compilation.GetSemanticModel(syntaxTree);
+ CodeAnalysis.TypeInfo typeInfo = semanticModel.GetTypeInfo(expressionTree, cancellationToken: token);
using (var ms = new MemoryStream())
{
- EmitResult result = compilation.Emit(ms);
+ EmitResult result = compilation.Emit(ms, cancellationToken: token);
if (!result.Success)
{
var sb = new StringBuilder();
- foreach (var d in result.Diagnostics)
+ foreach (Diagnostic d in result.Diagnostics)
sb.Append(d.ToString());
throw new ReturnAsErrorException(sb.ToString(), "CompilationError");
Assembly assembly = Assembly.Load(ms.ToArray());
Type type = assembly.GetType("CompileAndRunTheExpression");
- var ret = type.InvokeMember("Evaluate",
+ object ret = type.InvokeMember("Evaluate",
BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public,
null,
null,
}
}
- static readonly HashSet<Type> NumericTypes = new HashSet<Type>
+ private static readonly HashSet<Type> NumericTypes = new HashSet<Type>
{
typeof(decimal), typeof(byte), typeof(sbyte),
typeof(short), typeof(ushort),
typeof(float), typeof(double)
};
- static object ConvertCSharpToJSType(object v, ITypeSymbol type)
+ private static object ConvertCSharpToJSType(object v, ITypeSymbol type)
{
if (v == null)
return new { type = "object", subtype = "null", className = type.ToString() };
}
- class ReturnAsErrorException : Exception
+ internal class ReturnAsErrorException : Exception
{
public Result Error { get; }
public ReturnAsErrorException(JObject error)
private PerScopeCache scopeCache;
private VarInfo[] varIds;
private ILogger logger;
- private bool locals_fetched = false;
+ private bool locals_fetched;
public MemberReferenceResolver(MonoProxy proxy, ExecutionContext ctx, MessageId msg_id, int scope_id, ILogger logger)
{
{
if (scopeCache.Locals.Count == 0 && !locals_fetched)
{
- var scope_res = await proxy.GetScopeProperties(messageId, scopeId, token);
+ Result scope_res = await proxy.GetScopeProperties(messageId, scopeId, token);
if (scope_res.IsErr)
throw new Exception($"BUG: Unable to get properties for scope: {scopeId}. {scope_res}");
locals_fetched = true;
}
- if (scopeCache.Locals.TryGetValue(var_name, out var obj))
+ if (scopeCache.Locals.TryGetValue(var_name, out JObject obj))
{
return obj["value"]?.Value<JObject>();
}
- if (scopeCache.MemberReferences.TryGetValue(var_name, out var ret))
+ if (scopeCache.MemberReferences.TryGetValue(var_name, out JObject ret))
return ret;
if (varIds == null)
{
- var scope = ctx.CallStack.FirstOrDefault(s => s.Id == scopeId);
+ Frame scope = ctx.CallStack.FirstOrDefault(s => s.Id == scopeId);
varIds = scope.Method.GetLiveVarsAt(scope.Location.CliLocation.Offset);
}
- var res = await proxy.SendMonoCommand(messageId, MonoCommands.EvaluateMemberAccess(scopeId, var_name, varIds), token);
+ Result res = await proxy.SendMonoCommand(messageId, MonoCommands.EvaluateMemberAccess(scopeId, var_name, varIds), token);
if (res.IsOk)
{
ret = res.Value?["result"]?["value"]?["value"]?.Value<JObject>();
namespace Microsoft.WebAssembly.Diagnostics
{
-
internal class MonoProxy : DevToolsProxy
{
- IList<string> urlSymbolServerList;
- static HttpClient client = new HttpClient();
- HashSet<SessionId> sessions = new HashSet<SessionId>();
- Dictionary<SessionId, ExecutionContext> contexts = new Dictionary<SessionId, ExecutionContext>();
+ private IList<string> urlSymbolServerList;
+ private static HttpClient client = new HttpClient();
+ private HashSet<SessionId> sessions = new HashSet<SessionId>();
+ private Dictionary<SessionId, ExecutionContext> contexts = new Dictionary<SessionId, ExecutionContext>();
- public MonoProxy(ILoggerFactory loggerFactory, IList<string> urlSymbolServerList, bool hideWebDriver = true) : base(loggerFactory)
- {
+ public MonoProxy(ILoggerFactory loggerFactory, IList<string> urlSymbolServerList, bool hideWebDriver = true) : base(loggerFactory)
+ {
this.hideWebDriver = hideWebDriver;
this.urlSymbolServerList = urlSymbolServerList ?? new List<string>();
}
- readonly bool hideWebDriver;
+ private readonly bool hideWebDriver;
internal ExecutionContext GetContext(SessionId sessionId)
{
- if (contexts.TryGetValue(sessionId, out var context))
+ if (contexts.TryGetValue(sessionId, out ExecutionContext context))
return context;
throw new ArgumentException($"Invalid Session: \"{sessionId}\"", nameof(sessionId));
}
- bool UpdateContext(SessionId sessionId, ExecutionContext executionContext, out ExecutionContext previousExecutionContext)
+ private bool UpdateContext(SessionId sessionId, ExecutionContext executionContext, out ExecutionContext previousExecutionContext)
{
- var previous = contexts.TryGetValue(sessionId, out previousExecutionContext);
+ bool previous = contexts.TryGetValue(sessionId, out previousExecutionContext);
contexts[sessionId] = executionContext;
return previous;
}
{
case "Runtime.consoleAPICalled":
{
- var type = args["type"]?.ToString();
+ string type = args["type"]?.ToString();
if (type == "debug")
{
- var a = args["args"];
+ JToken a = args["args"];
if (a?[0]?["value"]?.ToString() == MonoConstants.RUNTIME_IS_READY &&
a?[1]?["value"]?.ToString() == "fe00e07a-5519-4dfe-b35a-f867dbaf2e28")
{
{
// The optional 3rd argument is the stringified assembly
// list so that we don't have to make more round trips
- var context = GetContext(sessionId);
- var loaded = a?[2]?["value"]?.ToString();
+ ExecutionContext context = GetContext(sessionId);
+ string loaded = a?[2]?["value"]?.ToString();
if (loaded != null)
context.LoadedFiles = JToken.Parse(loaded).ToObject<string[]>();
}
case "Runtime.executionContextCreated":
{
SendEvent(sessionId, method, args, token);
- var ctx = args?["context"];
+ JToken ctx = args?["context"];
var aux_data = ctx?["auxData"] as JObject;
- var id = ctx["id"].Value<int>();
+ int id = ctx["id"].Value<int>();
if (aux_data != null)
{
- var is_default = aux_data["isDefault"]?.Value<bool>();
+ bool? is_default = aux_data["isDefault"]?.Value<bool>();
if (is_default == true)
{
await OnDefaultContext(sessionId, new ExecutionContext { Id = id, AuxData = aux_data }, token);
case "Debugger.paused":
{
//TODO figure out how to stich out more frames and, in particular what happens when real wasm is on the stack
- var top_func = args?["callFrames"]?[0]?["functionName"]?.Value<string>();
+ string top_func = args?["callFrames"]?[0]?["functionName"]?.Value<string>();
if (top_func == "mono_wasm_fire_bp" || top_func == "_mono_wasm_fire_bp" || top_func == "_mono_wasm_fire_exception")
{
case "Debugger.scriptParsed":
{
- var url = args?["url"]?.Value<string>() ?? "";
+ string url = args?["url"]?.Value<string>() ?? "";
switch (url)
{
return false;
}
- async Task<bool> IsRuntimeAlreadyReadyAlready(SessionId sessionId, CancellationToken token)
+ private async Task<bool> IsRuntimeAlreadyReadyAlready(SessionId sessionId, CancellationToken token)
{
- if (contexts.TryGetValue(sessionId, out var context) && context.IsRuntimeReady)
+ if (contexts.TryGetValue(sessionId, out ExecutionContext context) && context.IsRuntimeReady)
return true;
- var res = await SendMonoCommand(sessionId, MonoCommands.IsRuntimeReady(), token);
+ Result res = await SendMonoCommand(sessionId, MonoCommands.IsRuntimeReady(), token);
return res.Value?["result"]?["value"]?.Value<bool>() ?? false;
}
if (hideWebDriver && id == SessionId.Null)
await DeleteWebDriver(id, token);
- if (!contexts.TryGetValue(id, out var context))
+ if (!contexts.TryGetValue(id, out ExecutionContext context))
return false;
switch (method)
{
case "Target.attachToTarget":
{
- var resp = await SendCommand(id, method, args, token);
+ Result resp = await SendCommand(id, method, args, token);
await DeleteWebDriver(new SessionId(resp.Value["sessionId"]?.ToString()), token);
break;
}
case "Debugger.enable":
{
- var resp = await SendCommand(id, method, args, token);
+ Result resp = await SendCommand(id, method, args, token);
context.DebuggerId = resp.Value["debuggerId"]?.ToString();
case "Debugger.getScriptSource":
{
- var script = args?["scriptId"]?.Value<string>();
+ string script = args?["scriptId"]?.Value<string>();
return await OnGetScriptSource(id, script, token);
}
case "Runtime.compileScript":
{
- var exp = args?["expression"]?.Value<string>();
+ string exp = args?["expression"]?.Value<string>();
if (exp.StartsWith("//dotnet:", StringComparison.Ordinal))
{
OnCompileDotnetScript(id, token);
case "Debugger.getPossibleBreakpoints":
{
- var resp = await SendCommand(id, method, args, token);
+ Result resp = await SendCommand(id, method, args, token);
if (resp.IsOk && resp.Value["locations"].HasValues)
{
SendResponse(id, resp, token);
case "Debugger.setBreakpointByUrl":
{
- var resp = await SendCommand(id, method, args, token);
+ Result resp = await SendCommand(id, method, args, token);
if (!resp.IsOk)
{
SendResponse(id, resp, token);
return true;
}
- var bpid = resp.Value["breakpointId"]?.ToString();
- var locations = resp.Value["locations"]?.Values<object>();
+ string bpid = resp.Value["breakpointId"]?.ToString();
+ IEnumerable<object> locations = resp.Value["locations"]?.Values<object>();
var request = BreakpointRequest.Parse(bpid, args);
// is the store done loading?
- var loaded = context.Source.Task.IsCompleted;
+ bool loaded = context.Source.Task.IsCompleted;
if (!loaded)
{
// Send and empty response immediately if not
if (await IsRuntimeAlreadyReadyAlready(id, token))
{
- var store = await RuntimeReady(id, token);
+ DebugStore store = await RuntimeReady(id, token);
Log("verbose", $"BP req {args}");
await SetBreakpoint(id, store, request, !loaded, token);
case "Debugger.evaluateOnCallFrame":
{
- if (!DotnetObjectId.TryParse(args?["callFrameId"], out var objectId))
+ if (!DotnetObjectId.TryParse(args?["callFrameId"], out DotnetObjectId objectId))
return false;
switch (objectId.Scheme)
case "Runtime.getProperties":
{
- if (!DotnetObjectId.TryParse(args?["objectId"], out var objectId))
+ if (!DotnetObjectId.TryParse(args?["objectId"], out DotnetObjectId objectId))
break;
- var result = await RuntimeGetProperties(id, objectId, args, token);
+ Result result = await RuntimeGetProperties(id, objectId, args, token);
SendResponse(id, result, token);
return true;
}
case "Runtime.releaseObject":
{
- if (!(DotnetObjectId.TryParse(args["objectId"], out var objectId) && objectId.Scheme == "cfo_res"))
+ if (!(DotnetObjectId.TryParse(args["objectId"], out DotnetObjectId objectId) && objectId.Scheme == "cfo_res"))
break;
await SendMonoCommand(id, MonoCommands.ReleaseObject(objectId), token);
case "DotnetDebugger.addSymbolServerUrl":
{
string url = args["url"]?.Value<string>();
- if (!String.IsNullOrEmpty(url) && !urlSymbolServerList.Contains(url))
+ if (!string.IsNullOrEmpty(url) && !urlSymbolServerList.Contains(url))
urlSymbolServerList.Add(url);
return true;
}
{
Console.WriteLine("set-breakpoint-by-method: " + id + " " + args);
- var store = await RuntimeReady(id, token);
+ DebugStore store = await RuntimeReady(id, token);
string aname = args["assemblyName"]?.Value<string>();
string typeName = args["typeName"]?.Value<string>();
string methodName = args["methodName"]?.Value<string>();
}
// GetAssemblyByName seems to work on file names
- var assembly = store.GetAssemblyByName(aname);
+ AssemblyInfo assembly = store.GetAssemblyByName(aname);
if (assembly == null)
assembly = store.GetAssemblyByName(aname + ".exe");
if (assembly == null)
return true;
}
- var type = assembly.GetTypeByName(typeName);
+ TypeInfo type = assembly.GetTypeByName(typeName);
if (type == null)
{
SendResponse(id, Result.Err($"Type '{typeName}' not found."), token);
return true;
}
- var methodInfo = type.Methods.FirstOrDefault(m => m.Name == methodName);
+ MethodInfo methodInfo = type.Methods.FirstOrDefault(m => m.Name == methodName);
if (methodInfo == null)
{
// Maybe this is an async method, in which case the debug info is attached
return true;
}
- var src_url = methodInfo.Assembly.Sources.Single(sf => sf.SourceId == methodInfo.SourceId).Url;
+ string src_url = methodInfo.Assembly.Sources.Single(sf => sf.SourceId == methodInfo.SourceId).Url;
SendResponse(id, Result.OkFromObject(new
{
result = new { line = methodInfo.StartLocation.Line, column = methodInfo.StartLocation.Column, url = src_url }
}
case "Runtime.callFunctionOn":
{
- if (!DotnetObjectId.TryParse(args["objectId"], out var objectId))
+ if (!DotnetObjectId.TryParse(args["objectId"], out DotnetObjectId objectId))
return false;
if (objectId.Scheme == "scope")
return true;
}
- var res = await SendMonoCommand(id, MonoCommands.CallFunctionOn(args), token);
- var res_value_type = res.Value?["result"]?["value"]?.Type;
+ Result res = await SendMonoCommand(id, MonoCommands.CallFunctionOn(args), token);
+ JTokenType? res_value_type = res.Value?["result"]?["value"]?.Type;
if (res.IsOk && res_value_type == JTokenType.Object || res_value_type == JTokenType.Object)
res = Result.OkFromObject(new { result = res.Value["result"]["value"] });
return false;
}
- async Task<Result> RuntimeGetProperties(MessageId id, DotnetObjectId objectId, JToken args, CancellationToken token)
+ private async Task<Result> RuntimeGetProperties(MessageId id, DotnetObjectId objectId, JToken args, CancellationToken token)
{
if (objectId.Scheme == "scope")
{
return await GetScopeProperties(id, int.Parse(objectId.Value), token);
}
- var res = await SendMonoCommand(id, MonoCommands.GetDetails(objectId, args), token);
+ Result res = await SendMonoCommand(id, MonoCommands.GetDetails(objectId, args), token);
if (res.IsErr)
return res;
if (objectId.Scheme == "cfo_res")
{
// Runtime.callFunctionOn result object
- var value_json_str = res.Value["result"]?["value"]?["__value_as_json_string__"]?.Value<string>();
+ string value_json_str = res.Value["result"]?["value"]?["__value_as_json_string__"]?.Value<string>();
if (value_json_str != null)
{
res = Result.OkFromObject(new
return res;
}
- async Task<bool> OnPause(SessionId sessionId, JObject args, CancellationToken token)
+ private async Task<bool> OnPause(SessionId sessionId, JObject args, CancellationToken token)
{
//FIXME we should send release objects every now and then? Or intercept those we inject and deal in the runtime
- var res = await SendMonoCommand(sessionId, MonoCommands.GetCallStack(), token);
- var orig_callframes = args?["callFrames"]?.Values<JObject>();
- var context = GetContext(sessionId);
+ Result res = await SendMonoCommand(sessionId, MonoCommands.GetCallStack(), token);
+ IEnumerable<JObject> orig_callframes = args?["callFrames"]?.Values<JObject>();
+ ExecutionContext context = GetContext(sessionId);
JObject data = null;
- var reason = "other";//other means breakpoint
+ string reason = "other";//other means breakpoint
if (res.IsErr)
{
}
//step one, figure out where did we hit
- var res_value = res.Value?["result"]?["value"];
+ JToken res_value = res.Value?["result"]?["value"];
if (res_value == null || res_value is JValue)
{
//Give up and send the original call stack
}
Log("verbose", $"call stack (err is {res.Error} value is:\n{res.Value}");
- var bp_id = res_value?["breakpoint_id"]?.Value<int>();
+ int? bp_id = res_value?["breakpoint_id"]?.Value<int>();
Log("verbose", $"We just hit bp {bp_id}");
if (!bp_id.HasValue)
{
return false;
}
- var bp = context.BreakpointRequests.Values.SelectMany(v => v.Locations).FirstOrDefault(b => b.RemoteId == bp_id.Value);
+ Breakpoint bp = context.BreakpointRequests.Values.SelectMany(v => v.Locations).FirstOrDefault(b => b.RemoteId == bp_id.Value);
var callFrames = new List<object>();
- foreach (var frame in orig_callframes)
+ foreach (JObject frame in orig_callframes)
{
- var function_name = frame["functionName"]?.Value<string>();
- var url = frame["url"]?.Value<string>();
+ string function_name = frame["functionName"]?.Value<string>();
+ string url = frame["url"]?.Value<string>();
if ("mono_wasm_fire_bp" == function_name || "_mono_wasm_fire_bp" == function_name ||
"_mono_wasm_fire_exception" == function_name)
{
if ("_mono_wasm_fire_exception" == function_name)
{
- var exception_obj_id = await SendMonoCommand(sessionId, MonoCommands.GetExceptionObject(), token);
- var res_val = exception_obj_id.Value?["result"]?["value"];
+ Result exception_obj_id = await SendMonoCommand(sessionId, MonoCommands.GetExceptionObject(), token);
+ JToken res_val = exception_obj_id.Value?["result"]?["value"];
var exception_dotnet_obj_id = new DotnetObjectId("object", res_val?["exception_id"]?.Value<string>());
data = JObject.FromObject(new
{
}
var frames = new List<Frame>();
- var the_mono_frames = res.Value?["result"]?["value"]?["frames"]?.Values<JObject>();
+ IEnumerable<JObject> the_mono_frames = res.Value?["result"]?["value"]?["frames"]?.Values<JObject>();
- foreach (var mono_frame in the_mono_frames)
+ foreach (JObject mono_frame in the_mono_frames)
{
int frame_id = mono_frame["frame_id"].Value<int>();
- var il_pos = mono_frame["il_pos"].Value<int>();
- var method_token = mono_frame["method_token"].Value<uint>();
- var assembly_name = mono_frame["assembly_name"].Value<string>();
+ int il_pos = mono_frame["il_pos"].Value<int>();
+ uint method_token = mono_frame["method_token"].Value<uint>();
+ string assembly_name = mono_frame["assembly_name"].Value<string>();
// This can be different than `method.Name`, like in case of generic methods
- var method_name = mono_frame["method_name"]?.Value<string>();
+ string method_name = mono_frame["method_name"]?.Value<string>();
- var store = await LoadStore(sessionId, token);
- var asm = store.GetAssemblyByName(assembly_name);
+ DebugStore store = await LoadStore(sessionId, token);
+ AssemblyInfo asm = store.GetAssemblyByName(assembly_name);
if (asm == null)
{
Log("debug", $"Unable to find assembly: {assembly_name}");
continue;
}
- var method = asm.GetMethodByToken(method_token);
+ MethodInfo method = asm.GetMethodByToken(method_token);
if (method == null && !asm.Image.HasSymbols)
{
continue;
}
- var location = method?.GetLocationByIl(il_pos);
+ SourceLocation location = method?.GetLocationByIl(il_pos);
// When hitting a breakpoint on the "IncrementCount" method in the standard
// Blazor project template, one of the stack frames is inside mscorlib.dll
}
}
- var bp_list = new string[bp == null ? 0 : 1];
+ string[] bp_list = new string[bp == null ? 0 : 1];
if (bp != null)
bp_list[0] = bp.StackId;
return true;
}
- async Task<MethodInfo> LoadSymbolsOnDemand(AssemblyInfo asm, uint method_token, SessionId sessionId, CancellationToken token)
+ private async Task<MethodInfo> LoadSymbolsOnDemand(AssemblyInfo asm, uint method_token, SessionId sessionId, CancellationToken token)
{
- var context = GetContext(sessionId);
+ ExecutionContext context = GetContext(sessionId);
if (asm.TriedToLoadSymbolsOnDemand)
return null;
asm.TriedToLoadSymbolsOnDemand = true;
ImageDebugHeader header = asm.Image.GetDebugHeader();
- for (var i = 0; i < header.Entries.Length; i++)
+ for (int i = 0; i < header.Entries.Length; i++)
{
- var entry = header.Entries[i];
+ ImageDebugHeaderEntry entry = header.Entries[i];
if (entry.Directory.Type != ImageDebugType.CodeView)
{
continue;
}
- var data = entry.Data;
+ byte[] data = entry.Data;
if (data.Length < 24)
return null;
- var pdbSignature = (data[0]
+ int pdbSignature = (data[0]
| (data[1] << 8)
| (data[2] << 16)
| (data[3] << 24));
if (pdbSignature != 0x53445352) // "SDSR" mono/metadata/debug-mono-ppdb.c#L101
return null;
- var buffer = new byte[16];
+ byte[] buffer = new byte[16];
Buffer.BlockCopy(data, 4, buffer, 0, 16);
- var pdbAge = (data[20]
+ int pdbAge = (data[20]
| (data[21] << 8)
| (data[22] << 16)
| (data[23] << 24));
var pdbGuid = new Guid(buffer);
- var buffer2 = new byte[(data.Length - 24) - 1];
+ byte[] buffer2 = new byte[(data.Length - 24) - 1];
Buffer.BlockCopy(data, 24, buffer2, 0, (data.Length - 24) - 1);
- var pdbName = System.Text.Encoding.UTF8.GetString(buffer2, 0, buffer2.Length);
+ string pdbName = System.Text.Encoding.UTF8.GetString(buffer2, 0, buffer2.Length);
pdbName = Path.GetFileName(pdbName);
- foreach (var urlSymbolServer in urlSymbolServerList)
+ foreach (string urlSymbolServer in urlSymbolServerList)
{
- var downloadURL = $"{urlSymbolServer}/{pdbName}/{pdbGuid.ToString("N").ToUpper() + pdbAge}/{pdbName}";
+ string downloadURL = $"{urlSymbolServer}/{pdbName}/{pdbGuid.ToString("N").ToUpper() + pdbAge}/{pdbName}";
try
{
- using HttpResponseMessage response = await client.GetAsync(downloadURL);
- using Stream streamToReadFrom = await response.Content.ReadAsStreamAsync();
+ using HttpResponseMessage response = await client.GetAsync(downloadURL, token);
+ using Stream streamToReadFrom = await response.Content.ReadAsStreamAsync(token);
var portablePdbReaderProvider = new PdbReaderProvider();
- var symbolReader = portablePdbReaderProvider.GetSymbolReader(asm.Image, streamToReadFrom);
+ ISymbolReader symbolReader = portablePdbReaderProvider.GetSymbolReader(asm.Image, streamToReadFrom);
asm.ClearDebugInfo(); //workaround while cecil PR #686 is not merged
asm.Image.ReadSymbols(symbolReader);
asm.Populate();
- foreach (var source in asm.Sources)
+ foreach (SourceFile source in asm.Sources)
{
var scriptSource = JObject.FromObject(source.ToScriptSource(context.Id, context.AuxData));
SendEvent(sessionId, "Debugger.scriptParsed", scriptSource, token);
Log("info", "Unable to load symbols on demand assembly: {asm.Name}");
return null;
}
-
- async Task OnDefaultContext(SessionId sessionId, ExecutionContext context, CancellationToken token)
+
+ private async Task OnDefaultContext(SessionId sessionId, ExecutionContext context, CancellationToken token)
{
Log("verbose", "Default context created, clearing state and sending events");
- if (UpdateContext(sessionId, context, out var previousContext))
+ if (UpdateContext(sessionId, context, out ExecutionContext previousContext))
{
- foreach (var kvp in previousContext.BreakpointRequests)
+ foreach (KeyValuePair<string, BreakpointRequest> kvp in previousContext.BreakpointRequests)
{
context.BreakpointRequests[kvp.Key] = kvp.Value.Clone();
}
await RuntimeReady(sessionId, token);
}
- async Task OnResume(MessageId msg_id, CancellationToken token)
+ private async Task OnResume(MessageId msg_id, CancellationToken token)
{
- var ctx = GetContext(msg_id);
+ ExecutionContext ctx = GetContext(msg_id);
if (ctx.CallStack != null)
{
// Stopped on managed code
GetContext(msg_id).ClearState();
}
- async Task<bool> Step(MessageId msg_id, StepKind kind, CancellationToken token)
+ private async Task<bool> Step(MessageId msg_id, StepKind kind, CancellationToken token)
{
- var context = GetContext(msg_id);
+ ExecutionContext context = GetContext(msg_id);
if (context.CallStack == null)
return false;
if (context.CallStack.Count <= 1 && kind == StepKind.Out)
return false;
- var res = await SendMonoCommand(msg_id, MonoCommands.StartSingleStepping(kind), token);
+ Result res = await SendMonoCommand(msg_id, MonoCommands.StartSingleStepping(kind), token);
- var ret_code = res.Value?["result"]?["value"]?.Value<int>();
+ int? ret_code = res.Value?["result"]?["value"]?.Value<int>();
if (ret_code.HasValue && ret_code.Value == 0)
{
return true;
}
- async Task<bool> OnJSEventRaised(SessionId sessionId, JObject eventArgs, CancellationToken token)
+ private async Task<bool> OnJSEventRaised(SessionId sessionId, JObject eventArgs, CancellationToken token)
{
string eventName = eventArgs?["eventName"]?.Value<string>();
if (string.IsNullOrEmpty(eventName))
}
}
- async Task<bool> OnEvaluateOnCallFrame(MessageId msg_id, int scope_id, string expression, CancellationToken token)
+ private async Task<bool> OnEvaluateOnCallFrame(MessageId msg_id, int scope_id, string expression, CancellationToken token)
{
try
{
- var context = GetContext(msg_id);
+ ExecutionContext context = GetContext(msg_id);
if (context.CallStack == null)
return false;
{
try
{
- var ctx = GetContext(msg_id);
- var scope = ctx.CallStack.FirstOrDefault(s => s.Id == scope_id);
+ ExecutionContext ctx = GetContext(msg_id);
+ Frame scope = ctx.CallStack.FirstOrDefault(s => s.Id == scope_id);
if (scope == null)
return Result.Err(JObject.FromObject(new { message = $"Could not find scope with id #{scope_id}" }));
- var var_ids = scope.Method.GetLiveVarsAt(scope.Location.CliLocation.Offset);
- var res = await SendMonoCommand(msg_id, MonoCommands.GetScopeVariables(scope.Id, var_ids), token);
+ VarInfo[] var_ids = scope.Method.GetLiveVarsAt(scope.Location.CliLocation.Offset);
+ Result res = await SendMonoCommand(msg_id, MonoCommands.GetScopeVariables(scope.Id, var_ids), token);
//if we fail we just buble that to the IDE (and let it panic over it)
if (res.IsErr)
return res;
- var values = res.Value?["result"]?["value"]?.Values<JObject>().ToArray();
+ JObject[] values = res.Value?["result"]?["value"]?.Values<JObject>().ToArray();
if (values == null || values.Length == 0)
return Result.OkFromObject(new { result = Array.Empty<object>() });
- var frameCache = ctx.GetCacheForScope(scope_id);
- foreach (var value in values)
+ PerScopeCache frameCache = ctx.GetCacheForScope(scope_id);
+ foreach (JObject value in values)
{
frameCache.Locals[value["name"]?.Value<string>()] = value;
}
}
}
- async Task<Breakpoint> SetMonoBreakpoint(SessionId sessionId, string reqId, SourceLocation location, CancellationToken token)
+ private async Task<Breakpoint> SetMonoBreakpoint(SessionId sessionId, string reqId, SourceLocation location, CancellationToken token)
{
var bp = new Breakpoint(reqId, location, BreakpointState.Pending);
- var asm_name = bp.Location.CliLocation.Method.Assembly.Name;
- var method_token = bp.Location.CliLocation.Method.Token;
- var il_offset = bp.Location.CliLocation.Offset;
+ string asm_name = bp.Location.CliLocation.Method.Assembly.Name;
+ uint method_token = bp.Location.CliLocation.Method.Token;
+ int il_offset = bp.Location.CliLocation.Offset;
- var res = await SendMonoCommand(sessionId, MonoCommands.SetBreakpoint(asm_name, method_token, il_offset), token);
- var ret_code = res.Value?["result"]?["value"]?.Value<int>();
+ Result res = await SendMonoCommand(sessionId, MonoCommands.SetBreakpoint(asm_name, method_token, il_offset), token);
+ int? ret_code = res.Value?["result"]?["value"]?.Value<int>();
if (ret_code.HasValue)
{
return bp;
}
- async Task<DebugStore> LoadStore(SessionId sessionId, CancellationToken token)
+ private async Task<DebugStore> LoadStore(SessionId sessionId, CancellationToken token)
{
- var context = GetContext(sessionId);
+ ExecutionContext context = GetContext(sessionId);
if (Interlocked.CompareExchange(ref context.store, new DebugStore(logger), null) != null)
return await context.Source.Task;
try
{
- var loaded_files = context.LoadedFiles;
+ string[] loaded_files = context.LoadedFiles;
if (loaded_files == null)
{
- var loaded = await SendMonoCommand(sessionId, MonoCommands.GetLoadedFiles(), token);
+ Result loaded = await SendMonoCommand(sessionId, MonoCommands.GetLoadedFiles(), token);
loaded_files = loaded.Value?["result"]?["value"]?.ToObject<string[]>();
}
await
- foreach (var source in context.store.Load(sessionId, loaded_files, token).WithCancellation(token))
+ foreach (SourceFile source in context.store.Load(sessionId, loaded_files, token).WithCancellation(token))
{
var scriptSource = JObject.FromObject(source.ToScriptSource(context.Id, context.AuxData));
Log("verbose", $"\tsending {source.Url} {context.Id} {sessionId.sessionId}");
SendEvent(sessionId, "Debugger.scriptParsed", scriptSource, token);
- foreach (var req in context.BreakpointRequests.Values)
+ foreach (BreakpointRequest req in context.BreakpointRequests.Values)
{
if (req.TryResolve(source))
{
return context.store;
}
- async Task<DebugStore> RuntimeReady(SessionId sessionId, CancellationToken token)
+ private async Task<DebugStore> RuntimeReady(SessionId sessionId, CancellationToken token)
{
- var context = GetContext(sessionId);
+ ExecutionContext context = GetContext(sessionId);
if (Interlocked.CompareExchange(ref context.ready, new TaskCompletionSource<DebugStore>(), null) != null)
return await context.ready.Task;
- var clear_result = await SendMonoCommand(sessionId, MonoCommands.ClearAllBreakpoints(), token);
+ Result clear_result = await SendMonoCommand(sessionId, MonoCommands.ClearAllBreakpoints(), token);
if (clear_result.IsErr)
{
Log("verbose", $"Failed to clear breakpoints due to {clear_result}");
}
- var store = await LoadStore(sessionId, token);
+ DebugStore store = await LoadStore(sessionId, token);
context.ready.SetResult(store);
SendEvent(sessionId, "Mono.runtimeReady", new JObject(), token);
return store;
}
- async Task RemoveBreakpoint(MessageId msg_id, JObject args, CancellationToken token)
+ private async Task RemoveBreakpoint(MessageId msg_id, JObject args, CancellationToken token)
{
- var bpid = args?["breakpointId"]?.Value<string>();
+ string bpid = args?["breakpointId"]?.Value<string>();
- var context = GetContext(msg_id);
- if (!context.BreakpointRequests.TryGetValue(bpid, out var breakpointRequest))
+ ExecutionContext context = GetContext(msg_id);
+ if (!context.BreakpointRequests.TryGetValue(bpid, out BreakpointRequest breakpointRequest))
return;
- foreach (var bp in breakpointRequest.Locations)
+ foreach (Breakpoint bp in breakpointRequest.Locations)
{
- var res = await SendMonoCommand(msg_id, MonoCommands.RemoveBreakpoint(bp.RemoteId), token);
- var ret_code = res.Value?["result"]?["value"]?.Value<int>();
+ Result res = await SendMonoCommand(msg_id, MonoCommands.RemoveBreakpoint(bp.RemoteId), token);
+ int? ret_code = res.Value?["result"]?["value"]?.Value<int>();
if (ret_code.HasValue)
{
context.BreakpointRequests.Remove(bpid);
}
- async Task SetBreakpoint(SessionId sessionId, DebugStore store, BreakpointRequest req, bool sendResolvedEvent, CancellationToken token)
+ private async Task SetBreakpoint(SessionId sessionId, DebugStore store, BreakpointRequest req, bool sendResolvedEvent, CancellationToken token)
{
- var context = GetContext(sessionId);
+ ExecutionContext context = GetContext(sessionId);
if (req.Locations.Any())
{
Log("debug", $"locations already loaded for {req.Id}");
var comparer = new SourceLocation.LocationComparer();
// if column is specified the frontend wants the exact matches
// and will clear the bp if it isn't close enoug
- var locations = store.FindBreakpointLocations(req)
+ IEnumerable<IGrouping<SourceId, SourceLocation>> locations = store.FindBreakpointLocations(req)
.Distinct(comparer)
.Where(l => l.Line == req.Line && (req.Column == 0 || l.Column == req.Column))
.OrderBy(l => l.Column)
var breakpoints = new List<Breakpoint>();
- foreach (var sourceId in locations)
+ foreach (IGrouping<SourceId, SourceLocation> sourceId in locations)
{
- var loc = sourceId.First();
- var bp = await SetMonoBreakpoint(sessionId, req.Id, loc, token);
+ SourceLocation loc = sourceId.First();
+ Breakpoint bp = await SetMonoBreakpoint(sessionId, req.Id, loc, token);
// If we didn't successfully enable the breakpoint
// don't add it to the list of locations for this id
return;
}
- async Task<bool> GetPossibleBreakpoints(MessageId msg, SourceLocation start, SourceLocation end, CancellationToken token)
+ private async Task<bool> GetPossibleBreakpoints(MessageId msg, SourceLocation start, SourceLocation end, CancellationToken token)
{
- var bps = (await RuntimeReady(msg, token)).FindPossibleBreakpoints(start, end);
+ List<SourceLocation> bps = (await RuntimeReady(msg, token)).FindPossibleBreakpoints(start, end);
if (bps == null)
return false;
return true;
}
- void OnCompileDotnetScript(MessageId msg_id, CancellationToken token)
+ private void OnCompileDotnetScript(MessageId msg_id, CancellationToken token)
{
SendResponse(msg_id, Result.OkFromObject(new { }), token);
}
- async Task<bool> OnGetScriptSource(MessageId msg_id, string script_id, CancellationToken token)
+ private async Task<bool> OnGetScriptSource(MessageId msg_id, string script_id, CancellationToken token)
{
- if (!SourceId.TryParse(script_id, out var id))
+ if (!SourceId.TryParse(script_id, out SourceId id))
return false;
- var src_file = (await LoadStore(msg_id, token)).GetFileById(id);
+ SourceFile src_file = (await LoadStore(msg_id, token)).GetFileById(id);
try
{
var uri = new Uri(src_file.Url);
string source = $"// Unable to find document {src_file.SourceUri}";
- using (var data = await src_file.GetSourceAsync(checkHash: false, token: token))
+ using (Stream data = await src_file.GetSourceAsync(checkHash: false, token: token))
{
if (data.Length == 0)
return false;
return true;
}
- async Task DeleteWebDriver(SessionId sessionId, CancellationToken token)
+ private async Task DeleteWebDriver(SessionId sessionId, CancellationToken token)
{
// see https://github.com/mono/mono/issues/19549 for background
if (hideWebDriver && sessions.Add(sessionId))
{
- var res = await SendCommand(sessionId,
+ Result res = await SendCommand(sessionId,
"Page.addScriptToEvaluateOnNewDocument",
JObject.FromObject(new { source = "delete navigator.constructor.prototype.webdriver" }),
token);
}
}
- bool JObjectTryParse(string str, out JObject obj, bool log_exception = true)
+ private bool JObjectTryParse(string str, out JObject obj, bool log_exception = true)
{
obj = null;
if (string.IsNullOrEmpty(str))
<PropertyGroup>
<TargetFramework>$(NetCoreAppCurrent)</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <RunAnalyzers>false</RunAnalyzers>
</PropertyGroup>
<ItemGroup>
<OutputType>Library</OutputType>
<NoWarn>219</NoWarn>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <RunAnalyzers>false</RunAnalyzers>
<DebugType>portable</DebugType>
</PropertyGroup>
<ProjectAssetsFile>$(RepoRoot)src\tests\Common\Coreclr.TestWrapper\obj\project.assets.json</ProjectAssetsFile>
<NuGetTargetMoniker>$(NetCoreAppCurrentTargetFrameworkMoniker)</NuGetTargetMoniker>
<NuGetTargetMonikerShort>$(NetCoreAppCurrent)</NuGetTargetMonikerShort>
+ <RunAnalyzers>false</RunAnalyzers>
</PropertyGroup>
<ItemGroup>
<AddAdditionalExplicitAssemblyReferences>false</AddAdditionalExplicitAssemblyReferences>
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
<!-- Disable some C# warnings for the tests. -->
- <NoWarn>78,162,164,168,169,219,251,252,414,429,642,649,652,675,1691,1717,1718,3001,3002,3003,3005,3008</NoWarn>
+ <NoWarn>78,162,164,168,169,219,251,252,414,429,618,642,649,652,659,675,1691,1717,1718,3001,3002,3003,3005,3008,SYSLIB0004,SYSLIB0011,SYSLIB0012</NoWarn>
+ <RunAnalyzers>false</RunAnalyzers>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<SkipSigning Condition="'$(CrossGen)' == 'true'">true</SkipSigning>
<AssemblyKey>Test</AssemblyKey>
<PropertyGroup>
<OutputPath>$(XUnitTestBinBase)\$(CategoryWithSlash)</OutputPath>
<RuntimeFrameworkVersion Condition="'$(__SkipFXRestore)' != 'true'">$(MicrosoftNETCoreAppVersion)</RuntimeFrameworkVersion>
+ <RunAnalyzers>false</RunAnalyzers>
</PropertyGroup>
<Import Sdk="Microsoft.NET.Sdk" Project="Sdk.props" />
<TargetFrameworks Condition="'$(OS)' == 'Windows_NT'">$(TargetFrameworks);net461</TargetFrameworks>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<IsShipping>false</IsShipping>
+ <RunAnalyzers>false</RunAnalyzers>
</PropertyGroup>
<ItemGroup>
public string? OutputDir { get; set; }
public string? AndroidSdk { get; set; }
-
+
public string? AndroidNdk { get; set; }
-
+
public string? MinApiLevel { get; set; }
-
+
public string? BuildApiLevel { get; set; }
-
+
public string? BuildToolsVersion { get; set; }
public bool StripDebugSymbols { get; set; }
[Output]
public string ApkBundlePath { get; set; } = ""!;
-
+
[Output]
public string ApkPackageId { get; set; } = ""!;
apkBuilder.BuildToolsVersion = BuildToolsVersion;
apkBuilder.StripDebugSymbols = StripDebugSymbols;
(ApkBundlePath, ApkPackageId) = apkBuilder.BuildApk(SourceDir, Abi, MainLibraryFileName, MonoRuntimeHeaders);
-
+
return true;
}
}
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<Nullable>enable</Nullable>
+ <NoWarn>$(NoWarn),CA1050</NoWarn>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Templates\*.*" />
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
using System;
using System.Collections.Generic;
using System.IO;
// make sure BuildApiLevel >= MinApiLevel
// only if these api levels are not "preview" (not integers)
- if (int.TryParse(BuildApiLevel, out int intApi) &&
- int.TryParse(MinApiLevel, out int intMinApi) &&
+ if (int.TryParse(BuildApiLevel, out int intApi) &&
+ int.TryParse(MinApiLevel, out int intMinApi) &&
intApi < intMinApi)
{
throw new ArgumentException($"BuildApiLevel={BuildApiLevel} <= MinApiLevel={MinApiLevel}. " +
Directory.CreateDirectory(Path.Combine(OutputDir, "obj"));
Directory.CreateDirectory(Path.Combine(OutputDir, "assets-tozip"));
Directory.CreateDirectory(Path.Combine(OutputDir, "assets"));
-
+
var extensionsToIgnore = new List<string> { ".so", ".a", ".gz" };
if (StripDebugSymbols)
{
Utils.RunProcess(zip, workingDir: Path.Combine(OutputDir, "assets-tozip"), args: "-q -r ../assets/assets.zip .");
Directory.Delete(Path.Combine(OutputDir, "assets-tozip"), true);
-
+
if (!File.Exists(androidJar))
throw new ArgumentException($"API level={BuildApiLevel} is not downloaded in Android SDK");
.Replace("%EntryPointLibName%", Path.GetFileName(entryPointLib)
.Replace("%RID%", GetRid(abi)));
File.WriteAllText(Path.Combine(OutputDir, "monodroid.c"), monodroidSrc);
-
- string cmakeGenArgs = $"-DCMAKE_TOOLCHAIN_FILE={androidToolchain} -DANDROID_ABI=\"{abi}\" -DANDROID_STL=none " +
+
+ string cmakeGenArgs = $"-DCMAKE_TOOLCHAIN_FILE={androidToolchain} -DANDROID_ABI=\"{abi}\" -DANDROID_STL=none " +
$"-DANDROID_NATIVE_API_LEVEL={MinApiLevel} -B monodroid";
string cmakeBuildArgs = "--build monodroid";
-
+
if (StripDebugSymbols)
{
// Use "-s" to strip debug symbols, it complains it's unused but it works
string packageId = $"net.dot.{ProjectName}";
- File.WriteAllText(Path.Combine(javaSrcFolder, "MainActivity.java"),
+ File.WriteAllText(Path.Combine(javaSrcFolder, "MainActivity.java"),
Utils.GetEmbeddedResource("MainActivity.java"));
- File.WriteAllText(Path.Combine(javaSrcFolder, "MonoRunner.java"),
+ File.WriteAllText(Path.Combine(javaSrcFolder, "MonoRunner.java"),
Utils.GetEmbeddedResource("MonoRunner.java"));
- File.WriteAllText(Path.Combine(OutputDir, "AndroidManifest.xml"),
+ File.WriteAllText(Path.Combine(OutputDir, "AndroidManifest.xml"),
Utils.GetEmbeddedResource("AndroidManifest.xml")
.Replace("%PackageName%", packageId)
.Replace("%MinSdkLevel%", MinApiLevel));
string apkFile = Path.Combine(OutputDir, "bin", $"{ProjectName}.unaligned.apk");
Utils.RunProcess(aapt, $"package -f -m -F {apkFile} -A assets -M AndroidManifest.xml -I {androidJar}", workingDir: OutputDir);
-
+
var dynamicLibs = new List<string>();
dynamicLibs.Add(Path.Combine(OutputDir, "monodroid", "libmonodroid.so"));
dynamicLibs.AddRange(Directory.GetFiles(sourceDir, "*.so"));
File.Delete(apkFile);
// 5. Generate key
-
+
string signingKey = Path.Combine(OutputDir, "debug.keystore");
if (!File.Exists(signingKey))
{
// 6. Sign APK
- Utils.RunProcess(apksigner, $"sign --min-sdk-version {MinApiLevel} --ks debug.keystore " +
+ Utils.RunProcess(apksigner, $"sign --min-sdk-version {MinApiLevel} --ks debug.keystore " +
$"--ks-pass pass:android --key-pass pass:android {alignedApk}", workingDir: OutputDir);
Utils.LogInfo($"\nAPK size: {(new FileInfo(alignedApk).Length / 1000_000.0):0.#} Mb.\n");
return (alignedApk, packageId);
}
- private static string GetRid(string abi) => abi switch
+ private static string GetRid(string abi) => abi switch
{
"arm64-v8a" => "android-arm64",
"armeabi-v7a" => "android-arm",
"x86_64" => "android-x64",
_ => "android-" + abi
};
-
+
/// <summary>
/// Scan android SDK for build tools (ignore preview versions)
/// </summary>
return buildTools;
}
-
+
/// <summary>
/// Scan android SDK for api levels (ignore preview versions)
/// </summary>
if (!ignoreErrors && process.ExitCode != 0)
throw new Exception("Error: " + errorBuilder);
- return outputBuilder.ToString().Trim('\r','\n');
+ return outputBuilder.ToString().Trim('\r', '\n');
}
public static void DirectoryCopy(string sourceDir, string destDir, Func<string, bool> predicate)
/// <summary>
/// Assemblies to be AOTd. They need to be in a self-contained directory.
- ///
+ ///
/// Metadata:
/// - AotArguments: semicolon-separated list of options that will be passed to --aot=
/// - ProcessArguments: semicolon-separated list of options that will be passed to the AOT compiler itself
/// </summary>
public string? MsymPath { get; set; }
- ConcurrentBag<ITaskItem> compiledAssemblies = new ConcurrentBag<ITaskItem>();
- MonoAotMode parsedAotMode;
- MonoAotOutputType parsedOutputType;
+ private ConcurrentBag<ITaskItem> compiledAssemblies = new ConcurrentBag<ITaskItem>();
+ private MonoAotMode parsedAotMode;
+ private MonoAotOutputType parsedOutputType;
public override bool Execute()
{
// we need to quote the entire --aot arguments here to make sure it is parsed
// on Windows as one argument. Otherwise it will be split up into multiple
// values, which wont work.
- processArgs.Add($"\"--aot={String.Join(",", aotArgs)}\"");
+ processArgs.Add($"\"--aot={string.Join(",", aotArgs)}\"");
processArgs.Add(assembly);
var envVariables = new Dictionary<string, string>
{
{"MONO_PATH", directory},
- {"MONO_ENV_OPTIONS", String.Empty} // we do not want options to be provided out of band to the cross compilers
+ {"MONO_ENV_OPTIONS", string.Empty} // we do not want options to be provided out of band to the cross compilers
};
// run the AOT compiler
- Utils.RunProcess(CompilerBinaryPath, String.Join(" ", processArgs), envVariables, directory);
+ Utils.RunProcess(CompilerBinaryPath, string.Join(" ", processArgs), envVariables, directory);
compiledAssemblies.Add(aotAssembly);
}
{
Normal,
AsmOnly,
-}
\ No newline at end of file
+}
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<Nullable>enable</Nullable>
+ <NoWarn>$(NoWarn),CA1050</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Build" Version="$(RefOnlyMicrosoftBuildVersion)" />
throw new Exception("Error: " + errorBuilder);
}
- return outputBuilder.ToString().Trim('\r','\n');
+ return outputBuilder.ToString().Trim('\r', '\n');
}
public static TaskLoggingHelper? Logger { get; set; }
throw new ArgumentException($"ProjectName='{ProjectName}' should not contain spaces");
}
- string[] excludes = new string[0];
+ string[] excludes = Array.Empty<string>();
if (ExcludeFromAppDir != null)
{
excludes = ExcludeFromAppDir
{
// use AOT files if available
var obj = file.GetMetadata("AssemblerFile");
- if (!String.IsNullOrEmpty(obj))
+ if (!string.IsNullOrEmpty(obj))
{
assemblerFiles.Add(obj);
}
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<Nullable>enable</Nullable>
+ <NoWarn>$(NoWarn),CA1050</NoWarn>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Templates\*.*" />
throw new Exception("Error: " + errorBuilder);
}
- return outputBuilder.ToString().Trim('\r','\n');
+ return outputBuilder.ToString().Trim('\r', '\n');
}
public static TaskLoggingHelper? Logger { get; set; }
cmakeLists = cmakeLists.Replace("%NativeLibrariesToLink%", toLink);
cmakeLists = cmakeLists.Replace("%AotSources%", aotSources);
- cmakeLists = cmakeLists.Replace("%Defines%",
+ cmakeLists = cmakeLists.Replace("%Defines%",
useAotForSimulator ? "add_definitions(-DUSE_AOT_FOR_SIMULATOR=1)" : "");
string plist = Utils.GetEmbeddedResource("Info.plist.template")
var pars = method.GetParameters();
foreach (var p in pars) {
if (pindex > 0)
- sb.Append(",");
+ sb.Append(',');
sb.Append(MapType(pars[pindex].ParameterType));
- pindex ++;
+ pindex++;
}
sb.Append(");");
return sb.ToString();
}
- void EmitNativeToInterp(StreamWriter w, List<PInvokeCallback> callbacks)
+ private void EmitNativeToInterp(StreamWriter w, List<PInvokeCallback> callbacks)
{
// Generate native->interp entry functions
// These are called by native code, so they need to obtain
int pindex = 0;
if (method.ReturnType.Name != "Void") {
sb.Append("int");
- pindex ++;
+ pindex++;
}
foreach (var p in method.GetParameters()) {
if (pindex > 0)
- sb.Append(",");
+ sb.Append(',');
sb.Append("int");
- pindex ++;
+ pindex++;
}
if (pindex > 0)
- sb.Append(",");
+ sb.Append(',');
// Extra arg
sb.Append("int");
sb.Append(");\n");
pindex = 0;
foreach (var p in method.GetParameters()) {
if (pindex > 0)
- sb.Append(",");
+ sb.Append(',');
sb.Append(MapType(method.GetParameters()[pindex].ParameterType));
sb.Append(" arg" + pindex);
- pindex ++;
+ pindex++;
}
sb.Append(") { \n");
if (!is_void)
pindex = 0;
if (!is_void) {
sb.Append("&res");
- pindex ++;
+ pindex++;
}
int aindex = 0;
foreach (var p in method.GetParameters()) {
if (pindex > 0)
sb.Append(", ");
sb.Append("&arg" + aindex);
- pindex ++;
- aindex ++;
+ pindex++;
+ aindex++;
}
if (pindex > 0)
sb.Append(", ");
sb.Append(");\n");
if (!is_void)
sb.Append("return res;\n");
- sb.Append("}");
+ sb.Append('}');
w.WriteLine(sb);
- cb_index ++;
+ cb_index++;
}
// Array of function pointers
w.WriteLine ("};");
}
- static bool IsBlittable (Type type)
+ private static bool IsBlittable (Type type)
{
if (type.IsPrimitive || type.IsByRef || type.IsPointer)
return true;
return false;
}
- static void Error (string msg)
+ private static void Error (string msg)
{
// FIXME:
throw new Exception(msg);
}
}
-class PInvoke
+internal class PInvoke
{
public PInvoke(string entryPoint, string module, MethodInfo method)
{
public MethodInfo Method;
}
-class PInvokeCallback
+internal class PInvokeCallback
{
public PInvokeCallback(MethodInfo method)
{
// If true, continue when a referenced assembly cannot be found.
// If false, throw an exception.
- public bool SkipMissingAssemblies { get; set; }
+ public bool SkipMissingAssemblies { get; set; }
// full list of ICU data files we produce can be found here:
// https://github.com/dotnet/icu/tree/maint/maint-67/icu-filters
public ITaskItem[]? RemoteSources { get; set; }
public bool InvariantGlobalization { get; set; }
- SortedDictionary<string, Assembly>? _assemblies;
- Resolver? _resolver;
+ private SortedDictionary<string, Assembly>? _assemblies;
+ private Resolver? _resolver;
private class WasmAppConfig
{
{
foreach (var item in ExtraAssemblies)
{
- try
- {
- var refAssembly = mlc.LoadFromAssemblyPath(item.ItemSpec);
- Add(mlc, refAssembly);
- }
- catch (System.IO.FileLoadException)
- {
- if (!SkipMissingAssemblies)
- {
- throw;
- }
- }
+ try
+ {
+ var refAssembly = mlc.LoadFromAssemblyPath(item.ItemSpec);
+ Add(mlc, refAssembly);
+ }
+ catch (System.IO.FileLoadException)
+ {
+ if (!SkipMissingAssemblies)
+ {
+ throw;
+ }
+ }
}
}
if (!InvariantGlobalization)
config.Assets.Add(new IcuData(IcuDataFileName!) { LoadRemote = RemoteSources?.Length > 0 });
-
+
config.Assets.Add(new VfsEntry ("dotnet.timezones.blat") { VirtualPath = "/usr/share/zoneinfo/"});
if (RemoteSources?.Length > 0) {
}
}
-class Resolver : MetadataAssemblyResolver
+internal class Resolver : MetadataAssemblyResolver
{
- List<String> _searchPaths;
+ private List<string> _searchPaths;
public Resolver(List<string> searchPaths)
{
<OutputType>Library</OutputType>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<Nullable>enable</Nullable>
+ <NoWarn>$(NoWarn),CA1050</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Build" Version="$(RefOnlyMicrosoftBuildVersion)" />
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
using System;
using System.Collections.Generic;
using System.IO;
private const string ZoneTabFileName = "zone1970.tab";
- private void CompileTimeZoneDataSource()
+ private void CompileTimeZoneDataSource()
{
- using (Process process = new Process())
+ using (Process process = new Process())
{
process.StartInfo.UseShellExecute = false;
process.StartInfo.FileName = "zic";
- foreach (var f in TimeZones!)
+ foreach (var f in TimeZones!)
{
process.StartInfo.Arguments = $"-d \"{OutputDirectory}\" \"{Path.Combine(InputDirectory!, f)}\"";
process.Start();
}
}
- private void FilterTimeZoneData()
+ private void FilterTimeZoneData()
{
- // Remove unnecessary timezone files in the root dir
- // for ex: `CST6CDT`, `MST`, etc.
- foreach (var entry in new DirectoryInfo (OutputDirectory!).EnumerateFiles())
+ // Remove unnecessary timezone files in the root dir
+ // for ex: `CST6CDT`, `MST`, etc.
+ foreach (var entry in new DirectoryInfo (OutputDirectory!).EnumerateFiles())
{
File.Delete(entry.FullName);
}
}
- private void FilterZoneTab(string[] filters, string ZoneTabFile)
+ private void FilterZoneTab(string[] filters, string ZoneTabFile)
{
var path = Path.Combine(OutputDirectory!, "zone.tab");
using (StreamReader sr = new StreamReader(ZoneTabFile))
{
string? line;
while ((line = sr.ReadLine()) != null) {
- if (filters.Any(x => Regex.IsMatch(line, $@"\b{x}\b")))
+ if (filters.Any(x => Regex.IsMatch(line, $@"\b{x}\b")))
{
sw.WriteLine(line);
}
}
}
- public override bool Execute()
+ public override bool Execute()
{
string ZoneTabFile = Path.Combine(InputDirectory!, ZoneTabFileName);
if (!Directory.Exists(OutputDirectory))
Directory.CreateDirectory(OutputDirectory!);
- if (!File.Exists(ZoneTabFile))
+ if (!File.Exists(ZoneTabFile))
{
- Log.LogError($"Could not find required file {ZoneTabFile}");
+ Log.LogError($"Could not find required file {ZoneTabFile}");
return false;
}
CompileTimeZoneDataSource();
-
- string[] filtered = new string[] { "America/Los_Angeles", "Australia/Sydney", "Europe/London", "Pacific/Tongatapu",
+
+ string[] filtered = new string[] { "America/Los_Angeles", "Australia/Sydney", "Europe/London", "Pacific/Tongatapu",
"America/Sao_Paulo", "Australia/Perth", "Africa/Nairobi", "Europe/Berlin",
"Europe/Moscow", "Africa/Tripoli", "America/Argentina/Catamarca", "Europe/Lisbon",
"America/St_Johns"};
-
+
FilterTimeZoneData();
FilterZoneTab(filtered, ZoneTabFile);
return !Log.HasLoggedErrors;
}
-}
\ No newline at end of file
+}
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
using System;
using System.Buffers.Binary;
using System.Collections.Generic;
public string? InputDirectory { get; set; }
[Required]
- public string? OutputFileName { get; set; }
+ public string? OutputFileName { get; set; }
- private (byte[] json_bytes, MemoryStream stream) EnumerateData()
+ private (byte[] json_bytes, MemoryStream stream) EnumerateData()
{
var indices = new List<object[]>();
var stream = new MemoryStream();
-
+
var directoryInfo = new DirectoryInfo(InputDirectory!);
-
- foreach (var entry in directoryInfo.EnumerateFiles("*", SearchOption.AllDirectories))
+
+ foreach (var entry in directoryInfo.EnumerateFiles("*", SearchOption.AllDirectories))
{
var relativePath = Path.GetRelativePath(InputDirectory!, entry.FullName);
indices.Add(new object[] { relativePath, entry.Length });
using (var readStream = entry.OpenRead())
readStream.CopyTo(stream);
}
-
+
stream.Position = 0;
var jsonBytes = JsonSerializer.SerializeToUtf8Bytes(indices);
-
+
return (jsonBytes, stream);
}
public override bool Execute()
{
- if (!Directory.Exists(InputDirectory))
+ if (!Directory.Exists(InputDirectory))
{
Log.LogError($"Input directory '{InputDirectory}' does not exist");
return false;
}
(byte[] json_bytes, MemoryStream stream) data = EnumerateData();
-
+
using (var file = File.Open(OutputFileName!, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
{
var lengthBytes = new byte[4];
file.Write(magicBytes);
file.Write(lengthBytes);
file.Write(data.json_bytes);
-
+
data.stream.CopyTo(file);
}
-
+
return true;
}
}
-
<TargetFramework>$(NetCoreAppCurrent)</TargetFramework>
<OutputType>Library</OutputType>
<Nullable>enable</Nullable>
+ <NoWarn>$(NoWarn),CA1050</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Build" Version="$(RefOnlyMicrosoftBuildVersion)" />