Skip to content

Commit b99d139

Browse files
committed
Use AutoWrapSeparatedSyntaxList instead of UnknownElementTypeSyntaxList
1 parent 59386e3 commit b99d139

2 files changed

Lines changed: 11 additions & 268 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/SA1141CodeFixProvider.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
namespace StyleCop.Analyzers.ReadabilityRules
55
{
6+
using System;
67
using System.Collections.Generic;
78
using System.Collections.Immutable;
89
using System.Composition;
@@ -97,23 +98,23 @@ private static SyntaxNode GetReplacementNode(SemanticModel semanticModel, Syntax
9798

9899
private static SyntaxNode TransformGenericNameToTuple(SemanticModel semanticModel, GenericNameSyntax genericName)
99100
{
100-
var tupleElements = new List<TupleElementSyntaxWrapper>();
101+
var implementationType = typeof(SeparatedSyntaxListWrapper<>.AutoWrapSeparatedSyntaxList<>).MakeGenericType(typeof(TupleElementSyntaxWrapper), TupleElementSyntaxWrapper.WrappedType);
102+
var tupleElements = (SeparatedSyntaxListWrapper<TupleElementSyntaxWrapper>)Activator.CreateInstance(implementationType);
101103

102104
foreach (var typeArgument in genericName.TypeArgumentList.Arguments)
103105
{
104106
if (IsValueTuple(semanticModel, typeArgument))
105107
{
106108
var tupleTypeSyntax = (TypeSyntax)GetReplacementNode(semanticModel, typeArgument);
107-
tupleElements.Add(SyntaxFactoryEx.TupleElement(tupleTypeSyntax));
109+
tupleElements = tupleElements.Add(SyntaxFactoryEx.TupleElement(tupleTypeSyntax));
108110
}
109111
else
110112
{
111-
tupleElements.Add(SyntaxFactoryEx.TupleElement(typeArgument));
113+
tupleElements = tupleElements.Add(SyntaxFactoryEx.TupleElement(typeArgument));
112114
}
113115
}
114116

115-
var elements = new SeparatedSyntaxListWrapper<TupleElementSyntaxWrapper>.UnknownElementTypeSyntaxList(tupleElements);
116-
return SyntaxFactoryEx.TupleType(elements);
117+
return SyntaxFactoryEx.TupleType(tupleElements);
117118
}
118119

119120
private static SyntaxNode TransformArgumentListToTuple(SemanticModel semanticModel, SeparatedSyntaxList<ArgumentSyntax> arguments)

StyleCop.Analyzers/StyleCop.Analyzers/Lightup/SeparatedSyntaxListWrapper`1.cs

Lines changed: 5 additions & 263 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,11 @@ internal sealed class AutoWrapSeparatedSyntaxList<TSyntax> : SeparatedSyntaxList
225225
{
226226
private readonly SeparatedSyntaxList<TSyntax> syntaxList;
227227

228+
public AutoWrapSeparatedSyntaxList()
229+
: this(default)
230+
{
231+
}
232+
228233
public AutoWrapSeparatedSyntaxList(SeparatedSyntaxList<TSyntax> syntaxList)
229234
{
230235
this.syntaxList = syntaxList;
@@ -318,269 +323,6 @@ public override string ToString()
318323
=> this.syntaxList.ToString();
319324
}
320325

321-
/// <summary>
322-
/// Wrapper class for elements that have no type definition at compile time.
323-
/// </summary>
324-
internal sealed class UnknownElementTypeSyntaxList : SeparatedSyntaxListWrapper<TNode>
325-
{
326-
private static readonly Type WrappedType = WrapperHelper.GetWrappedType(typeof(TNode));
327-
private static readonly MethodInfo EnumerableCastMethodInfo = typeof(Enumerable).GetTypeInfo().GetDeclaredMethod(nameof(Enumerable.Cast)).MakeGenericMethod(WrappedType);
328-
329-
private readonly object underlyingList;
330-
private readonly System.Reflection.TypeInfo underlyingListTypeInfo;
331-
332-
private Lazy<PropertyInfo> countPropertyInfo;
333-
private Lazy<PropertyInfo> fullSpanPropertyInfo;
334-
private Lazy<PropertyInfo> separatorCountPropertyInfo;
335-
private Lazy<PropertyInfo> spanPropertyInfo;
336-
private Lazy<PropertyInfo> indexerPropertyInfo;
337-
private Lazy<MethodInfo> anyMethodInfo;
338-
private Lazy<MethodInfo> containsMethodInfo;
339-
private Lazy<MethodInfo> firstMethodInfo;
340-
private Lazy<MethodInfo> firstOrDefaultMethodInfo;
341-
private Lazy<MethodInfo> getSeparatorMethodInfo;
342-
private Lazy<MethodInfo> getSeparatorsMethodInfo;
343-
private Lazy<MethodInfo> getWithSeparatorsMethodInfo;
344-
private Lazy<MethodInfo> indexOfPredicateMethodInfo;
345-
private Lazy<MethodInfo> indexOfItemMethodInfo;
346-
private Lazy<MethodInfo> insertMethodInfo;
347-
private Lazy<MethodInfo> insertRangeMethodInfo;
348-
private Lazy<MethodInfo> lastMethodInfo;
349-
private Lazy<MethodInfo> lastIndexOfPredicateMethodInfo;
350-
private Lazy<MethodInfo> lastIndexOfItemMethodInfo;
351-
private Lazy<MethodInfo> lastOrDefaultMethodInfo;
352-
private Lazy<MethodInfo> removeMethodInfo;
353-
private Lazy<MethodInfo> removeAtMethodInfo;
354-
private Lazy<MethodInfo> replaceMethodInfo;
355-
private Lazy<MethodInfo> replaceRangeMethodInfo;
356-
private Lazy<MethodInfo> replaceSeparatorMethodInfo;
357-
private Lazy<MethodInfo> toFullStringMethodInfo;
358-
359-
public UnknownElementTypeSyntaxList(IEnumerable<TNode> elements)
360-
{
361-
this.underlyingList = this.CreateUnderlyingList(elements);
362-
this.underlyingListTypeInfo = this.underlyingList.GetType().GetTypeInfo();
363-
364-
this.SetupMethodInfos();
365-
}
366-
367-
public UnknownElementTypeSyntaxList(object underlyingList)
368-
{
369-
this.underlyingList = underlyingList;
370-
this.underlyingListTypeInfo = this.underlyingList.GetType().GetTypeInfo();
371-
372-
this.SetupMethodInfos();
373-
}
374-
375-
public override int Count
376-
=> this.GetPropertyValue<int>(this.countPropertyInfo);
377-
378-
public override TextSpan FullSpan
379-
=> this.GetPropertyValue<TextSpan>(this.fullSpanPropertyInfo);
380-
381-
public override int SeparatorCount
382-
=> this.GetPropertyValue<int>(this.separatorCountPropertyInfo);
383-
384-
public override TextSpan Span
385-
=> this.GetPropertyValue<TextSpan>(this.spanPropertyInfo);
386-
387-
public override object UnderlyingList
388-
=> this.underlyingList;
389-
390-
public override TNode this[int index]
391-
=> SyntaxWrapper.Wrap((SyntaxNode)this.indexerPropertyInfo.Value.GetValue(this.underlyingList, new object[] { index }));
392-
393-
public override bool Any()
394-
=> this.InvokeFunction<bool>(this.anyMethodInfo);
395-
396-
public override bool Contains(TNode node)
397-
=> this.InvokeFunction<bool>(this.containsMethodInfo, SyntaxWrapper.Unwrap(node));
398-
399-
public override TNode First()
400-
=> SyntaxWrapper.Wrap(this.InvokeFunction<SyntaxNode>(this.firstMethodInfo));
401-
402-
public override TNode FirstOrDefault()
403-
=> SyntaxWrapper.Wrap(this.InvokeFunction<SyntaxNode>(this.firstOrDefaultMethodInfo));
404-
405-
public override int GetHashCode()
406-
=> this.underlyingList.GetHashCode();
407-
408-
public override SyntaxToken GetSeparator(int index)
409-
=> this.InvokeFunction<SyntaxToken>(this.getSeparatorMethodInfo, index);
410-
411-
public override IEnumerable<SyntaxToken> GetSeparators()
412-
=> this.InvokeFunction<IEnumerable<SyntaxToken>>(this.getSeparatorsMethodInfo);
413-
414-
public override SyntaxNodeOrTokenList GetWithSeparators()
415-
=> this.InvokeFunction<SyntaxNodeOrTokenList>(this.getWithSeparatorsMethodInfo);
416-
417-
public override int IndexOf(Func<TNode, bool> predicate)
418-
{
419-
//// TODO: create a new Func<TNode, bool> instance based on reflected information.
420-
//// => this.InvokeFunction<int>(this.indexOfPredicateMethodInfo, node => predicate(SyntaxWrapper.Wrap(node)));
421-
throw new NotImplementedException();
422-
}
423-
424-
public override int IndexOf(TNode node)
425-
=> this.InvokeFunction<int>(this.indexOfItemMethodInfo, SyntaxWrapper.Unwrap(node));
426-
427-
public override SeparatedSyntaxListWrapper<TNode> Insert(int index, TNode node)
428-
{
429-
var newUnderlyingList = this.InvokeFunction<object>(this.insertMethodInfo, index, SyntaxWrapper.Unwrap(node));
430-
return new UnknownElementTypeSyntaxList(newUnderlyingList);
431-
}
432-
433-
public override SeparatedSyntaxListWrapper<TNode> InsertRange(int index, IEnumerable<TNode> nodes)
434-
{
435-
var newUnderlyingList = this.InvokeFunction<object>(this.insertMethodInfo, index, CreateUnwrappedEnumerable(nodes));
436-
return new UnknownElementTypeSyntaxList(newUnderlyingList);
437-
}
438-
439-
public override TNode Last()
440-
=> SyntaxWrapper.Wrap(this.InvokeFunction<SyntaxNode>(this.lastMethodInfo));
441-
442-
public override int LastIndexOf(Func<TNode, bool> predicate)
443-
{
444-
//// TODO: See implementation of IndexOf with a predicate
445-
throw new NotImplementedException();
446-
}
447-
448-
public override int LastIndexOf(TNode node)
449-
=> this.InvokeFunction<int>(this.lastIndexOfItemMethodInfo, SyntaxWrapper.Unwrap(node));
450-
451-
public override TNode LastOrDefault()
452-
=> SyntaxWrapper.Wrap(this.InvokeFunction<SyntaxNode>(this.lastOrDefaultMethodInfo));
453-
454-
public override SeparatedSyntaxListWrapper<TNode> Remove(TNode node)
455-
{
456-
var newUnderlyingList = this.InvokeFunction<object>(this.removeMethodInfo, SyntaxWrapper.Unwrap(node));
457-
return new UnknownElementTypeSyntaxList(newUnderlyingList);
458-
}
459-
460-
public override SeparatedSyntaxListWrapper<TNode> RemoveAt(int index)
461-
{
462-
var newUnderlyingList = this.InvokeFunction<object>(this.removeAtMethodInfo, index);
463-
return new UnknownElementTypeSyntaxList(newUnderlyingList);
464-
}
465-
466-
public override SeparatedSyntaxListWrapper<TNode> Replace(TNode nodeInList, TNode newNode)
467-
{
468-
var newUnderlyingList = this.InvokeFunction<object>(this.replaceMethodInfo, SyntaxWrapper.Unwrap(nodeInList), SyntaxWrapper.Unwrap(newNode));
469-
return new UnknownElementTypeSyntaxList(newUnderlyingList);
470-
}
471-
472-
public override SeparatedSyntaxListWrapper<TNode> ReplaceRange(TNode nodeInList, IEnumerable<TNode> newNodes)
473-
{
474-
var newUnderlyingList = this.InvokeFunction<object>(this.replaceRangeMethodInfo, SyntaxWrapper.Unwrap(nodeInList), CreateUnwrappedEnumerable(newNodes));
475-
return new UnknownElementTypeSyntaxList(newUnderlyingList);
476-
}
477-
478-
public override SeparatedSyntaxListWrapper<TNode> ReplaceSeparator(SyntaxToken separatorToken, SyntaxToken newSeparator)
479-
{
480-
var newUnderlyingList = this.InvokeFunction<object>(this.replaceSeparatorMethodInfo, separatorToken, newSeparator);
481-
return new UnknownElementTypeSyntaxList(newUnderlyingList);
482-
}
483-
484-
public override string ToFullString()
485-
=> this.InvokeFunction<string>(this.toFullStringMethodInfo);
486-
487-
public override string ToString()
488-
=> this.underlyingList.ToString();
489-
490-
private static object CreateUnwrappedEnumerable(IEnumerable<TNode> elements)
491-
{
492-
return EnumerableCastMethodInfo.Invoke(null, new object[] { elements.Select(e => SyntaxWrapper.Unwrap(e)) });
493-
}
494-
495-
private object CreateUnderlyingList(IEnumerable<TNode> elements)
496-
{
497-
var syntaxFactoryTypeInfo = typeof(SyntaxFactory).GetTypeInfo();
498-
var method = syntaxFactoryTypeInfo.GetDeclaredMethods(nameof(SyntaxFactory.SeparatedList))
499-
.Single(m =>
500-
{
501-
if (!m.IsStatic)
502-
{
503-
return false;
504-
}
505-
506-
var parameters = m.GetParameters();
507-
if (parameters.Length != 1)
508-
{
509-
return false;
510-
}
511-
512-
var parameterType = parameters[0].ParameterType;
513-
if (!parameterType.IsConstructedGenericType || (parameterType.GetGenericTypeDefinition() != typeof(IEnumerable<>)))
514-
{
515-
return false;
516-
}
517-
518-
return parameterType.GenericTypeArguments[0].Name == "TNode";
519-
})
520-
.MakeGenericMethod(WrappedType);
521-
522-
return method.Invoke(null, new object[] { CreateUnwrappedEnumerable(elements) });
523-
}
524-
525-
private void SetupMethodInfos()
526-
{
527-
this.countPropertyInfo = new Lazy<PropertyInfo>(() => this.underlyingListTypeInfo.GetDeclaredProperty(nameof(SeparatedSyntaxList<SyntaxNode>.Count)));
528-
this.fullSpanPropertyInfo = new Lazy<PropertyInfo>(() => this.underlyingListTypeInfo.GetDeclaredProperty(nameof(SeparatedSyntaxList<SyntaxNode>.FullSpan)));
529-
this.separatorCountPropertyInfo = new Lazy<PropertyInfo>(() => this.underlyingListTypeInfo.GetDeclaredProperty(nameof(SeparatedSyntaxList<SyntaxNode>.SeparatorCount)));
530-
this.spanPropertyInfo = new Lazy<PropertyInfo>(() => this.underlyingListTypeInfo.GetDeclaredProperty(nameof(SeparatedSyntaxList<SyntaxNode>.Span)));
531-
this.indexerPropertyInfo = new Lazy<PropertyInfo>(() => this.underlyingListTypeInfo.GetDeclaredProperty("Item"));
532-
533-
this.anyMethodInfo = new Lazy<MethodInfo>(() => this.underlyingListTypeInfo.GetDeclaredMethod(nameof(SeparatedSyntaxList<SyntaxNode>.Any)));
534-
this.containsMethodInfo = new Lazy<MethodInfo>(() => this.underlyingListTypeInfo.GetDeclaredMethod(nameof(SeparatedSyntaxList<SyntaxNode>.Contains)));
535-
this.firstMethodInfo = new Lazy<MethodInfo>(() => this.underlyingListTypeInfo.GetDeclaredMethod(nameof(SeparatedSyntaxList<SyntaxNode>.First)));
536-
this.firstOrDefaultMethodInfo = new Lazy<MethodInfo>(() => this.underlyingListTypeInfo.GetDeclaredMethod(nameof(SeparatedSyntaxList<SyntaxNode>.FirstOrDefault)));
537-
this.getSeparatorMethodInfo = new Lazy<MethodInfo>(() => this.underlyingListTypeInfo.GetDeclaredMethod(nameof(SeparatedSyntaxList<SyntaxNode>.GetSeparator)));
538-
this.getSeparatorsMethodInfo = new Lazy<MethodInfo>(() => this.underlyingListTypeInfo.GetDeclaredMethod(nameof(SeparatedSyntaxList<SyntaxNode>.GetSeparators)));
539-
this.getWithSeparatorsMethodInfo = new Lazy<MethodInfo>(() => this.underlyingListTypeInfo.GetDeclaredMethod(nameof(SeparatedSyntaxList<SyntaxNode>.GetWithSeparators)));
540-
541-
this.indexOfPredicateMethodInfo = new Lazy<MethodInfo>(() =>
542-
{
543-
return this.underlyingListTypeInfo.GetDeclaredMethods(nameof(SeparatedSyntaxList<SyntaxNode>.IndexOf))
544-
.Single(m => m.GetParameters()[0].ParameterType.Name == "Func`2");
545-
});
546-
this.indexOfItemMethodInfo = new Lazy<MethodInfo>(() =>
547-
{
548-
return this.underlyingListTypeInfo.GetDeclaredMethods(nameof(SeparatedSyntaxList<SyntaxNode>.IndexOf))
549-
.Single(m => m.GetParameters()[0].ParameterType == WrappedType);
550-
});
551-
this.insertMethodInfo = new Lazy<MethodInfo>(() => this.underlyingListTypeInfo.GetDeclaredMethod(nameof(SeparatedSyntaxList<SyntaxNode>.Insert)));
552-
this.insertRangeMethodInfo = new Lazy<MethodInfo>(() => this.underlyingListTypeInfo.GetDeclaredMethod(nameof(SeparatedSyntaxList<SyntaxNode>.InsertRange)));
553-
this.lastMethodInfo = new Lazy<MethodInfo>(() => this.underlyingListTypeInfo.GetDeclaredMethod(nameof(SeparatedSyntaxList<SyntaxNode>.Last)));
554-
this.lastIndexOfPredicateMethodInfo = new Lazy<MethodInfo>(() =>
555-
{
556-
return this.underlyingListTypeInfo.GetDeclaredMethods(nameof(SeparatedSyntaxList<SyntaxNode>.LastIndexOf))
557-
.Single(m => m.GetParameters()[0].ParameterType.Name == "Func`2");
558-
});
559-
this.lastIndexOfItemMethodInfo = new Lazy<MethodInfo>(() =>
560-
{
561-
return this.underlyingListTypeInfo.GetDeclaredMethods(nameof(SeparatedSyntaxList<SyntaxNode>.LastIndexOf))
562-
.Single(m => m.GetParameters()[0].ParameterType == WrappedType);
563-
});
564-
this.lastOrDefaultMethodInfo = new Lazy<MethodInfo>(() => this.underlyingListTypeInfo.GetDeclaredMethod(nameof(SeparatedSyntaxList<SyntaxNode>.LastOrDefault)));
565-
this.removeMethodInfo = new Lazy<MethodInfo>(() => this.underlyingListTypeInfo.GetDeclaredMethod(nameof(SeparatedSyntaxList<SyntaxNode>.Remove)));
566-
this.removeAtMethodInfo = new Lazy<MethodInfo>(() => this.underlyingListTypeInfo.GetDeclaredMethod(nameof(SeparatedSyntaxList<SyntaxNode>.RemoveAt)));
567-
this.replaceMethodInfo = new Lazy<MethodInfo>(() => this.underlyingListTypeInfo.GetDeclaredMethod(nameof(SeparatedSyntaxList<SyntaxNode>.Replace)));
568-
this.replaceRangeMethodInfo = new Lazy<MethodInfo>(() => this.underlyingListTypeInfo.GetDeclaredMethod(nameof(SeparatedSyntaxList<SyntaxNode>.ReplaceRange)));
569-
this.replaceSeparatorMethodInfo = new Lazy<MethodInfo>(() => this.underlyingListTypeInfo.GetDeclaredMethod(nameof(SeparatedSyntaxList<SyntaxNode>.ReplaceSeparator)));
570-
this.toFullStringMethodInfo = new Lazy<MethodInfo>(() => this.underlyingListTypeInfo.GetDeclaredMethod(nameof(SeparatedSyntaxList<SyntaxNode>.ToFullString)));
571-
}
572-
573-
private T GetPropertyValue<T>(Lazy<PropertyInfo> propertyInfo)
574-
{
575-
return (T)propertyInfo.Value.GetValue(this.underlyingList);
576-
}
577-
578-
private T InvokeFunction<T>(Lazy<MethodInfo> methodInfo, params object[] parameters)
579-
{
580-
return (T)methodInfo.Value.Invoke(this.underlyingList, parameters);
581-
}
582-
}
583-
584326
private sealed class UnsupportedSyntaxList : SeparatedSyntaxListWrapper<TNode>
585327
{
586328
private static readonly SeparatedSyntaxList<SyntaxNode> SyntaxList = default(SeparatedSyntaxList<SyntaxNode>);

0 commit comments

Comments
 (0)