Skip to content

Commit b644e1c

Browse files
NikolayPianikovNikolayPianikov
authored andcommitted
Avoid NormalizeWhitespace to improve performance
1 parent de54484 commit b644e1c

File tree

10 files changed

+96
-30
lines changed

10 files changed

+96
-30
lines changed

.config/dotnet-tools.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"version": 1,
3+
"isRoot": true,
4+
"tools": {
5+
"teamcity.csi": {
6+
"version": "1.0.4-beta5",
7+
"commands": [
8+
"dotnet-csi"
9+
]
10+
}
11+
}
12+
}

Build/Build.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
<Nullable>enable</Nullable>
66
</PropertyGroup>
77
<ItemGroup>
8-
<PackageReference Include="TeamCity.CSharpInteractive" Version="1.0.4-beta3" />
8+
<PackageReference Include="TeamCity.CSharpInteractive" Version="1.0.4-beta4" />
99
</ItemGroup>
1010
</Project>

Immutype/Core/CommentsGenerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ where comment.StartsWith("//") && !comment.StartsWith("///")
4848
}
4949

5050
lines.Add("/// <returns>The modified copy of the original instance.</returns>");
51-
return target.WithLeadingTrivia(lines.Select(SyntaxFactory.Comment));
51+
return target.WithLeadingTrivia(lines.SelectMany(s => new List<SyntaxTrivia>() { SyntaxFactory.CarriageReturn, SyntaxFactory.LineFeed, SyntaxFactory.Comment(s)}));
5252
}
5353

5454
return target;

Immutype/Core/DataContainerFactory.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ public bool TryCreate(GenericNameSyntax genericNameSyntax, ref ExpressionSyntax?
8686
var elementType = genericNameSyntax.TypeArgumentList.Arguments[0];
8787
var newArgumentParameter = argumentParameter.WithType(
8888
SyntaxFactory.ArrayType(elementType).AddRankSpecifiers(SyntaxFactory.ArrayRankSpecifier()))
89-
.AddModifiers(SyntaxFactory.Token(SyntaxKind.ParamsKeyword));
89+
.AddModifiers(SyntaxKind.ParamsKeyword.WithSpace());
9090

9191
if (GenericTypeMap.TryGetValue(genericNameSyntax.Identifier.Text, out var genericTypeName))
9292
{
@@ -141,7 +141,7 @@ private static ExpressionSyntax CreateGenericContainer(ExpressionSyntax? express
141141
SyntaxFactory.Identifier($"System.Collections.Generic.{genericTypeName}"))
142142
.AddTypeArgumentListArguments(elementType);
143143

144-
var result = SyntaxFactory.ObjectCreationExpression(genericDataType);
144+
var result = SyntaxRepo.ObjectCreationExpression(genericDataType);
145145
return expressionSyntax != default
146146
? result.AddArgumentListArguments(SyntaxFactory.Argument(expressionSyntax))
147147
: result.AddArgumentListArguments();

Immutype/Core/ExtensionsFactory.cs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ internal class ExtensionsFactory : IUnitFactory
1313
{
1414
private static readonly UsingDirectiveSyntax[] AdditionalUsings =
1515
{
16-
SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System.Collections.Generic")), SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System.Linq"))
16+
SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System.Collections.Generic").WithSpace()), SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System.Linq").WithSpace())
1717
};
1818

