FxMap.Analyzers 1.0.3

dotnet add package FxMap.Analyzers --version 1.0.3
                    
NuGet\Install-Package FxMap.Analyzers -Version 1.0.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FxMap.Analyzers" Version="1.0.3">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FxMap.Analyzers" Version="1.0.3" />
                    
Directory.Packages.props
<PackageReference Include="FxMap.Analyzers">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add FxMap.Analyzers --version 1.0.3
                    
#r "nuget: FxMap.Analyzers, 1.0.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package FxMap.Analyzers@1.0.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=FxMap.Analyzers&version=1.0.3
                    
Install as a Cake Addin
#tool nuget:?package=FxMap.Analyzers&version=1.0.3
                    
Install as a Cake Tool

FxMap.Analyzers

Roslyn Code Analyzer for validating FxMap Expression syntax at compile-time.

Overview

FxMap.Analyzers provides comprehensive syntax validation for FxMap Expression strings used in ProfileOf<T> configurations. It catches expression syntax errors during compilation, preventing runtime failures.

Diagnostic Rules

OFX001: Expression Syntax Invalid

Severity: Error Category: Syntax

This analyzer validates FxMap Expression strings for correct syntax including:

1. Balanced Delimiters
  • Brackets [] for indexers
  • Braces {} for projections
  • Parentheses () for filters
2. Property Navigation
  • Projection requires dot: Country.{Id, Name} not Country{Id, Name}
  • Navigation after filter requires dot: Orders(Status = 'Done').Items not Orders(Status = 'Done')Items
  • Navigation after indexer requires dot: Provinces[0 asc Name].Name not Provinces[0 asc Name]Name
3. Function Validation
  • Function names must be valid (count, sum, avg, min, max, upper, lower, etc.)
  • Functions requiring arguments must have them (e.g., substring, replace)
4. Computed Expressions
  • Computed expressions in projections must have alias: {Id, (Name:upper) as UpperName} not {Id, (Name:upper)}
5. Operators
  • Must use valid operators: =, !=, >, <, >=, <=, contains, startswith, endswith
  • Logical operators: &&, ||, !, and, or, not

Examples

Valid Expressions

// In a ProfileOf<T> configuration:
public class ProvinceResponseProfile : ProfileOf<ProvinceResponse>
{
    protected override void Configure()
    {
        // Simple property navigation
        UseDistributedKey<CountryOfAttribute>()
            .Of(x => x.CountryId)
            .For(x => x.CountryName, "Country.Name");

        // Projection with proper dot
        UseDistributedKey<CountryOfAttribute>()
            .Of(x => x.CountryId)
            .For(x => x.CountryInfo, "Country.{Id, Name}");
    }
}

// Root projection
.For(x => x.MemberInfo, "{Id, Name, Email}")

// Projection with alias
.For(x => x.Data, "{Id, Country.Name as CountryName}")

// Filter with proper navigation
.For(x => x.OrderItems, "Orders(Status = 'Done').Items")

// Indexer with proper navigation
.For(x => x.ProvinceName, "Provinces[0 asc Name].Name")

// Complex filter with string operations
.For(x => x.ProvinceName, "Provinces(Name endswith 'a')[0 desc Name].Name")

// Functions with arguments
.For(x => x.ShortName, "{Id, Name:substring(0, 3) as Short}")

// Computed expressions with alias
.For(x => x.Data, "{Id, (Name:upper) as UpperName}")

// Ternary with alias
.For(x => x.Status, "{Id, (Active = true ? 'Yes' : 'No') as StatusText}")

Invalid Expressions (Analyzer Errors)

// Missing closing brace
.For(x => x.CountryInfo, "Country.{Id, Name")
// Error: Expected '}' after projection

// Missing closing bracket
.For(x => x.ProvinceInfo, "Provinces[asc Name")
// Error: Expected ']' after indexer

// Missing closing parenthesis
.For(x => x.OrderInfo, "Orders(Status = 'Done'")
// Error: Expected ')' after filter condition

