Category: RSCG

RSCG – RSCG_TimeBombComment

 
 

name RSCG_TimeBombComment
nuget https://www.nuget.org/packages/RSCG_TimeBombComment/
link http://msprogrammer.serviciipeweb.ro/category/roslyn/
author Andrei Ignat

This will generate an error from the comment after a certain date

 

This is how you can use RSCG_TimeBombComment .

The code that you start with is


<Project Sdk="Microsoft.NET.Sdk">
	<PropertyGroup>
		<OutputType>Exe</OutputType>
		<TargetFramework>net7.0</TargetFramework>
	</PropertyGroup>
	<PropertyGroup>
		<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
		<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedX</CompilerGeneratedFilesOutputPath>
	</PropertyGroup>
	<ItemGroup>
		<PackageReference Include="RSCG_TimeBombComment" Version="2023.5.9.2110" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
	</ItemGroup>
</Project>


The code that you will use is


namespace Console_TimeBombComment;
internal partial class TestClass
{
    [Obsolete("this will be obsolete",TB_20230508)]
    public int DataObsolete()
    {
        return 5;
    }

    public int CommentsWithErrors()
    {
        //JFD: test
        //TB: 2021-09-13 this is a comment transformed into an error
        //TB: and this is a warning
        //TB: 2050-12-30 and this should not appear yet
        return 5;
    }
}


 

The code that is generated is


namespace Console_TimeBombComment {
    partial class TestClass { 
        const bool TB_20230508 = true;
    }
}

                

Code and pdf at

https://ignatandrei.github.io/RSCG_Examples/v2/docs/RSCG_TimeBombComment

RSCG – ThisAssembly

RSCG – ThisAssembly
 
 

name ThisAssembly
nuget https://www.nuget.org/packages/ThisAssembly
link https://www.clarius.org/ThisAssembly/
author Daniel Cazzulino

The ThisAssembly.Info allows you access to the Assembly Information as constants, instead of going to reflection each time.

I found useful to see the assembly version right away in any project that I have.

 

This is how you can use ThisAssembly .

The code that you start with is


<Project Sdk="Microsoft.NET.Sdk">
	<PropertyGroup>
		<OutputType>Exe</OutputType>
		<TargetFramework>netcoreapp7.0</TargetFramework>
	</PropertyGroup>
	<PropertyGroup>
		<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
		<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedX</CompilerGeneratedFilesOutputPath>
	</PropertyGroup>
	<PropertyGroup>
		<Version>2023.5.7.800</Version>
	</PropertyGroup>
	<ItemGroup>
		<PackageReference Include="ThisAssembly" Version="1.2.14" OutputItemType="Analyzer" ReferenceOutputAssembly="false">
			<PrivateAssets>all</PrivateAssets>
			<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
		</PackageReference>
	</ItemGroup>
</Project>


The code that you will use is


var strVersion = ThisAssembly.Info.Version;
System.Console.WriteLine(strVersion);


 

The code that is generated is

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System.CodeDom.Compiler;
using System.Runtime.CompilerServices;

/// <summary>
/// Provides access to the current assembly information as pure constants, 
///  without requiring reflection.
/// </summary>
partial class ThisAssembly
{
    /// <summary>
    /// Gets the AssemblyInfo attributes.
    /// </summary>
    [GeneratedCode("ThisAssembly.AssemblyInfo", "1.2.14")]
    [CompilerGenerated]
    public static partial class Info
    {
        public const string Company = @"RSCG_Version";

        public const string Configuration = @"Debug";

        public const string FileVersion = @"2023.5.7.800";

        public const string InformationalVersion = @"2023.5.7.800";

        public const string Product = @"RSCG_Version";

        public const string Title = @"RSCG_Version";

        public const string Version = @"2023.5.7.800";

    }
}
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     ThisAssembly.Constants: 1.2.14
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Globalization;

partial class ThisAssembly
{
    public static partial class Git
    {
        /// <summary>
        /// => @"[pending build]"
        /// </summary>
        public const string Branch = @"[pending build]";
    }
}
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     ThisAssembly.Constants: 1.2.14
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Globalization;

partial class ThisAssembly
{
    public static partial class Git
    {
        /// <summary>
        /// => @"[pending build]"
        /// </summary>
        public const string Commit = @"[pending build]";
    }
}
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     ThisAssembly.Constants: 1.2.14
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Globalization;

partial class ThisAssembly
{
    public static partial class Git
    {
        /// <summary>
        /// => @"[pending build]"
        /// </summary>
        public const string Root = @"[pending build]";
    }
}
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     ThisAssembly.Constants: 1.2.14
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Globalization;

partial class ThisAssembly
{
    public static partial class Git
    {
        /// <summary>
        /// => @"[pending build]"
        /// </summary>
        public const string Sha = @"[pending build]";
    }
}
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     ThisAssembly.Constants: 1.2.14
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Globalization;

partial class ThisAssembly
{
    public static partial class Git
    {
        /// <summary>
        /// => @"[pending build]"
        /// </summary>
        public const string Url = @"[pending build]";
    }
}
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System.CodeDom.Compiler;
using System.Runtime.CompilerServices;

/// <summary>
/// Provides access to the current assembly information as pure constants, 
///  without requiring reflection.
/// </summary>
partial class ThisAssembly
{
    /// <summary>
    /// Gets the assembly metadata.
    /// </summary>
    [GeneratedCode("ThisAssembly.Metadata", "1.2.14")]
    [CompilerGenerated]
    public static partial class Metadata
    {
    }
}
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System.CodeDom.Compiler;
using System.Runtime.CompilerServices;