1919
private readonly IMethodsFactory _methodsFactory;
@@ -26,7 +26,7 @@ public IEnumerable<Source> Create(GenerationContext<TypeDeclarationSyntax> conte
2626
var typeDeclarationSyntax = context.Syntax;
2727
var ns = typeDeclarationSyntax.Ancestors()
2828
#if ROSLYN38
29-
.OfType<NamespaceDeclarationSyntax>()
29+
.OfType<NamespaceDeclarationSyntax>()
3030
#else
3131
.OfType<BaseNamespaceDeclarationSyntax>()
3232
#endif
@@ -42,14 +42,14 @@ public IEnumerable<Source> Create(GenerationContext<TypeDeclarationSyntax> conte
4242

4343
var typeSyntax = SyntaxFactory.ParseName(typeName);
4444
var className = $"{typeDeclarationSyntax.Identifier.Text}Extensions";
45-
var extensionsClass = SyntaxFactory.ClassDeclaration(className)
46-
.AddModifiers(typeDeclarationSyntax.Modifiers.Where(i => !i.IsKind(SyntaxKind.ReadOnlyKeyword) && !i.IsKind(SyntaxKind.PartialKeyword)).ToArray())
47-
.AddModifiers(SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.PartialKeyword))
48-
.AddMembers(_methodsFactory.Create(context, typeSyntax, parameters).ToArray());
45+
var extensionsClass = SyntaxRepo.ClassDeclaration(className)
46+
.AddModifiers(typeDeclarationSyntax.Modifiers.Where(i => !i.IsKind(SyntaxKind.ReadOnlyKeyword) && !i.IsKind(SyntaxKind.PartialKeyword)).Select(i => i.WithSpace()).ToArray())
47+
.AddModifiers(SyntaxKind.StaticKeyword.WithSpace(), SyntaxKind.PartialKeyword.WithSpace())
48+
.AddMembers(_methodsFactory.Create(context, typeSyntax, parameters).Select(i => i.WithNewLine().WithNewLine()).ToArray());
4949

5050
extensionsClass = TryAddAttribute(context.SemanticModel, extensionsClass, "System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage");
5151

52-
var code = CreateRootNode(typeDeclarationSyntax, AdditionalUsings, extensionsClass).NormalizeWhitespace().ToString();
52+
var code = CreateRootNode(typeDeclarationSyntax, AdditionalUsings, extensionsClass).ToString();
5353
var fileName = string.Join(".", ns.Select(i => i.Name.ToString()).Concat(new[]
5454
{
5555
typeDeclarationSyntax.Identifier.Text
@@ -82,16 +82,17 @@ private static CompilationUnitSyntax CreateRootNode(SyntaxNode targetNode, Using
8282
private static UsingDirectiveSyntax[] GetUsings(IEnumerable<UsingDirectiveSyntax> usings, IEnumerable<UsingDirectiveSyntax> additionalUsings)
8383
{
8484
var currentUsins = usings.Select(i => i.Name.ToString()).ToImmutableHashSet();
85-
return additionalUsings.Where(i => !currentUsins.Contains(i.Name.ToString())).ToArray();
85+
return additionalUsings.Where(i => !currentUsins.Contains(i.Name.ToString())).Select(i => i.WithNewLine()).ToArray();
8686
}
8787

8888
private static ClassDeclarationSyntax TryAddAttribute(SemanticModel semanticModel, ClassDeclarationSyntax classDeclarationSyntax, string attributeClassName)
8989
{
9090
var excludeFromCodeCoverageType = semanticModel.Compilation.GetTypeByMetadataName(attributeClassName + "Attribute");
9191
if (excludeFromCodeCoverageType != default)
9292
{
93-
classDeclarationSyntax = classDeclarationSyntax
94-
.AddAttributeLists(SyntaxFactory.AttributeList().AddAttributes(SyntaxFactory.Attribute(SyntaxFactory.IdentifierName(attributeClassName))));
93+
classDeclarationSyntax = classDeclarationSyntax.WithNewLine()
94+
.AddAttributeLists(SyntaxFactory.AttributeList().AddAttributes(SyntaxFactory.Attribute(SyntaxFactory.IdentifierName(attributeClassName))))
95+
.WithNewLine();
9596
}
9697

9798
return classDeclarationSyntax;

Immutype/Core/MethodAddRemoveFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public IEnumerable<MethodDeclarationSyntax> Create(GenerationContext<TypeDeclara
3737
}
3838

3939
var arrayType = SyntaxFactory.ArrayType(elementType).AddRankSpecifiers(SyntaxFactory.ArrayRankSpecifier());
40-
var arrayParameter = SyntaxFactory.Parameter(currentParameter.Identifier).WithType(arrayType).AddModifiers(SyntaxFactory.Token(SyntaxKind.ParamsKeyword));
40+
var arrayParameter = SyntaxRepo.Parameter(currentParameter.Identifier).WithType(arrayType).AddModifiers(SyntaxKind.ParamsKeyword.WithSpace());
4141

4242
var addArgs = CreateArguments(nameof(Enumerable.Concat), targetDeclaration, thisParameter, curParameters, currentParameter, arrayParameter);
4343
if (addArgs.Any())

Immutype/Core/MethodWithFactory.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public IEnumerable<MethodDeclarationSyntax> Create(GenerationContext<TypeDeclara
4848
var isCollectionParam = !AreEqu(argumentParameter, newArgumentParameter) || isArrayParam;
4949
if (isArrayParam && argumentParameter.Modifiers.All(i => i.Kind() != SyntaxKind.ParamsKeyword))
5050
{
51-
argumentParameter = argumentParameter.AddModifiers(SyntaxFactory.Token(SyntaxKind.ParamsKeyword));
51+
argumentParameter = argumentParameter.AddModifiers(SyntaxKind.ParamsKeyword.WithSpace());
5252
}
5353

5454
var variants = new List<ParameterSyntax>();
@@ -90,7 +90,7 @@ public IEnumerable<MethodDeclarationSyntax> Create(GenerationContext<TypeDeclara
9090
.AddParameterListParameters(thisParameter)
9191
.WithConstraintClauses(targetDeclaration.ConstraintClauses)
9292
.AddBodyStatements(
93-
SyntaxFactory.ReturnStatement(
93+
SyntaxRepo.ReturnStatement(
9494
SyntaxFactory.InvocationExpression(
9595
SyntaxFactory.MemberAccessExpression(
9696
SyntaxKind.SimpleMemberAccessExpression,
@@ -154,7 +154,7 @@ private ExpressionSyntax CreateWithExpression(TypeSyntax? currentParameterType,
154154
case ArrayTypeSyntax:
155155
if (!argumentParameter.Modifiers.Any(i => i.IsKind(SyntaxKind.ParamsKeyword)))
156156
{
157-
argumentParameter = argumentParameter.AddModifiers(SyntaxFactory.Token(SyntaxKind.ParamsKeyword));
157+
argumentParameter = argumentParameter.AddModifiers(SyntaxKind.ParamsKeyword.WithSpace());
158158
}
159159

160160
break;

Immutype/Core/MethodsFactory.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ public MethodsFactory(ImmutableArray<IMethodFactory> methodFactories, ISyntaxNod
1515
public IEnumerable<MemberDeclarationSyntax> Create(GenerationContext<TypeDeclarationSyntax> context, TypeSyntax targetType, IReadOnlyList<ParameterSyntax> parameters)
1616
{
1717
var thisParameter =
18-
SyntaxFactory.Parameter(SyntaxFactory.Identifier("it"))
18+
SyntaxRepo.Parameter(SyntaxFactory.Identifier("it"))
1919
.WithType(targetType)
20-
.AddModifiers(SyntaxFactory.Token(SyntaxKind.ThisKeyword));
20+
.AddModifiers(SyntaxKind.ThisKeyword.WithSpace());
2121

2222
if (
2323
context.Options is CSharpParseOptions { LanguageVersion: >= LanguageVersion.CSharp7_2 }
2424
&& _syntaxNodeFactory.IsReadonlyType(context.Syntax))
2525
{
26-
thisParameter = thisParameter.AddModifiers(SyntaxFactory.Token(SyntaxKind.InKeyword));
26+
thisParameter = thisParameter.AddModifiers(SyntaxKind.InKeyword.WithSpace());
2727
}
2828

2929
return

Immutype/Core/SyntaxNodeFactory.cs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,18 @@ public bool IsAccessible(IEnumerable<SyntaxToken> modifiers) =>
4545
!modifiers.Any(i => i.IsKind(SyntaxKind.StaticKeyword) || i.IsKind(SyntaxKind.PrivateKeyword) || i.IsKind(SyntaxKind.ProtectedKeyword));
4646

4747
public ReturnStatementSyntax CreateReturnStatement(TypeSyntax typeSyntax, IEnumerable<ArgumentSyntax> arguments) =>
48-
SyntaxFactory.ReturnStatement(
49-
SyntaxFactory.ObjectCreationExpression(typeSyntax)
48+
SyntaxRepo.ReturnStatement(
49+
SyntaxRepo.ObjectCreationExpression(typeSyntax)
5050
.AddArgumentListArguments(
51-
arguments.ToArray()));
51+
arguments.ToArray()))
52+
.WithNewLine();
5253

5354
public MethodDeclarationSyntax CreateExtensionMethod(TypeSyntax returnTypeSyntax, string name) =>
54-
SyntaxFactory.MethodDeclaration(returnTypeSyntax, name)
55+
SyntaxRepo.MethodDeclaration(returnTypeSyntax, name)
5556
.AddModifiers(
56-
SyntaxFactory.Token(SyntaxKind.PublicKeyword),
57-
SyntaxFactory.Token(SyntaxKind.StaticKeyword))
57+
SyntaxKind.PublicKeyword.WithSpace(),
58+
SyntaxKind.StaticKeyword.WithSpace())
59+
.WithNewLine()
5860
.AddAttributeLists(
5961
SyntaxFactory.AttributeList()
6062
.AddAttributes(AggressiveInliningAttr, PureAttr));
@@ -88,14 +90,15 @@ public IEnumerable<StatementSyntax> CreateGuards(GenerationContext<TypeDeclarati
8890
yield return
8991
SyntaxFactory.IfStatement(
9092
checkDefault,
91-
SyntaxFactory.ThrowStatement(
92-
SyntaxFactory.ObjectCreationExpression(
93+
SyntaxRepo.ThrowStatement(
94+
SyntaxRepo.ObjectCreationExpression(
9395
SyntaxFactory.IdentifierName(
9496
SyntaxFactory.Identifier("System.ArgumentNullException"))).AddArgumentListArguments(
9597
SyntaxFactory.Argument(
9698
SyntaxFactory.LiteralExpression(
9799
SyntaxKind.StringLiteralExpression,
98-
SyntaxFactory.Literal(parameter.Identifier.Text))))));
100+
SyntaxFactory.Literal(parameter.Identifier.Text))))))
101+
.WithNewLine();
99102
}
100103

101104
private static bool IsReferenceType(GenerationContext<TypeDeclarationSyntax> context, TypeSyntax type)

Immutype/Core/SyntaxRepo.cs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
namespace Immutype.Core;
2+
3+
internal static class SyntaxRepo
4+
{
5+
public static SyntaxToken WithSpace(this SyntaxKind syntaxKind) =>
6+
SyntaxFactory.Token(SyntaxFactory.TriviaList(), syntaxKind, SyntaxFactory.TriviaList(SyntaxFactory.ElasticSpace));
7+
8+
public static SyntaxToken WithSpace(this SyntaxToken syntaxToken) =>
9+
syntaxToken.WithLeadingTrivia(syntaxToken.LeadingTrivia.Concat(new []{SyntaxFactory.ElasticSpace}));
10+
11+
private static SyntaxToken WithNewLine(this SyntaxKind syntaxKind) =>
12+
SyntaxFactory.Token(SyntaxFactory.TriviaList(), syntaxKind, SyntaxFactory.TriviaList(SyntaxFactory.CarriageReturn, SyntaxFactory.LineFeed));
13+
14+
public static TSyntax WithSpace<TSyntax>(this TSyntax node) where TSyntax : SyntaxNode =>
15+
node.WithLeadingTrivia(node.GetLeadingTrivia().Concat(new []{SyntaxFactory.ElasticSpace}));
16+
17+
public static TSyntax WithNewLine<TSyntax>(this TSyntax node) where TSyntax : SyntaxNode =>
18+
node.WithLeadingTrivia(node.GetLeadingTrivia().Concat(new []{SyntaxFactory.CarriageReturn, SyntaxFactory.LineFeed}));
19+
20+
public static ExpressionStatementSyntax ExpressionStatement(ExpressionSyntax expression)
21+
=> SyntaxFactory.ExpressionStatement(default, expression, SyntaxKind.SemicolonToken.WithNewLine());
22+
23+
public static ObjectCreationExpressionSyntax ObjectCreationExpression(TypeSyntax type, ArgumentListSyntax? argumentList = default, InitializerExpressionSyntax? initializer = default)
24+
=> SyntaxFactory.ObjectCreationExpression(SyntaxKind.NewKeyword.WithSpace(), type, argumentList, initializer);
25+
26+
#pragma warning disable RS0027
27+
public static ReturnStatementSyntax ReturnStatement(ExpressionSyntax? expression = default)
28+
=> SyntaxFactory.ReturnStatement(default, SyntaxKind.ReturnKeyword.WithSpace(), expression, SyntaxFactory.Token(SyntaxKind.SemicolonToken));
29+
#pragma warning restore RS0027
30+
31+
public static ArrayCreationExpressionSyntax ArrayCreationExpression(ArrayTypeSyntax type, InitializerExpressionSyntax? initializer = default)
32+
=> SyntaxFactory.ArrayCreationExpression(SyntaxKind.NewKeyword.WithSpace(), type, initializer);
33+
34+
public static MethodDeclarationSyntax MethodDeclaration(TypeSyntax returnType, string identifier)
35+
=> SyntaxFactory.MethodDeclaration(default, default, returnType, default, SyntaxFactory.Identifier(identifier).WithSpace(), default, SyntaxFactory.ParameterList(), default, default, default, default);
36+
37+
public static MethodDeclarationSyntax MethodDeclaration(TypeSyntax returnType, SyntaxToken identifier)
38+
=> SyntaxFactory.MethodDeclaration(default, default, returnType, default, identifier.WithSpace(), default, SyntaxFactory.ParameterList(), default, default, default, default);
39+
40+
public static ClassDeclarationSyntax ClassDeclaration(string identifier)
41+
=> SyntaxFactory.ClassDeclaration(default, default, SyntaxKind.ClassKeyword.WithSpace(), SyntaxFactory.Identifier(identifier), default, default, default, SyntaxKind.OpenBraceToken.WithNewLine(), default, SyntaxKind.CloseBraceToken.WithNewLine(), default);
42+
43+
public static ParameterSyntax Parameter(SyntaxToken identifier)
44+
=> SyntaxFactory.Parameter(default, default, default, identifier.WithSpace(), default);
45+
46+
#pragma warning disable RS0027
47+
public static ThrowStatementSyntax ThrowStatement(ExpressionSyntax? expression = default)
48+
=> SyntaxFactory.ThrowStatement(default, SyntaxKind.ThrowKeyword.WithSpace(), expression, SyntaxFactory.Token(SyntaxKind.SemicolonToken));
49+
#pragma warning restore RS0027
50+
}

0 commit comments

Comments
 (0)