// Missing dot before projection
.For(x => x.CountryInfo, "Country{Id, Name}")
// Error: Projection requires '.' before '{'

// Missing dot after filter
.For(x => x.OrderItems, "Orders(Status = 'Done')Items")
// Error: Property navigation requires '.' before identifier

// Missing dot after indexer
.For(x => x.ProvinceName, "Provinces[0 asc Name]Name")
// Error: Property navigation requires '.' before identifier

// Unknown function
.For(x => x.Name, "Name:invalid")
// Error: Unknown function 'invalid'

// Function missing required arguments
.For(x => x.Name, "Name:substring")
// Error: Function 'substring' requires arguments

// Computed expression without alias
.For(x => x.Data, "{Id, (Name:upper)}")
// Error: Expected 'as' keyword after computed expression - alias is required

// Invalid operator
.For(x => x.Users, "Users(Age >> 18)")
// Error: Expected value ('>>' is not a valid operator)

Installation

Via NuGet Package

dotnet add package FxMap.Analyzers

Via Project Reference

Add to your .csproj:

<ItemGroup>
  <ProjectReference Include="../path/to/FxMap.Analyzers/FxMap.Analyzers.csproj" />
</ItemGroup>

How It Works

  1. Compile-Time Analysis: The analyzer runs during compilation and inspects all FluentAPI configurations
  2. Expression Parsing: Each expression string passed to .For(), .Expression(), or .Else() is validated using the full FxMap ExpressionParser
  3. Immediate Feedback: Syntax errors are reported as compiler errors with detailed messages including position information

Features

Current Validations

  • Syntax Structure: All brackets, braces, parentheses must be balanced
  • Navigation Syntax: Dot requirements for property navigation
  • Function Names: Validates against known function list
  • Function Arguments: Ensures required arguments are provided
  • Operator Validation: Only valid operators are allowed
  • Alias Requirements: Computed expressions must have aliases in projections
  • Position Information: Error messages include exact position of syntax errors

Current Limitations

This is a syntax-only analyzer. It does NOT validate:

  • Whether property names exist in your entities
  • Whether navigation paths are valid for your data model
  • Data types or type compatibility
  • Semantic correctness of expressions

These semantic validations happen at runtime when expressions are executed.

Demo Project

See the demo project at sample/Service1.Contract for comprehensive examples of both valid and invalid expressions.

cd sample/Service1.Contract
dotnet build

The demo build will show analyzer errors for all invalid expressions.

Error Message Format

error OFX001: Expression '{expression}' is invalid: {detailed-error-message}

Example:

error OFX001: Expression 'Country{Id, Name}' is invalid: Projection requires '.' before '{' at position 7

Supported FxMap Expression Features

  • Property navigation: Country.Name, Country.Province.Name
  • Projections: Country.{Id, Name}, {Id, Name as UserName}
  • Root projections: {Id, Email, Country.Name as CountryName}
  • Filters: Countries(Active = true), Provinces(Name contains 'land')
  • Indexers: Provinces[0 10 asc Name], Items[0 10 desc Price]
  • Functions: Name:upper, Price:round(2), Items:count
  • String functions: upper, lower, trim, substring, replace, concat, split
  • Math functions: round, floor, ceil, abs, add, subtract, multiply, divide
  • Date functions: year, month, day, format
  • Aggregate functions: count, sum, avg, min, max, distinct
  • Collection functions: any, all, groupBy
  • Boolean functions: any(condition), all(condition)
  • Ternary operator: (Status = 'Active' ? 'Yes' : 'No') as StatusText
  • Null coalescing: (Nickname ?? Name) as DisplayName
  • Chained functions: Name:trim:upper, Price:add(10):round(2)

Contributing

Found a bug or want to contribute? Please visit GitHub Repository.

License

This project is licensed under the Apache-2.0 license.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.3 71 3/15/2026
1.0.2 79 3/7/2026
1.0.1 78 3/6/2026
1.0.0 75 3/6/2026