/// <summary>
/// Provides access to the current assembly information as pure constants, 
///  without requiring reflection.
/// </summary>
partial class ThisAssembly
{
    /// <summary>
    /// Gets the project properties.
    /// </summary>
    [GeneratedCode("ThisAssembly.Project", "1.2.14")]
    [CompilerGenerated]
    public static partial class Project
    {
        /// <summary>AssemblyName = RSCG_Version</summary>
        public const string AssemblyName = @"RSCG_Version";

        /// <summary>RootNamespace = RSCG_Version</summary>
        public const string RootNamespace = @"RSCG_Version";

        /// <summary>TargetFrameworkIdentifier = .NETCoreApp</summary>
        public const string TargetFrameworkIdentifier = @".NETCoreApp";

        /// <summary>TargetFrameworkMoniker = .NETCoreApp,Version=v7.0</summary>
        public const string TargetFrameworkMoniker = @".NETCoreApp,Version=v7.0";

        /// <summary>TargetFrameworkVersion = v7.0</summary>
        public const string TargetFrameworkVersion = @"v7.0";

    }
}
using System;
using System.IO;
using System.Linq;
using System.Reflection;

static class EmbeddedResource
{
    static readonly string baseDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? "";

    public static string GetContent(string relativePath)
    {
        using var stream = GetStream(relativePath);
        using var reader = new StreamReader(stream);
        return reader.ReadToEnd();
    }

    public static byte[] GetBytes(string relativePath)
    {
        using var stream = GetStream(relativePath);
        var bytes = new byte[stream.Length];
        stream.Read(bytes, 0, bytes.Length);
        return bytes;
    }

    public static Stream GetStream(string relativePath)
    {
        var filePath = Path.Combine(baseDir, Path.GetFileName(relativePath));
        if (File.Exists(filePath))
            return File.OpenRead(filePath);

        var baseName = Assembly.GetExecutingAssembly().GetName().Name;
        var resourceName = relativePath
            .TrimStart('.')
            .Replace('/', '.')
            .Replace('\\', '.');

        var manifestResourceName = Assembly.GetExecutingAssembly()
            .GetManifestResourceNames().FirstOrDefault(x => x.EndsWith(resourceName));

        if (string.IsNullOrEmpty(manifestResourceName))
            throw new InvalidOperationException($"Did not find required resource ending in '{resourceName}' in assembly '{baseName}'.");

        return
            Assembly.GetExecutingAssembly().GetManifestResourceStream(manifestResourceName) ??
            throw new InvalidOperationException($"Did not find required resource '{manifestResourceName}' in assembly '{baseName}'.");
    }
}
using System.Collections.Concurrent;
using System.Resources;
using System.Runtime.CompilerServices;

/// <summary>
/// Provides access to the current assembly information as pure constants, 
///  without requiring reflection.
/// </summary>
partial class ThisAssembly
{
    /// <summary>
    /// Access the strings provided by resource files in the project.
    /// </summary>
    [CompilerGenerated]
    public static partial class Strings
    {
        static ConcurrentDictionary<string, ResourceManager> resourceManagers = new ConcurrentDictionary<string, ResourceManager>();

        static ResourceManager GetResourceManager(string resourceName)
            => resourceManagers.GetOrAdd(resourceName, name => new ResourceManager(name, typeof(Strings).Assembly));
    }
}

Code and pdf at

https://ignatandrei.github.io/RSCG_Examples/v2/docs/ThisAssembly

RSCG–ISourceGenerator porting to IIncrementalGenerator in 3 steps

Roslyn Source Code Generators (RSCG) have deprecated the ISourceGenerator  (roslyn/source-generators.md at main · dotnet/roslyn · GitHub )   vs the new interface IIncrementalGenerator , roslyn/incremental-generators.md at main · dotnet/roslyn · GitHub . That because of the idea of speed of generating code – and the idea of not generating twice the same code.

How is the implementation of IIncrementalGenerator , when you have already an ISourceGenerator  ?

I have moved the https://github.com/ignatandrei/rsCG_timeBombComment/ ( the generates code to transform comments / obsolete attribute as errors , after a time) and  https://github.com/ignatandrei/SkinnyControllersGenerator/ those are my findings

  1. Read the theory from https://github.com/dotnet/roslyn/blob/main/docs/features/incremental-generators.md .  The ISourceGenerator was simpler to understand. After you read you can see how  the IIncrementalGenerator makes sense for increasing performance of RSCG.
  2. The code from ISourceGenerator  could be copy and paste to IIncrementalGenerator . The code from ISourceGenerator.Initialize belongs now to context.SyntaxProvider.CreateSyntaxProvider –> predicate , where the code that obtain the datas is written after this
  3. The real code that generates the new source code belong to context.RegisterSourceOutput

 

There are some problems

  1. Register a diagnostic occurs later  – could be fixed with Analyzers – see Incremental Roslyn Source Generators In .NET 6: Better Experience Through Roslyn Analyzers & Code Fixes – Part 2 – Thinktecture AG
  2. The additional files also occurs later – could be fixed by having a prefix in the file name in the order to not load all files content

Overall , this is a nicer way to wrote code ( although the learning curve is bigger). You can see the result at file RSCG_TimeBombComment\src\RSCG_TimeBombComment\RSCG_TimeBombComment\GenerateFromComments.cs vs RSCG_TimeBombComment\src\RSCG_TimeBombComment\RSCG_TimeBombComment\GenerateFromCommentsIncremental.cs from repo https://github.com/ignatandrei/rsCG_timeBombComment/

If you want to see more RSCG with the new method, keep an eye to https://ignatandrei.github.io/RSCG_Examples/v2/

 

 

Andrei Ignat weekly software news(mostly .NET)

* indicates required

Please select all the ways you would like to hear from me:

You can unsubscribe at any time by clicking the link in the footer of our emails. For information about our privacy practices, please visit our website.

We use Mailchimp as our marketing platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp's privacy practices here.